Skip to content

Commit 2592513

Browse files
committed
8350577: Fix missing Assertion Predicates when splitting loops
Reviewed-by: epeter, kvn
1 parent 59629f8 commit 2592513

File tree

5 files changed

+1782
-110
lines changed

5 files changed

+1782
-110
lines changed

src/hotspot/share/opto/loopTransform.cpp

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -812,7 +812,7 @@ void PhaseIdealLoop::do_peeling(IdealLoopTree *loop, Node_List &old_new) {
812812
}
813813

814814
// Step 5: Assertion Predicates initialization
815-
if (counted_loop && UseLoopPredicate) {
815+
if (counted_loop) {
816816
initialize_assertion_predicates_for_peeled_loop(new_head->as_CountedLoop(), head->as_CountedLoop(),
817817
first_node_index_in_post_loop_body, old_new);
818818
}
@@ -1450,11 +1450,9 @@ void PhaseIdealLoop::insert_pre_post_loops(IdealLoopTree *loop, Node_List &old_n
14501450
DEBUG_ONLY(const uint last_node_index_from_backedge_goo = Compile::current()->unique() - 1);
14511451

14521452
DEBUG_ONLY(ensure_zero_trip_guard_proj(outer_main_head->in(LoopNode::EntryControl), true);)
1453-
if (UseLoopPredicate) {
1454-
initialize_assertion_predicates_for_main_loop(pre_head, main_head, first_node_index_in_pre_loop_body,
1455-
last_node_index_in_pre_loop_body,
1456-
DEBUG_ONLY(last_node_index_from_backedge_goo COMMA) old_new);
1457-
}
1453+
initialize_assertion_predicates_for_main_loop(pre_head, main_head, first_node_index_in_pre_loop_body,
1454+
last_node_index_in_pre_loop_body,
1455+
DEBUG_ONLY(last_node_index_from_backedge_goo COMMA) old_new);
14581456

14591457
// Step B4: Shorten the pre-loop to run only 1 iteration (for now).
14601458
// RCE and alignment may change this later.
@@ -1683,9 +1681,7 @@ Node *PhaseIdealLoop::insert_post_loop(IdealLoopTree* loop, Node_List& old_new,
16831681
}
16841682

16851683
DEBUG_ONLY(ensure_zero_trip_guard_proj(post_head->in(LoopNode::EntryControl), false);)
1686-
if (UseLoopPredicate) {
1687-
initialize_assertion_predicates_for_post_loop(main_head, post_head, first_node_index_in_cloned_loop_body);
1688-
}
1684+
initialize_assertion_predicates_for_post_loop(main_head, post_head, first_node_index_in_cloned_loop_body);
16891685
return new_main_exit;
16901686
}
16911687

@@ -1719,7 +1715,7 @@ void PhaseIdealLoop::initialize_assertion_predicates_for_peeled_loop(CountedLoop
17191715
const uint first_node_index_in_cloned_loop_body,
17201716
const Node_List& old_new) {
17211717
const NodeInOriginalLoopBody node_in_original_loop_body(first_node_index_in_cloned_loop_body, old_new);
1722-
create_assertion_predicates_at_loop(peeled_loop_head, remaining_loop_head, node_in_original_loop_body, false);
1718+
create_assertion_predicates_at_loop(peeled_loop_head, remaining_loop_head, node_in_original_loop_body, true);
17231719
}
17241720

17251721
// Source Loop: Cloned - pre_loop_head
@@ -1739,6 +1735,9 @@ void PhaseIdealLoop::initialize_assertion_predicates_for_main_loop(CountedLoopNo
17391735

17401736
// Source Loop: Original - main_loop_head
17411737
// Target Loop: Cloned - post_loop_head
1738+
//
1739+
// The post loop is cloned before the pre loop. Do not kill the old Template Assertion Predicates, yet. We need to clone
1740+
// from them when creating the pre loop. Only then we can kill them.
17421741
void PhaseIdealLoop::initialize_assertion_predicates_for_post_loop(CountedLoopNode* main_loop_head,
17431742
CountedLoopNode* post_loop_head,
17441743
const uint first_node_index_in_cloned_loop_body) {
@@ -1749,9 +1748,9 @@ void PhaseIdealLoop::initialize_assertion_predicates_for_post_loop(CountedLoopNo
17491748
void PhaseIdealLoop::create_assertion_predicates_at_loop(CountedLoopNode* source_loop_head,
17501749
CountedLoopNode* target_loop_head,
17511750
const NodeInLoopBody& _node_in_loop_body,
1752-
const bool clone_template) {
1751+
const bool kill_old_template) {
17531752
CreateAssertionPredicatesVisitor create_assertion_predicates_visitor(target_loop_head, this, _node_in_loop_body,
1754-
clone_template);
1753+
kill_old_template);
17551754
Node* source_loop_entry = source_loop_head->skip_strip_mined()->in(LoopNode::EntryControl);
17561755
PredicateIterator predicate_iterator(source_loop_entry);
17571756
predicate_iterator.for_each(create_assertion_predicates_visitor);
@@ -1760,11 +1759,11 @@ void PhaseIdealLoop::create_assertion_predicates_at_loop(CountedLoopNode* source
17601759
void PhaseIdealLoop::create_assertion_predicates_at_main_or_post_loop(CountedLoopNode* source_loop_head,
17611760
CountedLoopNode* target_loop_head,
17621761
const NodeInLoopBody& _node_in_loop_body,
1763-
bool clone_template) {
1762+
const bool kill_old_template) {
17641763
Node* old_target_loop_head_entry = target_loop_head->skip_strip_mined()->in(LoopNode::EntryControl);
17651764
const uint node_index_before_new_assertion_predicate_nodes = C->unique();
17661765
const bool need_to_rewire_old_target_loop_entry_dependencies = old_target_loop_head_entry->outcnt() > 1;
1767-
create_assertion_predicates_at_loop(source_loop_head, target_loop_head, _node_in_loop_body, clone_template);
1766+
create_assertion_predicates_at_loop(source_loop_head, target_loop_head, _node_in_loop_body, kill_old_template);
17681767
if (need_to_rewire_old_target_loop_entry_dependencies) {
17691768
rewire_old_target_loop_entry_dependency_to_new_entry(target_loop_head, old_target_loop_head_entry,
17701769
node_index_before_new_assertion_predicate_nodes);

src/hotspot/share/opto/loopnode.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -993,10 +993,11 @@ class PhaseIdealLoop : public PhaseTransform {
993993
void initialize_assertion_predicates_for_post_loop(CountedLoopNode* main_loop_head, CountedLoopNode* post_loop_head,
994994
uint first_node_index_in_cloned_loop_body);
995995
void create_assertion_predicates_at_loop(CountedLoopNode* source_loop_head, CountedLoopNode* target_loop_head,
996-
const NodeInLoopBody& _node_in_loop_body, bool clone_template);
996+
const NodeInLoopBody& _node_in_loop_body, bool kill_old_template);
997997
void create_assertion_predicates_at_main_or_post_loop(CountedLoopNode* source_loop_head,
998998
CountedLoopNode* target_loop_head,
999-
const NodeInLoopBody& _node_in_loop_body, bool clone_template);
999+
const NodeInLoopBody& _node_in_loop_body,
1000+
bool kill_old_template);
10001001
void rewire_old_target_loop_entry_dependency_to_new_entry(LoopNode* target_loop_head,
10011002
const Node* old_target_loop_entry,
10021003
uint node_index_before_new_assertion_predicate_nodes);

src/hotspot/share/opto/predicates.cpp

Lines changed: 10 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -960,41 +960,24 @@ void Predicates::dump_for_loop(LoopNode* loop_node) {
960960
CreateAssertionPredicatesVisitor::CreateAssertionPredicatesVisitor(CountedLoopNode* target_loop_head,
961961
PhaseIdealLoop* phase,
962962
const NodeInLoopBody& node_in_loop_body,
963-
const bool clone_template)
963+
bool kill_old_template)
964964
: _init(target_loop_head->init_trip()),
965965
_stride(target_loop_head->stride()),
966966
_target_loop_head(target_loop_head),
967967
_old_target_loop_entry(target_loop_head->skip_strip_mined()->in(LoopNode::EntryControl)),
968968
_current_predicate_chain_head(target_loop_head->skip_strip_mined()), // Initially no predicates, yet.
969969
_phase(phase),
970-
_has_hoisted_check_parse_predicates(false),
971970
_node_in_loop_body(node_in_loop_body),
972-
_clone_template(clone_template) {}
973-
974-
// Keep track of whether we are in the correct Predicate Block where Template Assertion Predicates can be found.
975-
// The PredicateIterator will always start at the loop entry and first visits the Loop Limit Check Predicate Block.
976-
void CreateAssertionPredicatesVisitor::visit(const ParsePredicate& parse_predicate) {
977-
Deoptimization::DeoptReason deopt_reason = parse_predicate.head()->deopt_reason();
978-
if (deopt_reason == Deoptimization::Reason_predicate ||
979-
deopt_reason == Deoptimization::Reason_profile_predicate) {
980-
_has_hoisted_check_parse_predicates = true;
981-
}
982-
}
971+
_kill_old_template(kill_old_template) {}
983972

973+
// Clone Template Assertion Predicate and create an Initialized Assertion Predicate from it.
984974
void CreateAssertionPredicatesVisitor::visit(const TemplateAssertionPredicate& template_assertion_predicate) {
985-
if (!_has_hoisted_check_parse_predicates) {
986-
// Only process if we are in the correct Predicate Block.
987-
return;
988-
}
989-
if (_clone_template) {
990-
TemplateAssertionPredicate cloned_template_assertion_predicate =
991-
clone_template_and_replace_init_input(template_assertion_predicate);
992-
initialize_from_template(template_assertion_predicate, cloned_template_assertion_predicate.tail());
993-
_current_predicate_chain_head = cloned_template_assertion_predicate.head();
994-
} else {
995-
InitializedAssertionPredicate initialized_assertion_predicate =
996-
initialize_from_template(template_assertion_predicate, _old_target_loop_entry);
997-
_current_predicate_chain_head = initialized_assertion_predicate.head();
975+
TemplateAssertionPredicate cloned_template_assertion_predicate =
976+
clone_template_and_replace_init_input(template_assertion_predicate);
977+
initialize_from_template(template_assertion_predicate, cloned_template_assertion_predicate.tail());
978+
_current_predicate_chain_head = cloned_template_assertion_predicate.head();
979+
if (_kill_old_template) {
980+
template_assertion_predicate.kill(_phase->igvn());
998981
}
999982
}
1000983

@@ -1110,18 +1093,11 @@ CloneUnswitchedLoopPredicatesVisitor::CloneUnswitchedLoopPredicatesVisitor(
11101093
PhaseIdealLoop* phase)
11111094
: _clone_predicate_to_true_path_loop(true_path_loop_head, node_in_true_path_loop_body, phase),
11121095
_clone_predicate_to_false_path_loop(false_path_loop_head, node_in_false_path_loop_body, phase),
1113-
_phase(phase),
1114-
_has_hoisted_check_parse_predicates(false) {}
1096+
_phase(phase) {}
11151097

11161098
// Keep track of whether we are in the correct Predicate Block where Template Assertion Predicates can be found.
11171099
// The PredicateIterator will always start at the loop entry and first visits the Loop Limit Check Predicate Block.
11181100
void CloneUnswitchedLoopPredicatesVisitor::visit(const ParsePredicate& parse_predicate) {
1119-
Deoptimization::DeoptReason deopt_reason = parse_predicate.head()->deopt_reason();
1120-
if (deopt_reason == Deoptimization::Reason_predicate ||
1121-
deopt_reason == Deoptimization::Reason_profile_predicate) {
1122-
_has_hoisted_check_parse_predicates = true;
1123-
}
1124-
11251101
_clone_predicate_to_true_path_loop.clone_parse_predicate(parse_predicate, false);
11261102
_clone_predicate_to_false_path_loop.clone_parse_predicate(parse_predicate, true);
11271103
parse_predicate.kill(_phase->igvn());
@@ -1130,11 +1106,6 @@ void CloneUnswitchedLoopPredicatesVisitor::visit(const ParsePredicate& parse_pre
11301106
// Clone the Template Assertion Predicate, which is currently found before the newly added unswitched loop selector,
11311107
// to the true path and false path loop.
11321108
void CloneUnswitchedLoopPredicatesVisitor::visit(const TemplateAssertionPredicate& template_assertion_predicate) {
1133-
if (!_has_hoisted_check_parse_predicates) {
1134-
// Only process if we are in the correct Predicate Block.
1135-
return;
1136-
}
1137-
11381109
_clone_predicate_to_true_path_loop.clone_template_assertion_predicate(template_assertion_predicate);
11391110
_clone_predicate_to_false_path_loop.clone_template_assertion_predicate(template_assertion_predicate);
11401111
template_assertion_predicate.kill(_phase->igvn());

src/hotspot/share/opto/predicates.hpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,9 +1091,8 @@ class CreateAssertionPredicatesVisitor : public PredicateVisitor {
10911091
Node* const _old_target_loop_entry;
10921092
Node* _current_predicate_chain_head;
10931093
PhaseIdealLoop* const _phase;
1094-
bool _has_hoisted_check_parse_predicates;
10951094
const NodeInLoopBody& _node_in_loop_body;
1096-
const bool _clone_template;
1095+
const bool _kill_old_template;
10971096

10981097
TemplateAssertionPredicate
10991098
clone_template_and_replace_init_input(const TemplateAssertionPredicate& template_assertion_predicate) const;
@@ -1104,12 +1103,11 @@ class CreateAssertionPredicatesVisitor : public PredicateVisitor {
11041103

11051104
public:
11061105
CreateAssertionPredicatesVisitor(CountedLoopNode* target_loop_head, PhaseIdealLoop* phase,
1107-
const NodeInLoopBody& node_in_loop_body, bool clone_template);
1106+
const NodeInLoopBody& node_in_loop_body, bool kill_old_template);
11081107
NONCOPYABLE(CreateAssertionPredicatesVisitor);
11091108

11101109
using PredicateVisitor::visit;
11111110

1112-
void visit(const ParsePredicate& parse_predicate) override;
11131111
void visit(const TemplateAssertionPredicate& template_assertion_predicate) override;
11141112
};
11151113

@@ -1178,7 +1176,6 @@ class CloneUnswitchedLoopPredicatesVisitor : public PredicateVisitor {
11781176
ClonePredicateToTargetLoop _clone_predicate_to_false_path_loop;
11791177

11801178
PhaseIdealLoop* const _phase;
1181-
bool _has_hoisted_check_parse_predicates;
11821179

11831180
public:
11841181
CloneUnswitchedLoopPredicatesVisitor(LoopNode* true_path_loop_head,

0 commit comments

Comments
 (0)