From 95de99ea65d7f7acf1bfee4a68ef49a0378c5aef Mon Sep 17 00:00:00 2001 From: Christian Hagedorn Date: Fri, 11 Oct 2024 15:02:22 +0200 Subject: [PATCH] 8342945: Replace predicate walking code in get_assertion_predicates() used for Loop Unswitching and cleaning useless Template Assertion Predicates with a predicate visitor --- src/hotspot/share/opto/loopPredicate.cpp | 44 ++++++------------------ src/hotspot/share/opto/loopnode.cpp | 4 +-- src/hotspot/share/opto/loopnode.hpp | 4 +-- src/hotspot/share/opto/predicates.hpp | 22 ++++++++++++ 4 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/hotspot/share/opto/loopPredicate.cpp b/src/hotspot/share/opto/loopPredicate.cpp index 9a639b1f9a1f2..589e8e82fff8d 100644 --- a/src/hotspot/share/opto/loopPredicate.cpp +++ b/src/hotspot/share/opto/loopPredicate.cpp @@ -288,7 +288,7 @@ IfProjNode* PhaseIdealLoop::clone_parse_predicate_to_unswitched_loop(ParsePredic // cloned predicates. void PhaseIdealLoop::clone_assertion_predicates_to_unswitched_loop(IdealLoopTree* loop, const Node_List& old_new, Deoptimization::DeoptReason reason, - IfProjNode* old_predicate_proj, + ParsePredicateSuccessProj* old_parse_predicate_proj, ParsePredicateSuccessProj* fast_loop_parse_predicate_proj, ParsePredicateSuccessProj* slow_loop_parse_predicate_proj) { assert(fast_loop_parse_predicate_proj->in(0)->is_ParsePredicate() && @@ -297,17 +297,15 @@ void PhaseIdealLoop::clone_assertion_predicates_to_unswitched_loop(IdealLoopTree // and doing loop unrolling. Push the original predicates on a list to later process them in reverse order to keep the // original predicate order. Unique_Node_List list; - get_assertion_predicates(old_predicate_proj, list); + get_assertion_predicates(old_parse_predicate_proj, list); Node_List to_process; - IfNode* iff = old_predicate_proj->in(0)->as_If(); - IfProjNode* uncommon_proj = iff->proj_out(1 - old_predicate_proj->as_Proj()->_con)->as_IfProj(); // Process in reverse order such that 'create_new_if_for_predicate' can be used in // 'clone_assertion_predicate_for_unswitched_loops' and the original order is maintained. for (int i = list.size() - 1; i >= 0; i--) { Node* predicate = list.at(i); assert(predicate->in(0)->is_If(), "must be If node"); - iff = predicate->in(0)->as_If(); + IfNode* iff = predicate->in(0)->as_If(); assert(predicate->is_Proj() && predicate->as_Proj()->is_IfProj(), "predicate must be a projection of an if node"); IfProjNode* predicate_proj = predicate->as_IfProj(); @@ -337,34 +335,14 @@ void PhaseIdealLoop::clone_assertion_predicates_to_unswitched_loop(IdealLoopTree } // Put all Assertion Predicate projections on a list, starting at 'predicate' and going up in the tree. If 'get_opaque' -// is set, then the OpaqueTemplateAssertionPredicate nodes of the Assertion Predicates are put on the list instead of -// the projections. -void PhaseIdealLoop::get_assertion_predicates(Node* predicate, Unique_Node_List& list, bool get_opaque) { - ParsePredicateNode* parse_predicate = predicate->in(0)->as_ParsePredicate(); - ProjNode* uncommon_proj = parse_predicate->proj_out(1 - predicate->as_Proj()->_con); - Node* rgn = uncommon_proj->unique_ctrl_out(); - assert(rgn->is_Region() || rgn->is_Call(), "must be a region or call uct"); - predicate = parse_predicate->in(0); - while (predicate != nullptr && predicate->is_Proj() && predicate->in(0)->is_If()) { - IfNode* iff = predicate->in(0)->as_If(); - uncommon_proj = iff->proj_out(1 - predicate->as_Proj()->_con); - if (uncommon_proj->unique_ctrl_out() != rgn) { - break; - } - Node* bol = iff->in(1); - assert(!bol->is_OpaqueInitializedAssertionPredicate(), "should not find an Initialized Assertion Predicate"); - if (bol->is_OpaqueTemplateAssertionPredicate()) { - assert(assertion_predicate_has_loop_opaque_node(iff), "must find OpaqueLoop* nodes"); - if (get_opaque) { - // Collect the OpaqueTemplateAssertionPredicateNode. - list.push(bol); - } else { - // Collect the predicate projection. - list.push(predicate); - } - } - predicate = predicate->in(0)->in(0); - } +// is set, then the OpaqueTemplateAssertionPredicateNode nodes of the Assertion Predicates are put on the list instead +// of the projections. +void PhaseIdealLoop::get_assertion_predicates(ParsePredicateSuccessProj* parse_predicate_proj, Unique_Node_List& list, + const bool get_opaque) { + Deoptimization::DeoptReason deopt_reason = parse_predicate_proj->in(0)->as_ParsePredicate()->deopt_reason(); + PredicateBlockIterator predicate_iterator(parse_predicate_proj, deopt_reason); + TemplateAssertionPredicateCollector assertion_predicate_collector(list, get_opaque); + predicate_iterator.for_each(assertion_predicate_collector); } // Clone an Assertion Predicate for an unswitched loop. OpaqueLoopInit and OpaqueLoopStride nodes are cloned and uncommon diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index e2db179676df8..225d04366004f 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -4469,7 +4469,7 @@ void PhaseIdealLoop::collect_useful_template_assertion_predicates_for_loop(Ideal if (UseProfiledLoopPredicate) { const PredicateBlock* profiled_loop_predicate_block = predicates.profiled_loop_predicate_block(); if (profiled_loop_predicate_block->has_parse_predicate()) { - IfProjNode* parse_predicate_proj = profiled_loop_predicate_block->parse_predicate_success_proj(); + ParsePredicateSuccessProj* parse_predicate_proj = profiled_loop_predicate_block->parse_predicate_success_proj(); get_assertion_predicates(parse_predicate_proj, useful_predicates, true); } } @@ -4477,7 +4477,7 @@ void PhaseIdealLoop::collect_useful_template_assertion_predicates_for_loop(Ideal if (UseLoopPredicate) { const PredicateBlock* loop_predicate_block = predicates.loop_predicate_block(); if (loop_predicate_block->has_parse_predicate()) { - IfProjNode* parse_predicate_proj = loop_predicate_block->parse_predicate_success_proj(); + ParsePredicateSuccessProj* parse_predicate_proj = loop_predicate_block->parse_predicate_success_proj(); get_assertion_predicates(parse_predicate_proj, useful_predicates, true); } } diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp index 487c447328089..d4f8e2e254a12 100644 --- a/src/hotspot/share/opto/loopnode.hpp +++ b/src/hotspot/share/opto/loopnode.hpp @@ -947,7 +947,7 @@ class PhaseIdealLoop : public PhaseTransform { DEBUG_ONLY(static bool assertion_predicate_has_loop_opaque_node(IfNode* iff);) private: DEBUG_ONLY(static void count_opaque_loop_nodes(Node* n, uint& init, uint& stride);) - static void get_assertion_predicates(Node* predicate, Unique_Node_List& list, bool get_opaque = false); + static void get_assertion_predicates(ParsePredicateSuccessProj* parse_predicate_proj, Unique_Node_List& list, bool get_opaque = false); void update_main_loop_assertion_predicates(Node* ctrl, CountedLoopNode* loop_head, Node* init, int stride_con); void initialize_assertion_predicates_for_peeled_loop(CountedLoopNode* peeled_loop_head, CountedLoopNode* remaining_loop_head, @@ -1672,7 +1672,7 @@ class PhaseIdealLoop : public PhaseTransform { IfProjNode* clone_parse_predicate_to_unswitched_loop(ParsePredicateSuccessProj* parse_predicate_proj, Node* new_entry, Deoptimization::DeoptReason reason, bool slow_loop); void clone_assertion_predicates_to_unswitched_loop(IdealLoopTree* loop, const Node_List& old_new, - Deoptimization::DeoptReason reason, IfProjNode* old_predicate_proj, + Deoptimization::DeoptReason reason, ParsePredicateSuccessProj* old_parse_predicate_proj, ParsePredicateSuccessProj* fast_loop_parse_predicate_proj, ParsePredicateSuccessProj* slow_loop_parse_predicate_proj); IfProjNode* clone_assertion_predicate_for_unswitched_loops(IfNode* template_assertion_predicate, IfProjNode* predicate, diff --git a/src/hotspot/share/opto/predicates.hpp b/src/hotspot/share/opto/predicates.hpp index f57948f8ab902..2d4cb0cac2f57 100644 --- a/src/hotspot/share/opto/predicates.hpp +++ b/src/hotspot/share/opto/predicates.hpp @@ -1010,4 +1010,26 @@ class CreateAssertionPredicatesVisitor : public PredicateVisitor { } }; +// This visitor collects all Template Assertion Predicates If nodes or the corresponding Opaque nodes depending on the +// provided 'get_opaque' flag to the provided list. +class TemplateAssertionPredicateCollector : public PredicateVisitor { + Unique_Node_List& _list; + const bool _get_opaque; + + public: + TemplateAssertionPredicateCollector(Unique_Node_List& list, const bool get_opaque) + : _list(list), + _get_opaque(get_opaque) {} + + using PredicateVisitor::visit; + + void visit(const TemplateAssertionPredicate& template_assertion_predicate) override { + if (_get_opaque) { + _list.push(template_assertion_predicate.opaque_node()); + } else { + _list.push(template_assertion_predicate.tail()); + } + } +}; + #endif // SHARE_OPTO_PREDICATES_HPP