Skip to content

Commit a5f401f

Browse files
committed
8334650: Add debug information about whether an Assertion Predicate is for the init or last value
Reviewed-by: roland, kvn
1 parent 25c3845 commit a5f401f

File tree

6 files changed

+97
-36
lines changed

6 files changed

+97
-36
lines changed

src/hotspot/share/opto/cfgnode.hpp

+25-12
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ class JProjNode;
5757
class JumpProjNode;
5858
class SCMemProjNode;
5959
class PhaseIdealLoop;
60+
enum class AssertionPredicateType;
6061

6162
// The success projection of a Parse Predicate is always an IfTrueNode and the uncommon projection an IfFalseNode
6263
typedef IfTrueNode ParsePredicateSuccessProj;
@@ -318,11 +319,23 @@ class MultiBranchNode : public MultiNode {
318319
//------------------------------IfNode-----------------------------------------
319320
// Output selected Control, based on a boolean test
320321
class IfNode : public MultiBranchNode {
322+
public:
323+
float _prob; // Probability of true path being taken.
324+
float _fcnt; // Frequency counter
325+
326+
private:
327+
NOT_PRODUCT(AssertionPredicateType _assertion_predicate_type;)
328+
329+
void init_node(Node* control, Node* bol) {
330+
init_class_id(Class_If);
331+
init_req(0, control);
332+
init_req(1, bol);
333+
}
334+
321335
// Size is bigger to hold the probability field. However, _prob does not
322336
// change the semantics so it does not appear in the hash & cmp functions.
323337
virtual uint size_of() const { return sizeof(*this); }
324338

325-
private:
326339
// Helper methods for fold_compares
327340
bool cmpi_folds(PhaseIterGVN* igvn, bool fold_ne = false);
328341
bool is_ctrl_folds(Node* ctrl, PhaseIterGVN* igvn);
@@ -413,14 +426,8 @@ class IfNode : public MultiBranchNode {
413426
// Magic manifest probabilities such as 0.83, 0.7, ... can be found in
414427
// gen_subtype_check() and catch_inline_exceptions().
415428

416-
float _prob; // Probability of true path being taken.
417-
float _fcnt; // Frequency counter
418-
IfNode( Node *control, Node *b, float p, float fcnt )
419-
: MultiBranchNode(2), _prob(p), _fcnt(fcnt) {
420-
init_class_id(Class_If);
421-
init_req(0,control);
422-
init_req(1,b);
423-
}
429+
IfNode(Node* control, Node* bol, float p, float fcnt);
430+
NOT_PRODUCT(IfNode(Node* control, Node* bol, float p, float fcnt, AssertionPredicateType assertion_predicate_type);)
424431

425432
static IfNode* make_with_same_profile(IfNode* if_node_profile, Node* ctrl, BoolNode* bol);
426433

@@ -450,13 +457,19 @@ class IfNode : public MultiBranchNode {
450457

451458
class RangeCheckNode : public IfNode {
452459
private:
453-
int is_range_check(Node* &range, Node* &index, jint &offset);
460+
int is_range_check(Node*& range, Node*& index, jint& offset);
454461

455462
public:
456-
RangeCheckNode(Node* control, Node *b, float p, float fcnt)
457-
: IfNode(control, b, p, fcnt) {
463+
RangeCheckNode(Node* control, Node* bol, float p, float fcnt) : IfNode(control, bol, p, fcnt) {
464+
init_class_id(Class_RangeCheck);
465+
}
466+
467+
#ifndef PRODUCT
468+
RangeCheckNode(Node* control, Node* bol, float p, float fcnt, AssertionPredicateType assertion_predicate_type)
469+
: IfNode(control, bol, p, fcnt, assertion_predicate_type) {
458470
init_class_id(Class_RangeCheck);
459471
}
472+
#endif // NOT PRODUCT
460473

461474
virtual int Opcode() const;
462475
virtual Node* Ideal(PhaseGVN *phase, bool can_reshape);

src/hotspot/share/opto/ifnode.cpp

+37-5
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,24 @@
4747
extern uint explicit_null_checks_elided;
4848
#endif
4949

50+
IfNode::IfNode(Node* control, Node* bol, float p, float fcnt)
51+
: MultiBranchNode(2),
52+
_prob(p),
53+
_fcnt(fcnt)
54+
NOT_PRODUCT(COMMA _assertion_predicate_type(AssertionPredicateType::None)) {
55+
init_node(control, bol);
56+
}
57+
58+
#ifndef PRODUCT
59+
IfNode::IfNode(Node* control, Node* bol, float p, float fcnt, AssertionPredicateType assertion_predicate_type)
60+
: MultiBranchNode(2),
61+
_prob(p),
62+
_fcnt(fcnt),
63+
_assertion_predicate_type(assertion_predicate_type) {
64+
init_node(control, bol);
65+
}
66+
#endif // NOT_PRODUCT
67+
5068
//=============================================================================
5169
//------------------------------Value------------------------------------------
5270
// Return a tuple for whichever arm of the IF is reachable
@@ -1822,11 +1840,23 @@ void IfProjNode::pin_array_access_nodes(PhaseIterGVN* igvn) {
18221840
}
18231841

18241842
#ifndef PRODUCT
1825-
//------------------------------dump_spec--------------------------------------
1826-
void IfNode::dump_spec(outputStream *st) const {
1827-
st->print("P=%f, C=%f",_prob,_fcnt);
1843+
void IfNode::dump_spec(outputStream* st) const {
1844+
switch (_assertion_predicate_type) {
1845+
case AssertionPredicateType::Init_value:
1846+
st->print("#Init Value Assertion Predicate ");
1847+
break;
1848+
case AssertionPredicateType::Last_value:
1849+
st->print("#Last Value Assertion Predicate ");
1850+
break;
1851+
case AssertionPredicateType::None:
1852+
// No Assertion Predicate
1853+
break;
1854+
default:
1855+
fatal("Unknown Assertion Predicate type");
1856+
}
1857+
st->print("P=%f, C=%f", _prob, _fcnt);
18281858
}
1829-
#endif
1859+
#endif // NOT PRODUCT
18301860

18311861
//------------------------------idealize_test----------------------------------
18321862
// Try to canonicalize tests better. Peek at the Cmp/Bool/If sequence and
@@ -2181,6 +2211,8 @@ void ParsePredicateNode::dump_spec(outputStream* st) const {
21812211
default:
21822212
fatal("unknown kind");
21832213
}
2214+
if (_useless) {
2215+
st->print("#useless ");
2216+
}
21842217
}
2185-
21862218
#endif // NOT PRODUCT

src/hotspot/share/opto/loopPredicate.cpp

+10-5
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ void PhaseIdealLoop::register_control(Node* n, IdealLoopTree *loop, Node* pred,
101101
// is an IfTrue projection. This code is also used to clone predicates to cloned loops.
102102
IfTrueNode* PhaseIdealLoop::create_new_if_for_predicate(ParsePredicateSuccessProj* parse_predicate_success_proj,
103103
Node* new_entry, const Deoptimization::DeoptReason reason,
104-
const int opcode, const bool rewire_uncommon_proj_phi_inputs) {
104+
const int opcode, const bool rewire_uncommon_proj_phi_inputs
105+
NOT_PRODUCT (COMMA AssertionPredicateType assertion_predicate_type)) {
105106
assert(parse_predicate_success_proj->is_uncommon_trap_if_pattern(reason), "must be a uct if pattern!");
106107
ParsePredicateNode* parse_predicate = parse_predicate_success_proj->in(0)->as_ParsePredicate();
107108
ParsePredicateUncommonProj* uncommon_proj = parse_predicate->uncommon_proj();
@@ -143,10 +144,12 @@ IfTrueNode* PhaseIdealLoop::create_new_if_for_predicate(ParsePredicateSuccessPro
143144
IfNode* new_iff = nullptr;
144145
switch (opcode) {
145146
case Op_If:
146-
new_iff = new IfNode(entry, parse_predicate->in(1), parse_predicate->_prob, parse_predicate->_fcnt);
147+
new_iff = new IfNode(entry, parse_predicate->in(1), parse_predicate->_prob, parse_predicate->_fcnt
148+
NOT_PRODUCT(COMMA assertion_predicate_type));
147149
break;
148150
case Op_RangeCheck:
149-
new_iff = new RangeCheckNode(entry, parse_predicate->in(1), parse_predicate->_prob, parse_predicate->_fcnt);
151+
new_iff = new RangeCheckNode(entry, parse_predicate->in(1), parse_predicate->_prob, parse_predicate->_fcnt
152+
NOT_PRODUCT(COMMA assertion_predicate_type));
150153
break;
151154
case Op_ParsePredicate:
152155
new_iff = new ParsePredicateNode(entry, reason, &_igvn);
@@ -1320,7 +1323,8 @@ IfTrueNode* PhaseIdealLoop::add_template_assertion_predicate(IfNode* iff, IdealL
13201323
Node* opaque_bol = new Opaque4Node(C, bol, _igvn.intcon(1)); // This will go away once loop opts are over
13211324
C->add_template_assertion_predicate_opaq(opaque_bol);
13221325
register_new_node(opaque_bol, upper_bound_proj);
1323-
IfTrueNode* new_proj = create_new_if_for_predicate(parse_predicate_proj, nullptr, reason, overflow ? Op_If : iff->Opcode());
1326+
IfTrueNode* new_proj = create_new_if_for_predicate(parse_predicate_proj, nullptr, reason, overflow ? Op_If : iff->Opcode(),
1327+
false NOT_PRODUCT(COMMA AssertionPredicateType::Init_value));
13241328
_igvn.replace_input_of(new_proj->in(0), 1, opaque_bol);
13251329
assert(opaque_init->outcnt() > 0, "should be used");
13261330

@@ -1345,7 +1349,8 @@ IfTrueNode* PhaseIdealLoop::add_template_assertion_predicate(IfNode* iff, IdealL
13451349
opaque_bol = new Opaque4Node(C, bol, _igvn.intcon(1));
13461350
C->add_template_assertion_predicate_opaq(opaque_bol);
13471351
register_new_node(opaque_bol, new_proj);
1348-
new_proj = create_new_if_for_predicate(parse_predicate_proj, nullptr, reason, overflow ? Op_If : iff->Opcode());
1352+
new_proj = create_new_if_for_predicate(parse_predicate_proj, nullptr, reason, overflow ? Op_If : iff->Opcode(),
1353+
false NOT_PRODUCT(COMMA AssertionPredicateType::Last_value));
13491354
_igvn.replace_input_of(new_proj->in(0), 1, opaque_bol);
13501355
assert(max_value->outcnt() > 0, "should be used");
13511356
assert(assertion_predicate_has_loop_opaque_node(new_proj->in(0)->as_If()), "unexpected");

src/hotspot/share/opto/loopTransform.cpp

+9-8
Original file line numberDiff line numberDiff line change
@@ -2769,10 +2769,9 @@ bool PhaseIdealLoop::is_scaled_iv_plus_extra_offset(Node* exp1, Node* offset3, N
27692769

27702770
// Same as PhaseIdealLoop::duplicate_predicates() but for range checks
27712771
// eliminated by iteration splitting.
2772-
Node* PhaseIdealLoop::add_range_check_elimination_assertion_predicate(IdealLoopTree* loop, Node* ctrl,
2773-
const int scale_con, Node* offset, Node* limit,
2774-
jint stride_con, Node* value,
2775-
const bool is_template) {
2772+
Node* PhaseIdealLoop::add_range_check_elimination_assertion_predicate(
2773+
IdealLoopTree* loop, Node* ctrl, const int scale_con, Node* offset, Node* limit, jint stride_con, Node* value,
2774+
const bool is_template NOT_PRODUCT(COMMA AssertionPredicateType assertion_predicate_type)) {
27762775
bool overflow = false;
27772776
BoolNode* bol = rc_predicate(ctrl, scale_con, offset, value, nullptr, stride_con,
27782777
limit, (stride_con > 0) != (scale_con > 0), overflow);
@@ -2993,8 +2992,9 @@ void PhaseIdealLoop::do_range_check(IdealLoopTree *loop, Node_List &old_new) {
29932992

29942993
// Add two Template Assertion Predicates to create new Initialized Assertion Predicates from when either
29952994
// unrolling or splitting this main-loop further.
2996-
loop_entry = add_range_check_elimination_assertion_predicate(loop, loop_entry, scale_con, int_offset,
2997-
int_limit, stride_con, opaque_init, true);
2995+
loop_entry = add_range_check_elimination_assertion_predicate(
2996+
loop, loop_entry, scale_con, int_offset, int_limit, stride_con, opaque_init, true
2997+
NOT_PRODUCT(COMMA AssertionPredicateType::Init_value));
29982998
assert(assertion_predicate_has_loop_opaque_node(loop_entry->in(0)->as_If()), "unexpected");
29992999

30003000
Node* opaque_stride = new OpaqueLoopStrideNode(C, cl->stride());
@@ -3006,8 +3006,9 @@ void PhaseIdealLoop::do_range_check(IdealLoopTree *loop, Node_List &old_new) {
30063006
// init + (current stride - initial stride) is within the loop so narrow its type by leveraging the type of the iv Phi
30073007
max_value = new CastIINode(max_value, loop->_head->as_CountedLoop()->phi()->bottom_type());
30083008
register_new_node(max_value, loop_entry);
3009-
loop_entry = add_range_check_elimination_assertion_predicate(loop, loop_entry, scale_con, int_offset,
3010-
int_limit, stride_con, max_value, true);
3009+
loop_entry = add_range_check_elimination_assertion_predicate(
3010+
loop, loop_entry, scale_con, int_offset, int_limit, stride_con, max_value, true
3011+
NOT_PRODUCT(COMMA AssertionPredicateType::Last_value));
30113012
assert(assertion_predicate_has_loop_opaque_node(loop_entry->in(0)->as_If()), "unexpected");
30123013

30133014
} else {

src/hotspot/share/opto/loopnode.hpp

+7-6
Original file line numberDiff line numberDiff line change
@@ -1339,9 +1339,10 @@ class PhaseIdealLoop : public PhaseTransform {
13391339
bool* p_short_scale, int depth);
13401340

13411341
// Create a new if above the uncommon_trap_if_pattern for the predicate to be promoted
1342-
IfTrueNode* create_new_if_for_predicate(ParsePredicateSuccessProj* parse_predicate_proj, Node* new_entry,
1343-
Deoptimization::DeoptReason reason, int opcode,
1344-
bool rewire_uncommon_proj_phi_inputs = false);
1342+
IfTrueNode* create_new_if_for_predicate(
1343+
ParsePredicateSuccessProj* parse_predicate_proj, Node* new_entry, Deoptimization::DeoptReason reason, int opcode,
1344+
bool rewire_uncommon_proj_phi_inputs = false
1345+
NOT_PRODUCT (COMMA AssertionPredicateType assertion_predicate_type = AssertionPredicateType::None));
13451346

13461347
private:
13471348
// Helper functions for create_new_if_for_predicate()
@@ -1382,9 +1383,9 @@ class PhaseIdealLoop : public PhaseTransform {
13821383
IfProjNode* upper_bound_proj, int scale, Node* offset, Node* init, Node* limit,
13831384
jint stride, Node* rng, bool& overflow, Deoptimization::DeoptReason reason);
13841385
void eliminate_hoisted_range_check(IfTrueNode* hoisted_check_proj, IfTrueNode* template_assertion_predicate_proj);
1385-
Node* add_range_check_elimination_assertion_predicate(IdealLoopTree* loop, Node* predicate_proj, int scale_con,
1386-
Node* offset, Node* limit, int stride_con, Node* value,
1387-
bool is_template);
1386+
Node* add_range_check_elimination_assertion_predicate(
1387+
IdealLoopTree* loop, Node* predicate_proj, int scale_con, Node* offset, Node* limit, int stride_con, Node* value,
1388+
bool is_template NOT_PRODUCT(COMMA AssertionPredicateType assertion_predicate_type = AssertionPredicateType::None));
13881389

13891390
// Helper function to collect predicate for eliminating the useless ones
13901391
void eliminate_useless_predicates();

src/hotspot/share/opto/predicates.hpp

+9
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,15 @@
193193
* Main Loop Head
194194
*/
195195

196+
#ifndef PRODUCT
197+
// Assertion Predicates are either emitted to check the initial value of a range check in the first iteration or the last
198+
// value of a range check in the last iteration of a loop.
199+
enum class AssertionPredicateType {
200+
None, // Not an Assertion Predicate
201+
Init_value,
202+
Last_value
203+
};
204+
#endif // NOT PRODUCT
196205

197206
// Class to represent Assertion Predicates with a HaltNode instead of an UCT (i.e. either an Initialized Assertion
198207
// Predicate or a Template Assertion Predicate created after the initial one at Loop Predication).

0 commit comments

Comments
 (0)