Skip to content

Commit 8598306

Browse files
ichtttmhaessig
authored andcommitted
8364766: C2: Improve Value() of DivI and DivL for non-constant inputs
Reviewed-by: mhaessig, epeter, bmaillard
1 parent e678050 commit 8598306

File tree

2 files changed

+627
-104
lines changed

2 files changed

+627
-104
lines changed

src/hotspot/share/opto/divnode.cpp

Lines changed: 122 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,102 @@ Node* unsigned_div_ideal(PhaseGVN* phase, bool can_reshape, Node* div) {
504504
return nullptr;
505505
}
506506

507+
template<typename IntegerType>
508+
static const IntegerType* compute_signed_div_type(const IntegerType* i1, const IntegerType* i2) {
509+
typedef typename IntegerType::NativeType NativeType;
510+
assert(!i2->is_con() || i2->get_con() != 0, "Can't handle zero constant divisor");
511+
int widen = MAX2(i1->_widen, i2->_widen);
512+
513+
// Case A: divisor range spans zero (i2->_lo < 0 < i2->_hi)
514+
// We split into two subproblems to avoid division by 0:
515+
// - negative part: [i2->_lo, −1]
516+
// - positive part: [1, i2->_hi]
517+
// Then we union the results by taking the min of all lower‐bounds and
518+
// the max of all upper‐bounds from the two halves.
519+
if (i2->_lo < 0 && i2->_hi > 0) {
520+
// Handle negative part of the divisor range
521+
const IntegerType* neg_part = compute_signed_div_type(i1, IntegerType::make(i2->_lo, -1, widen));
522+
// Handle positive part of the divisor range
523+
const IntegerType* pos_part = compute_signed_div_type(i1, IntegerType::make(1, i2->_hi, widen));
524+
// Merge results
525+
NativeType new_lo = MIN2(neg_part->_lo, pos_part->_lo);
526+
NativeType new_hi = MAX2(neg_part->_hi, pos_part->_hi);
527+
assert(new_hi >= new_lo, "sanity");
528+
return IntegerType::make(new_lo, new_hi, widen);
529+
}
530+
531+
// Case B: divisor range does NOT span zero.
532+
// Here i2 is entirely negative or entirely positive.
533+
// Then i1/i2 is monotonic in i1 and i2 (when i2 keeps the same sign).
534+
// Therefore the extrema occur at the four “corners”:
535+
// (i1->_lo, i2->_hi), (i1->_lo, i2->_lo), (i1->_hi, i2->_lo), (i1->_hi, i2->_hi).
536+
// We compute all four and take the min and max.
537+
// A special case handles overflow when dividing the most‐negative value by −1.
538+
539+
// adjust i2 bounds to not include zero, as zero always throws
540+
NativeType i2_lo = i2->_lo == 0 ? 1 : i2->_lo;
541+
NativeType i2_hi = i2->_hi == 0 ? -1 : i2->_hi;
542+
constexpr NativeType min_val = std::numeric_limits<NativeType>::min();
543+
static_assert(min_val == min_jint || min_val == min_jlong, "min has to be either min_jint or min_jlong");
544+
constexpr NativeType max_val = std::numeric_limits<NativeType>::max();
545+
static_assert(max_val == max_jint || max_val == max_jlong, "max has to be either max_jint or max_jlong");
546+
547+
// Special overflow case: min_val / (-1) == min_val (cf. JVMS§6.5 idiv/ldiv)
548+
// We need to be careful that we never run min_val / (-1) in C++ code, as this overflow is UB there
549+
if (i1->_lo == min_val && i2_hi == -1) {
550+
NativeType new_lo = min_val;
551+
NativeType new_hi;
552+
// compute new_hi depending on whether divisor or dividend is non-constant.
553+
// i2 is purely in the negative domain here (as i2_hi is -1)
554+
// which means the maximum value this division can yield is either
555+
if (!i1->is_con()) {
556+
// a) non-constant dividend: i1 could be min_val + 1.
557+
// -> i1 / i2 = (min_val + 1) / -1 = max_val is possible.
558+
new_hi = max_val;
559+
assert((min_val + 1) / -1 == new_hi, "new_hi should be max_val");
560+
} else if (i2_lo != i2_hi) {
561+
// b) i1 is constant min_val, i2 is non-constant.
562+
// if i2 = -1 -> i1 / i2 = min_val / -1 = min_val
563+
// if i2 < -1 -> i1 / i2 <= min_val / -2 = (max_val / 2) + 1
564+
new_hi = (max_val / 2) + 1;
565+
assert(min_val / -2 == new_hi, "new_hi should be (max_val / 2) + 1)");
566+
} else {
567+
// c) i1 is constant min_val, i2 is constant -1.
568+
// -> i1 / i2 = min_val / -1 = min_val
569+
new_hi = min_val;
570+
}
571+
572+
#ifdef ASSERT
573+
// validate new_hi for non-constant divisor
574+
if (i2_lo != i2_hi) {
575+
assert(i2_lo != -1, "Special case not possible here, as i2_lo has to be < i2_hi");
576+
NativeType result = i1->_lo / i2_lo;
577+
assert(new_hi >= result, "computed wrong value for new_hi");
578+
}
579+
580+
// validate new_hi for non-constant dividend
581+
if (!i1->is_con()) {
582+
assert(i2_hi > min_val, "Special case not possible here, as i1->_hi has to be > min");
583+
NativeType result1 = i1->_hi / i2_lo;
584+
NativeType result2 = i1->_hi / i2_hi;
585+
assert(new_hi >= result1 && new_hi >= result2, "computed wrong value for new_hi");
586+
}
587+
#endif
588+
589+
return IntegerType::make(new_lo, new_hi, widen);
590+
}
591+
assert((i1->_lo != min_val && i1->_hi != min_val) || (i2_hi != -1 && i2_lo != -1), "should have filtered out before");
592+
593+
// Special case not possible here, calculate all corners normally
594+
NativeType corner1 = i1->_lo / i2_lo;
595+
NativeType corner2 = i1->_lo / i2_hi;
596+
NativeType corner3 = i1->_hi / i2_lo;
597+
NativeType corner4 = i1->_hi / i2_hi;
598+
599+
NativeType new_lo = MIN4(corner1, corner2, corner3, corner4);
600+
NativeType new_hi = MAX4(corner1, corner2, corner3, corner4);
601+
return IntegerType::make(new_lo, new_hi, widen);
602+
}
507603

508604
//=============================================================================
509605
//------------------------------Identity---------------------------------------
@@ -549,65 +645,26 @@ Node *DivINode::Ideal(PhaseGVN *phase, bool can_reshape) {
549645
// prevent hoisting the divide above an unsafe test.
550646
const Type* DivINode::Value(PhaseGVN* phase) const {
551647
// Either input is TOP ==> the result is TOP
552-
const Type *t1 = phase->type( in(1) );
553-
const Type *t2 = phase->type( in(2) );
554-
if( t1 == Type::TOP ) return Type::TOP;
555-
if( t2 == Type::TOP ) return Type::TOP;
648+
const Type* t1 = phase->type(in(1));
649+
const Type* t2 = phase->type(in(2));
650+
if (t1 == Type::TOP || t2 == Type::TOP) {
651+
return Type::TOP;
652+
}
653+
654+
if (t2 == TypeInt::ZERO) {
655+
// this division will always throw an exception
656+
return Type::TOP;
657+
}
556658

557659
// x/x == 1 since we always generate the dynamic divisor check for 0.
558660
if (in(1) == in(2)) {
559661
return TypeInt::ONE;
560662
}
561663

562-
// Either input is BOTTOM ==> the result is the local BOTTOM
563-
const Type *bot = bottom_type();
564-
if( (t1 == bot) || (t2 == bot) ||
565-
(t1 == Type::BOTTOM) || (t2 == Type::BOTTOM) )
566-
return bot;
664+
const TypeInt* i1 = t1->is_int();
665+
const TypeInt* i2 = t2->is_int();
567666

568-
// Divide the two numbers. We approximate.
569-
// If divisor is a constant and not zero
570-
const TypeInt *i1 = t1->is_int();
571-
const TypeInt *i2 = t2->is_int();
572-
int widen = MAX2(i1->_widen, i2->_widen);
573-
574-
if( i2->is_con() && i2->get_con() != 0 ) {
575-
int32_t d = i2->get_con(); // Divisor
576-
jint lo, hi;
577-
if( d >= 0 ) {
578-
lo = i1->_lo/d;
579-
hi = i1->_hi/d;
580-
} else {
581-
if( d == -1 && i1->_lo == min_jint ) {
582-
// 'min_jint/-1' throws arithmetic exception during compilation
583-
lo = min_jint;
584-
// do not support holes, 'hi' must go to either min_jint or max_jint:
585-
// [min_jint, -10]/[-1,-1] ==> [min_jint] UNION [10,max_jint]
586-
hi = i1->_hi == min_jint ? min_jint : max_jint;
587-
} else {
588-
lo = i1->_hi/d;
589-
hi = i1->_lo/d;
590-
}
591-
}
592-
return TypeInt::make(lo, hi, widen);
593-
}
594-
595-
// If the dividend is a constant
596-
if( i1->is_con() ) {
597-
int32_t d = i1->get_con();
598-
if( d < 0 ) {
599-
if( d == min_jint ) {
600-
// (-min_jint) == min_jint == (min_jint / -1)
601-
return TypeInt::make(min_jint, max_jint/2 + 1, widen);
602-
} else {
603-
return TypeInt::make(d, -d, widen);
604-
}
605-
}
606-
return TypeInt::make(-d, d, widen);
607-
}
608-
609-
// Otherwise we give up all hope
610-
return TypeInt::INT;
667+
return compute_signed_div_type<TypeInt>(i1, i2);
611668
}
612669

613670

@@ -655,65 +712,26 @@ Node *DivLNode::Ideal( PhaseGVN *phase, bool can_reshape) {
655712
// prevent hoisting the divide above an unsafe test.
656713
const Type* DivLNode::Value(PhaseGVN* phase) const {
657714
// Either input is TOP ==> the result is TOP
658-
const Type *t1 = phase->type( in(1) );
659-
const Type *t2 = phase->type( in(2) );
660-
if( t1 == Type::TOP ) return Type::TOP;
661-
if( t2 == Type::TOP ) return Type::TOP;
715+
const Type* t1 = phase->type(in(1));
716+
const Type* t2 = phase->type(in(2));
717+
if (t1 == Type::TOP || t2 == Type::TOP) {
718+
return Type::TOP;
719+
}
720+
721+
if (t2 == TypeLong::ZERO) {
722+
// this division will always throw an exception
723+
return Type::TOP;
724+
}
662725

663726
// x/x == 1 since we always generate the dynamic divisor check for 0.
664727
if (in(1) == in(2)) {
665728
return TypeLong::ONE;
666729
}
667730

668-
// Either input is BOTTOM ==> the result is the local BOTTOM
669-
const Type *bot = bottom_type();
670-
if( (t1 == bot) || (t2 == bot) ||
671-
(t1 == Type::BOTTOM) || (t2 == Type::BOTTOM) )
672-
return bot;
673-
674-
// Divide the two numbers. We approximate.
675-
// If divisor is a constant and not zero
676-
const TypeLong *i1 = t1->is_long();
677-
const TypeLong *i2 = t2->is_long();
678-
int widen = MAX2(i1->_widen, i2->_widen);
679-
680-
if( i2->is_con() && i2->get_con() != 0 ) {
681-
jlong d = i2->get_con(); // Divisor
682-
jlong lo, hi;
683-
if( d >= 0 ) {
684-
lo = i1->_lo/d;
685-
hi = i1->_hi/d;
686-
} else {
687-
if( d == CONST64(-1) && i1->_lo == min_jlong ) {
688-
// 'min_jlong/-1' throws arithmetic exception during compilation
689-
lo = min_jlong;
690-
// do not support holes, 'hi' must go to either min_jlong or max_jlong:
691-
// [min_jlong, -10]/[-1,-1] ==> [min_jlong] UNION [10,max_jlong]
692-
hi = i1->_hi == min_jlong ? min_jlong : max_jlong;
693-
} else {
694-
lo = i1->_hi/d;
695-
hi = i1->_lo/d;
696-
}
697-
}
698-
return TypeLong::make(lo, hi, widen);
699-
}
731+
const TypeLong* i1 = t1->is_long();
732+
const TypeLong* i2 = t2->is_long();
700733

701-
// If the dividend is a constant
702-
if( i1->is_con() ) {
703-
jlong d = i1->get_con();
704-
if( d < 0 ) {
705-
if( d == min_jlong ) {
706-
// (-min_jlong) == min_jlong == (min_jlong / -1)
707-
return TypeLong::make(min_jlong, max_jlong/2 + 1, widen);
708-
} else {
709-
return TypeLong::make(d, -d, widen);
710-
}
711-
}
712-
return TypeLong::make(-d, d, widen);
713-
}
714-
715-
// Otherwise we give up all hope
716-
return TypeLong::LONG;
734+
return compute_signed_div_type<TypeLong>(i1, i2);
717735
}
718736

719737

0 commit comments

Comments
 (0)