Skip to content

Commit c953e0e

Browse files
committed
8350579: Remove Template Assertion Predicates belonging to a loop once it is folded away
Reviewed-by: epeter, roland
1 parent 67c4405 commit c953e0e

File tree

9 files changed

+656
-128
lines changed

9 files changed

+656
-128
lines changed

src/hotspot/share/opto/loopTransform.cpp

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1699,17 +1699,16 @@ bool IdealLoopTree::is_invariant(Node* n) const {
16991699

17001700
// Search the Assertion Predicates added by loop predication and/or range check elimination and update them according
17011701
// to the new stride.
1702-
void PhaseIdealLoop::update_main_loop_assertion_predicates(CountedLoopNode* main_loop_head) {
1703-
Node* init = main_loop_head->init_trip();
1704-
1702+
void PhaseIdealLoop::update_main_loop_assertion_predicates(CountedLoopNode* new_main_loop_head,
1703+
const int stride_con_before_unroll) {
17051704
// Compute the value of the loop induction variable at the end of the
17061705
// first iteration of the unrolled loop: init + new_stride_con - init_inc
1707-
int unrolled_stride_con = main_loop_head->stride_con() * 2;
1706+
int unrolled_stride_con = stride_con_before_unroll * 2;
17081707
Node* unrolled_stride = intcon(unrolled_stride_con);
17091708

1710-
Node* loop_entry = main_loop_head->skip_strip_mined()->in(LoopNode::EntryControl);
1709+
Node* loop_entry = new_main_loop_head->skip_strip_mined()->in(LoopNode::EntryControl);
17111710
PredicateIterator predicate_iterator(loop_entry);
1712-
UpdateStrideForAssertionPredicates update_stride_for_assertion_predicates(unrolled_stride, this);
1711+
UpdateStrideForAssertionPredicates update_stride_for_assertion_predicates(unrolled_stride, new_main_loop_head, this);
17131712
predicate_iterator.for_each(update_stride_for_assertion_predicates);
17141713
}
17151714

@@ -1748,9 +1747,9 @@ void PhaseIdealLoop::initialize_assertion_predicates_for_post_loop(CountedLoopNo
17481747
}
17491748

17501749
void PhaseIdealLoop::create_assertion_predicates_at_loop(CountedLoopNode* source_loop_head,
1751-
CountedLoopNode* target_loop_head,
1752-
const NodeInLoopBody& _node_in_loop_body,
1753-
const bool clone_template) {
1750+
CountedLoopNode* target_loop_head,
1751+
const NodeInLoopBody& _node_in_loop_body,
1752+
const bool clone_template) {
17541753
CreateAssertionPredicatesVisitor create_assertion_predicates_visitor(target_loop_head, this, _node_in_loop_body,
17551754
clone_template);
17561755
Node* source_loop_entry = source_loop_head->skip_strip_mined()->in(LoopNode::EntryControl);
@@ -1854,15 +1853,13 @@ void PhaseIdealLoop::do_unroll(IdealLoopTree *loop, Node_List &old_new, bool adj
18541853
C->set_major_progress();
18551854

18561855
Node* new_limit = nullptr;
1857-
int stride_con = stride->get_int();
1856+
const int stride_con = stride->get_int();
18581857
int stride_p = (stride_con > 0) ? stride_con : -stride_con;
18591858
uint old_trip_count = loop_head->trip_count();
18601859
// Verify that unroll policy result is still valid.
18611860
assert(old_trip_count > 1 && (!adjust_min_trip || stride_p <=
18621861
MIN2<int>(max_jint / 2 - 2, MAX2(1<<3, Matcher::max_vector_size(T_BYTE)) * loop_head->unrolled_count())), "sanity");
18631862

1864-
update_main_loop_assertion_predicates(loop_head);
1865-
18661863
// Adjust loop limit to keep valid iterations number after unroll.
18671864
// Use (limit - stride) instead of (((limit - init)/stride) & (-2))*stride
18681865
// which may overflow.
@@ -1996,7 +1993,7 @@ void PhaseIdealLoop::do_unroll(IdealLoopTree *loop, Node_List &old_new, bool adj
19961993
phi ->set_req(LoopNode::LoopBackControl, C->top());
19971994
}
19981995
}
1999-
Node *clone_head = old_new[loop_head->_idx];
1996+
CountedLoopNode* clone_head = old_new[loop_head->_idx]->as_CountedLoop();
20001997
_igvn.hash_delete(clone_head);
20011998
loop_head ->set_req(LoopNode:: EntryControl, clone_head->in(LoopNode::LoopBackControl));
20021999
clone_head->set_req(LoopNode::LoopBackControl, loop_head ->in(LoopNode::LoopBackControl));
@@ -2025,6 +2022,8 @@ void PhaseIdealLoop::do_unroll(IdealLoopTree *loop, Node_List &old_new, bool adj
20252022
loop->record_for_igvn();
20262023
loop_head->clear_strip_mined();
20272024

2025+
update_main_loop_assertion_predicates(clone_head, stride_con);
2026+
20282027
#ifndef PRODUCT
20292028
if (C->do_vector_loop() && (PrintOpto && (VerifyLoopOptimizations || TraceLoopOpts))) {
20302029
tty->print("\nnew loop after unroll\n"); loop->dump_head();

src/hotspot/share/opto/loopUnswitch.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -279,14 +279,16 @@ class UnswitchedLoopSelector : public StackObj {
279279
// Class to unswitch the original loop and create Predicates at the new unswitched loop versions. The newly cloned loop
280280
// becomes the false-path-loop while original loop becomes the true-path-loop.
281281
class OriginalLoop : public StackObj {
282-
LoopNode* const _loop_head; // OuterStripMinedLoopNode if loop strip mined, else just the loop head.
282+
LoopNode* const _loop_head;
283+
LoopNode* const _outer_loop_head; // OuterStripMinedLoopNode if loop strip mined, else just the loop head.
283284
IdealLoopTree* const _loop;
284285
Node_List& _old_new;
285286
PhaseIdealLoop* const _phase;
286287

287288
public:
288289
OriginalLoop(IdealLoopTree* loop, Node_List& old_new)
289-
: _loop_head(loop->_head->as_Loop()->skip_strip_mined()),
290+
: _loop_head(loop->_head->as_Loop()),
291+
_outer_loop_head(loop->_head->as_Loop()->skip_strip_mined()),
290292
_loop(loop),
291293
_old_new(old_new),
292294
_phase(loop->_phase) {}
@@ -314,14 +316,14 @@ class OriginalLoop : public StackObj {
314316

315317
private:
316318
void clone_loop(const LoopSelector& loop_selector) {
317-
_phase->clone_loop(_loop, _old_new, _phase->dom_depth(_loop_head),
319+
_phase->clone_loop(_loop, _old_new, _phase->dom_depth(_outer_loop_head),
318320
PhaseIdealLoop::CloneIncludesStripMined, loop_selector.selector());
319321
fix_loop_entries(loop_selector);
320322
}
321323

322-
void fix_loop_entries(const LoopSelector& loop_selector) {
323-
_phase->replace_loop_entry(_loop_head, loop_selector.true_path_loop_proj());
324-
LoopNode* false_path_loop_strip_mined_head = old_to_new(_loop_head)->as_Loop();
324+
void fix_loop_entries(const LoopSelector& loop_selector) const {
325+
_phase->replace_loop_entry(_outer_loop_head, loop_selector.true_path_loop_proj());
326+
LoopNode* false_path_loop_strip_mined_head = old_to_new(_outer_loop_head)->as_Loop();
325327
_phase->replace_loop_entry(false_path_loop_strip_mined_head,
326328
loop_selector.false_path_loop_proj());
327329
}

src/hotspot/share/opto/loopnode.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -979,7 +979,7 @@ class PhaseIdealLoop : public PhaseTransform {
979979
private:
980980
static void get_opaque_template_assertion_predicate_nodes(ParsePredicateSuccessProj* parse_predicate_proj,
981981
Unique_Node_List& list);
982-
void update_main_loop_assertion_predicates(CountedLoopNode* main_loop_head);
982+
void update_main_loop_assertion_predicates(CountedLoopNode* new_main_loop_head, int stride_con_before_unroll);
983983
void initialize_assertion_predicates_for_peeled_loop(CountedLoopNode* peeled_loop_head,
984984
CountedLoopNode* remaining_loop_head,
985985
uint first_node_index_in_cloned_loop_body,

src/hotspot/share/opto/opaquenode.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,10 @@ const Type* OpaqueNotNullNode::Value(PhaseGVN* phase) const {
112112
return phase->type(in(1));
113113
}
114114

115-
OpaqueTemplateAssertionPredicateNode::OpaqueTemplateAssertionPredicateNode(BoolNode* bol): Node(nullptr, bol),
116-
_predicate_state(PredicateState::Useful) {
115+
OpaqueTemplateAssertionPredicateNode::OpaqueTemplateAssertionPredicateNode(BoolNode* bol, CountedLoopNode* loop_node)
116+
: Node(nullptr, bol),
117+
_loop_node(loop_node),
118+
_predicate_state(PredicateState::Useful) {
117119
init_class_id(Class_OpaqueTemplateAssertionPredicate);
118120
}
119121

@@ -148,6 +150,7 @@ void OpaqueTemplateAssertionPredicateNode::mark_useless(PhaseIterGVN& igvn) {
148150

149151
#ifndef PRODUCT
150152
void OpaqueTemplateAssertionPredicateNode::dump_spec(outputStream* st) const {
153+
st->print("loop_idx=%d ", _loop_node->_idx);
151154
if (is_useless()) {
152155
st->print("#useless ");
153156
}

src/hotspot/share/opto/opaquenode.hpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,9 @@ class OpaqueNotNullNode : public Node {
152152
// OpaqueTemplateAssertionPredicateNode is replaced by true in order to fold the Template Assertion Predicate away.
153153
class OpaqueTemplateAssertionPredicateNode : public Node {
154154

155+
// The counted loop this Template Assertion Predicate is associated with.
156+
CountedLoopNode* _loop_node;
157+
155158
// When splitting a loop or when the associated loop dies, the Template Assertion Predicate with this
156159
// OpaqueTemplateAssertionPredicateNode also needs to be removed. We set this flag and then clean this node up in the
157160
// next IGVN phase by checking this flag in Value().
@@ -164,14 +167,23 @@ class OpaqueTemplateAssertionPredicateNode : public Node {
164167
}
165168

166169
public:
167-
OpaqueTemplateAssertionPredicateNode(BoolNode* bol);
170+
OpaqueTemplateAssertionPredicateNode(BoolNode* bol, CountedLoopNode* loop_node);
168171

169172
virtual int Opcode() const;
170173
virtual uint size_of() const { return sizeof(*this); }
171174
virtual Node* Identity(PhaseGVN* phase);
172175
virtual const Type* Value(PhaseGVN* phase) const;
173176
virtual const Type* bottom_type() const { return TypeInt::BOOL; }
174177

178+
CountedLoopNode* loop_node() const {
179+
return _loop_node;
180+
}
181+
182+
// Should only be called during Loop Unrolling when we only update the OpaqueLoopStride input but don't require a full
183+
// clone of the Template Assertion Expression.
184+
void update_loop_node(CountedLoopNode* loop_node) {
185+
_loop_node = loop_node;
186+
}
175187

176188
bool is_useless() const {
177189
return _predicate_state == PredicateState::Useless;

0 commit comments

Comments
 (0)