comparison src/share/vm/opto/loopnode.hpp @ 2465:3af54845df98

7004555: Add new policy for one iteration loops Summary: Add new policy for one iteration loops (mostly formal pre- loops). Reviewed-by: never
author kvn
date Fri, 08 Apr 2011 14:56:22 -0700
parents 08eb13460b3a
children bad7ecd0b6ed
comparison
equal deleted inserted replaced
2463:3f49d30f8184 2465:3af54845df98
55 // the semantics so it does not appear in the hash & cmp functions. 55 // the semantics so it does not appear in the hash & cmp functions.
56 virtual uint size_of() const { return sizeof(*this); } 56 virtual uint size_of() const { return sizeof(*this); }
57 protected: 57 protected:
58 short _loop_flags; 58 short _loop_flags;
59 // Names for flag bitfields 59 // Names for flag bitfields
60 enum { pre_post_main=0, inner_loop=8, partial_peel_loop=16, partial_peel_failed=32 }; 60 enum { Normal=0, Pre=1, Main=2, Post=3, PreMainPostFlagsMask=3,
61 MainHasNoPreLoop=4,
62 HasExactTripCount=8,
63 InnerLoop=16,
64 PartialPeelLoop=32,
65 PartialPeelFailed=64 };
61 char _unswitch_count; 66 char _unswitch_count;
62 enum { _unswitch_max=3 }; 67 enum { _unswitch_max=3 };
63 68
64 public: 69 public:
65 // Names for edge indices 70 // Names for edge indices
66 enum { Self=0, EntryControl, LoopBackControl }; 71 enum { Self=0, EntryControl, LoopBackControl };
67 72
68 int is_inner_loop() const { return _loop_flags & inner_loop; } 73 int is_inner_loop() const { return _loop_flags & InnerLoop; }
69 void set_inner_loop() { _loop_flags |= inner_loop; } 74 void set_inner_loop() { _loop_flags |= InnerLoop; }
70 75
71 int is_partial_peel_loop() const { return _loop_flags & partial_peel_loop; } 76 int is_partial_peel_loop() const { return _loop_flags & PartialPeelLoop; }
72 void set_partial_peel_loop() { _loop_flags |= partial_peel_loop; } 77 void set_partial_peel_loop() { _loop_flags |= PartialPeelLoop; }
73 int partial_peel_has_failed() const { return _loop_flags & partial_peel_failed; } 78 int partial_peel_has_failed() const { return _loop_flags & PartialPeelFailed; }
74 void mark_partial_peel_failed() { _loop_flags |= partial_peel_failed; } 79 void mark_partial_peel_failed() { _loop_flags |= PartialPeelFailed; }
75 80
76 int unswitch_max() { return _unswitch_max; } 81 int unswitch_max() { return _unswitch_max; }
77 int unswitch_count() { return _unswitch_count; } 82 int unswitch_count() { return _unswitch_count; }
78 void set_unswitch_count(int val) { 83 void set_unswitch_count(int val) {
79 assert (val <= unswitch_max(), "too many unswitches"); 84 assert (val <= unswitch_max(), "too many unswitches");
135 140
136 // For Pre- and Post-loops during debugging ONLY, this holds the index of 141 // For Pre- and Post-loops during debugging ONLY, this holds the index of
137 // the Main CountedLoop. Used to assert that we understand the graph shape. 142 // the Main CountedLoop. Used to assert that we understand the graph shape.
138 node_idx_t _main_idx; 143 node_idx_t _main_idx;
139 144
140 // Known trip count calculated by policy_maximally_unroll 145 // Known trip count calculated by compute_exact_trip_count()
141 int _trip_count; 146 uint _trip_count;
142 147
143 // Expected trip count from profile data 148 // Expected trip count from profile data
144 float _profile_trip_cnt; 149 float _profile_trip_cnt;
145 150
146 // Log2 of original loop bodies in unrolled loop 151 // Log2 of original loop bodies in unrolled loop
150 // unroll,optimize,unroll,optimize,... is making progress 155 // unroll,optimize,unroll,optimize,... is making progress
151 int _node_count_before_unroll; 156 int _node_count_before_unroll;
152 157
153 public: 158 public:
154 CountedLoopNode( Node *entry, Node *backedge ) 159 CountedLoopNode( Node *entry, Node *backedge )
155 : LoopNode(entry, backedge), _trip_count(max_jint), 160 : LoopNode(entry, backedge), _main_idx(0), _trip_count(max_juint),
156 _profile_trip_cnt(COUNT_UNKNOWN), _unrolled_count_log2(0), 161 _profile_trip_cnt(COUNT_UNKNOWN), _unrolled_count_log2(0),
157 _node_count_before_unroll(0) { 162 _node_count_before_unroll(0) {
158 init_class_id(Class_CountedLoop); 163 init_class_id(Class_CountedLoop);
159 // Initialize _trip_count to the largest possible value. 164 // Initialize _trip_count to the largest possible value.
160 // Will be reset (lower) if the loop's trip count is known. 165 // Will be reset (lower) if the loop's trip count is known.
192 // so the following main loop 'knows' that it is striding down cache 197 // so the following main loop 'knows' that it is striding down cache
193 // lines. 198 // lines.
194 199
195 // A 'main' loop that is ONLY unrolled or peeled, never RCE'd or 200 // A 'main' loop that is ONLY unrolled or peeled, never RCE'd or
196 // Aligned, may be missing it's pre-loop. 201 // Aligned, may be missing it's pre-loop.
197 enum { Normal=0, Pre=1, Main=2, Post=3, PrePostFlagsMask=3, Main_Has_No_Pre_Loop=4 }; 202 int is_normal_loop() const { return (_loop_flags&PreMainPostFlagsMask) == Normal; }
198 int is_normal_loop() const { return (_loop_flags&PrePostFlagsMask) == Normal; } 203 int is_pre_loop () const { return (_loop_flags&PreMainPostFlagsMask) == Pre; }
199 int is_pre_loop () const { return (_loop_flags&PrePostFlagsMask) == Pre; } 204 int is_main_loop () const { return (_loop_flags&PreMainPostFlagsMask) == Main; }
200 int is_main_loop () const { return (_loop_flags&PrePostFlagsMask) == Main; } 205 int is_post_loop () const { return (_loop_flags&PreMainPostFlagsMask) == Post; }
201 int is_post_loop () const { return (_loop_flags&PrePostFlagsMask) == Post; } 206 int is_main_no_pre_loop() const { return _loop_flags & MainHasNoPreLoop; }
202 int is_main_no_pre_loop() const { return _loop_flags & Main_Has_No_Pre_Loop; } 207 void set_main_no_pre_loop() { _loop_flags |= MainHasNoPreLoop; }
203 void set_main_no_pre_loop() { _loop_flags |= Main_Has_No_Pre_Loop; }
204 208
205 int main_idx() const { return _main_idx; } 209 int main_idx() const { return _main_idx; }
206 210
207 211
208 void set_pre_loop (CountedLoopNode *main) { assert(is_normal_loop(),""); _loop_flags |= Pre ; _main_idx = main->_idx; } 212 void set_pre_loop (CountedLoopNode *main) { assert(is_normal_loop(),""); _loop_flags |= Pre ; _main_idx = main->_idx; }
209 void set_main_loop ( ) { assert(is_normal_loop(),""); _loop_flags |= Main; } 213 void set_main_loop ( ) { assert(is_normal_loop(),""); _loop_flags |= Main; }
210 void set_post_loop (CountedLoopNode *main) { assert(is_normal_loop(),""); _loop_flags |= Post; _main_idx = main->_idx; } 214 void set_post_loop (CountedLoopNode *main) { assert(is_normal_loop(),""); _loop_flags |= Post; _main_idx = main->_idx; }
211 void set_normal_loop( ) { _loop_flags &= ~PrePostFlagsMask; } 215 void set_normal_loop( ) { _loop_flags &= ~PreMainPostFlagsMask; }
212 216
213 void set_trip_count(int tc) { _trip_count = tc; } 217 void set_trip_count(uint tc) { _trip_count = tc; }
214 int trip_count() { return _trip_count; } 218 uint trip_count() { return _trip_count; }
219
220 bool has_exact_trip_count() const { return (_loop_flags & HasExactTripCount) != 0; }
221 void set_exact_trip_count(uint tc) {
222 _trip_count = tc;
223 _loop_flags |= HasExactTripCount;
224 }
225 void set_nonexact_trip_count() {
226 _loop_flags &= ~HasExactTripCount;
227 }
215 228
216 void set_profile_trip_cnt(float ptc) { _profile_trip_cnt = ptc; } 229 void set_profile_trip_cnt(float ptc) { _profile_trip_cnt = ptc; }
217 float profile_trip_cnt() { return _profile_trip_cnt; } 230 float profile_trip_cnt() { return _profile_trip_cnt; }
218 231
219 void double_unrolled_count() { _unrolled_count_log2++; } 232 void double_unrolled_count() { _unrolled_count_log2++; }
382 bool policy_unswitching( PhaseIdealLoop *phase ) const; 395 bool policy_unswitching( PhaseIdealLoop *phase ) const;
383 396
384 // Micro-benchmark spamming. Remove empty loops. 397 // Micro-benchmark spamming. Remove empty loops.
385 bool policy_do_remove_empty_loop( PhaseIdealLoop *phase ); 398 bool policy_do_remove_empty_loop( PhaseIdealLoop *phase );
386 399
400 // Convert one iteration loop into normal code.
401 bool policy_do_one_iteration_loop( PhaseIdealLoop *phase );
402
387 // Return TRUE or FALSE if the loop should be peeled or not. Peel if we can 403 // Return TRUE or FALSE if the loop should be peeled or not. Peel if we can
388 // make some loop-invariant test (usually a null-check) happen before the 404 // make some loop-invariant test (usually a null-check) happen before the
389 // loop. 405 // loop.
390 bool policy_peeling( PhaseIdealLoop *phase ) const; 406 bool policy_peeling( PhaseIdealLoop *phase ) const;
391 407
409 // into longer memory ops, we may want to increase alignment. 425 // into longer memory ops, we may want to increase alignment.
410 bool policy_align( PhaseIdealLoop *phase ) const; 426 bool policy_align( PhaseIdealLoop *phase ) const;
411 427
412 // Return TRUE if "iff" is a range check. 428 // Return TRUE if "iff" is a range check.
413 bool is_range_check_if(IfNode *iff, PhaseIdealLoop *phase, Invariance& invar) const; 429 bool is_range_check_if(IfNode *iff, PhaseIdealLoop *phase, Invariance& invar) const;
430
431 // Compute loop exact trip count if possible
432 void compute_exact_trip_count( PhaseIdealLoop *phase );
414 433
415 // Compute loop trip count from profile data 434 // Compute loop trip count from profile data
416 void compute_profile_trip_cnt( PhaseIdealLoop *phase ); 435 void compute_profile_trip_cnt( PhaseIdealLoop *phase );
417 436
418 // Reassociate invariant expressions. 437 // Reassociate invariant expressions.