@@ -610,28 +610,82 @@ static KnownBits computeForSatAddSub(bool Add, bool Signed,
610610 const KnownBits &RHS) {
611611 // We don't see NSW even for sadd/ssub as we want to check if the result has
612612 // signed overflow.
613- KnownBits Res =
614- KnownBits::computeForAddSub (Add, /* NSW=*/ false , /* NUW=*/ false , LHS, RHS);
615- unsigned BitWidth = Res.getBitWidth ();
616- auto SignBitKnown = [&](const KnownBits &K) {
617- return K.Zero [BitWidth - 1 ] || K.One [BitWidth - 1 ];
618- };
619- std::optional<bool > Overflow;
613+ unsigned BitWidth = LHS.getBitWidth ();
620614
615+ std::optional<bool > Overflow;
616+ // Even if we can't entirely rule out overflow, we may be able to rule out
617+ // overflow in one direction. This allows us to potentially keep some of the
618+ // add/sub bits. I.e if we can't overflow in the positive direction we won't
619+ // clamp to INT_MAX so we can keep low 0s from the add/sub result.
620+ bool MayNegClamp = true ;
621+ bool MayPosClamp = true ;
621622 if (Signed) {
622- // If we can actually detect overflow do so. Otherwise leave Overflow as
623- // nullopt (we assume it may have happened).
624- if (SignBitKnown (LHS) && SignBitKnown (RHS) && SignBitKnown (Res)) {
623+ // Easy cases we can rule out any overflow.
624+ if (Add && ((LHS.isNegative () && RHS.isNonNegative ()) ||
625+ (LHS.isNonNegative () && RHS.isNegative ())))
626+ Overflow = false ;
627+ else if (!Add && (((LHS.isNegative () && RHS.isNegative ()) ||
628+ (LHS.isNonNegative () && RHS.isNonNegative ()))))
629+ Overflow = false ;
630+ else {
631+ // Check if we may overflow. If we can't rule out overflow then check if
632+ // we can rule out a direction at least.
633+ KnownBits UnsignedLHS = LHS;
634+ KnownBits UnsignedRHS = RHS;
635+ // Get version of LHS/RHS with clearer signbit. This allows us to detect
636+ // how the addition/subtraction might overflow into the signbit. Then
637+ // using the actual known signbits of LHS/RHS, we can figure out which
638+ // overflows are/aren't possible.
639+ UnsignedLHS.One .clearSignBit ();
640+ UnsignedLHS.Zero .setSignBit ();
641+ UnsignedRHS.One .clearSignBit ();
642+ UnsignedRHS.Zero .setSignBit ();
643+ KnownBits Res =
644+ KnownBits::computeForAddSub (Add, /* NSW=*/ false ,
645+ /* NUW=*/ false , UnsignedLHS, UnsignedRHS);
625646 if (Add) {
626- // sadd.sat
627- Overflow = (LHS.isNonNegative () == RHS.isNonNegative () &&
628- Res.isNonNegative () != LHS.isNonNegative ());
647+ if (Res.isNegative ()) {
648+ // Only overflow scenario is Pos + Pos.
649+ MayNegClamp = false ;
650+ // Pos + Pos will overflow with extra signbit.
651+ if (LHS.isNonNegative () && RHS.isNonNegative ())
652+ Overflow = true ;
653+ } else if (Res.isNonNegative ()) {
654+ // Only overflow scenario is Neg + Neg
655+ MayPosClamp = false ;
656+ // Neg + Neg will overflow without extra signbit.
657+ if (LHS.isNegative () && RHS.isNegative ())
658+ Overflow = true ;
659+ }
660+ // We will never clamp to the opposite sign of N-bit result.
661+ if (LHS.isNegative () || RHS.isNegative ())
662+ MayPosClamp = false ;
663+ if (LHS.isNonNegative () || RHS.isNonNegative ())
664+ MayNegClamp = false ;
629665 } else {
630- // ssub.sat
631- Overflow = (LHS.isNonNegative () != RHS.isNonNegative () &&
632- Res.isNonNegative () != LHS.isNonNegative ());
666+ if (Res.isNegative ()) {
667+ // Only overflow scenario is Neg - Pos.
668+ MayPosClamp = false ;
669+ // Neg - Pos will overflow with extra signbit.
670+ if (LHS.isNegative () && RHS.isNonNegative ())
671+ Overflow = true ;
672+ } else if (Res.isNonNegative ()) {
673+ // Only overflow scenario is Pos - Neg.
674+ MayNegClamp = false ;
675+ // Pos - Neg will overflow without extra signbit.
676+ if (LHS.isNonNegative () && RHS.isNegative ())
677+ Overflow = true ;
678+ }
679+ // We will never clamp to the opposite sign of N-bit result.
680+ if (LHS.isNegative () || RHS.isNonNegative ())
681+ MayPosClamp = false ;
682+ if (LHS.isNonNegative () || RHS.isNegative ())
683+ MayNegClamp = false ;
633684 }
634685 }
686+ // If we have ruled out all clamping, we will never overflow.
687+ if (!MayNegClamp && !MayPosClamp)
688+ Overflow = false ;
635689 } else if (Add) {
636690 // uadd.sat
637691 bool Of;
@@ -656,52 +710,8 @@ static KnownBits computeForSatAddSub(bool Add, bool Signed,
656710 }
657711 }
658712
659- if (Signed) {
660- if (Add) {
661- if (LHS.isNonNegative () && RHS.isNonNegative ()) {
662- // Pos + Pos -> Pos
663- Res.One .clearSignBit ();
664- Res.Zero .setSignBit ();
665- }
666- if (LHS.isNegative () && RHS.isNegative ()) {
667- // Neg + Neg -> Neg
668- Res.One .setSignBit ();
669- Res.Zero .clearSignBit ();
670- }
671- } else {
672- if (LHS.isNegative () && RHS.isNonNegative ()) {
673- // Neg - Pos -> Neg
674- Res.One .setSignBit ();
675- Res.Zero .clearSignBit ();
676- } else if (LHS.isNonNegative () && RHS.isNegative ()) {
677- // Pos - Neg -> Pos
678- Res.One .clearSignBit ();
679- Res.Zero .setSignBit ();
680- }
681- }
682- } else {
683- // Add: Leading ones of either operand are preserved.
684- // Sub: Leading zeros of LHS and leading ones of RHS are preserved
685- // as leading zeros in the result.
686- unsigned LeadingKnown;
687- if (Add)
688- LeadingKnown =
689- std::max (LHS.countMinLeadingOnes (), RHS.countMinLeadingOnes ());
690- else
691- LeadingKnown =
692- std::max (LHS.countMinLeadingZeros (), RHS.countMinLeadingOnes ());
693-
694- // We select between the operation result and all-ones/zero
695- // respectively, so we can preserve known ones/zeros.
696- APInt Mask = APInt::getHighBitsSet (BitWidth, LeadingKnown);
697- if (Add) {
698- Res.One |= Mask;
699- Res.Zero &= ~Mask;
700- } else {
701- Res.Zero |= Mask;
702- Res.One &= ~Mask;
703- }
704- }
713+ KnownBits Res = KnownBits::computeForAddSub (Add, /* NSW=*/ Signed,
714+ /* NUW=*/ !Signed, LHS, RHS);
705715
706716 if (Overflow) {
707717 // We know whether or not we overflowed.
@@ -714,7 +724,7 @@ static KnownBits computeForSatAddSub(bool Add, bool Signed,
714724 APInt C;
715725 if (Signed) {
716726 // sadd.sat / ssub.sat
717- assert (SignBitKnown ( LHS) &&
727+ assert (! LHS. isSignUnknown ( ) &&
718728 " We somehow know overflow without knowing input sign" );
719729 C = LHS.isNegative () ? APInt::getSignedMinValue (BitWidth)
720730 : APInt::getSignedMaxValue (BitWidth);
@@ -735,8 +745,10 @@ static KnownBits computeForSatAddSub(bool Add, bool Signed,
735745 if (Signed) {
736746 // sadd.sat/ssub.sat
737747 // We can keep our information about the sign bits.
738- Res.Zero .clearLowBits (BitWidth - 1 );
739- Res.One .clearLowBits (BitWidth - 1 );
748+ if (MayPosClamp)
749+ Res.Zero .clearLowBits (BitWidth - 1 );
750+ if (MayNegClamp)
751+ Res.One .clearLowBits (BitWidth - 1 );
740752 } else if (Add) {
741753 // uadd.sat
742754 // We need to clear all the known zeros as we can only use the leading ones.
0 commit comments