@@ -594,36 +594,80 @@ const Type* MulHiValue(const Type *t1, const Type *t2, const Type *bot) {
594594 return TypeLong::LONG;
595595}
596596
597+ template <typename IntegerType>
598+ static const IntegerType* and_value (const IntegerType* r0, const IntegerType* r1) {
599+ typedef typename IntegerType::NativeType NativeType;
600+ static_assert (std::is_signed<NativeType>::value, " Native type of IntegerType must be signed!" );
601+
602+ int widen = MAX2 (r0->_widen , r1->_widen );
603+
604+ // If both types are constants, we can calculate a constant result.
605+ if (r0->is_con () && r1->is_con ()) {
606+ return IntegerType::make (r0->get_con () & r1->get_con ());
607+ }
608+
609+ // If both ranges are positive, the result will range from 0 up to the hi value of the smaller range. The minimum
610+ // of the two constrains the upper bound because any higher value in the other range will see all zeroes, so it will be masked out.
611+ if (r0->_lo >= 0 && r1->_lo >= 0 ) {
612+ return IntegerType::make (0 , MIN2 (r0->_hi , r1->_hi ), widen);
613+ }
614+
615+ // If only one range is positive, the result will range from 0 up to that range's maximum value.
616+ // For the operation 'x & C' where C is a positive constant, the result will be in the range [0..C]. With that observation,
617+ // we can say that for any integer c such that 0 <= c <= C will also be in the range [0..C]. Therefore, 'x & [c..C]'
618+ // where c >= 0 will be in the range [0..C].
619+ if (r0->_lo >= 0 ) {
620+ return IntegerType::make (0 , r0->_hi , widen);
621+ }
622+
623+ if (r1->_lo >= 0 ) {
624+ return IntegerType::make (0 , r1->_hi , widen);
625+ }
626+
627+ // At this point, all positive ranges will have already been handled, so the only remaining cases will be negative ranges
628+ // and constants.
629+
630+ assert (r0->_lo < 0 && r1->_lo < 0 , " positive ranges should already be handled!" );
631+
632+ // As two's complement means that both numbers will start with leading 1s, the lower bound of both ranges will contain
633+ // the common leading 1s of both minimum values. In order to count them with count_leading_zeros, the bits are inverted.
634+ NativeType sel_val = ~MIN2 (r0->_lo, r1->_lo);
635+
636+ NativeType min;
637+ if (sel_val == 0 ) {
638+ // Since count_leading_zeros is undefined at 0, we short-circuit the condition where both ranges have a minimum of -1.
639+ min = -1 ;
640+ } else {
641+ // To get the number of bits to shift, we count the leading 0-bits and then subtract one, as the sign bit is already set.
642+ int shift_bits = count_leading_zeros (sel_val) - 1 ;
643+ min = std::numeric_limits<NativeType>::min () >> shift_bits;
644+ }
645+
646+ NativeType max;
647+ if (r0->_hi < 0 && r1->_hi < 0 ) {
648+ // If both ranges are negative, then the same optimization as both positive ranges will apply, and the smaller hi
649+ // value will mask off any bits set by higher values.
650+ max = MIN2 (r0->_hi , r1->_hi );
651+ } else {
652+ // In the case of ranges that cross zero, negative values can cause the higher order bits to be set, so the maximum
653+ // positive value can be as high as the larger hi value.
654+ max = MAX2 (r0->_hi , r1->_hi );
655+ }
656+
657+ return IntegerType::make (min, max, widen);
658+ }
659+
597660// =============================================================================
598661// ------------------------------mul_ring---------------------------------------
599662// Supplied function returns the product of the inputs IN THE CURRENT RING.
600663// For the logical operations the ring's MUL is really a logical AND function.
601664// This also type-checks the inputs for sanity. Guaranteed never to
602665// be passed a TOP or BOTTOM type, these are filtered out by pre-check.
603666const Type *AndINode::mul_ring ( const Type *t0, const Type *t1 ) const {
604- const TypeInt *r0 = t0->is_int (); // Handy access
605- const TypeInt *r1 = t1->is_int ();
606- int widen = MAX2 (r0->_widen ,r1->_widen );
607-
608- // If either input is a constant, might be able to trim cases
609- if ( !r0->is_con () && !r1->is_con () )
610- return TypeInt::INT; // No constants to be had
611-
612- // Both constants? Return bits
613- if ( r0->is_con () && r1->is_con () )
614- return TypeInt::make ( r0->get_con () & r1->get_con () );
615-
616- if ( r0->is_con () && r0->get_con () > 0 )
617- return TypeInt::make (0 , r0->get_con (), widen);
667+ const TypeInt* r0 = t0->is_int ();
668+ const TypeInt* r1 = t1->is_int ();
618669
619- if ( r1->is_con () && r1->get_con () > 0 )
620- return TypeInt::make (0 , r1->get_con (), widen);
621-
622- if ( r0 == TypeInt::BOOL || r1 == TypeInt::BOOL ) {
623- return TypeInt::BOOL;
624- }
625-
626- return TypeInt::INT; // No constants to be had
670+ return and_value<TypeInt>(r0, r1);
627671}
628672
629673const Type* AndINode::Value (PhaseGVN* phase) const {
@@ -751,25 +795,10 @@ Node *AndINode::Ideal(PhaseGVN *phase, bool can_reshape) {
751795// This also type-checks the inputs for sanity. Guaranteed never to
752796// be passed a TOP or BOTTOM type, these are filtered out by pre-check.
753797const Type *AndLNode::mul_ring ( const Type *t0, const Type *t1 ) const {
754- const TypeLong *r0 = t0->is_long (); // Handy access
755- const TypeLong *r1 = t1->is_long ();
756- int widen = MAX2 (r0->_widen ,r1->_widen );
757-
758- // If either input is a constant, might be able to trim cases
759- if ( !r0->is_con () && !r1->is_con () )
760- return TypeLong::LONG; // No constants to be had
761-
762- // Both constants? Return bits
763- if ( r0->is_con () && r1->is_con () )
764- return TypeLong::make ( r0->get_con () & r1->get_con () );
765-
766- if ( r0->is_con () && r0->get_con () > 0 )
767- return TypeLong::make (CONST64 (0 ), r0->get_con (), widen);
768-
769- if ( r1->is_con () && r1->get_con () > 0 )
770- return TypeLong::make (CONST64 (0 ), r1->get_con (), widen);
798+ const TypeLong* r0 = t0->is_long ();
799+ const TypeLong* r1 = t1->is_long ();
771800
772- return TypeLong::LONG; // No constants to be had
801+ return and_value< TypeLong>(r0, r1);
773802}
774803
775804const Type* AndLNode::Value (PhaseGVN* phase) const {
0 commit comments