@@ -281,44 +281,115 @@ Node *MulINode::Ideal(PhaseGVN *phase, bool can_reshape) {
281281 return res; // Return final result
282282}
283283
284- // ------------------------------mul_ring---------------------------------------
285- // Compute the product type of two integer ranges into this node.
286- const Type *MulINode::mul_ring (const Type *t0, const Type *t1) const {
287- const TypeInt *r0 = t0->is_int (); // Handy access
288- const TypeInt *r1 = t1->is_int ();
289-
290- // Fetch endpoints of all ranges
291- jint lo0 = r0->_lo ;
292- double a = (double )lo0;
293- jint hi0 = r0->_hi ;
294- double b = (double )hi0;
295- jint lo1 = r1->_lo ;
296- double c = (double )lo1;
297- jint hi1 = r1->_hi ;
298- double d = (double )hi1;
299-
300- // Compute all endpoints & check for overflow
301- int32_t A = java_multiply (lo0, lo1);
302- if ( (double )A != a*c ) return TypeInt::INT; // Overflow?
303- int32_t B = java_multiply (lo0, hi1);
304- if ( (double )B != a*d ) return TypeInt::INT; // Overflow?
305- int32_t C = java_multiply (hi0, lo1);
306- if ( (double )C != b*c ) return TypeInt::INT; // Overflow?
307- int32_t D = java_multiply (hi0, hi1);
308- if ( (double )D != b*d ) return TypeInt::INT; // Overflow?
309-
310- if ( A < B ) { lo0 = A; hi0 = B; } // Sort range endpoints
311- else { lo0 = B; hi0 = A; }
312- if ( C < D ) {
313- if ( C < lo0 ) lo0 = C;
314- if ( D > hi0 ) hi0 = D;
315- } else {
316- if ( D < lo0 ) lo0 = D;
317- if ( C > hi0 ) hi0 = C;
284+ // Classes to perform mul_ring() for MulI/MulLNode.
285+ //
286+ // This class checks if all cross products of the left and right input of a multiplication have the same "overflow value".
287+ // Without overflow/underflow:
288+ // Product is positive? High signed multiplication result: 0
289+ // Product is negative? High signed multiplication result: -1
290+ //
291+ // We normalize these values (see normalize_overflow_value()) such that we get the same "overflow value" by adding 1 if
292+ // the product is negative. This allows us to compare all the cross product "overflow values". If one is different,
293+ // compared to the others, then we know that this multiplication has a different number of over- or underflows compared
294+ // to the others. In this case, we need to use bottom type and cannot guarantee a better type. Otherwise, we can take
295+ // the min und max of all computed cross products as type of this Mul node.
296+ template <typename IntegerType>
297+ class IntegerMulRing {
298+ using NativeType = std::conditional_t <std::is_same<TypeInt, IntegerType>::value, jint, jlong>;
299+
300+ NativeType _lo_left;
301+ NativeType _lo_right;
302+ NativeType _hi_left;
303+ NativeType _hi_right;
304+ NativeType _lo_lo_product;
305+ NativeType _lo_hi_product;
306+ NativeType _hi_lo_product;
307+ NativeType _hi_hi_product;
308+ short _widen_left;
309+ short _widen_right;
310+
311+ static const Type* overflow_type ();
312+ static NativeType multiply_high_signed_overflow_value (NativeType x, NativeType y);
313+
314+ // Pre-compute cross products which are used at several places
315+ void compute_cross_products () {
316+ _lo_lo_product = java_multiply (_lo_left, _lo_right);
317+ _lo_hi_product = java_multiply (_lo_left, _hi_right);
318+ _hi_lo_product = java_multiply (_hi_left, _lo_right);
319+ _hi_hi_product = java_multiply (_hi_left, _hi_right);
320+ }
321+
322+ bool cross_products_not_same_overflow () const {
323+ const NativeType lo_lo_high_product = multiply_high_signed_overflow_value (_lo_left, _lo_right);
324+ const NativeType lo_hi_high_product = multiply_high_signed_overflow_value (_lo_left, _hi_right);
325+ const NativeType hi_lo_high_product = multiply_high_signed_overflow_value (_hi_left, _lo_right);
326+ const NativeType hi_hi_high_product = multiply_high_signed_overflow_value (_hi_left, _hi_right);
327+ return lo_lo_high_product != lo_hi_high_product ||
328+ lo_hi_high_product != hi_lo_high_product ||
329+ hi_lo_high_product != hi_hi_high_product;
330+ }
331+
332+ static NativeType normalize_overflow_value (const NativeType x, const NativeType y, NativeType result) {
333+ return java_multiply (x, y) < 0 ? result + 1 : result;
334+ }
335+
336+ public:
337+ IntegerMulRing (const IntegerType* left, const IntegerType* right) : _lo_left(left->_lo), _lo_right(right->_lo),
338+ _hi_left (left->_hi), _hi_right(right->_hi), _widen_left(left->_widen), _widen_right(right->_widen) {
339+ compute_cross_products ();
340+ }
341+
342+ // Compute the product type by multiplying the two input type ranges. We take the minimum and maximum of all possible
343+ // values (requires 4 multiplications of all possible combinations of the two range boundary values). If any of these
344+ // multiplications overflows/underflows, we need to make sure that they all have the same number of overflows/underflows
345+ // If that is not the case, we return the bottom type to cover all values due to the inconsistent overflows/underflows).
346+ const Type* compute () const {
347+ if (cross_products_not_same_overflow ()) {
348+ return overflow_type ();
349+ }
350+ const NativeType min = MIN4 (_lo_lo_product, _lo_hi_product, _hi_lo_product, _hi_hi_product);
351+ const NativeType max = MAX4 (_lo_lo_product, _lo_hi_product, _hi_lo_product, _hi_hi_product);
352+ return IntegerType::make (min, max, MAX2 (_widen_left, _widen_right));
318353 }
319- return TypeInt::make (lo0, hi0, MAX2 (r0->_widen ,r1->_widen ));
354+ };
355+
356+
357+ template <>
358+ const Type* IntegerMulRing<TypeInt>::overflow_type() {
359+ return TypeInt::INT;
360+ }
361+
362+ template <>
363+ jint IntegerMulRing<TypeInt>::multiply_high_signed_overflow_value(const jint x, const jint y) {
364+ const jlong x_64 = x;
365+ const jlong y_64 = y;
366+ const jlong product = x_64 * y_64;
367+ const jint result = (jint)((uint64_t )product >> 32u );
368+ return normalize_overflow_value (x, y, result);
369+ }
370+
371+ template <>
372+ const Type* IntegerMulRing<TypeLong>::overflow_type() {
373+ return TypeLong::LONG;
320374}
321375
376+ template <>
377+ jlong IntegerMulRing<TypeLong>::multiply_high_signed_overflow_value(const jlong x, const jlong y) {
378+ const jlong result = multiply_high_signed (x, y);
379+ return normalize_overflow_value (x, y, result);
380+ }
381+
382+ // Compute the product type of two integer ranges into this node.
383+ const Type* MulINode::mul_ring (const Type* type_left, const Type* type_right) const {
384+ const IntegerMulRing<TypeInt> integer_mul_ring (type_left->is_int (), type_right->is_int ());
385+ return integer_mul_ring.compute ();
386+ }
387+
388+ // Compute the product type of two long ranges into this node.
389+ const Type* MulLNode::mul_ring (const Type* type_left, const Type* type_right) const {
390+ const IntegerMulRing<TypeLong> integer_mul_ring (type_left->is_long (), type_right->is_long ());
391+ return integer_mul_ring.compute ();
392+ }
322393
323394// =============================================================================
324395// ------------------------------Ideal------------------------------------------
@@ -377,44 +448,6 @@ Node *MulLNode::Ideal(PhaseGVN *phase, bool can_reshape) {
377448 return res; // Return final result
378449}
379450
380- // ------------------------------mul_ring---------------------------------------
381- // Compute the product type of two integer ranges into this node.
382- const Type *MulLNode::mul_ring (const Type *t0, const Type *t1) const {
383- const TypeLong *r0 = t0->is_long (); // Handy access
384- const TypeLong *r1 = t1->is_long ();
385-
386- // Fetch endpoints of all ranges
387- jlong lo0 = r0->_lo ;
388- double a = (double )lo0;
389- jlong hi0 = r0->_hi ;
390- double b = (double )hi0;
391- jlong lo1 = r1->_lo ;
392- double c = (double )lo1;
393- jlong hi1 = r1->_hi ;
394- double d = (double )hi1;
395-
396- // Compute all endpoints & check for overflow
397- jlong A = java_multiply (lo0, lo1);
398- if ( (double )A != a*c ) return TypeLong::LONG; // Overflow?
399- jlong B = java_multiply (lo0, hi1);
400- if ( (double )B != a*d ) return TypeLong::LONG; // Overflow?
401- jlong C = java_multiply (hi0, lo1);
402- if ( (double )C != b*c ) return TypeLong::LONG; // Overflow?
403- jlong D = java_multiply (hi0, hi1);
404- if ( (double )D != b*d ) return TypeLong::LONG; // Overflow?
405-
406- if ( A < B ) { lo0 = A; hi0 = B; } // Sort range endpoints
407- else { lo0 = B; hi0 = A; }
408- if ( C < D ) {
409- if ( C < lo0 ) lo0 = C;
410- if ( D > hi0 ) hi0 = D;
411- } else {
412- if ( D < lo0 ) lo0 = D;
413- if ( C > hi0 ) hi0 = C;
414- }
415- return TypeLong::make (lo0, hi0, MAX2 (r0->_widen ,r1->_widen ));
416- }
417-
418451// =============================================================================
419452// ------------------------------mul_ring---------------------------------------
420453// Compute the product type of two double ranges into this node.
0 commit comments