@@ -1152,7 +1152,6 @@ bool PhaseIdealLoop::loop_predication_impl_helper(IdealLoopTree* loop, IfProjNod
1152
1152
ParsePredicateSuccessProj* parse_predicate_proj, CountedLoopNode* cl,
1153
1153
ConNode* zero, Invariance& invar, Deoptimization::DeoptReason reason) {
1154
1154
// Following are changed to nonnull when a predicate can be hoisted
1155
- IfProjNode* new_predicate_proj = nullptr ;
1156
1155
IfNode* iff = if_success_proj->in (0 )->as_If ();
1157
1156
Node* test = iff->in (1 );
1158
1157
if (!test->is_Bool ()) { // Conv2B, ...
@@ -1163,10 +1162,9 @@ bool PhaseIdealLoop::loop_predication_impl_helper(IdealLoopTree* loop, IfProjNod
1163
1162
if (invar.is_invariant (bol)) {
1164
1163
C->print_method (PHASE_BEFORE_LOOP_PREDICATION_IC, 4 , iff);
1165
1164
// Invariant test
1166
- new_predicate_proj = create_new_if_for_predicate (parse_predicate_proj, nullptr ,
1167
- reason,
1168
- iff->Opcode ());
1169
- Node* ctrl = new_predicate_proj->in (0 )->as_If ()->in (0 );
1165
+ IfProjNode* hoisted_check_predicate_proj = create_new_if_for_predicate (parse_predicate_proj, nullptr , reason,
1166
+ iff->Opcode ());
1167
+ Node* ctrl = hoisted_check_predicate_proj->in (0 )->as_If ()->in (0 );
1170
1168
BoolNode* hoisted_check_predicate_bool = invar.clone (bol, ctrl)->as_Bool ();
1171
1169
1172
1170
// Negate test if necessary (Parse Predicates always have IfTrue as success projection and IfFalse as uncommon trap)
@@ -1177,11 +1175,16 @@ bool PhaseIdealLoop::loop_predication_impl_helper(IdealLoopTree* loop, IfProjNod
1177
1175
register_new_node (hoisted_check_predicate_bool, ctrl);
1178
1176
negated = true ;
1179
1177
}
1180
- IfNode* new_predicate_iff = new_predicate_proj ->in (0 )->as_If ();
1178
+ IfNode* new_predicate_iff = hoisted_check_predicate_proj ->in (0 )->as_If ();
1181
1179
_igvn.hash_delete (new_predicate_iff);
1182
1180
new_predicate_iff->set_req (1 , hoisted_check_predicate_bool);
1183
1181
1184
- C->print_method (PHASE_AFTER_LOOP_PREDICATION_IC, 4 , new_predicate_proj->in (0 ));
1182
+ invar.map_ctrl (if_success_proj, hoisted_check_predicate_proj); // Mark hoisted check as invariant
1183
+
1184
+ // Eliminate the old If in the loop body.
1185
+ dominated_by (hoisted_check_predicate_proj, iff, negated);
1186
+
1187
+ C->print_method (PHASE_AFTER_LOOP_PREDICATION_IC, 4 , hoisted_check_predicate_proj->in (0 ));
1185
1188
1186
1189
#ifndef PRODUCT
1187
1190
if (TraceLoopPredicate) {
@@ -1193,10 +1196,10 @@ bool PhaseIdealLoop::loop_predication_impl_helper(IdealLoopTree* loop, IfProjNod
1193
1196
}
1194
1197
#endif
1195
1198
} else if (cl != nullptr && loop->is_range_check_if (if_success_proj, this , invar DEBUG_ONLY (COMMA parse_predicate_proj))) {
1196
- range_check_predicate = true ;
1197
1199
C->print_method (PHASE_BEFORE_LOOP_PREDICATION_RC, 4 , iff);
1198
1200
// Range check for counted loops
1199
1201
assert (if_success_proj->is_IfTrue (), " trap must be on false projection for a range check" );
1202
+ IfTrueNode* hoisted_check_proj = if_success_proj->as_IfTrue ();
1200
1203
const Node* cmp = bol->in (1 )->as_Cmp ();
1201
1204
Node* idx = cmp->in (1 );
1202
1205
assert (!invar.is_invariant (idx), " index is variant" );
@@ -1265,10 +1268,18 @@ bool PhaseIdealLoop::loop_predication_impl_helper(IdealLoopTree* loop, IfProjNod
1265
1268
// Fall through into rest of the cleanup code which will move any dependent nodes to the skeleton predicates of the
1266
1269
// upper bound test. We always need to create skeleton predicates in order to properly remove dead loops when later
1267
1270
// splitting the predicated loop into (unreachable) sub-loops (i.e. done by unrolling, peeling, pre/main/post etc.).
1268
- new_predicate_proj = add_template_assertion_predicate (iff, loop, if_success_proj, parse_predicate_proj, upper_bound_proj, scale,
1269
- offset, init, limit, stride, rng, overflow, reason);
1271
+ IfTrueNode* template_assertion_predicate_proj =
1272
+ add_template_assertion_predicate (iff, loop, hoisted_check_proj, parse_predicate_proj, upper_bound_proj, scale,
1273
+ offset, init, limit, stride, rng, overflow, reason);
1274
+
1275
+ // Eliminate the old range check in the loop body.
1276
+ // When a range check is eliminated, data dependent nodes (Load and range check CastII nodes) are now dependent on 2
1277
+ // Hoisted Check Predicates (one for the start of the loop, one for the end) but we can only keep track of one control
1278
+ // dependency: pin the data dependent nodes.
1279
+ eliminate_hoisted_range_check (hoisted_check_proj, template_assertion_predicate_proj);
1280
+ invar.map_ctrl (hoisted_check_proj, template_assertion_predicate_proj); // Mark hoisted check as invariant
1270
1281
1271
- C->print_method (PHASE_AFTER_LOOP_PREDICATION_RC, 4 , new_predicate_proj ->in (0 ));
1282
+ C->print_method (PHASE_AFTER_LOOP_PREDICATION_RC, 4 , template_assertion_predicate_proj ->in (0 ));
1272
1283
1273
1284
#ifndef PRODUCT
1274
1285
if (TraceLoopOpts && !TraceLoopPredicate) {
@@ -1281,24 +1292,21 @@ bool PhaseIdealLoop::loop_predication_impl_helper(IdealLoopTree* loop, IfProjNod
1281
1292
// with uncommon trap.
1282
1293
return false ;
1283
1294
}
1284
- assert (new_predicate_proj != nullptr , " sanity" );
1285
- // Success - attach condition (new_predicate_bol) to predicate if
1286
- invar.map_ctrl (if_success_proj, new_predicate_proj); // so that invariance test can be appropriate
1287
-
1288
- // Eliminate the old If in the loop body
1289
- // If a range check is eliminated, data dependent nodes (Load and range check CastII nodes) are now dependent on 2
1290
- // Hoisted Check Predicates (one for the start of the loop, one for the end) but we can only keep track of one control
1291
- // dependency: pin the data dependent nodes.
1292
- dominated_by (new_predicate_proj, iff, if_success_proj->_con != new_predicate_proj->_con , range_check_predicate);
1293
1295
1294
1296
C->set_major_progress ();
1295
1297
return true ;
1296
1298
}
1297
1299
1300
+ void PhaseIdealLoop::eliminate_hoisted_range_check (IfTrueNode* hoisted_check_proj,
1301
+ IfTrueNode* template_assertion_predicate_proj) {
1302
+ _igvn.replace_input_of (hoisted_check_proj->in (0 ), 1 , _igvn.intcon (1 ));
1303
+ rewire_safe_outputs_to_dominator (hoisted_check_proj, template_assertion_predicate_proj, true );
1304
+ }
1305
+
1298
1306
// Each newly created Hoisted Check Predicate is accompanied by two Template Assertion Predicates. Later, we initialize
1299
1307
// them by making a copy of them when splitting a loop into sub loops. The Assertion Predicates ensure that dead sub
1300
1308
// loops are removed properly.
1301
- IfProjNode * PhaseIdealLoop::add_template_assertion_predicate (IfNode* iff, IdealLoopTree* loop, IfProjNode* if_proj,
1309
+ IfTrueNode * PhaseIdealLoop::add_template_assertion_predicate (IfNode* iff, IdealLoopTree* loop, IfProjNode* if_proj,
1302
1310
ParsePredicateSuccessProj* parse_predicate_proj,
1303
1311
IfProjNode* upper_bound_proj, const int scale, Node* offset,
1304
1312
Node* init, Node* limit, const jint stride,
@@ -1312,7 +1320,7 @@ IfProjNode* PhaseIdealLoop::add_template_assertion_predicate(IfNode* iff, IdealL
1312
1320
Node* opaque_bol = new Opaque4Node (C, bol, _igvn.intcon (1 )); // This will go away once loop opts are over
1313
1321
C->add_template_assertion_predicate_opaq (opaque_bol);
1314
1322
register_new_node (opaque_bol, upper_bound_proj);
1315
- IfProjNode * new_proj = create_new_if_for_predicate (parse_predicate_proj, nullptr , reason, overflow ? Op_If : iff->Opcode ());
1323
+ IfTrueNode * new_proj = create_new_if_for_predicate (parse_predicate_proj, nullptr , reason, overflow ? Op_If : iff->Opcode ());
1316
1324
_igvn.replace_input_of (new_proj->in (0 ), 1 , opaque_bol);
1317
1325
assert (opaque_init->outcnt () > 0 , " should be used" );
1318
1326
0 commit comments