@@ -2066,14 +2066,18 @@ static Instruction *simplifyIRemMulShl(BinaryOperator &I,
20662066 bool ShiftByX = false ;
20672067
20682068 // 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 {
20702071 const APInt *Tmp = nullptr ;
20712072 if ((!V && match (Op, m_Mul (m_Value (V), m_APInt (Tmp)))) ||
20722073 (V && match (Op, m_Mul (m_Specific (V), m_APInt (Tmp)))))
20732074 C = *Tmp;
20742075 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))))) {
20762077 C = APInt (Tmp->getBitWidth (), 1 ) << *Tmp;
2078+ // We cannot preserve NSW when shifting by BW - 1.
2079+ PreserveNSW = Tmp->ult (Tmp->getBitWidth () - 1 );
2080+ }
20772081 if (Tmp != nullptr )
20782082 return true ;
20792083
@@ -2095,7 +2099,9 @@ static Instruction *simplifyIRemMulShl(BinaryOperator &I,
20952099 return false ;
20962100 };
20972101
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)) {
20992105 // pass
21002106 } else if (MatchShiftCX (Op0, Y, X) && MatchShiftCX (Op1, Z, X)) {
21012107 ShiftByX = true ;
@@ -2108,7 +2114,7 @@ static Instruction *simplifyIRemMulShl(BinaryOperator &I,
21082114 OverflowingBinaryOperator *BO0 = cast<OverflowingBinaryOperator>(Op0);
21092115 // TODO: We may be able to deduce more about nsw/nuw of BO0/BO1 based on Y >=
21102116 // Z or Z >= Y.
2111- bool BO0HasNSW = BO0->hasNoSignedWrap ();
2117+ bool BO0HasNSW = Op0PreserveNSW && BO0->hasNoSignedWrap ();
21122118 bool BO0HasNUW = BO0->hasNoUnsignedWrap ();
21132119 bool BO0NoWrap = IsSRem ? BO0HasNSW : BO0HasNUW;
21142120
@@ -2131,7 +2137,7 @@ static Instruction *simplifyIRemMulShl(BinaryOperator &I,
21312137 };
21322138
21332139 OverflowingBinaryOperator *BO1 = cast<OverflowingBinaryOperator>(Op1);
2134- bool BO1HasNSW = BO1->hasNoSignedWrap ();
2140+ bool BO1HasNSW = Op1PreserveNSW && BO1->hasNoSignedWrap ();
21352141 bool BO1HasNUW = BO1->hasNoUnsignedWrap ();
21362142 bool BO1NoWrap = IsSRem ? BO1HasNSW : BO1HasNUW;
21372143 // (rem (mul X, Y), (mul nuw/nsw X, Z))
0 commit comments