Skip to content

Commit ef266d7

Browse files
committedMar 7, 2022
8278296: Generalize long range check transformation
Reviewed-by: jrose, thartmann
1 parent f0995ab commit ef266d7

File tree

7 files changed

+644
-234
lines changed

7 files changed

+644
-234
lines changed
 

‎src/hotspot/share/opto/loopPredicate.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -759,7 +759,7 @@ bool IdealLoopTree::is_range_check_if(IfNode *iff, PhaseIdealLoop *phase, BasicT
759759
}
760760
scale = 0;
761761
offset = NULL;
762-
if (!phase->is_scaled_iv_plus_offset(cmp->in(1), iv, &scale, &offset, bt)) {
762+
if (!phase->is_scaled_iv_plus_offset(cmp->in(1), iv, bt, &scale, &offset)) {
763763
return false;
764764
}
765765
return true;

‎src/hotspot/share/opto/loopTransform.cpp

+174-72
Original file line numberDiff line numberDiff line change
@@ -1121,18 +1121,18 @@ bool IdealLoopTree::policy_range_check(PhaseIdealLoop* phase, bool provisional,
11211121
continue; // not RC
11221122
}
11231123
Node *cmp = bol->in(1);
1124-
Node *rc_exp = cmp->in(1);
1125-
Node *limit = cmp->in(2);
11261124

11271125
if (provisional) {
11281126
// Try to pattern match with either cmp inputs, do not check
11291127
// whether one of the inputs is loop independent as it may not
11301128
// have had a chance to be hoisted yet.
1131-
if (!phase->is_scaled_iv_plus_offset(cmp->in(1), trip_counter, NULL, NULL, bt) &&
1132-
!phase->is_scaled_iv_plus_offset(cmp->in(2), trip_counter, NULL, NULL, bt)) {
1129+
if (!phase->is_scaled_iv_plus_offset(cmp->in(1), trip_counter, bt, NULL, NULL) &&
1130+
!phase->is_scaled_iv_plus_offset(cmp->in(2), trip_counter, bt, NULL, NULL)) {
11331131
continue;
11341132
}
11351133
} else {
1134+
Node *rc_exp = cmp->in(1);
1135+
Node *limit = cmp->in(2);
11361136
Node *limit_c = phase->get_ctrl(limit);
11371137
if (limit_c == phase->C->top()) {
11381138
return false; // Found dead test on live IF? No RCE!
@@ -1147,7 +1147,7 @@ bool IdealLoopTree::policy_range_check(PhaseIdealLoop* phase, bool provisional,
11471147
}
11481148
}
11491149

1150-
if (!phase->is_scaled_iv_plus_offset(rc_exp, trip_counter, NULL, NULL, bt)) {
1150+
if (!phase->is_scaled_iv_plus_offset(rc_exp, trip_counter, bt, NULL, NULL)) {
11511151
continue;
11521152
}
11531153
}
@@ -2522,134 +2522,236 @@ void PhaseIdealLoop::add_constraint(jlong stride_con, jlong scale_con, Node* off
25222522
}
25232523
}
25242524

2525+
//----------------------------------is_iv------------------------------------
2526+
// Return true if exp is the value (of type bt) of the given induction var.
2527+
// This grammar of cases is recognized, where X is I|L according to bt:
2528+
// VIV[iv] = iv | (CastXX VIV[iv]) | (ConvI2X VIV[iv])
25252529
bool PhaseIdealLoop::is_iv(Node* exp, Node* iv, BasicType bt) {
2526-
if (exp == iv) {
2530+
exp = exp->uncast();
2531+
if (exp == iv && iv->bottom_type()->isa_integer(bt)) {
25272532
return true;
25282533
}
25292534

2530-
if (bt == T_LONG && iv->bottom_type()->isa_int() && exp->Opcode() == Op_ConvI2L && exp->in(1) == iv) {
2535+
if (bt == T_LONG && iv->bottom_type()->isa_int() && exp->Opcode() == Op_ConvI2L && exp->in(1)->uncast() == iv) {
25312536
return true;
25322537
}
25332538
return false;
25342539
}
25352540

25362541
//------------------------------is_scaled_iv---------------------------------
2537-
// Return true if exp is a constant times an induction var
2538-
bool PhaseIdealLoop::is_scaled_iv(Node* exp, Node* iv, jlong* p_scale, BasicType bt, bool* converted) {
2539-
exp = exp->uncast();
2540-
assert(bt == T_INT || bt == T_LONG, "unexpected int type");
2541-
if (is_iv(exp, iv, bt)) {
2542+
// Return true if exp is a constant times the given induction var (of type bt).
2543+
// The multiplication is either done in full precision (exactly of type bt),
2544+
// or else bt is T_LONG but iv is scaled using 32-bit arithmetic followed by a ConvI2L.
2545+
// This grammar of cases is recognized, where X is I|L according to bt:
2546+
// SIV[iv] = VIV[iv] | (CastXX SIV[iv])
2547+
// | (MulX VIV[iv] ConX) | (MulX ConX VIV[iv])
2548+
// | (LShiftX VIV[iv] ConI)
2549+
// | (ConvI2L SIV[iv]) -- a "short-scale" can occur here; note recursion
2550+
// | (SubX 0 SIV[iv]) -- same as MulX(iv, -scale); note recursion
2551+
// VIV[iv] = [either iv or its value converted; see is_iv() above]
2552+
// On success, the constant scale value is stored back to *p_scale.
2553+
// The value (*p_short_scale) reports if such a ConvI2L conversion was present.
2554+
bool PhaseIdealLoop::is_scaled_iv(Node* exp, Node* iv, BasicType bt, jlong* p_scale, bool* p_short_scale, int depth) {
2555+
BasicType exp_bt = bt;
2556+
exp = exp->uncast(); //strip casts
2557+
assert(exp_bt == T_INT || exp_bt == T_LONG, "unexpected int type");
2558+
if (is_iv(exp, iv, exp_bt)) {
25422559
if (p_scale != NULL) {
25432560
*p_scale = 1;
25442561
}
2562+
if (p_short_scale != NULL) {
2563+
*p_short_scale = false;
2564+
}
25452565
return true;
25462566
}
2547-
if (bt == T_LONG && iv->bottom_type()->isa_int() && exp->Opcode() == Op_ConvI2L) {
2567+
if (exp_bt == T_LONG && iv->bottom_type()->isa_int() && exp->Opcode() == Op_ConvI2L) {
25482568
exp = exp->in(1);
2549-
bt = T_INT;
2550-
if (converted != NULL) {
2551-
*converted = true;
2552-
}
2569+
exp_bt = T_INT;
25532570
}
25542571
int opc = exp->Opcode();
2572+
int which = 0; // this is which subexpression we find the iv in
25552573
// Can't use is_Mul() here as it's true for AndI and AndL
2556-
if (opc == Op_Mul(bt)) {
2557-
if (is_iv(exp->in(1)->uncast(), iv, bt) && exp->in(2)->is_Con()) {
2574+
if (opc == Op_Mul(exp_bt)) {
2575+
if ((is_iv(exp->in(which = 1), iv, exp_bt) && exp->in(2)->is_Con()) ||
2576+
(is_iv(exp->in(which = 2), iv, exp_bt) && exp->in(1)->is_Con())) {
2577+
Node* factor = exp->in(which == 1 ? 2 : 1); // the other argument
2578+
jlong scale = factor->find_integer_as_long(exp_bt, 0);
2579+
if (scale == 0) {
2580+
return false; // might be top
2581+
}
25582582
if (p_scale != NULL) {
2559-
*p_scale = exp->in(2)->get_integer_as_long(bt);
2583+
*p_scale = scale;
2584+
}
2585+
if (p_short_scale != NULL) {
2586+
// (ConvI2L (MulI iv K)) can be 64-bit linear if iv is kept small enough...
2587+
*p_short_scale = (exp_bt != bt && scale != 1);
25602588
}
25612589
return true;
25622590
}
2563-
if (is_iv(exp->in(2)->uncast(), iv, bt) && exp->in(1)->is_Con()) {
2591+
} else if (opc == Op_LShift(exp_bt)) {
2592+
if (is_iv(exp->in(1), iv, exp_bt) && exp->in(2)->is_Con()) {
2593+
jint shift_amount = exp->in(2)->find_int_con(min_jint);
2594+
if (shift_amount == min_jint) {
2595+
return false; // might be top
2596+
}
2597+
jlong scale;
2598+
if (exp_bt == T_INT) {
2599+
scale = java_shift_left((jint)1, (juint)shift_amount);
2600+
} else if (exp_bt == T_LONG) {
2601+
scale = java_shift_left((jlong)1, (julong)shift_amount);
2602+
}
25642603
if (p_scale != NULL) {
2565-
*p_scale = exp->in(1)->get_integer_as_long(bt);
2604+
*p_scale = scale;
2605+
}
2606+
if (p_short_scale != NULL) {
2607+
// (ConvI2L (MulI iv K)) can be 64-bit linear if iv is kept small enough...
2608+
*p_short_scale = (exp_bt != bt && scale != 1);
25662609
}
25672610
return true;
25682611
}
2569-
} else if (opc == Op_LShift(bt)) {
2570-
if (is_iv(exp->in(1)->uncast(), iv, bt) && exp->in(2)->is_Con()) {
2612+
} else if (opc == Op_Sub(exp_bt) &&
2613+
exp->in(1)->find_integer_as_long(exp_bt, -1) == 0) {
2614+
jlong scale = 0;
2615+
if (depth == 0 && is_scaled_iv(exp->in(2), iv, exp_bt, &scale, p_short_scale, depth + 1)) {
2616+
// SubX(0, iv*K) => iv*(-K)
2617+
if (scale == min_signed_integer(exp_bt)) {
2618+
// This should work even if -K overflows, but let's not.
2619+
return false;
2620+
}
2621+
scale = java_multiply(scale, (jlong)-1);
25712622
if (p_scale != NULL) {
2572-
jint shift_amount = exp->in(2)->get_int();
2573-
if (bt == T_INT) {
2574-
*p_scale = java_shift_left((jint)1, (juint)shift_amount);
2575-
} else if (bt == T_LONG) {
2576-
*p_scale = java_shift_left((jlong)1, (julong)shift_amount);
2577-
}
2623+
*p_scale = scale;
2624+
}
2625+
if (p_short_scale != NULL) {
2626+
// (ConvI2L (MulI iv K)) can be 64-bit linear if iv is kept small enough...
2627+
*p_short_scale = *p_short_scale || (exp_bt != bt && scale != 1);
25782628
}
25792629
return true;
25802630
}
25812631
}
2632+
// We could also recognize (iv*K1)*K2, even with overflow, but let's not.
25822633
return false;
25832634
}
25842635

2585-
//-----------------------------is_scaled_iv_plus_offset------------------------------
2586-
// Return true if exp is a simple induction variable expression: k1*iv + (invar + k2)
2587-
bool PhaseIdealLoop::is_scaled_iv_plus_offset(Node* exp, Node* iv, jlong* p_scale, Node** p_offset, BasicType bt, bool* converted, int depth) {
2636+
//-------------------------is_scaled_iv_plus_offset--------------------------
2637+
// Return true if exp is a simple linear transform of the given induction var.
2638+
// The scale must be constant and the addition tree (if any) must be simple.
2639+
// This grammar of cases is recognized, where X is I|L according to bt:
2640+
//
2641+
// OIV[iv] = SIV[iv] | (CastXX OIV[iv])
2642+
// | (AddX SIV[iv] E) | (AddX E SIV[iv])
2643+
// | (SubX SIV[iv] E) | (SubX E SIV[iv])
2644+
// SSIV[iv] = (ConvI2X SIV[iv]) -- a "short scale" might occur here
2645+
// SIV[iv] = [a possibly scaled value of iv; see is_scaled_iv() above]
2646+
//
2647+
// On success, the constant scale value is stored back to *p_scale unless null.
2648+
// Likewise, the addend (perhaps a synthetic AddX node) is stored to *p_offset.
2649+
// Also, (*p_short_scale) reports if a ConvI2L conversion was seen after a MulI,
2650+
// meaning bt is T_LONG but iv was scaled using 32-bit arithmetic.
2651+
// To avoid looping, the match is depth-limited, and so may fail to match the grammar to complex expressions.
2652+
bool PhaseIdealLoop::is_scaled_iv_plus_offset(Node* exp, Node* iv, BasicType bt, jlong* p_scale, Node** p_offset, bool* p_short_scale, int depth) {
25882653
assert(bt == T_INT || bt == T_LONG, "unexpected int type");
2589-
if (is_scaled_iv(exp, iv, p_scale, bt, converted)) {
2654+
jlong scale = 0; // to catch result from is_scaled_iv()
2655+
BasicType exp_bt = bt;
2656+
exp = exp->uncast();
2657+
if (is_scaled_iv(exp, iv, exp_bt, &scale, p_short_scale)) {
2658+
if (p_scale != NULL) {
2659+
*p_scale = scale;
2660+
}
25902661
if (p_offset != NULL) {
2591-
Node *zero = _igvn.integercon(0, bt);
2662+
Node *zero = _igvn.zerocon(bt);
25922663
set_ctrl(zero, C->root());
25932664
*p_offset = zero;
25942665
}
25952666
return true;
25962667
}
2597-
exp = exp->uncast();
2668+
if (exp_bt != bt) {
2669+
// We would now be matching inputs like (ConvI2L exp:(AddI (MulI iv S) E)).
2670+
// It's hard to make 32-bit arithmetic linear if it overflows. Although we do
2671+
// cope with overflowing multiplication by S, it would be even more work to
2672+
// handle overflowing addition of E. So we bail out here on ConvI2L input.
2673+
return false;
2674+
}
25982675
int opc = exp->Opcode();
2599-
if (opc == Op_Add(bt)) {
2600-
if (is_scaled_iv(exp->in(1), iv, p_scale, bt, converted)) {
2676+
int which = 0; // this is which subexpression we find the iv in
2677+
Node* offset = NULL;
2678+
if (opc == Op_Add(exp_bt)) {
2679+
// Check for a scaled IV in (AddX (MulX iv S) E) or (AddX E (MulX iv S)).
2680+
if (is_scaled_iv(exp->in(which = 1), iv, bt, &scale, p_short_scale) ||
2681+
is_scaled_iv(exp->in(which = 2), iv, bt, &scale, p_short_scale)) {
2682+
offset = exp->in(which == 1 ? 2 : 1); // the other argument
2683+
if (p_scale != NULL) {
2684+
*p_scale = scale;
2685+
}
26012686
if (p_offset != NULL) {
2602-
*p_offset = exp->in(2);
2687+
*p_offset = offset;
26032688
}
26042689
return true;
26052690
}
2606-
if (is_scaled_iv(exp->in(2), iv, p_scale, bt, converted)) {
2607-
if (p_offset != NULL) {
2608-
*p_offset = exp->in(1);
2609-
}
2691+
// Check for more addends, like (AddX (AddX (MulX iv S) E1) E2), etc.
2692+
if (is_scaled_iv_plus_extra_offset(exp->in(1), exp->in(2), iv, bt, p_scale, p_offset, p_short_scale, depth) ||
2693+
is_scaled_iv_plus_extra_offset(exp->in(2), exp->in(1), iv, bt, p_scale, p_offset, p_short_scale, depth)) {
26102694
return true;
26112695
}
2612-
if (exp->in(2)->is_Con()) {
2613-
Node* offset2 = NULL;
2614-
if (depth < 2 &&
2615-
is_scaled_iv_plus_offset(exp->in(1), iv, p_scale,
2616-
p_offset != NULL ? &offset2 : NULL, bt, converted, depth+1)) {
2617-
if (p_offset != NULL) {
2618-
Node *ctrl_off2 = get_ctrl(offset2);
2619-
Node* offset = AddNode::make(offset2, exp->in(2), bt);
2620-
register_new_node(offset, ctrl_off2);
2621-
*p_offset = offset;
2696+
} else if (opc == Op_Sub(exp_bt)) {
2697+
if (is_scaled_iv(exp->in(which = 1), iv, bt, &scale, p_short_scale) ||
2698+
is_scaled_iv(exp->in(which = 2), iv, bt, &scale, p_short_scale)) {
2699+
// Match (SubX SIV[iv] E) as if (AddX SIV[iv] (SubX 0 E)), and
2700+
// match (SubX E SIV[iv]) as if (AddX E (SubX 0 SIV[iv])).
2701+
offset = exp->in(which == 1 ? 2 : 1); // the other argument
2702+
if (which == 2) {
2703+
// We can't handle a scale of min_jint (or min_jlong) here as -1 * min_jint = min_jint
2704+
if (scale == min_signed_integer(bt)) {
2705+
return false; // cannot negate the scale of the iv
26222706
}
2623-
return true;
2707+
scale = java_multiply(scale, (jlong)-1);
26242708
}
2625-
}
2626-
} else if (opc == Op_Sub(bt)) {
2627-
if (is_scaled_iv(exp->in(1), iv, p_scale, bt, converted)) {
2628-
if (p_offset != NULL) {
2629-
Node *zero = _igvn.integercon(0, bt);
2630-
set_ctrl(zero, C->root());
2631-
Node *ctrl_off = get_ctrl(exp->in(2));
2632-
Node* offset = SubNode::make(zero, exp->in(2), bt);
2633-
register_new_node(offset, ctrl_off);
2634-
*p_offset = offset;
2709+
if (p_scale != NULL) {
2710+
*p_scale = scale;
26352711
}
2636-
return true;
2637-
}
2638-
if (is_scaled_iv(exp->in(2), iv, p_scale, bt, converted)) {
26392712
if (p_offset != NULL) {
2640-
// We can't handle a scale of min_jint (or min_jlong) here as -1 * min_jint = min_jint
2641-
if (*p_scale == min_signed_integer(bt)) {
2642-
return false;
2713+
if (which == 1) { // must negate the extracted offset
2714+
Node *zero = _igvn.integercon(0, exp_bt);
2715+
set_ctrl(zero, C->root());
2716+
Node *ctrl_off = get_ctrl(offset);
2717+
offset = SubNode::make(zero, offset, exp_bt);
2718+
register_new_node(offset, ctrl_off);
26432719
}
2644-
*p_scale *= -1;
2645-
*p_offset = exp->in(1);
2720+
*p_offset = offset;
26462721
}
26472722
return true;
26482723
}
26492724
}
26502725
return false;
26512726
}
26522727

2728+
// Helper for is_scaled_iv_plus_offset(), not called separately.
2729+
// The caller encountered (AddX exp1 offset3) or (AddX offset3 exp1).
2730+
// Here, exp1 is inspected to see if it is a simple linear transform of iv.
2731+
// If so, the offset3 is combined with any other offset2 from inside exp1.
2732+
bool PhaseIdealLoop::is_scaled_iv_plus_extra_offset(Node* exp1, Node* offset3, Node* iv,
2733+
BasicType bt,
2734+
jlong* p_scale, Node** p_offset,
2735+
bool* p_short_scale, int depth) {
2736+
// By the time we reach here, it is unlikely that exp1 is a simple iv*K.
2737+
// If is a linear iv transform, it is probably an add or subtract.
2738+
// Let's collect the internal offset2 from it.
2739+
Node* offset2 = NULL;
2740+
if (offset3->is_Con() &&
2741+
depth < 2 &&
2742+
is_scaled_iv_plus_offset(exp1, iv, bt, p_scale,
2743+
&offset2, p_short_scale, depth+1)) {
2744+
if (p_offset != NULL) {
2745+
Node* ctrl_off2 = get_ctrl(offset2);
2746+
Node* offset = AddNode::make(offset2, offset3, bt);
2747+
register_new_node(offset, ctrl_off2);
2748+
*p_offset = offset;
2749+
}
2750+
return true;
2751+
}
2752+
return false;
2753+
}
2754+
26532755
// Same as PhaseIdealLoop::duplicate_predicates() but for range checks
26542756
// eliminated by iteration splitting.
26552757
Node* PhaseIdealLoop::add_range_check_predicate(IdealLoopTree* loop, CountedLoopNode* cl,

0 commit comments

Comments
 (0)
Please sign in to comment.