Skip to content

Commit 7131f05

Browse files
committed
8342043: Split Opaque4Node into OpaqueTemplateAssertionPredicateNode and OpaqueNotNullNode
Reviewed-by: kvn, roland
1 parent 37cfaa8 commit 7131f05

18 files changed

+218
-171
lines changed

src/hotspot/share/opto/classes.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,8 +270,9 @@ macro(Opaque1)
270270
macro(OpaqueLoopInit)
271271
macro(OpaqueLoopStride)
272272
macro(OpaqueZeroTripGuard)
273-
macro(Opaque4)
273+
macro(OpaqueNotNull)
274274
macro(OpaqueInitializedAssertionPredicate)
275+
macro(OpaqueTemplateAssertionPredicate)
275276
macro(ProfileBoolean)
276277
macro(OrI)
277278
macro(OrL)

src/hotspot/share/opto/compile.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ void Compile::remove_useless_node(Node* dead) {
393393
if (dead->is_expensive()) {
394394
remove_expensive_node(dead);
395395
}
396-
if (dead->Opcode() == Op_Opaque4) {
396+
if (dead->is_OpaqueTemplateAssertionPredicate()) {
397397
remove_template_assertion_predicate_opaq(dead);
398398
}
399399
if (dead->is_ParsePredicate()) {

src/hotspot/share/opto/compile.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,8 @@ class Compile : public Phase {
370370
GrowableArray<CallGenerator*> _intrinsics; // List of intrinsics.
371371
GrowableArray<Node*> _macro_nodes; // List of nodes which need to be expanded before matching.
372372
GrowableArray<ParsePredicateNode*> _parse_predicates; // List of Parse Predicates.
373-
GrowableArray<Node*> _template_assertion_predicate_opaqs; // List of Opaque4 nodes for Template Assertion Predicates.
373+
// List of OpaqueTemplateAssertionPredicateNode nodes for Template Assertion Predicates.
374+
GrowableArray<Node*> _template_assertion_predicate_opaqs;
374375
GrowableArray<Node*> _expensive_nodes; // List of nodes that are expensive to compute and that we'd better not let the GVN freely common
375376
GrowableArray<Node*> _for_post_loop_igvn; // List of nodes for IGVN after loop opts are over
376377
GrowableArray<UnstableIfTrap*> _unstable_if_traps; // List of ifnodes after IGVN
@@ -770,7 +771,7 @@ class Compile : public Phase {
770771

771772
void add_template_assertion_predicate_opaq(Node* n) {
772773
assert(!_template_assertion_predicate_opaqs.contains(n),
773-
"duplicate entry in template assertion predicate opaque4 list");
774+
"Duplicate entry in Template Assertion Predicate OpaqueTemplateAssertionPredicate list");
774775
_template_assertion_predicate_opaqs.append(n);
775776
}
776777

src/hotspot/share/opto/escape.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -574,14 +574,14 @@ bool ConnectionGraph::can_reduce_check_users(Node* n, uint nesting) const {
574574
// CmpP/N used by the If controlling the cast.
575575
if (use->in(0)->is_IfTrue() || use->in(0)->is_IfFalse()) {
576576
Node* iff = use->in(0)->in(0);
577-
// We may have Opaque4 node between If and Bool nodes.
578-
// Bail out in such case - we need to preserve Opaque4 for correct
579-
// processing predicates after loop opts.
577+
// We may have an OpaqueNotNull node between If and Bool nodes. Bail out in such case.
580578
bool can_reduce = (iff->Opcode() == Op_If) && iff->in(1)->is_Bool() && iff->in(1)->in(1)->is_Cmp();
581579
if (can_reduce) {
582580
Node* iff_cmp = iff->in(1)->in(1);
583581
int opc = iff_cmp->Opcode();
584582
can_reduce = (opc == Op_CmpP || opc == Op_CmpN) && can_reduce_cmp(n, iff_cmp);
583+
} else {
584+
assert(iff->in(1)->is_OpaqueNotNull(), "must be OpaqueNotNull");
585585
}
586586
if (!can_reduce) {
587587
#ifndef PRODUCT

src/hotspot/share/opto/graphKit.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1458,17 +1458,17 @@ Node* GraphKit::cast_not_null(Node* obj, bool do_replace_in_map) {
14581458
// In that case that data path will die and we need the control path
14591459
// to become dead as well to keep the graph consistent. So we have to
14601460
// add a check for null for which one branch can't be taken. It uses
1461-
// an Opaque4 node that will cause the check to be removed after loop
1461+
// an OpaqueNotNull node that will cause the check to be removed after loop
14621462
// opts so the test goes away and the compiled code doesn't execute a
14631463
// useless check.
14641464
Node* GraphKit::must_be_not_null(Node* value, bool do_replace_in_map) {
14651465
if (!TypePtr::NULL_PTR->higher_equal(_gvn.type(value))) {
14661466
return value;
14671467
}
14681468
Node* chk = _gvn.transform(new CmpPNode(value, null()));
1469-
Node *tst = _gvn.transform(new BoolNode(chk, BoolTest::ne));
1470-
Node* opaq = _gvn.transform(new Opaque4Node(C, tst, intcon(1)));
1471-
IfNode *iff = new IfNode(control(), opaq, PROB_MAX, COUNT_UNKNOWN);
1469+
Node* tst = _gvn.transform(new BoolNode(chk, BoolTest::ne));
1470+
Node* opaq = _gvn.transform(new OpaqueNotNullNode(C, tst));
1471+
IfNode* iff = new IfNode(control(), opaq, PROB_MAX, COUNT_UNKNOWN);
14721472
_gvn.set_type(iff, iff->Value(&_gvn));
14731473
if (!tst->is_Con()) {
14741474
record_for_igvn(iff);

src/hotspot/share/opto/loopPredicate.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,8 @@ void PhaseIdealLoop::clone_assertion_predicates_to_unswitched_loop(IdealLoopTree
338338
}
339339

340340
// Put all Assertion Predicate projections on a list, starting at 'predicate' and going up in the tree. If 'get_opaque'
341-
// is set, then the Opaque4 nodes of the Assertion Predicates are put on the list instead of the projections.
341+
// is set, then the OpaqueTemplateAssertionPredicate nodes of the Assertion Predicates are put on the list instead of
342+
// the projections.
342343
void PhaseIdealLoop::get_assertion_predicates(Node* predicate, Unique_Node_List& list, bool get_opaque) {
343344
ParsePredicateNode* parse_predicate = predicate->in(0)->as_ParsePredicate();
344345
ProjNode* uncommon_proj = parse_predicate->proj_out(1 - predicate->as_Proj()->_con);
@@ -353,10 +354,10 @@ void PhaseIdealLoop::get_assertion_predicates(Node* predicate, Unique_Node_List&
353354
}
354355
Node* bol = iff->in(1);
355356
assert(!bol->is_OpaqueInitializedAssertionPredicate(), "should not find an Initialized Assertion Predicate");
356-
if (bol->is_Opaque4()) {
357+
if (bol->is_OpaqueTemplateAssertionPredicate()) {
357358
assert(assertion_predicate_has_loop_opaque_node(iff), "must find OpaqueLoop* nodes");
358359
if (get_opaque) {
359-
// Collect the predicate Opaque4 node.
360+
// Collect the OpaqueTemplateAssertionPredicateNode.
360361
list.push(bol);
361362
} else {
362363
// Collect the predicate projection.
@@ -374,11 +375,11 @@ IfProjNode* PhaseIdealLoop::clone_assertion_predicate_for_unswitched_loops(IfNod
374375
IfProjNode* predicate,
375376
Deoptimization::DeoptReason reason,
376377
ParsePredicateSuccessProj* parse_predicate_proj) {
377-
TemplateAssertionExpression template_assertion_expression(template_assertion_predicate->in(1)->as_Opaque4());
378-
Opaque4Node* cloned_opaque4_node = template_assertion_expression.clone(parse_predicate_proj->in(0)->in(0), this);
378+
TemplateAssertionExpression template_assertion_expression(template_assertion_predicate->in(1)->as_OpaqueTemplateAssertionPredicate());
379+
OpaqueTemplateAssertionPredicateNode* cloned_opaque_node = template_assertion_expression.clone(parse_predicate_proj->in(0)->in(0), this);
379380
IfProjNode* if_proj = create_new_if_for_predicate(parse_predicate_proj, nullptr, reason,
380381
template_assertion_predicate->Opcode(), false);
381-
_igvn.replace_input_of(if_proj->in(0), 1, cloned_opaque4_node);
382+
_igvn.replace_input_of(if_proj->in(0), 1, cloned_opaque_node);
382383
_igvn.replace_input_of(parse_predicate_proj->in(0), 0, if_proj);
383384
set_idom(parse_predicate_proj->in(0), if_proj, dom_depth(if_proj));
384385
return if_proj;

src/hotspot/share/opto/loopTransform.cpp

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,8 +1189,10 @@ bool IdealLoopTree::policy_range_check(PhaseIdealLoop* phase, bool provisional,
11891189
continue;
11901190
}
11911191
if (!bol->is_Bool()) {
1192-
assert(bol->is_Opaque4() || bol->is_OpaqueInitializedAssertionPredicate(),
1193-
"Opaque node of non-null-check or of Initialized Assertion Predicate");
1192+
assert(bol->is_OpaqueNotNull() ||
1193+
bol->is_OpaqueTemplateAssertionPredicate() ||
1194+
bol->is_OpaqueInitializedAssertionPredicate(),
1195+
"Opaque node of a non-null-check or an Assertion Predicate");
11941196
continue;
11951197
}
11961198
if (bol->as_Bool()->_test._test == BoolTest::ne) {
@@ -1359,7 +1361,7 @@ void PhaseIdealLoop::copy_assertion_predicates_to_main_loop_helper(const Predica
13591361
break;
13601362
Node* bol = iff->in(1);
13611363
assert(!bol->is_OpaqueInitializedAssertionPredicate(), "should not find an Initialized Assertion Predicate");
1362-
if (bol->is_Opaque4()) {
1364+
if (bol->is_OpaqueTemplateAssertionPredicate()) {
13631365
// Clone the Assertion Predicate twice and initialize one with the initial
13641366
// value of the loop induction variable. Leave the other predicate
13651367
// to be initialized when increasing the stride during loop unrolling.
@@ -1399,11 +1401,11 @@ void PhaseIdealLoop::copy_assertion_predicates_to_main_loop_helper(const Predica
13991401
}
14001402
}
14011403

1404+
#ifdef ASSERT
14021405
bool PhaseIdealLoop::assertion_predicate_has_loop_opaque_node(IfNode* iff) {
14031406
uint init;
14041407
uint stride;
14051408
count_opaque_loop_nodes(iff->in(1)->in(1), init, stride);
1406-
#ifdef ASSERT
14071409
ResourceMark rm;
14081410
Unique_Node_List wq;
14091411
wq.clear();
@@ -1429,10 +1431,10 @@ bool PhaseIdealLoop::assertion_predicate_has_loop_opaque_node(IfNode* iff) {
14291431
}
14301432
}
14311433
assert(init == verif_init && stride == verif_stride, "missed opaque node");
1432-
#endif
14331434
assert(stride == 0 || init != 0, "init should be there every time stride is");
14341435
return init != 0;
14351436
}
1437+
#endif // ASSERT
14361438

14371439
void PhaseIdealLoop::count_opaque_loop_nodes(Node* n, uint& init, uint& stride) {
14381440
init = 0;
@@ -1475,14 +1477,15 @@ IfTrueNode* PhaseIdealLoop::create_initialized_assertion_predicate(IfNode* templ
14751477

14761478
// Clone the Template Assertion Predicate and set a new OpaqueLoopInitNode to create a new Template Assertion Predicate.
14771479
// This is done when creating a new Template Assertion Predicate for the main loop which requires a new init node.
1478-
// We keep the Opaque4 node since it's still a template. Since the templates are eventually removed after loop opts,
1479-
// these are never executed. We therefore insert a Halt node instead of an uncommon trap.
1480+
// We keep the OpaqueTemplateAssertionPredicate node since it's still a template. Since the templates are eventually
1481+
// removed after loop opts, these are never executed. We therefore insert a Halt node instead of an uncommon trap.
14801482
Node* PhaseIdealLoop::clone_template_assertion_predicate(IfNode* iff, Node* new_init, Node* predicate, Node* uncommon_proj,
14811483
Node* control, IdealLoopTree* outer_loop, Node* new_control) {
14821484
assert(assertion_predicate_has_loop_opaque_node(iff), "must find OpaqueLoop* nodes for Template Assertion Predicate");
1483-
TemplateAssertionExpression template_assertion_expression(iff->in(1)->as_Opaque4());
1485+
TemplateAssertionExpression template_assertion_expression(iff->in(1)->as_OpaqueTemplateAssertionPredicate());
14841486
assert(new_init->is_OpaqueLoopInit(), "only for creating new Template Assertion Predicates");
1485-
Opaque4Node* new_opaque_node = template_assertion_expression.clone_and_replace_init(new_init, control, this);
1487+
OpaqueTemplateAssertionPredicateNode* new_opaque_node =
1488+
template_assertion_expression.clone_and_replace_init(new_init, control, this);
14861489
AssertionPredicateIfCreator assertion_predicate_if_creator(this);
14871490
IfTrueNode* success_proj =
14881491
assertion_predicate_if_creator.create_for_template(new_control, iff->Opcode(), new_opaque_node
@@ -1922,25 +1925,21 @@ void PhaseIdealLoop::update_main_loop_assertion_predicates(Node* ctrl, CountedLo
19221925
break;
19231926
}
19241927
Node* bol = iff->in(1);
1925-
if (bol->is_Opaque4()) {
1926-
if (assertion_predicate_has_loop_opaque_node(iff)) {
1927-
// This is a Template Assertion Predicate for the initial or last access.
1928-
// Create an Initialized Assertion Predicates for it accordingly:
1929-
// - For the initial access a[init] (same as before)
1930-
// - For the last access a[init+new_stride-orig_stride] (with the new unroll stride)
1931-
prev_proj = create_initialized_assertion_predicate(iff, init, max_value, prev_proj);
1932-
} else {
1933-
// Ignore Opaque4 from a non-null-check for an intrinsic or unsafe access. This could happen when we maximally
1934-
// unroll a non-main loop with such an If with an Opaque4 node directly above the loop entry.
1935-
assert(!loop_head->is_main_loop(), "Opaque4 node from a non-null check - should not be at main loop");
1936-
}
1928+
if (bol->is_OpaqueTemplateAssertionPredicate()) {
1929+
assert(assertion_predicate_has_loop_opaque_node(iff), "must find OpaqueLoop* nodes");
1930+
// This is a Template Assertion Predicate for the initial or last access.
1931+
// Create an Initialized Assertion Predicates for it accordingly:
1932+
// - For the initial access a[init] (same as before)
1933+
// - For the last access a[init+new_stride-orig_stride] (with the new unroll stride)
1934+
prev_proj = create_initialized_assertion_predicate(iff, init, max_value, prev_proj);
19371935
} else if (bol->is_OpaqueInitializedAssertionPredicate()) {
19381936
// This is one of the two Initialized Assertion Predicates:
19391937
// - For the initial access a[init]
19401938
// - For the last access a[init+old_stride-orig_stride]
19411939
// We could keep the one for the initial access but we do not know which one we currently have here. Just kill both.
19421940
_igvn.replace_input_of(iff, 1, _igvn.intcon(1));
19431941
}
1942+
assert(!bol->is_OpaqueNotNull() || !loop_head->is_main_loop(), "OpaqueNotNull should not be at main loop");
19441943
entry = entry->in(0)->in(0);
19451944
}
19461945
if (prev_proj != ctrl) {
@@ -1967,7 +1966,7 @@ void PhaseIdealLoop::copy_assertion_predicates_to_post_loop(LoopNode* main_loop_
19671966
if (!proj->unique_ctrl_out()->is_Halt()) {
19681967
break;
19691968
}
1970-
if (iff->in(1)->is_Opaque4()) {
1969+
if (iff->in(1)->is_OpaqueTemplateAssertionPredicate()) {
19711970
// Initialize from Template Assertion Predicate.
19721971
prev_proj = create_initialized_assertion_predicate(iff, init, stride, prev_proj);
19731972
}
@@ -2000,7 +1999,7 @@ void PhaseIdealLoop::initialize_assertion_predicates_for_peeled_loop(const Predi
20001999
}
20012000
Node* bol = iff->in(1);
20022001
assert(!bol->is_OpaqueInitializedAssertionPredicate(), "should not find an Initialized Assertion Predicate");
2003-
if (bol->is_Opaque4()) {
2002+
if (bol->is_OpaqueTemplateAssertionPredicate()) {
20042003
// Initialize from Template Assertion Predicate.
20052004
input_proj = create_initialized_assertion_predicate(iff, init, stride, input_proj);
20062005

src/hotspot/share/opto/loopnode.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4443,7 +4443,8 @@ void PhaseIdealLoop::add_useless_parse_predicates_to_igvn_worklist() {
44434443

44444444

44454445
// Eliminate all Template Assertion Predicates that do not belong to their originally associated loop anymore by
4446-
// replacing the Opaque4 node of the If node with true. These nodes will be removed during the next round of IGVN.
4446+
// replacing the OpaqueTemplateAssertionPredicate node of the If node with true. These nodes will be removed during the
4447+
// next round of IGVN.
44474448
void PhaseIdealLoop::eliminate_useless_template_assertion_predicates() {
44484449
Unique_Node_List useful_predicates;
44494450
if (C->has_loops()) {
@@ -4484,9 +4485,10 @@ void PhaseIdealLoop::collect_useful_template_assertion_predicates_for_loop(Ideal
44844485

44854486
void PhaseIdealLoop::eliminate_useless_template_assertion_predicates(Unique_Node_List& useful_predicates) {
44864487
for (int i = C->template_assertion_predicate_count(); i > 0; i--) {
4487-
Opaque4Node* opaque4_node = C->template_assertion_predicate_opaq_node(i - 1)->as_Opaque4();
4488-
if (!useful_predicates.member(opaque4_node)) { // not in the useful list
4489-
_igvn.replace_node(opaque4_node, opaque4_node->in(2));
4488+
OpaqueTemplateAssertionPredicateNode* opaque_node =
4489+
C->template_assertion_predicate_opaq_node(i - 1)->as_OpaqueTemplateAssertionPredicate();
4490+
if (!useful_predicates.member(opaque_node)) { // not in the useful list
4491+
_igvn.replace_node(opaque_node, _igvn.intcon(1));
44904492
}
44914493
}
44924494
}

src/hotspot/share/opto/loopnode.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -955,7 +955,7 @@ class PhaseIdealLoop : public PhaseTransform {
955955
IfTrueNode* create_initialized_assertion_predicate(IfNode* template_assertion_predicate, Node* new_init,
956956
Node* new_stride, Node* control);
957957
static void count_opaque_loop_nodes(Node* n, uint& init, uint& stride);
958-
static bool assertion_predicate_has_loop_opaque_node(IfNode* iff);
958+
DEBUG_ONLY(static bool assertion_predicate_has_loop_opaque_node(IfNode* iff);)
959959
static void get_assertion_predicates(Node* predicate, Unique_Node_List& list, bool get_opaque = false);
960960
void update_main_loop_assertion_predicates(Node* ctrl, CountedLoopNode* loop_head, Node* init, int stride_con);
961961
void copy_assertion_predicates_to_post_loop(LoopNode* main_loop_head, CountedLoopNode* post_loop_head,

src/hotspot/share/opto/loopopts.cpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -787,10 +787,9 @@ Node *PhaseIdealLoop::conditional_move( Node *region ) {
787787
}//for
788788
Node* bol = iff->in(1);
789789
assert(!bol->is_OpaqueInitializedAssertionPredicate(), "Initialized Assertion Predicates cannot form a diamond with Halt");
790-
if (bol->is_Opaque4()) {
791-
// Ignore Template Assertion Predicates with Opaque4 nodes.
792-
assert(assertion_predicate_has_loop_opaque_node(iff),
793-
"must be Template Assertion Predicate, non-null-check with Opaque4 cannot form a diamond with Halt");
790+
if (bol->is_OpaqueTemplateAssertionPredicate()) {
791+
// Ignore Template Assertion Predicates with OpaqueTemplateAssertionPredicate nodes.
792+
assert(assertion_predicate_has_loop_opaque_node(iff), "must find OpaqueLoop* nodes");
794793
return nullptr;
795794
}
796795
assert(bol->Opcode() == Op_Bool, "Unexpected node");
@@ -1702,8 +1701,9 @@ void PhaseIdealLoop::try_sink_out_of_loop(Node* n) {
17021701
!n->is_Proj() &&
17031702
!n->is_MergeMem() &&
17041703
!n->is_CMove() &&
1705-
!n->is_Opaque4() &&
1704+
!n->is_OpaqueNotNull() &&
17061705
!n->is_OpaqueInitializedAssertionPredicate() &&
1706+
!n->is_OpaqueTemplateAssertionPredicate() &&
17071707
!n->is_Type()) {
17081708
Node *n_ctrl = get_ctrl(n);
17091709
IdealLoopTree *n_loop = get_loop(n_ctrl);
@@ -2021,14 +2021,14 @@ Node* PhaseIdealLoop::clone_iff(PhiNode* phi) {
20212021
if (b->is_Phi()) {
20222022
_igvn.replace_input_of(phi, i, clone_iff(b->as_Phi()));
20232023
} else {
2024-
assert(b->is_Bool() || b->is_Opaque4() || b->is_OpaqueInitializedAssertionPredicate(),
2025-
"bool, non-null check with Opaque4 node or Initialized Assertion Predicate with its Opaque node");
2024+
assert(b->is_Bool() || b->is_OpaqueNotNull() || b->is_OpaqueInitializedAssertionPredicate(),
2025+
"bool, non-null check with OpaqueNotNull or Initialized Assertion Predicate with its Opaque node");
20262026
}
20272027
}
20282028
Node* n = phi->in(1);
20292029
Node* sample_opaque = nullptr;
20302030
Node *sample_bool = nullptr;
2031-
if (n->is_Opaque4() || n->is_OpaqueInitializedAssertionPredicate()) {
2031+
if (n->is_OpaqueNotNull() || n->is_OpaqueInitializedAssertionPredicate()) {
20322032
sample_opaque = n;
20332033
sample_bool = n->in(1);
20342034
assert(sample_bool->is_Bool(), "wrong type");
@@ -2202,7 +2202,9 @@ void PhaseIdealLoop::clone_loop_handle_data_uses(Node* old, Node_List &old_new,
22022202
// For example, it is unexpected that there is a Phi between an
22032203
// AllocateArray node and its ValidLengthTest input that could cause
22042204
// split if to break.
2205-
if (use->is_If() || use->is_CMove() || use->is_Opaque4() || use->is_OpaqueInitializedAssertionPredicate() ||
2205+
assert(!use->is_OpaqueTemplateAssertionPredicate(),
2206+
"should not clone a Template Assertion Predicate which should be removed once it's useless");
2207+
if (use->is_If() || use->is_CMove() || use->is_OpaqueNotNull() || use->is_OpaqueInitializedAssertionPredicate() ||
22062208
(use->Opcode() == Op_AllocateArray && use->in(AllocateNode::ValidLengthTest) == old)) {
22072209
// Since this code is highly unlikely, we lazily build the worklist
22082210
// of such Nodes to go split.

0 commit comments

Comments
 (0)