| /* |
| * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| * |
| */ |
| |
| #ifndef SHARE_OPTO_PREDICATES_HPP |
| #define SHARE_OPTO_PREDICATES_HPP |
| |
| #include "opto/cfgnode.hpp" |
| #include "opto/opaquenode.hpp" |
| #include "opto/predicates_enums.hpp" |
| |
| class IdealLoopTree; |
| class InitializedAssertionPredicate; |
| class ParsePredicate; |
| class PredicateVisitor; |
| class RuntimePredicate; |
| class TemplateAssertionPredicate; |
| |
| /* |
| * There are different kinds of predicates throughout the code. We differentiate between the following predicates: |
| * |
| * - Regular Predicate: This term is used to refer to a Runtime Predicate or an Assertion Predicate and can be used to |
| * distinguish from any Parse Predicate which is not a real predicate but rather a placeholder. |
| * - Parse Predicate: Added during parsing to capture the current JVM state. This predicate represents a "placeholder" |
| * above which Regular Predicates can be created later after parsing. |
| * |
| * There are initially three Parse Predicates for each loop: |
| * - Loop Parse Predicate: The Parse Predicate added for Loop Predicates. |
| * - Profiled Loop Parse Predicate: The Parse Predicate added for Profiled Loop Predicates. |
| * - Loop Limit Check Parse Predicate: The Parse Predicate added for a Loop Limit Check Predicate. |
| * - Runtime Predicate: This term is used to refer to a Hoisted Check Predicate (either a Loop Predicate or a Profiled |
| * Loop Predicate) or a Loop Limit Check Predicate. These predicates will be checked at runtime while |
| * the Parse and Assertion Predicates are always removed before code generation (except for |
| * Initialized Assertion Predicates which are kept in debug builds while being removed in product |
| * builds). |
| * - Hoisted Check Predicate: Either a Loop Predicate or a Profiled Loop Predicate that is created during Loop |
| * Predication to hoist a check out of a loop. |
| * - Loop Predicate: This predicate is created to hoist a loop-invariant check or a range check of the |
| * form "a[i*scale + offset]", where scale and offset are loop-invariant, out of a |
| * counted loop. The hoisted check must be executed in each loop iteration. This predicate |
| * is created during Loop Predication and is inserted above the Loop Parse Predicate. Each |
| * predicate for a range check is accompanied by additional Assertion Predicates (see below). |
| * - Profiled Loop: This predicate is very similar to a Loop Predicate but the check to be hoisted does not |
| * Predicate need to be executed in each loop iteration. By using profiling information, only checks |
| * with a high execution frequency are chosen to be replaced by a Profiled Loop Predicate. |
| * This predicate is created during Loop Predication and is inserted above the Profiled |
| * Loop Parse Predicate. |
| * - Loop Limit Check: This predicate is created when transforming a loop to a counted loop to protect against |
| * Predicate the case when adding the stride to the induction variable would cause an overflow which |
| * will not satisfy the loop limit exit condition. This overflow is unexpected for further |
| * counted loop optimizations and could lead to wrong results. Therefore, when this predicate |
| * fails at runtime, we must trap and recompile the method without turning the loop into a |
| * counted loop to avoid these overflow problems. |
| * The predicate does not replace an actual check inside the loop. This predicate can only |
| * be added once above the Loop Limit Check Parse Predicate for a loop. |
| * - Assertion Predicate: An always true predicate which will never fail (its range is already covered by an earlier |
| * Hoisted Check Predicate or the main-loop entry guard) but is required in order to fold away a |
| * dead sub loop in which some data could be proven to be dead (by the type system) and replaced |
| * by top. Without such Assertion Predicates, we could find that type ranges in Cast and ConvX2Y |
| * data nodes become impossible and are replaced by top. This is an indicator that the sub loop |
| * is never executed and must be dead. But there is no way for C2 to prove that the sub loop is |
| * actually dead. Assertion Predicates come to the rescue to fold such seemingly dead sub loops |
| * away to avoid a broken graph. Assertion Predicates are left in the graph as a sanity checks in |
| * debug builds (they must never fail at runtime) while they are being removed in product builds. |
| * We use special OpaqueTemplateAssertionPredicateNode nodes to block some optimizations and replace |
| * the Assertion Predicates later in product builds. |
| * |
| * There are two kinds of Assertion Predicates: |
| * - Template Assertion Predicate: A template for an Assertion Predicate that uses OpaqueLoop* |
| * nodes as placeholders for the init and stride value of a loop. |
| * This predicate does not represent an actual check, yet, and |
| * just serves as a template to create an Initialized Assertion |
| * Predicate for a (sub) loop. |
| * - Initialized Assertion Predicate: An Assertion Predicate that represents an actual check for a |
| * (sub) loop that was initialized by cloning a Template |
| * Assertion Predicate. The check is always true and is covered |
| * by an earlier check (a Hoisted Check Predicate or the |
| * main-loop entry guard). |
| * |
| * Assertion Predicates are required when removing a range check from a loop. These are inserted |
| * either at Loop Predication or at Range Check Elimination: |
| * - Loop Predication: A range check inside a loop is replaced by a Hoisted Check Predicate |
| * before the loop. We add two additional Template Assertion Predicates |
| * from which we can later create Initialized Assertion Predicates. One |
| * would have been enough if the number of array accesses inside a sub |
| * loop does not change. But when unrolling the sub loop, we are |
| * doubling the number of array accesses - we need to cover them all. |
| * To do that, we only need to create an Initialized Assertion Predicate |
| * for the first, initial value and for the last value: |
| * Let a[i] be an array access in the original, not-yet unrolled loop |
| * with stride 1. When unrolling this loop, we double the stride |
| * (i.e. stride 2) and have now two accesses a[i] and a[i+1]. We need |
| * checks for both. When further unrolling this loop, we only need to |
| * keep the checks on the first and last access (e.g. a[i] and a[i+3] |
| * on the next unrolling step as they cover the checks in the middle |
| * for a[i+1] and a[i+2]). |
| * Therefore, we just need to cover: |
| * - Initial value: a[init] |
| * - Last value: a[init + new stride - original stride] |
| * (We could still only use one Template Assertion Predicate to create |
| * both Initialized Assertion Predicates from - might be worth doing |
| * at some point). |
| * When later splitting a loop (pre/main/post, peeling, unrolling), |
| * we create two Initialized Assertion Predicates from the Template |
| * Assertion Predicates by replacing the OpaqueLoop* nodes by actual |
| * values. Initially (before unrolling), both Assertion Predicates are |
| * equal. The Initialized Assertion Predicates are always true because |
| * their range is covered by a corresponding Hoisted Check Predicate. |
| * - Range Check Elimination: A range check is removed from the main-loop by changing the pre |
| * and main-loop iterations. We add two additional Template Assertion |
| * Predicates (see explanation in section above) and one Initialized |
| * Assertion Predicate for the just removed range check. When later |
| * unrolling the main-loop, we create two Initialized Assertion |
| * Predicates from the Template Assertion Predicates by replacing the |
| * OpaqueLoop* nodes by actual values for the unrolled loop. |
| * The Initialized Assertion Predicates are always true: They are true |
| * when entering the main-loop (because we adjusted the pre-loop exit |
| * condition), when executing the last iteration of the main-loop |
| * (because we adjusted the main-loop exit condition), and during all |
| * other iterations of the main-loop in-between by implication. |
| * Note that Range Check Elimination could remove additional range |
| * checks which were not possible to remove with Loop Predication |
| * before (for example, because no Parse Predicates were available |
| * before the loop to create Hoisted Check Predicates with). |
| * |
| * |
| * In order to group predicates and refer to them throughout the code, we introduce the following additional term: |
| * - Predicate Block: A block containing all Runtime Predicates, including the Assertion Predicates for Range Check |
| * Predicates, and the associated Parse Predicate which all share the same uncommon trap. This block |
| * could be empty if there were no Runtime Predicates created and the Parse Predicate was already |
| * removed. |
| * There are three different Predicate Blocks: |
| * - Loop Predicate Block: Groups the Loop Predicates (if any), including the Assertion Predicates, |
| * and the Loop Parse Predicate (if not removed, yet) together. |
| * - Profiled Loop Groups the Profiled Loop Predicates (if any), including the Assertion |
| * Predicate Block: Predicates, and the Profiled Loop Parse Predicate (if not removed, yet) |
| * together. |
| * - Loop Limit Check Groups the Loop Limit Check Predicate (if created) and the Loop Limit |
| * Predicate Block: Check Parse Predicate (if not removed, yet) together. |
| * - Regular Predicate Block: A block that only contains the Regular Predicates of a Predicate Block without the |
| * Parse Predicate. |
| * |
| * Initially, before applying any loop-splitting optimizations, we find the following structure after Loop Predication |
| * (predicates inside square brackets [] do not need to exist if there are no checks to hoist): |
| * |
| * [Loop Predicate 1 + two Template Assertion Predicates] \ |
| * [Loop Predicate 2 + two Template Assertion Predicates] | |
| * ... | Loop Predicate Block |
| * [Loop Predicate n + two Template Assertion Predicates] | |
| * Loop Parse Predicate / |
| * |
| * [Profiled Loop Predicate 1 + two Template Assertion Predicates] \ |
| * [Profiled Loop Predicate 2 + two Template Assertion Predicates] | Profiled Loop |
| * ... | Predicate Block |
| * [Profiled Loop Predicate m + two Template Assertion Predicates] | |
| * Profiled Loop Parse Predicate / |
| * |
| * [Loop Limit Check Predicate] (at most one) \ Loop Limit Check |
| * Loop Limit Check Parse Predicate / Predicate Block |
| * Loop Head |
| * |
| * As an example, let's look at how the predicate structure looks for the main-loop after creating pre/main/post loops |
| * and applying Range Check Elimination (the order is insignificant): |
| * |
| * Main Loop entry (zero-trip) guard |
| * [For Loop Predicate 1: Two Template + two Initialized Assertion Predicates] |
| * [For Loop Predicate 2: Two Template + two Initialized Assertion Predicates] |
| * ... |
| * [For Loop Predicate n: Two Template + two Initialized Assertion Predicates] |
| * |
| * [For Profiled Loop Predicate 1: Two Template + two Initialized Assertion Predicates] |
| * [For Profiled Loop Predicate 2: Two Template + two Initialized Assertion Predicates] |
| * ... |
| * [For Profiled Loop Predicate m: Two Template + two Initialized Assertion Predicates] |
| * |
| * (after unrolling, we have two Initialized Assertion Predicates for the Assertion Predicates of Range Check Elimination) |
| * [For Range Check Elimination Check 1: Two Templates + one Initialized Assertion Predicate] |
| * [For Range Check Elimination Check 2: Two Templates + one Initialized Assertion Predicate] |
| * ... |
| * [For Range Check Elimination Check k: Two Templates + one Initialized Assertion Predicate] |
| * Main Loop Head |
| */ |
| |
| // Interface to represent a C2 predicate. A predicate is always represented by two CFG nodes: |
| // - An If node (head) |
| // - An IfProj node representing the success projection of the If node (tail). |
| class Predicate : public StackObj { |
| public: |
| // Return the unique entry CFG node into the predicate. |
| virtual Node* entry() const = 0; |
| |
| // Return the head node of the predicate which is either: |
| // - A ParsePredicateNode if the predicate is a Parse Predicate |
| // - An IfNode or RangeCheckNode, otherwise. |
| virtual IfNode* head() const = 0; |
| |
| // Return the tail node of the predicate. Runtime Predicates can either have a true of false projection as success |
| // projection while Parse Predicates and Assertion Predicates always have a true projection as success projection. |
| virtual IfProjNode* tail() const = 0; |
| }; |
| |
| // Generic predicate visitor that does nothing. Subclass this visitor to add customized actions for each predicate. |
| // The visit methods of this visitor are called from the predicate iterator classes which walk the predicate chain. |
| // Use the UnifiedPredicateVisitor if the type of the predicate does not matter. |
| class PredicateVisitor : public StackObj { |
| public: |
| virtual void visit(const ParsePredicate& parse_predicate) {} |
| virtual void visit(const RuntimePredicate& runtime_predicate) {} |
| virtual void visit(const TemplateAssertionPredicate& template_assertion_predicate) {} |
| virtual void visit(const InitializedAssertionPredicate& initialized_assertion_predicate) {} |
| |
| // This method can be overridden to stop the predicate iterators from visiting more predicates further up in the |
| // predicate chain. |
| virtual bool should_continue() const { |
| return true; |
| } |
| }; |
| |
| // Interface to check whether a node is in a loop body or not. |
| class NodeInLoopBody : public StackObj { |
| public: |
| virtual bool check_node_in_loop_body(Node* node) const = 0; |
| }; |
| |
| // Class to represent Assertion Predicates (i.e. either Initialized and/or Template Assertion Predicates). |
| class AssertionPredicates : public StackObj { |
| Node* const _entry; |
| |
| static Node* find_entry(Node* start_proj); |
| |
| public: |
| explicit AssertionPredicates(Node* assertion_predicate_proj) : _entry(find_entry(assertion_predicate_proj)) {} |
| NONCOPYABLE(AssertionPredicates); |
| |
| // Returns the control input node into the first assertion predicate If. If there are no assertion predicates, it |
| // returns the same node initially passed to the constructor. |
| Node* entry() const { |
| return _entry; |
| } |
| }; |
| |
| // Class to represent a single Assertion Predicate. This could either be: |
| // - A Template Assertion Predicate. |
| // - An Initialized Assertion Predicate. |
| class AssertionPredicate : public StackObj { |
| static bool has_assertion_predicate_opaque(const Node* predicate_proj); |
| |
| public: |
| static bool is_predicate(const Node* maybe_success_proj); |
| static bool has_halt(const IfTrueNode* success_proj); |
| }; |
| |
| // Utility class representing a Regular Predicate which is either a Runtime Predicate or an Assertion Predicate. |
| class RegularPredicate : public StackObj { |
| public: |
| static bool may_be_predicate_if(const Node* node); |
| }; |
| |
| // Class to represent a Parse Predicate. |
| class ParsePredicate : public Predicate { |
| ParsePredicateSuccessProj* _success_proj; |
| ParsePredicateNode* _parse_predicate_node; |
| Node* _entry; |
| |
| static IfTrueNode* init_success_proj(const Node* parse_predicate_proj) { |
| assert(parse_predicate_proj != nullptr, "must not be null"); |
| return parse_predicate_proj->isa_IfTrue(); |
| } |
| |
| static ParsePredicateNode* init_parse_predicate(const Node* parse_predicate_proj, Deoptimization::DeoptReason deopt_reason); |
| NOT_PRODUCT(static void trace_cloned_parse_predicate(bool is_false_path_loop, |
| const ParsePredicateSuccessProj* success_proj);) |
| |
| public: |
| ParsePredicate(Node* parse_predicate_proj, Deoptimization::DeoptReason deopt_reason) |
| : _success_proj(init_success_proj(parse_predicate_proj)), |
| _parse_predicate_node(init_parse_predicate(parse_predicate_proj, deopt_reason)), |
| _entry(_parse_predicate_node != nullptr ? _parse_predicate_node->in(0) : parse_predicate_proj) {} |
| |
| // Returns the control input node into this Parse Predicate if it is valid. Otherwise, it returns the passed node |
| // into the constructor of this class. |
| Node* entry() const override { |
| return _entry; |
| } |
| |
| // This Parse Predicate is valid if the node passed to the constructor is a projection of a ParsePredicateNode, the |
| // deopt_reason of the uncommon trap of the ParsePredicateNode matches the passed deopt_reason to the constructor and |
| // the ParsePredicateNode is not marked useless. |
| bool is_valid() const { |
| return _parse_predicate_node != nullptr && !_parse_predicate_node->is_useless(); |
| } |
| |
| ParsePredicateNode* head() const override { |
| assert(is_valid(), "must be valid"); |
| return _parse_predicate_node; |
| } |
| |
| ParsePredicateSuccessProj* tail() const override { |
| assert(is_valid(), "must be valid"); |
| return _success_proj; |
| } |
| |
| ParsePredicate clone_to_unswitched_loop(Node* new_control, bool is_false_path_loop, |
| PhaseIdealLoop* phase) const; |
| |
| void kill(PhaseIterGVN& igvn) const; |
| }; |
| |
| // Class to represent a Runtime Predicate which always has an associated UCT on the failing path. |
| class RuntimePredicate : public Predicate { |
| IfProjNode* _success_proj; |
| IfNode* _if_node; |
| |
| public: |
| explicit RuntimePredicate(IfProjNode* success_proj) |
| : _success_proj(success_proj), |
| _if_node(success_proj->in(0)->as_If()) { |
| assert(is_predicate(success_proj), "must be valid"); |
| } |
| NONCOPYABLE(RuntimePredicate); |
| |
| private: |
| static bool is_predicate(const Node* maybe_success_proj); |
| static bool has_valid_uncommon_trap(const Node* success_proj); |
| static Deoptimization::DeoptReason uncommon_trap_reason(const IfProjNode* if_proj); |
| |
| public: |
| Node* entry() const override { |
| return _if_node->in(0); |
| } |
| |
| IfNode* head() const override { |
| return _if_node; |
| } |
| |
| IfProjNode* tail() const override { |
| return _success_proj; |
| } |
| |
| static bool is_predicate(const Node* node, Deoptimization::DeoptReason deopt_reason); |
| }; |
| |
| // Class to represent a Template Assertion Predicate. |
| class TemplateAssertionPredicate : public Predicate { |
| IfTrueNode* const _success_proj; |
| IfNode* const _if_node; |
| |
| public: |
| explicit TemplateAssertionPredicate(IfTrueNode* success_proj) |
| : _success_proj(success_proj), |
| _if_node(success_proj->in(0)->as_If()) { |
| assert(is_predicate(success_proj), "must be valid"); |
| } |
| |
| Node* entry() const override { |
| return _if_node->in(0); |
| } |
| |
| OpaqueTemplateAssertionPredicateNode* opaque_node() const { |
| return _if_node->in(1)->as_OpaqueTemplateAssertionPredicate(); |
| } |
| |
| IfNode* head() const override { |
| return _if_node; |
| } |
| |
| IfTrueNode* tail() const override { |
| return _success_proj; |
| } |
| |
| bool is_last_value() const { |
| return _if_node->assertion_predicate_type() == AssertionPredicateType::LastValue; |
| } |
| |
| bool is_useless() const { |
| return opaque_node()->is_useless(); |
| } |
| |
| TemplateAssertionPredicate clone(Node* new_control, CountedLoopNode* new_loop_node, PhaseIdealLoop* phase) const; |
| TemplateAssertionPredicate clone_and_replace_opaque_input(Node* new_control, Node* new_opaque_input, |
| CountedLoopNode* new_loop_node, PhaseIdealLoop* phase) const; |
| void replace_opaque_stride_input(Node* new_stride, PhaseIterGVN& igvn) const; |
| InitializedAssertionPredicate initialize(PhaseIdealLoop* phase) const; |
| void rewire_loop_data_dependencies(IfTrueNode* target_predicate, const NodeInLoopBody& data_in_loop_body, |
| const PhaseIdealLoop* phase) const; |
| void kill(PhaseIterGVN& igvn) const; |
| |
| // Should only be called during Loop Unrolling when we only update the OpaqueLoopStride input but don't require a full |
| // clone of the Template Assertion Expression. |
| void update_associated_loop_node(CountedLoopNode* loop_node) const { |
| opaque_node()->update_loop_node(loop_node); |
| } |
| |
| static bool is_predicate(const Node* maybe_success_proj); |
| |
| #ifdef ASSERT |
| static void verify(IfTrueNode* template_assertion_predicate_success_proj) { |
| TemplateAssertionPredicate template_assertion_predicate(template_assertion_predicate_success_proj); |
| template_assertion_predicate.verify(); |
| } |
| |
| void verify() const; |
| #endif // ASSERT |
| }; |
| |
| // Class to represent an Initialized Assertion Predicate which always has a halt node on the failing path. |
| // This predicate should never fail at runtime by design. |
| class InitializedAssertionPredicate : public Predicate { |
| IfTrueNode* const _success_proj; |
| IfNode* const _if_node; |
| |
| DEBUG_ONLY(static bool has_halt(const IfTrueNode* success_proj);) |
| |
| public: |
| explicit InitializedAssertionPredicate(IfTrueNode* success_proj) |
| : _success_proj(success_proj), |
| _if_node(success_proj->in(0)->as_If()) { |
| assert(is_predicate(success_proj), "must be valid"); |
| } |
| |
| Node* entry() const override { |
| return _if_node->in(0); |
| } |
| |
| OpaqueInitializedAssertionPredicateNode* opaque_node() const { |
| return _if_node->in(1)->as_OpaqueInitializedAssertionPredicate(); |
| } |
| |
| IfNode* head() const override { |
| return _if_node; |
| } |
| |
| IfTrueNode* tail() const override { |
| return _success_proj; |
| } |
| |
| bool is_last_value() const { |
| return _if_node->assertion_predicate_type() == AssertionPredicateType::LastValue; |
| } |
| |
| bool is_useless() const { |
| return opaque_node()->is_useless(); |
| } |
| |
| void kill(PhaseIterGVN& igvn) const; |
| static bool is_predicate(const Node* maybe_success_proj); |
| |
| #ifdef ASSERT |
| static void verify(IfTrueNode* initialized_assertion_predicate_success_proj) { |
| InitializedAssertionPredicate initialized_assertion_predicate(initialized_assertion_predicate_success_proj); |
| initialized_assertion_predicate.verify(); |
| } |
| |
| void verify() const; |
| #endif // ASSERT |
| }; |
| |
| // Interface to transform OpaqueLoopInit and OpaqueLoopStride nodes of a Template Assertion Expression. |
| class TransformStrategyForOpaqueLoopNodes : public StackObj { |
| public: |
| virtual Node* transform_opaque_init(OpaqueLoopInitNode* opaque_init) const = 0; |
| virtual Node* transform_opaque_stride(OpaqueLoopStrideNode* opaque_stride) const = 0; |
| }; |
| |
| // A Template Assertion Predicate represents the OpaqueTemplateAssertionPredicateNode for the initial value or the last |
| // value of a Template Assertion Predicate and all the nodes up to and including the OpaqueLoop* nodes. |
| class TemplateAssertionExpression : public StackObj { |
| OpaqueTemplateAssertionPredicateNode* const _opaque_node; |
| PhaseIdealLoop* const _phase; |
| public: |
| TemplateAssertionExpression(OpaqueTemplateAssertionPredicateNode* opaque_node, PhaseIdealLoop* phase) |
| : _opaque_node(opaque_node), |
| _phase(phase) {} |
| NONCOPYABLE(TemplateAssertionExpression); |
| |
| private: |
| OpaqueTemplateAssertionPredicateNode* clone(const TransformStrategyForOpaqueLoopNodes& transform_strategy, |
| Node* new_control, CountedLoopNode* new_loop_node) const; |
| |
| public: |
| OpaqueTemplateAssertionPredicateNode* clone(Node* new_control, CountedLoopNode* new_loop_node) const; |
| OpaqueTemplateAssertionPredicateNode* clone_and_replace_init(Node* new_control, Node* new_init, |
| CountedLoopNode* new_loop_node) const; |
| OpaqueTemplateAssertionPredicateNode* clone_and_replace_init_and_stride(Node* new_control, Node* new_init, |
| Node* new_stride) const; |
| OpaqueInitializedAssertionPredicateNode* clone_and_fold_opaque_loop_nodes(Node* new_control) const; |
| }; |
| |
| // Class to represent a node being part of a Template Assertion Expression. Note that this is not an IR node. |
| // |
| // The expression itself can belong to no, one, or two Template Assertion Predicates: |
| // - None: This node is already dead (i.e. we replaced the Bool condition of the Template Assertion Predicate). |
| // - Two: A OpaqueLoopInitNode could be part of two Template Assertion Predicates. |
| // - One: In all other cases. |
| class TemplateAssertionExpressionNode : public StackObj { |
| Node* const _node; |
| |
| public: |
| explicit TemplateAssertionExpressionNode(Node* node) : _node(node) { |
| assert(is_in_expression(node), "must be valid"); |
| } |
| NONCOPYABLE(TemplateAssertionExpressionNode); |
| |
| private: |
| static bool is_template_assertion_predicate(const Node* node); |
| |
| public: |
| // Check whether the provided node is part of a Template Assertion Expression or not. |
| static bool is_in_expression(Node* node); |
| |
| // Check if the opcode of node could be found in a Template Assertion Expression. |
| // This also provides a fast check whether a node is unrelated. |
| static bool is_maybe_in_expression(const Node* node) { |
| const int opcode = node->Opcode(); |
| return (node->is_OpaqueLoopInit() || |
| node->is_OpaqueLoopStride() || |
| node->is_Bool() || |
| node->is_Cmp() || |
| opcode == Op_AndL || |
| opcode == Op_OrL || |
| opcode == Op_RShiftL || |
| opcode == Op_LShiftL || |
| opcode == Op_LShiftI || |
| opcode == Op_AddL || |
| opcode == Op_AddI || |
| opcode == Op_MulL || |
| opcode == Op_MulI || |
| opcode == Op_SubL || |
| opcode == Op_SubI || |
| opcode == Op_ConvI2L || |
| opcode == Op_CastII); |
| } |
| |
| // Apply the given function to all Template Assertion Predicates (if any) to which this Template Assertion Predicate |
| // Expression Node belongs to. |
| template <class Callback> |
| void for_each_template_assertion_predicate(Callback callback) { |
| ResourceMark rm; |
| Unique_Node_List list; |
| list.push(_node); |
| DEBUG_ONLY(int template_counter = 0;) |
| for (uint i = 0; i < list.size(); i++) { |
| Node* next = list.at(i); |
| if (is_template_assertion_predicate(next)) { |
| callback(next->as_If()); |
| DEBUG_ONLY(template_counter++;) |
| } else { |
| assert(!next->is_CFG(), "no CFG expected in Template Assertion Expression"); |
| list.push_outputs_of(next); |
| } |
| } |
| |
| // Each node inside a Template Assertion Expression is in between a Template Assertion Predicate and its OpaqueLoop* |
| // nodes (or an OpaqueLoop* node itself). The OpaqueLoop* nodes do not common up. Therefore, each Template Assertion |
| // Expression node belongs to a single expression - except for OpaqueLoopInitNodes. An OpaqueLoopInitNode is shared |
| // between the init and last value Template Assertion Predicate at creation. Later, when cloning the expressions, |
| // they are no longer shared. |
| assert(template_counter <= 2, "a node cannot be part of more than two templates"); |
| assert(template_counter <= 1 || _node->is_OpaqueLoopInit(), "only OpaqueLoopInit nodes can be part of two templates"); |
| } |
| }; |
| |
| // This class is used to create the actual If node with a success path and a fail path with a Halt node. |
| class AssertionPredicateIfCreator : public StackObj { |
| PhaseIdealLoop* const _phase; |
| |
| public: |
| explicit AssertionPredicateIfCreator(PhaseIdealLoop* const phase) : _phase(phase) {} |
| NONCOPYABLE(AssertionPredicateIfCreator); |
| |
| IfTrueNode* create_for_initialized(Node* new_control, int if_opcode, Node* assertion_expression, |
| AssertionPredicateType assertion_predicate_type) const; |
| IfTrueNode* create_for_template(Node* new_control, int if_opcode, Node* assertion_expression, |
| AssertionPredicateType assertion_predicate_type) const; |
| private: |
| IfTrueNode* create(Node* new_control, int if_opcode, Node* assertion_expression, const char* halt_message, |
| AssertionPredicateType assertion_predicate_type) const; |
| IfNode* create_if_node(Node* new_control, int if_opcode, Node* assertion_expression, IdealLoopTree* loop, |
| AssertionPredicateType assertion_predicate_type) const; |
| IfTrueNode* create_success_path(IfNode* if_node, IdealLoopTree* loop) const; |
| void create_fail_path(IfNode* if_node, IdealLoopTree* loop, const char* halt_message) const; |
| void create_halt_node(IfFalseNode* fail_proj, IdealLoopTree* loop, const char* halt_message) const; |
| }; |
| |
| // This class is used to create a Template Assertion Predicate either with a Halt Node from scratch. |
| class TemplateAssertionPredicateCreator : public StackObj { |
| CountedLoopNode* const _loop_head; |
| const int _scale; |
| Node* const _offset; |
| Node* const _range; |
| PhaseIdealLoop* const _phase; |
| |
| OpaqueLoopInitNode* create_opaque_init(Node* new_control) const; |
| OpaqueTemplateAssertionPredicateNode* create_for_init_value(Node* new_control, OpaqueLoopInitNode* opaque_init, |
| bool& does_overflow) const; |
| OpaqueTemplateAssertionPredicateNode* create_for_last_value(Node* new_control, OpaqueLoopInitNode* opaque_init, |
| bool& does_overflow) const; |
| Node* create_last_value(Node* new_control, OpaqueLoopInitNode* opaque_init) const; |
| IfTrueNode* create_if_node(Node* new_control, |
| OpaqueTemplateAssertionPredicateNode* template_assertion_predicate_expression, |
| bool does_overflow, AssertionPredicateType assertion_predicate_type) const; |
| |
| public: |
| TemplateAssertionPredicateCreator(CountedLoopNode* loop_head, int scale, Node* offset, Node* range, |
| PhaseIdealLoop* phase) |
| : _loop_head(loop_head), |
| _scale(scale), |
| _offset(offset), |
| _range(range), |
| _phase(phase) {} |
| NONCOPYABLE(TemplateAssertionPredicateCreator); |
| |
| IfTrueNode* create(Node* new_control) const; |
| }; |
| |
| // This class creates a new Initialized Assertion Predicate either from a template or from scratch. |
| class InitializedAssertionPredicateCreator : public StackObj { |
| PhaseIdealLoop* const _phase; |
| |
| public: |
| explicit InitializedAssertionPredicateCreator(PhaseIdealLoop* phase); |
| NONCOPYABLE(InitializedAssertionPredicateCreator); |
| |
| InitializedAssertionPredicate create_from_template(const IfNode* template_assertion_predicate, Node* new_control, |
| Node* new_init, Node* new_stride) const; |
| |
| InitializedAssertionPredicate |
| create_from_template_and_insert_below(const TemplateAssertionPredicate& template_assertion_predicate) const; |
| IfTrueNode* create(Node* operand, Node* new_control, jint stride, int scale, Node* offset, Node* range, |
| AssertionPredicateType assertion_predicate_type) const; |
| |
| private: |
| OpaqueInitializedAssertionPredicateNode* create_assertion_expression_from_template(const IfNode* template_assertion_predicate, |
| Node* new_control, Node* new_init, |
| Node* new_stride) const; |
| IfTrueNode* create_control_nodes(Node* new_control, int if_opcode, |
| OpaqueInitializedAssertionPredicateNode* assertion_expression, |
| AssertionPredicateType assertion_predicate_type) const; |
| }; |
| |
| // This class iterates through all predicates of a Regular Predicate Block and applies the given visitor to each. |
| class RegularPredicateBlockIterator : public StackObj { |
| Node* _current_node; |
| const Deoptimization::DeoptReason _deopt_reason; |
| |
| public: |
| RegularPredicateBlockIterator(Node* start_node, Deoptimization::DeoptReason deopt_reason) |
| : _current_node(start_node), |
| _deopt_reason(deopt_reason) {} |
| NONCOPYABLE(RegularPredicateBlockIterator); |
| |
| // Skip all predicates by just following the inputs. We do not call any user provided visitor. |
| Node* skip_all() { |
| PredicateVisitor do_nothing; // No real visits, just do nothing. |
| return for_each(do_nothing); |
| } |
| |
| // Walk over all predicates of this block (if any) and apply the given 'predicate_visitor' to each predicate. |
| // Returns the entry to the earliest predicate. |
| Node* for_each(PredicateVisitor& predicate_visitor) { |
| while (predicate_visitor.should_continue()) { |
| if (process_template_assertion_predicate(predicate_visitor)) { |
| continue; |
| } |
| |
| if (process_runtime_predicate(predicate_visitor)) { |
| continue; |
| } |
| |
| if (process_initialized_assertion_predicate(predicate_visitor)) { |
| continue; |
| } |
| // Either a Parse Predicate or not a Regular Predicate. In both cases, the node does not belong to this block. |
| break; |
| } |
| return _current_node; |
| } |
| |
| bool process_template_assertion_predicate(PredicateVisitor& predicate_visitor) { |
| if (!TemplateAssertionPredicate::is_predicate(_current_node)) { |
| return false; |
| } |
| |
| TemplateAssertionPredicate template_assertion_predicate(_current_node->as_IfTrue()); |
| if (!template_assertion_predicate.is_useless()) { |
| // Only visit if not useless. Otherwise, just skip over it to possibly process other predicates above. |
| predicate_visitor.visit(template_assertion_predicate); |
| } |
| _current_node = template_assertion_predicate.entry(); |
| return true; |
| } |
| |
| bool process_runtime_predicate(PredicateVisitor& predicate_visitor) { |
| if (!RuntimePredicate::is_predicate(_current_node, _deopt_reason)) { |
| return false; |
| } |
| RuntimePredicate runtime_predicate(_current_node->as_IfProj()); |
| predicate_visitor.visit(runtime_predicate); |
| _current_node = runtime_predicate.entry(); |
| return true; |
| } |
| |
| bool process_initialized_assertion_predicate(PredicateVisitor& predicate_visitor) { |
| if (!InitializedAssertionPredicate::is_predicate(_current_node)) { |
| return false; |
| } |
| |
| InitializedAssertionPredicate initialized_assertion_predicate(_current_node->as_IfTrue()); |
| if (!initialized_assertion_predicate.is_useless()) { |
| // Only visit if not useless. Otherwise, just skip over it to possibly process other predicates above. |
| predicate_visitor.visit(initialized_assertion_predicate); |
| } |
| _current_node = initialized_assertion_predicate.entry(); |
| return true; |
| } |
| }; |
| |
| // This class iterates through all predicates of a Predicate Block and applies the given visitor to each. |
| class PredicateBlockIterator : public StackObj { |
| Node* const _start_node; |
| const ParsePredicate _parse_predicate; // Could be missing. |
| RegularPredicateBlockIterator _regular_predicate_block_iterator; |
| |
| public: |
| PredicateBlockIterator(Node* start_node, Deoptimization::DeoptReason deopt_reason) |
| : _start_node(start_node), |
| _parse_predicate(start_node, deopt_reason), |
| _regular_predicate_block_iterator(_parse_predicate.entry(), deopt_reason) {} |
| |
| // Walk over all predicates of this block (if any) and apply the given 'predicate_visitor' to each predicate. |
| // Returns the entry to the earliest predicate. |
| Node* for_each(PredicateVisitor& predicate_visitor) { |
| if (!predicate_visitor.should_continue()) { |
| return _start_node; |
| } |
| if (_parse_predicate.is_valid()) { |
| predicate_visitor.visit(_parse_predicate); |
| } |
| return _regular_predicate_block_iterator.for_each(predicate_visitor); |
| } |
| }; |
| |
| // Class to walk over all predicates starting at a node, which usually is the loop entry node, and following the inputs. |
| // At each predicate, a PredicateVisitor is applied which the user can implement freely. |
| class PredicateIterator : public StackObj { |
| Node* _start_node; |
| |
| public: |
| explicit PredicateIterator(Node* start_node) |
| : _start_node(start_node) {} |
| NONCOPYABLE(PredicateIterator); |
| |
| // Apply the 'predicate_visitor' for each predicate found in the predicate chain started at the provided node. |
| // Returns the entry to the earliest predicate. |
| Node* for_each(PredicateVisitor& predicate_visitor) const { |
| Node* current_node = _start_node; |
| PredicateBlockIterator loop_limit_check_predicate_iterator(current_node, Deoptimization::Reason_loop_limit_check); |
| current_node = loop_limit_check_predicate_iterator.for_each(predicate_visitor); |
| PredicateBlockIterator auto_vectorization_check_iterator(current_node, Deoptimization::Reason_auto_vectorization_check); |
| current_node = auto_vectorization_check_iterator.for_each(predicate_visitor); |
| if (UseLoopPredicate) { |
| if (UseProfiledLoopPredicate) { |
| PredicateBlockIterator profiled_loop_predicate_iterator(current_node, Deoptimization::Reason_profile_predicate); |
| current_node = profiled_loop_predicate_iterator.for_each(predicate_visitor); |
| } |
| PredicateBlockIterator loop_predicate_iterator(current_node, Deoptimization::Reason_predicate); |
| current_node = loop_predicate_iterator.for_each(predicate_visitor); |
| } |
| return current_node; |
| } |
| }; |
| |
| // Unified PredicateVisitor which only provides a single visit method for a generic Predicate. This visitor can be used |
| // when it does not matter what kind of predicate is visited. Note that we override all normal visit methods from |
| // PredicateVisitor by calling the unified method. These visit methods are marked final such that they cannot be |
| // overridden by implementors of this class. |
| class UnifiedPredicateVisitor : public PredicateVisitor { |
| public: |
| virtual void visit(const TemplateAssertionPredicate& template_assertion_predicate) override final { |
| visit_predicate(template_assertion_predicate); |
| } |
| |
| virtual void visit(const ParsePredicate& parse_predicate) override final { |
| visit_predicate(parse_predicate); |
| } |
| |
| virtual void visit(const RuntimePredicate& runtime_predicate) override final { |
| visit_predicate(runtime_predicate); |
| } |
| |
| virtual void visit(const InitializedAssertionPredicate& initialized_assertion_predicate) override final { |
| visit_predicate(initialized_assertion_predicate); |
| } |
| |
| virtual void visit_predicate(const Predicate& predicate) = 0; |
| }; |
| |
| // A block of Regular Predicates inside a Predicate Block without its Parse Predicate. |
| class RegularPredicateBlock : public StackObj { |
| const Deoptimization::DeoptReason _deopt_reason; |
| Node* const _entry; |
| |
| public: |
| RegularPredicateBlock(Node* tail, Deoptimization::DeoptReason deopt_reason) |
| : _deopt_reason(deopt_reason), |
| _entry(skip_all(tail)) { |
| DEBUG_ONLY(verify_block(tail);) |
| } |
| NONCOPYABLE(RegularPredicateBlock); |
| |
| private: |
| // Walk over all Regular Predicates of this block (if any) and return the first node not belonging to the block |
| // anymore (i.e. entry to the first Regular Predicate in this block if any or `tail` otherwise). |
| Node* skip_all(Node* tail) const { |
| RegularPredicateBlockIterator iterator(tail, _deopt_reason); |
| return iterator.skip_all(); |
| } |
| |
| DEBUG_ONLY(void verify_block(Node* tail) const;) |
| |
| public: |
| Node* entry() const { |
| return _entry; |
| } |
| }; |
| |
| #ifndef PRODUCT |
| // Visitor class to print all the visited predicates. Used by the Predicates class which does the printing starting |
| // at the loop node and then following the inputs to the earliest predicate. |
| class PredicatePrinter : public PredicateVisitor { |
| const char* _prefix; // Prefix added to each dumped string. |
| |
| public: |
| explicit PredicatePrinter(const char* prefix) : _prefix(prefix) {} |
| NONCOPYABLE(PredicatePrinter); |
| |
| void visit(const ParsePredicate& parse_predicate) override { |
| print_predicate_node("Parse Predicate", parse_predicate); |
| } |
| |
| void visit(const RuntimePredicate& runtime_predicate) override { |
| print_predicate_node("Runtime Predicate", runtime_predicate); |
| } |
| |
| void visit(const TemplateAssertionPredicate& template_assertion_predicate) override { |
| print_predicate_node("Template Assertion Predicate", template_assertion_predicate); |
| } |
| |
| void visit(const InitializedAssertionPredicate& initialized_assertion_predicate) override { |
| print_predicate_node("Initialized Assertion Predicate", initialized_assertion_predicate); |
| } |
| |
| private: |
| void print_predicate_node(const char* predicate_name, const Predicate& predicate) const { |
| tty->print_cr("%s- %s: %d %s", _prefix, predicate_name, predicate.head()->_idx, predicate.head()->Name()); |
| } |
| }; |
| #endif // NOT PRODUCT |
| |
| // This class represents a Predicate Block (i.e. either a Loop Predicate Block, a Profiled Loop Predicate Block, |
| // or a Loop Limit Check Predicate Block). It contains zero or more Regular Predicates followed by a Parse Predicate |
| // which, however, does not need to exist (we could already have decided to remove Parse Predicates for this loop). |
| class PredicateBlock : public StackObj { |
| const ParsePredicate _parse_predicate; // Could be missing. |
| const RegularPredicateBlock _regular_predicate_block; |
| Node* const _entry; |
| #ifndef PRODUCT |
| // Used for dumping. |
| Node* const _tail; |
| const Deoptimization::DeoptReason _deopt_reason; |
| #endif // NOT PRODUCT |
| |
| public: |
| PredicateBlock(Node* tail, Deoptimization::DeoptReason deopt_reason) |
| : _parse_predicate(tail, deopt_reason), |
| _regular_predicate_block(_parse_predicate.entry(), deopt_reason), |
| _entry(_regular_predicate_block.entry()) |
| #ifndef PRODUCT |
| , _tail(tail) |
| , _deopt_reason(deopt_reason) |
| #endif // NOT PRODUCT |
| {} |
| NONCOPYABLE(PredicateBlock); |
| |
| // Returns the control input node into this Regular Predicate block. This is either: |
| // - The control input to the first If node in the block representing a Runtime Predicate if there is at least one |
| // Runtime Predicate. |
| // - The control input node into the ParsePredicate node if there is only a Parse Predicate and no Runtime Predicate. |
| // - The same node initially passed to the constructor if this Regular Predicate block is empty (i.e. no Parse |
| // Predicate or Runtime Predicate). |
| Node* entry() const { |
| return _entry; |
| } |
| |
| bool is_non_empty() const { |
| return has_parse_predicate() || has_runtime_predicates(); |
| } |
| |
| bool has_parse_predicate() const { |
| return _parse_predicate.is_valid(); |
| } |
| |
| ParsePredicateNode* parse_predicate() const { |
| return _parse_predicate.head(); |
| } |
| |
| ParsePredicateSuccessProj* parse_predicate_success_proj() const { |
| return _parse_predicate.tail(); |
| } |
| |
| bool has_runtime_predicates() const { |
| return _parse_predicate.entry() != _entry; |
| } |
| |
| // Returns either: |
| // - The entry to the Parse Predicate if present. |
| // - The last Runtime Predicate success projection if Parse Predicate is not present. |
| // - The entry to this Regular Predicate Block if the block is empty. |
| Node* skip_parse_predicate() const { |
| return _parse_predicate.entry(); |
| } |
| |
| #ifndef PRODUCT |
| void dump() const; |
| void dump(const char* prefix) const; |
| #endif // NOT PRODUCT |
| }; |
| |
| // This class takes a loop entry node and finds all the available predicates for the loop. |
| class Predicates : public StackObj { |
| Node* const _tail; |
| const PredicateBlock _loop_limit_check_predicate_block; |
| const PredicateBlock _auto_vectorization_check_block; |
| const PredicateBlock _profiled_loop_predicate_block; |
| const PredicateBlock _loop_predicate_block; |
| Node* const _entry; |
| |
| public: |
| explicit Predicates(Node* loop_entry) |
| : _tail(loop_entry), |
| _loop_limit_check_predicate_block(loop_entry, Deoptimization::Reason_loop_limit_check), |
| _auto_vectorization_check_block(_loop_limit_check_predicate_block.entry(), |
| Deoptimization::Reason_auto_vectorization_check), |
| _profiled_loop_predicate_block(_auto_vectorization_check_block.entry(), |
| Deoptimization::Reason_profile_predicate), |
| _loop_predicate_block(_profiled_loop_predicate_block.entry(), |
| Deoptimization::Reason_predicate), |
| _entry(_loop_predicate_block.entry()) {} |
| NONCOPYABLE(Predicates); |
| |
| // Returns the control input the first predicate if there are any predicates. If there are no predicates, the same |
| // node initially passed to the constructor is returned. |
| Node* entry() const { |
| return _entry; |
| } |
| |
| const PredicateBlock* loop_predicate_block() const { |
| return &_loop_predicate_block; |
| } |
| |
| const PredicateBlock* profiled_loop_predicate_block() const { |
| return &_profiled_loop_predicate_block; |
| } |
| |
| const PredicateBlock* auto_vectorization_check_block() const { |
| return &_auto_vectorization_check_block; |
| } |
| |
| const PredicateBlock* loop_limit_check_predicate_block() const { |
| return &_loop_limit_check_predicate_block; |
| } |
| |
| bool has_any() const { |
| return _entry != _tail; |
| } |
| |
| #ifndef PRODUCT |
| /* |
| * Debug printing functions. |
| */ |
| void dump() const; |
| static void dump_at(Node* node); |
| static void dump_for_loop(LoopNode* loop_node); |
| #endif // NOT PRODUCT |
| }; |
| |
| // This class checks whether a node is in the original loop body and not the cloned one. |
| class NodeInOriginalLoopBody : public NodeInLoopBody { |
| const uint _first_node_index_in_cloned_loop_body; |
| const Node_List& _old_new; |
| |
| public: |
| NodeInOriginalLoopBody(const uint first_node_index_in_cloned_loop_body, const Node_List& old_new) |
| : _first_node_index_in_cloned_loop_body(first_node_index_in_cloned_loop_body), |
| _old_new(old_new) {} |
| NONCOPYABLE(NodeInOriginalLoopBody); |
| |
| // Check if 'node' is not a cloned node (i.e. "< _first_node_index_in_cloned_loop_body") and if we've created a |
| // clone from 'node' (i.e. _old_new entry is non-null). Then we know that 'node' belongs to the original loop body. |
| bool check_node_in_loop_body(Node* node) const override { |
| if (node->_idx < _first_node_index_in_cloned_loop_body) { |
| Node* cloned_node = _old_new[node->_idx]; |
| // Check that the clone is actually part of the cloned loop body and not from some earlier cloning. |
| return cloned_node != nullptr && cloned_node->_idx >= _first_node_index_in_cloned_loop_body; |
| } |
| return false; |
| } |
| }; |
| |
| // This class checks whether a node is in the main loop body and not the pre loop body. We cannot use the |
| // NodeInOriginalLoopBody class because PhaseIdealLoop::clone_up_backedge_goo() could clone additional nodes that |
| // should be pinned at the main loop body entry. The check in NodeInOriginalLoopBody will ignore these. |
| class NodeInMainLoopBody : public NodeInLoopBody { |
| const uint _first_node_index_in_pre_loop_body; |
| const uint _last_node_index_in_pre_loop_body; |
| DEBUG_ONLY(const uint _last_node_index_from_backedge_goo;) |
| const Node_List& _old_new; |
| |
| public: |
| NodeInMainLoopBody(const uint first_node_index_in_pre_loop_body, const uint last_node_index_in_pre_loop_body, |
| DEBUG_ONLY(const uint last_node_index_from_backedge_goo COMMA) const Node_List& old_new) |
| : _first_node_index_in_pre_loop_body(first_node_index_in_pre_loop_body), |
| _last_node_index_in_pre_loop_body(last_node_index_in_pre_loop_body), |
| DEBUG_ONLY(_last_node_index_from_backedge_goo(last_node_index_from_backedge_goo) COMMA) |
| _old_new(old_new) {} |
| NONCOPYABLE(NodeInMainLoopBody); |
| |
| // Check if 'node' is not a cloned node (i.e. "< _first_node_index_in_cloned_loop_body") and if we've created a |
| // clone from 'node' (i.e. _old_new entry is non-null). Then we know that 'node' belongs to the original loop body. |
| // Additionally check if a node was cloned after the pre loop was created. This indicates that it was created by |
| // PhaseIdealLoop::clone_up_backedge_goo(). These nodes should also be pinned at the main loop entry. |
| bool check_node_in_loop_body(Node* node) const override { |
| if (node->_idx < _first_node_index_in_pre_loop_body) { |
| Node* cloned_node = _old_new[node->_idx]; |
| // Check that the clone is actually part of the cloned loop body and not from some earlier cloning. |
| bool cloned_node_in_pre_loop_body = cloned_node != nullptr && cloned_node->_idx >= _first_node_index_in_pre_loop_body; |
| assert(!cloned_node_in_pre_loop_body || cloned_node->_idx <= _last_node_index_in_pre_loop_body, |
| "clone must be part of pre loop body"); |
| return cloned_node_in_pre_loop_body; |
| } |
| // Created in PhaseIdealLoop::clone_up_backedge_goo()? |
| bool node_created_by_backedge_goo = node->_idx > _last_node_index_in_pre_loop_body; |
| assert(!node_created_by_backedge_goo || node->_idx <= _last_node_index_from_backedge_goo, |
| "cloned node must have been created in PhaseIdealLoop::clone_up_backedge_goo()"); |
| return node_created_by_backedge_goo; |
| } |
| }; |
| |
| // This class checks whether a node is in the cloned loop body and not the original one from which the loop was cloned. |
| class NodeInClonedLoopBody : public NodeInLoopBody { |
| const uint _first_node_index_in_cloned_loop_body; |
| |
| public: |
| explicit NodeInClonedLoopBody(const uint first_node_index_in_cloned_loop_body) |
| : _first_node_index_in_cloned_loop_body(first_node_index_in_cloned_loop_body) {} |
| NONCOPYABLE(NodeInClonedLoopBody); |
| |
| // Check if 'node' is a clone. This can easily be achieved by comparing its node index to the first node index |
| // inside the cloned loop body (all of them are clones). |
| bool check_node_in_loop_body(Node* node) const override { |
| return node->_idx >= _first_node_index_in_cloned_loop_body; |
| } |
| }; |
| |
| // Visitor to create Initialized Assertion Predicates at a target loop from Template Assertion Predicates from a source |
| // loop. This visitor can be used in combination with a PredicateIterator. |
| class CreateAssertionPredicatesVisitor : public PredicateVisitor { |
| Node* const _init; |
| Node* const _stride; |
| CountedLoopNode* const _target_loop_head; |
| Node* const _old_target_loop_entry; |
| Node* _current_predicate_chain_head; |
| PhaseIdealLoop* const _phase; |
| const NodeInLoopBody& _node_in_loop_body; |
| const bool _kill_old_template; |
| |
| TemplateAssertionPredicate |
| clone_template_and_replace_init_input(const TemplateAssertionPredicate& template_assertion_predicate) const; |
| |
| InitializedAssertionPredicate initialize_from_template(const TemplateAssertionPredicate& template_assertion_predicate, |
| IfTrueNode* cloned_template_predicate_tail) const; |
| void rewire_to_old_predicate_chain_head(Node* initialized_assertion_predicate_success_proj) const; |
| |
| public: |
| CreateAssertionPredicatesVisitor(CountedLoopNode* target_loop_head, PhaseIdealLoop* phase, |
| const NodeInLoopBody& node_in_loop_body, bool kill_old_template); |
| NONCOPYABLE(CreateAssertionPredicatesVisitor); |
| |
| using PredicateVisitor::visit; |
| |
| void visit(const TemplateAssertionPredicate& template_assertion_predicate) override; |
| }; |
| |
| // This class establishes a predicate chain at the target loop by rewiring newly cloned predicates to the current head |
| // of the predicate chain. |
| class TargetLoopPredicateChain : public StackObj { |
| DEBUG_ONLY(const Node* const _old_target_loop_entry;) |
| DEBUG_ONLY(const node_idx_t _node_index_before_cloning;) |
| Node* _current_predicate_chain_head; |
| PhaseIdealLoop* const _phase; |
| |
| void rewire_to_target_chain_head(IfTrueNode* template_assertion_predicate_success_proj) const; |
| |
| public: |
| TargetLoopPredicateChain(LoopNode* loop_head, PhaseIdealLoop* phase); |
| NONCOPYABLE(TargetLoopPredicateChain); |
| |
| void insert_predicate(const Predicate& predicate); |
| }; |
| |
| // This class clones Parse and Template Assertion Predicates to the provided target loop. This also involves rewiring |
| // of any data pinned to Template Assertion Predicates. The Template Assertion Predicate Expressions are cloned |
| // without applying any changes to them. |
| // |
| // Each time a predicate is cloned, it is inserted at the top of previously cloned predicates. This ensures that the |
| // target loop predicate chain order of the newly cloned predicates is the same as in the source loop from which the |
| // predicates were cloned from. |
| // |
| // Template Assertion Predicate Example: |
| // |
| // x _old_target_loop_entry _old_target_loop_entry |
| // | | | | |
| // Template Assertion | Cloned Template 2. rewire data Cloned Template |
| // Predicate 1. clone | Assertion Predicate and predicate Assertion Predicate |
| // | \ =======> | ===============> | \ |
| // | data | | data |
| // | | | |
| // source loop head target loop head target loop head |
| class ClonePredicateToTargetLoop : public StackObj { |
| LoopNode* const _target_loop_head; |
| LoopNode* const _target_outer_loop_head; |
| Node* const _old_target_loop_entry; // Used as control for each newly cloned predicate. |
| TargetLoopPredicateChain _target_loop_predicate_chain; |
| const NodeInLoopBody& _node_in_loop_body; |
| PhaseIdealLoop* const _phase; |
| |
| public: |
| ClonePredicateToTargetLoop(LoopNode* target_loop_head, const NodeInLoopBody& node_in_loop_body, PhaseIdealLoop* phase); |
| |
| // Clones the provided Parse Predicate to the head of the current predicate chain at the target loop. |
| void clone_parse_predicate(const ParsePredicate& parse_predicate, bool is_false_path_loop) { |
| ParsePredicate cloned_parse_predicate = parse_predicate.clone_to_unswitched_loop(_old_target_loop_entry, |
| is_false_path_loop, _phase); |
| _target_loop_predicate_chain.insert_predicate(cloned_parse_predicate); |
| } |
| |
| void clone_template_assertion_predicate(const TemplateAssertionPredicate& template_assertion_predicate); |
| }; |
| |
| // Visitor to clone Parse and Template Assertion Predicates from a loop to its unswitched true and false path loop. |
| // The cloned predicates are not updated in any way. Thus, an Initialized Assertion Predicate is also not required to |
| // be created. Note that the data dependencies from the Template Assertion Predicates are also updated to the newly |
| // cloned Template Assertion Predicates, depending on whether they belong to the true or false path loop. |
| class CloneUnswitchedLoopPredicatesVisitor : public PredicateVisitor { |
| ClonePredicateToTargetLoop _clone_predicate_to_true_path_loop; |
| ClonePredicateToTargetLoop _clone_predicate_to_false_path_loop; |
| |
| PhaseIdealLoop* const _phase; |
| const bool _is_counted_loop; |
| |
| public: |
| CloneUnswitchedLoopPredicatesVisitor(LoopNode* true_path_loop_head, |
| LoopNode* false_path_loop_head, |
| const NodeInOriginalLoopBody& node_in_true_path_loop_body, |
| const NodeInClonedLoopBody& node_in_false_path_loop_body, |
| PhaseIdealLoop* phase); |
| NONCOPYABLE(CloneUnswitchedLoopPredicatesVisitor); |
| |
| using PredicateVisitor::visit; |
| |
| void visit(const ParsePredicate& parse_predicate) override; |
| void visit(const TemplateAssertionPredicate& template_assertion_predicate) override; |
| }; |
| |
| // This visitor collects all OpaqueTemplateAssertionNodes of Template Assertion Predicates. This is used for cleaning |
| // up unused Template Assertion Predicates. |
| class OpaqueTemplateAssertionPredicateCollector : public PredicateVisitor { |
| Unique_Node_List& _list; |
| |
| public: |
| explicit OpaqueTemplateAssertionPredicateCollector(Unique_Node_List& list) : _list(list) {} |
| |
| using PredicateVisitor::visit; |
| |
| void visit(const TemplateAssertionPredicate& template_assertion_predicate) override { |
| _list.push(template_assertion_predicate.opaque_node()); |
| } |
| }; |
| |
| // This visitor updates the stride for an Assertion Predicate during Loop Unrolling. The inputs to the OpaqueLoopStride |
| // nodes Template of Template Assertion Predicates are updated and new Initialized Assertion Predicates are created |
| // from the updated templates. The old Initialized Assertion Predicates are killed. |
| class UpdateStrideForAssertionPredicates : public PredicateVisitor { |
| Node* const _new_stride; |
| CountedLoopNode* const _loop_node; |
| PhaseIdealLoop* const _phase; |
| |
| void replace_opaque_stride_input(const TemplateAssertionPredicate& template_assertion_predicate) const; |
| |
| InitializedAssertionPredicate |
| initialize_from_updated_template(const TemplateAssertionPredicate& template_assertion_predicate) const; |
| void connect_initialized_assertion_predicate(Node* new_control_out, const InitializedAssertionPredicate& initialized_assertion_predicate) const; |
| |
| public: |
| UpdateStrideForAssertionPredicates(Node* const new_stride, CountedLoopNode* loop_node, PhaseIdealLoop* phase) |
| : _new_stride(new_stride), |
| _loop_node(loop_node), |
| _phase(phase) {} |
| NONCOPYABLE(UpdateStrideForAssertionPredicates); |
| |
| using PredicateVisitor::visit; |
| |
| void visit(const TemplateAssertionPredicate& template_assertion_predicate) override; |
| void visit(const InitializedAssertionPredicate& initialized_assertion_predicate) override; |
| }; |
| |
| // Eliminate all useless Parse and Template Assertion Predicates. They become useless when they can no longer be found |
| // from a loop head. We mark these useless to clean them up later during IGVN. A Predicate that is marked useless will |
| // no longer be visited by a PredicateVisitor. |
| class EliminateUselessPredicates : public StackObj { |
| Compile* const C; |
| const GrowableArray<ParsePredicateNode*>& _parse_predicates; |
| const GrowableArray<OpaqueTemplateAssertionPredicateNode*>& _template_assertion_predicate_opaques; |
| PhaseIterGVN& _igvn; |
| IdealLoopTree* const _ltree_root; |
| |
| void mark_all_predicates_maybe_useful() const; |
| template <class PredicateList> |
| static void mark_predicates_on_list_maybe_useful(const PredicateList& predicate_list); |
| |
| void mark_loop_associated_predicates_useful() const; |
| static void mark_useful_predicates_for_loop(IdealLoopTree* loop); |
| |
| void mark_maybe_useful_predicates_useless() const; |
| template <class PredicateList> |
| void mark_maybe_useful_predicates_on_list_useless(const PredicateList& predicate_list) const; |
| |
| #ifdef ASSERT |
| void verify_loop_nodes_of_useless_templates_assertion_predicates_are_dead() const; |
| Unique_Node_List collect_loop_nodes_of_useless_template_assertion_predicates() const; |
| void verify_associated_loop_nodes_are_dead(const Unique_Node_List& loop_nodes_of_useless_template_assertion_predicates) const; |
| #endif // ASSERT |
| public: |
| EliminateUselessPredicates(PhaseIterGVN& igvn, IdealLoopTree* ltree_root) |
| : C(igvn.C), _parse_predicates(igvn.C->parse_predicates()), |
| _template_assertion_predicate_opaques(igvn.C->template_assertion_predicate_opaques()), |
| _igvn(igvn), |
| _ltree_root(ltree_root) {} |
| |
| void eliminate() const; |
| }; |
| |
| #endif // SHARE_OPTO_PREDICATES_HPP |