Skip to content

Commit

Permalink
Misc cleanups
Browse files Browse the repository at this point in the history
  • Loading branch information
chhagedorn committed Nov 23, 2023
1 parent 7a3d8cf commit dda0daa
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 81 deletions.
9 changes: 5 additions & 4 deletions src/hotspot/share/opto/cfgnode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -291,8 +291,9 @@ class GotoNode : public Node {
virtual const RegMask &out_RegMask() const;
};

// This node represents a Template Assertion Predicate with two bools as input which can be used to create and
// This node represents a Template Assertion Predicate with two bools as input which can be used to create an
// Initialized Assertion Predicate from (more information can be found in the summary at predicates.hpp).
// This node is folded either after loop opts or once the associated CountedLoopNode is removed.
class TemplateAssertionPredicateNode : public Node {
int _initialized_init_value_opcode;
int _initialized_last_value_opcode;
Expand All @@ -308,7 +309,6 @@ class TemplateAssertionPredicateNode : public Node {

TemplateAssertionPredicateNode(Node* control, BoolNode* bool_init_value, BoolNode* bool_last_value,
int initialized_init_value_opcode, int initialized_last_value_opcode);

IfNode* create_initialized_assertion_predicate(Node* control, OpaqueAssertionPredicateNode* opaque_bool,
AssertionPredicateType initialized_assertion_predicate_type) const;

Expand Down Expand Up @@ -492,7 +492,8 @@ class IfNode : public MultiBranchNode {

class RangeCheckNode : public IfNode {
private:
int is_range_check(Node* &range, Node* &index, jint &offset);
int is_range_check(Node*& range, Node*& index, jint& offset);

public:
RangeCheckNode(Node* control, Node* bol, float p, float fcnt)
: IfNode(control, bol, p, fcnt) {
Expand All @@ -516,7 +517,7 @@ class RangeCheckNode : public IfNode {
// There are three kinds of Parse Predicates:
// Loop Parse Predicate, Profiled Loop Parse Predicate (both used by Loop Predication), and Loop Limit Check Parse
// Predicate (used for integer overflow checks when creating a counted loop).
// More information about predicates can be found in loopPredicate.cpp.
// More information about predicates can be found in predicates.hpp.
class ParsePredicateNode : public IfNode {
Deoptimization::DeoptReason _deopt_reason;
bool _useless; // If the associated loop dies, this parse predicate becomes useless and can be cleaned up by Value().
Expand Down
18 changes: 10 additions & 8 deletions src/hotspot/share/opto/loopPredicate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,7 @@ bool IdealLoopTree::is_range_check_if(IfProjNode* if_success_proj, PhaseIdealLoo
// (2) stride*scale < 0
// max(scale*i + offset) = scale*init + offset
BoolNode* PhaseIdealLoop::rc_predicate(Node* ctrl, const int scale, Node* offset, Node* init, Node* limit,
const jint stride, Node* range, const bool upper, bool &overflow) {
const jint stride, Node* range, const bool upper, bool& overflow) {
jint con_limit = (limit != nullptr && limit->is_Con()) ? limit->get_int() : 0;
jint con_init = init->is_Con() ? init->get_int() : 0;
jint con_offset = offset->is_Con() ? offset->get_int() : 0;
Expand Down Expand Up @@ -1000,10 +1000,8 @@ void PhaseIdealLoop::loop_predication_follow_branches(Node *n, IdealLoopTree *lo
bool PhaseIdealLoop::loop_predication_impl_helper(IdealLoopTree* loop, IfProjNode* if_success_proj,
ParsePredicateSuccessProj* parse_predicate_proj, CountedLoopNode* cl,
ConNode* zero, Invariance& invar, Deoptimization::DeoptReason reason) {
// Following are changed to nonnull when a predicate can be hoisted
Node* new_predicate_tail = nullptr;
IfNode* iff = if_success_proj->in(0)->as_If();
Node* test = iff->in(1);
IfNode* iff = if_success_proj->in(0)->as_If();
Node* test = iff->in(1);
if (!test->is_Bool()) { // Conv2B, ...
return false;
}
Expand Down Expand Up @@ -1085,7 +1083,9 @@ bool PhaseIdealLoop::loop_predication_impl_helper(IdealLoopTree* loop, IfProjNod
IfNode* lower_bound_iff = lower_bound_proj->in(0)->as_If();
_igvn.hash_delete(lower_bound_iff);
lower_bound_iff->set_req(1, lower_bound_bol);
if (TraceLoopPredicate) tty->print_cr("lower bound check if: %d", lower_bound_iff->_idx);
if (TraceLoopPredicate) {
tty->print_cr("lower bound check if: %d", lower_bound_iff->_idx);
}

// Test the upper bound
BoolNode* upper_bound_bol = rc_predicate(lower_bound_proj, scale, offset, init, limit, stride, rng, true, overflow);
Expand All @@ -1095,7 +1095,9 @@ bool PhaseIdealLoop::loop_predication_impl_helper(IdealLoopTree* loop, IfProjNod
IfNode* upper_bound_iff = upper_bound_proj->in(0)->as_If();
_igvn.hash_delete(upper_bound_iff);
upper_bound_iff->set_req(1, upper_bound_bol);
if (TraceLoopPredicate) tty->print_cr("upper bound check if: %d", lower_bound_iff->_idx);
if (TraceLoopPredicate) {
tty->print_cr("upper bound check if: %d", upper_bound_iff->_idx);
}

// Each newly created Hoisted Check Predicate is accompanied by two Template Assertion Predicates. Later, we initialize
// them by making a copy of them when splitting a loop into sub loops. The Assertion Predicates ensure that dead sub
Expand Down Expand Up @@ -1293,7 +1295,7 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree* loop) {
return hoisted;
}

// We cannot add Loop Predicates if:
// We cannot create Loop Predicates if:
// (1) There is no Loop Parse Predicate.
// (2) Already added Profiled Loop Predicates (Loop Predicates and Profiled Loop Predicates can be dependent
// through a data node, and thus we should only add new Profiled Loop Predicates which are below Loop Predicates
Expand Down
4 changes: 2 additions & 2 deletions src/hotspot/share/opto/loopTransform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -788,8 +788,8 @@ void PhaseIdealLoop::do_peeling(IdealLoopTree *loop, Node_List &old_new) {

// Creates new Assertion Predicates at the 'target_loop_head' (cloned loop). A new Template Assertion Predicate is
// inserted with the new init and stride values of the target loop for each existing Template Assertion Predicate found
// 'source_loop_head (original loop). For each new Template Assertion Predicate, an init and last value Initialized
// Assertion Predicate is created.
// at 'source_loop_head (original loop). For each new Template Assertion Predicate, an Initialized Assertion Predicate
// for the new init and stride value is created.
void PhaseIdealLoop::clone_assertion_predicates_from_original_loop(CountedLoopNode* source_loop_head,
CountedLoopNode* target_loop_head,
const uint first_cloned_loop_node_index) {
Expand Down
41 changes: 20 additions & 21 deletions src/hotspot/share/opto/loopUnswitch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,13 @@ bool IdealLoopTree::policy_unswitching( PhaseIdealLoop *phase ) const {
return phase->may_require_nodes(est_loop_clone_sz(2));
}

//------------------------------find_unswitching_candidate-----------------------------
// Find candidate "if" for unswitching
// Find invariant test in loop body that does not exit the loop. If multiple are found, we pick the first one in the
// loop body. Return the candidate "if" for unswitching.
IfNode* PhaseIdealLoop::find_unswitching_candidate(const IdealLoopTree *loop) const {

// Find first invariant test that doesn't exit the loop
LoopNode *head = loop->_head->as_Loop();
IfNode* unswitch_iff = nullptr;
IfNode* unswitching_candidate = nullptr;
Node* n = head->in(LoopNode::LoopBackControl);
while (n != head) {
Node* n_dom = idom(n);
Expand All @@ -102,24 +102,26 @@ IfNode* PhaseIdealLoop::find_unswitching_candidate(const IdealLoopTree *loop) co
// If condition is invariant and not a loop exit,
// then found reason to unswitch.
if (loop->is_invariant(bol) && !loop->is_loop_exit(iff)) {
unswitch_iff = iff;
unswitching_candidate = iff;
}
}
}
}
}
n = n_dom;
}
return unswitch_iff;
return unswitching_candidate;
}

//------------------------------do_unswitching-----------------------------
// Clone loop with an invariant test (that does not exit) and
// insert a clone of the test that selects which version to
// execute.
void PhaseIdealLoop::do_unswitching(IdealLoopTree *loop, Node_List &old_new) {
// Find first invariant test that doesn't exit the loop
IfNode* unswitching_candidate = find_unswitching_candidate((const IdealLoopTree *)loop);
// Perform Loop Unswitching on the loop containing an invariant test that does not exit the loop. The loop is cloned
// such that we have two identical loops next to each other - a fast and a slow loop. We modify the loops as follows:
// - Fast loop: We remove the invariant test together with the false path and only leave the true path in the loop.
// - Slow loop: We remove the invariant test together with the true path and only leave the false path in the loop.
//
// We insert a new If node before both loops that performs the removed invariant test. If the test is true at runtime,
// we select the fast loop. Otherwise, we select the slow loop.
void PhaseIdealLoop::do_unswitching(IdealLoopTree* loop, Node_List& old_new) {
IfNode* unswitching_candidate = find_unswitching_candidate(loop);
assert(unswitching_candidate != nullptr, "should be at least one");

LoopNode* head = loop->_head->as_Loop();
Expand Down Expand Up @@ -304,7 +306,7 @@ class UnswitchedLoop : public StackObj {
NewParsePredicate* _new_parse_predicate;
TemplateAssertionPredicateDataOutput* _node_in_target_loop;
PhaseIdealLoop* _phase;
PredicateChain _predicate_chain;
PredicateInserter _predicate_inserter;

public:
UnswitchedLoop(IfProjNode* unswitch_if_proj, LoopNode* unswitched_loop_head, NewParsePredicate* new_parse_predicate,
Expand All @@ -313,19 +315,19 @@ class UnswitchedLoop : public StackObj {
_new_parse_predicate(new_parse_predicate),
_node_in_target_loop(node_in_target_loop),
_phase(phase),
_predicate_chain(unswitched_loop_head, phase) {}
_predicate_inserter(unswitched_loop_head, phase) {}

// Clone the Template Assertion Predicate to this loop.
void clone_to(TemplateAssertionPredicate& template_assertion_predicate) {
TemplateAssertionPredicate cloned_template =
template_assertion_predicate.clone(_entry, _node_in_target_loop, _phase);
_predicate_chain.insert_new_predicate(cloned_template);
_predicate_inserter.insert(cloned_template);
}

// Clone the Parse Predicate to this loop.
void clone_to(ParsePredicate& parse_predicate) {
ParsePredicate cloned_parse_predicate = parse_predicate.clone(_entry, _new_parse_predicate, _phase);
_predicate_chain.insert_new_predicate(cloned_parse_predicate);
_predicate_inserter.insert(cloned_parse_predicate);
}

};
Expand Down Expand Up @@ -522,15 +524,12 @@ class OriginalLoop {
#endif // ASSERT
};

//-------------------------create_slow_version_of_loop------------------------
// Create a slow version of the loop by cloning the loop
// and inserting an if to select fast-slow versions.
// Return the inserted if.
// Create a slow version of the loop by cloning the loop and inserting an If to select the fast or slow version.
// Return the inserted loop selector If.
IfNode* PhaseIdealLoop::create_slow_version_of_loop(IdealLoopTree* loop, Node_List& old_new,
IfNode* unswitching_candidate) {
OriginalLoop original_loop(loop, &old_new);
IfNode* loop_selector_if = original_loop.unswitch(unswitching_candidate);
recompute_dom_depth();
return loop_selector_if;
}

1 change: 0 additions & 1 deletion src/hotspot/share/opto/loopnode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1315,7 +1315,6 @@ class PhaseIdealLoop : public PhaseTransform {
Deoptimization::DeoptReason reason, int opcode,
bool rewire_uncommon_proj_phi_inputs = false);


private:
// Helper functions for create_new_if_for_predicate()
void set_ctrl_of_nodes_with_same_ctrl(Node* node, ProjNode* old_ctrl, Node* new_ctrl);
Expand Down
Loading

0 comments on commit dda0daa

Please sign in to comment.