@@ -2066,14 +2066,18 @@ static Instruction *simplifyIRemMulShl(BinaryOperator &I,
2066
2066
bool ShiftByX = false ;
2067
2067
2068
2068
// If V is not nullptr, it will be matched using m_Specific.
2069
- auto MatchShiftOrMulXC = [](Value *Op, Value *&V, APInt &C) -> bool {
2069
+ auto MatchShiftOrMulXC = [](Value *Op, Value *&V, APInt &C,
2070
+ bool &PreserveNSW) -> bool {
2070
2071
const APInt *Tmp = nullptr ;
2071
2072
if ((!V && match (Op, m_Mul (m_Value (V), m_APInt (Tmp)))) ||
2072
2073
(V && match (Op, m_Mul (m_Specific (V), m_APInt (Tmp)))))
2073
2074
C = *Tmp;
2074
2075
else if ((!V && match (Op, m_Shl (m_Value (V), m_APInt (Tmp)))) ||
2075
- (V && match (Op, m_Shl (m_Specific (V), m_APInt (Tmp)))))
2076
+ (V && match (Op, m_Shl (m_Specific (V), m_APInt (Tmp))))) {
2076
2077
C = APInt (Tmp->getBitWidth (), 1 ) << *Tmp;
2078
+ // We cannot preserve NSW when shifting by BW - 1.
2079
+ PreserveNSW = Tmp->ult (Tmp->getBitWidth () - 1 );
2080
+ }
2077
2081
if (Tmp != nullptr )
2078
2082
return true ;
2079
2083
@@ -2095,7 +2099,9 @@ static Instruction *simplifyIRemMulShl(BinaryOperator &I,
2095
2099
return false ;
2096
2100
};
2097
2101
2098
- if (MatchShiftOrMulXC (Op0, X, Y) && MatchShiftOrMulXC (Op1, X, Z)) {
2102
+ bool Op0PreserveNSW = true , Op1PreserveNSW = true ;
2103
+ if (MatchShiftOrMulXC (Op0, X, Y, Op0PreserveNSW) &&
2104
+ MatchShiftOrMulXC (Op1, X, Z, Op1PreserveNSW)) {
2099
2105
// pass
2100
2106
} else if (MatchShiftCX (Op0, Y, X) && MatchShiftCX (Op1, Z, X)) {
2101
2107
ShiftByX = true ;
@@ -2108,7 +2114,7 @@ static Instruction *simplifyIRemMulShl(BinaryOperator &I,
2108
2114
OverflowingBinaryOperator *BO0 = cast<OverflowingBinaryOperator>(Op0);
2109
2115
// TODO: We may be able to deduce more about nsw/nuw of BO0/BO1 based on Y >=
2110
2116
// Z or Z >= Y.
2111
- bool BO0HasNSW = BO0->hasNoSignedWrap ();
2117
+ bool BO0HasNSW = Op0PreserveNSW && BO0->hasNoSignedWrap ();
2112
2118
bool BO0HasNUW = BO0->hasNoUnsignedWrap ();
2113
2119
bool BO0NoWrap = IsSRem ? BO0HasNSW : BO0HasNUW;
2114
2120
@@ -2131,7 +2137,7 @@ static Instruction *simplifyIRemMulShl(BinaryOperator &I,
2131
2137
};
2132
2138
2133
2139
OverflowingBinaryOperator *BO1 = cast<OverflowingBinaryOperator>(Op1);
2134
- bool BO1HasNSW = BO1->hasNoSignedWrap ();
2140
+ bool BO1HasNSW = Op1PreserveNSW && BO1->hasNoSignedWrap ();
2135
2141
bool BO1HasNUW = BO1->hasNoUnsignedWrap ();
2136
2142
bool BO1NoWrap = IsSRem ? BO1HasNSW : BO1HasNUW;
2137
2143
// (rem (mul X, Y), (mul nuw/nsw X, Z))
0 commit comments