[llvm] fe97f95 - [InstCombine] propagate "exact" through folds of div

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 12 06:26:45 PDT 2022


Author: Sanjay Patel
Date: 2022-10-12T09:25:05-04:00
New Revision: fe97f95036674692dd85939c867c4312b73df88f

URL: https://github.com/llvm/llvm-project/commit/fe97f95036674692dd85939c867c4312b73df88f
DIFF: https://github.com/llvm/llvm-project/commit/fe97f95036674692dd85939c867c4312b73df88f.diff

LOG: [InstCombine] propagate "exact" through folds of div

These folds were added recently with:
6b869be8100d
8da2fa856f1b
...but they didn't account for the "exact" attribute,
and that can be safely propagated:
https://alive2.llvm.org/ce/z/F_WhnR
https://alive2.llvm.org/ce/z/ft9Cgr

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
    llvm/test/Transforms/InstCombine/div-shift.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index c7a7be1886d9..b861406246ec 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -827,28 +827,34 @@ static Instruction *foldIDivShl(BinaryOperator &I,
   Type *Ty = I.getType();
 
   // With appropriate no-wrap constraints, remove a common factor in the
-  // dividend and divisor that is disguised as a left-shift.
+  // dividend and divisor that is disguised as a left-shifted value.
   Value *X, *Y, *Z;
-  if (match(Op1, m_Shl(m_Value(X), m_Value(Z))) &&
-      match(Op0, m_c_Mul(m_Specific(X), m_Value(Y)))) {
-    // Both operands must have the matching no-wrap for this kind of division.
-    auto *Mul = cast<OverflowingBinaryOperator>(Op0);
-    auto *Shl = cast<OverflowingBinaryOperator>(Op1);
-    bool HasNUW = Mul->hasNoUnsignedWrap() && Shl->hasNoUnsignedWrap();
-    bool HasNSW = Mul->hasNoSignedWrap() && Shl->hasNoSignedWrap();
-
-    // (X * Y) u/ (X << Z) --> Y u>> Z
-    if (!IsSigned && HasNUW)
-      return BinaryOperator::CreateLShr(Y, Z);
-
-    // (X * Y) s/ (X << Z) --> Y s/ (1 << Z)
-    if (IsSigned && HasNSW && (Op0->hasOneUse() || Op1->hasOneUse())) {
-      Value *Shl = Builder.CreateShl(ConstantInt::get(Ty, 1), Z);
-      return BinaryOperator::CreateSDiv(Y, Shl);
-    }
+  if (!match(Op1, m_Shl(m_Value(X), m_Value(Z))) ||
+      !match(Op0, m_c_Mul(m_Specific(X), m_Value(Y))))
+    return nullptr;
+
+  // Both operands must have the matching no-wrap for this kind of division.
+  Instruction *Ret = nullptr;
+  auto *Mul = cast<OverflowingBinaryOperator>(Op0);
+  auto *Shl = cast<OverflowingBinaryOperator>(Op1);
+  bool HasNUW = Mul->hasNoUnsignedWrap() && Shl->hasNoUnsignedWrap();
+  bool HasNSW = Mul->hasNoSignedWrap() && Shl->hasNoSignedWrap();
+
+  // (X * Y) u/ (X << Z) --> Y u>> Z
+  if (!IsSigned && HasNUW)
+    Ret = BinaryOperator::CreateLShr(Y, Z);
+
+  // (X * Y) s/ (X << Z) --> Y s/ (1 << Z)
+  if (IsSigned && HasNSW && (Op0->hasOneUse() || Op1->hasOneUse())) {
+    Value *Shl = Builder.CreateShl(ConstantInt::get(Ty, 1), Z);
+    Ret = BinaryOperator::CreateSDiv(Y, Shl);
   }
 
-  return nullptr;
+  if (!Ret)
+    return nullptr;
+
+  Ret->setIsExact(I.isExact());
+  return Ret;
 }
 
 /// This function implements the transforms common to both integer division

diff  --git a/llvm/test/Transforms/InstCombine/div-shift.ll b/llvm/test/Transforms/InstCombine/div-shift.ll
index d357ec742894..bac752a750db 100644
--- a/llvm/test/Transforms/InstCombine/div-shift.ll
+++ b/llvm/test/Transforms/InstCombine/div-shift.ll
@@ -314,7 +314,7 @@ define i5 @sdiv_mul_shl_nsw(i5 %x, i5 %y, i5 %z) {
 define i5 @sdiv_mul_shl_nsw_exact_commute1(i5 %x, i5 %y, i5 %z) {
 ; CHECK-LABEL: @sdiv_mul_shl_nsw_exact_commute1(
 ; CHECK-NEXT:    [[TMP1:%.*]] = shl nuw i5 1, [[Z:%.*]]
-; CHECK-NEXT:    [[D:%.*]] = sdiv i5 [[Y:%.*]], [[TMP1]]
+; CHECK-NEXT:    [[D:%.*]] = sdiv exact i5 [[Y:%.*]], [[TMP1]]
 ; CHECK-NEXT:    ret i5 [[D]]
 ;
   %m1 = mul nsw i5 %y, %x
@@ -453,7 +453,7 @@ define i5 @udiv_mul_shl_nuw(i5 %x, i5 %y, i5 %z) {
 
 define i5 @udiv_mul_shl_nuw_exact_commute1(i5 %x, i5 %y, i5 %z) {
 ; CHECK-LABEL: @udiv_mul_shl_nuw_exact_commute1(
-; CHECK-NEXT:    [[D:%.*]] = lshr i5 [[Y:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[D:%.*]] = lshr exact i5 [[Y:%.*]], [[Z:%.*]]
 ; CHECK-NEXT:    ret i5 [[D]]
 ;
   %m1 = mul nuw i5 %y, %x


        


More information about the llvm-commits mailing list