Mercurial > hg > graal-compiler
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. |