Skip to content

Commit

Permalink
8344213: Cleanup OpaqueLoop*Node verification code for Assertion Pred…
Browse files Browse the repository at this point in the history
…icates
  • Loading branch information
chhagedorn committed Nov 15, 2024
1 parent b54bd82 commit 94abb68
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 125 deletions.
2 changes: 0 additions & 2 deletions src/hotspot/share/opto/loopPredicate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,8 +348,6 @@ PhaseIdealLoop::clone_assertion_predicate_for_unswitched_loops(IfTrueNode* templ
ParsePredicateNode* unswitched_loop_parse_predicate) {
TemplateAssertionPredicate template_assertion_predicate(template_assertion_predicate_success_proj);
IfTrueNode* template_success_proj = template_assertion_predicate.clone(unswitched_loop_parse_predicate->in(0), this);
assert(assertion_predicate_has_loop_opaque_node(template_success_proj->in(0)->as_If()),
"must find Assertion Predicate for fast loop");
_igvn.replace_input_of(unswitched_loop_parse_predicate, 0, template_success_proj);
set_idom(unswitched_loop_parse_predicate, template_success_proj, dom_depth(template_success_proj));
return template_success_proj;
Expand Down
77 changes: 0 additions & 77 deletions src/hotspot/share/opto/loopTransform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1312,80 +1312,6 @@ void PhaseIdealLoop::ensure_zero_trip_guard_proj(Node* node, bool is_main_loop)
}
#endif

#ifdef ASSERT
bool PhaseIdealLoop::assertion_predicate_has_loop_opaque_node(IfNode* iff) {
uint init;
uint stride;
count_opaque_loop_nodes(iff->in(1)->in(1), init, stride);
ResourceMark rm;
Unique_Node_List wq;
wq.clear();
wq.push(iff->in(1)->in(1));
uint verif_init = 0;
uint verif_stride = 0;
for (uint i = 0; i < wq.size(); i++) {
Node* n = wq.at(i);
int op = n->Opcode();
if (!n->is_CFG()) {
if (n->Opcode() == Op_OpaqueLoopInit) {
verif_init++;
} else if (n->Opcode() == Op_OpaqueLoopStride) {
verif_stride++;
} else {
for (uint j = 1; j < n->req(); j++) {
Node* m = n->in(j);
if (m != nullptr) {
wq.push(m);
}
}
}
}
}
assert(init == verif_init && stride == verif_stride, "missed opaque node");
assert(stride == 0 || init != 0, "init should be there every time stride is");
return init != 0;
}

void PhaseIdealLoop::count_opaque_loop_nodes(Node* n, uint& init, uint& stride) {
init = 0;
stride = 0;
ResourceMark rm;
Unique_Node_List wq;
wq.push(n);
for (uint i = 0; i < wq.size(); i++) {
Node* n = wq.at(i);
if (TemplateAssertionExpressionNode::is_maybe_in_expression(n)) {
if (n->is_OpaqueLoopInit()) {
init++;
} else if (n->is_OpaqueLoopStride()) {
stride++;
} else {
for (uint j = 1; j < n->req(); j++) {
Node* m = n->in(j);
if (m != nullptr) {
wq.push(m);
}
}
}
}
}
}
#endif // ASSERT

// Create an Initialized Assertion Predicate from the template_assertion_predicate
IfTrueNode* PhaseIdealLoop::create_initialized_assertion_predicate(IfNode* template_assertion_predicate, Node* new_init,
Node* new_stride, Node* new_control) {
assert(assertion_predicate_has_loop_opaque_node(template_assertion_predicate),
"must find OpaqueLoop* nodes for Template Assertion Predicate");
InitializedAssertionPredicateCreator initialized_assertion_predicate(this);
IfTrueNode* success_proj = initialized_assertion_predicate.create_from_template(template_assertion_predicate,
new_control, new_init, new_stride);

assert(!assertion_predicate_has_loop_opaque_node(success_proj->in(0)->as_If()),
"Initialized Assertion Predicates do not have OpaqueLoop* nodes in the bool expression anymore");
return success_proj;
}

//------------------------------insert_pre_post_loops--------------------------
// Insert pre and post loops. If peel_only is set, the pre-loop can not have
// more iterations added. It acts as a 'peel' only, no lower-bound RCE, no
Expand Down Expand Up @@ -2761,21 +2687,18 @@ void PhaseIdealLoop::do_range_check(IdealLoopTree *loop, Node_List &old_new) {
loop_entry = initialized_assertion_predicate_creator.create(final_iv_placeholder, loop_entry, stride_con,
scale_con, int_offset, int_limit,
AssertionPredicateType::FinalIv);
assert(!assertion_predicate_has_loop_opaque_node(loop_entry->in(0)->as_If()), "unexpected");
}

// Add two Template Assertion Predicates to create new Initialized Assertion Predicates from when either
// unrolling or splitting this main-loop further.
TemplateAssertionPredicateCreator template_assertion_predicate_creator(cl, scale_con , int_offset, int_limit,
this);
loop_entry = template_assertion_predicate_creator.create(loop_entry);
assert(assertion_predicate_has_loop_opaque_node(loop_entry->in(0)->as_If()), "unexpected");

// Initialized Assertion Predicate for the value of the initial main-loop.
loop_entry = initialized_assertion_predicate_creator.create(init, loop_entry, stride_con, scale_con,
int_offset, int_limit,
AssertionPredicateType::InitValue);
assert(!assertion_predicate_has_loop_opaque_node(loop_entry->in(0)->as_If()), "unexpected");

} else {
if (PrintOpto) {
Expand Down
5 changes: 0 additions & 5 deletions src/hotspot/share/opto/loopnode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -941,12 +941,7 @@ class PhaseIdealLoop : public PhaseTransform {
#ifdef ASSERT
static void ensure_zero_trip_guard_proj(Node* node, bool is_main_loop);
#endif
public:
IfTrueNode* create_initialized_assertion_predicate(IfNode* template_assertion_predicate, Node* new_init,
Node* new_stride, Node* control);
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_template_assertion_predicates(ParsePredicateSuccessProj* parse_predicate_proj, Unique_Node_List& list, bool get_opaque = false);
void update_main_loop_assertion_predicates(CountedLoopNode* main_loop_head);
void initialize_assertion_predicates_for_peeled_loop(CountedLoopNode* peeled_loop_head,
Expand Down
1 change: 0 additions & 1 deletion src/hotspot/share/opto/loopopts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -789,7 +789,6 @@ Node *PhaseIdealLoop::conditional_move( Node *region ) {
assert(!bol->is_OpaqueInitializedAssertionPredicate(), "Initialized Assertion Predicates cannot form a diamond with Halt");
if (bol->is_OpaqueTemplateAssertionPredicate()) {
// Ignore Template Assertion Predicates with OpaqueTemplateAssertionPredicate nodes.
assert(assertion_predicate_has_loop_opaque_node(iff), "must find OpaqueLoop* nodes");
return nullptr;
}
assert(bol->Opcode() == Op_Bool, "Unexpected node");
Expand Down
47 changes: 47 additions & 0 deletions src/hotspot/share/opto/node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2111,4 +2111,51 @@ inline int Op_DivModIL(BasicType bt, bool is_unsigned) {
}
}

// Interface to define actions that should be taken when running DataNodeBFS. Each use can extend this class to specify
// a customized BFS.
class BFSActions : public StackObj {
public:
// Should a node's inputs further be visit in the BFS traversal? By default, we visit all data inputs. Override this
// method to provide a costum filter.
virtual bool should_visit(Node* node) const {
// By default, visit all inputs.
return true;
};

// Is the visited node a target node that we are looking for in the BFS traversal? We do not visit its inputs further
// but the BFS will continue to visited all unvisited nodes in the queue.
virtual bool is_target_node(Node* node) const = 0;

// Defines an action that should be taken when we visit a target node in the BFS traversal.
virtual void target_node_action(Node* target_node) = 0;
};

// Class to perform a BFS traversal on the data nodes from a given start node. The provided BFSActions guide which
// data node's inputs should be further visited, which data nodes are target nodes and what to do with the target nodes.
class DataNodeBFS : public StackObj {
BFSActions& _bfs_actions;

public:
explicit DataNodeBFS(BFSActions& bfs_action) : _bfs_actions(bfs_action) {}

// Run the BFS starting from 'start_node' and apply the actions provided to this class.
void run(Node* start_node) {
ResourceMark rm;
Unique_Node_List _nodes_to_visit;
_nodes_to_visit.push(start_node);
for (uint i = 0; i < _nodes_to_visit.size(); i++) {
Node* next = _nodes_to_visit[i];
for (uint j = 1; j < next->req(); j++) {
Node* input = next->in(j);
if (_bfs_actions.is_target_node(input)) {
assert(_bfs_actions.should_visit(input), "must also pass node filter");
_bfs_actions.target_node_action(input);
} else if (_bfs_actions.should_visit(input)) {
_nodes_to_visit.push(input);
}
}
}
}
};

#endif // SHARE_OPTO_NODE_HPP
Loading

0 comments on commit 94abb68

Please sign in to comment.