[llvm] [InstCombine] Fold -X/-Y -> X / Y (PR #88422)

via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 11 11:10:21 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: AtariDreams (AtariDreams)

<details>
<summary>Changes</summary>

Alive Proofs:

https://alive2.llvm.org/ce/z/zLMokH
https://alive2.llvm.org/ce/z/xviNg3
https://alive2.llvm.org/ce/z/4rdGvf

---
Full diff: https://github.com/llvm/llvm-project/pull/88422.diff


2 Files Affected:

- (modified) llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp (+20-1) 
- (modified) llvm/test/Transforms/InstCombine/div.ll (+41) 


``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index 8c698e52b5a0e6..e45bd49dbb14a7 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -1581,12 +1581,31 @@ Instruction *InstCombinerImpl::visitSDiv(BinaryOperator &I) {
     }
   }
 
-  // -X / Y --> -(X / Y)
   Value *Y;
+  // -X / -Y --> (X / Y)
+  if (match(&I, m_SDiv(m_NSWSub(m_Zero(), m_Value(X)),
+                       m_NSWSub(m_Zero(), m_Value(Y))))) {
+    auto *NewDiv = BinaryOperator::CreateSDiv(X, Y);
+    NewDiv->setIsExact(I.isExact());
+    return NewDiv;
+  }
+
+  // -X / Y --> -(X / Y)
   if (match(&I, m_SDiv(m_OneUse(m_NSWSub(m_Zero(), m_Value(X))), m_Value(Y))))
     return BinaryOperator::CreateNSWNeg(
         Builder.CreateSDiv(X, Y, I.getName(), I.isExact()));
 
+  // X / -Y --> -(X / Y), if X is known to not be INT_MIN
+  KnownBits KnownDivisor = computeKnownBits(Op1, 0, &I);
+  if (KnownDivisor.getSignedMinValue().isMinSignedValue() &&
+      match(&I, m_SDiv(m_Value(X), m_OneUse(m_NUWSub(m_Zero(), m_Value(Y)))))) {
+    auto *NewNeg = BinaryOperator::CreateNSWNeg(
+        Builder.CreateSDiv(X, Y, I.getName(), I.isExact()));
+    NewNeg->setHasNoUnsignedWrap(true);
+    NewNeg->setHasNoSignedWrap(true);
+    return NewNeg;
+  }
+
   // abs(X) / X --> X > -1 ? 1 : -1
   // X / abs(X) --> X > -1 ? 1 : -1
   if (match(&I, m_c_BinOp(
diff --git a/llvm/test/Transforms/InstCombine/div.ll b/llvm/test/Transforms/InstCombine/div.ll
index e8a25ff44d0296..c66bc0d2fae9a6 100644
--- a/llvm/test/Transforms/InstCombine/div.ll
+++ b/llvm/test/Transforms/InstCombine/div.ll
@@ -1648,6 +1648,47 @@ define i32 @sdiv_mul_nsw_sub_nsw(i32 %x, i32 %y) {
   ret i32 %d
 }
 
+define i32 @sdiv_neg_divisor_known_non_min(i32 %x, i32 %z) {
+; CHECK-LABEL: @sdiv_neg_divisor_known_non_min(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    ret i32 poison
+;
+entry:
+  %or = or i32 %z, 1
+  %sub = sub nuw i32 0, %or
+  %div = sdiv i32 %x, %sub
+  ret i32 %div
+}
+
+define i32 @double_negative_division(i32 %x, i32 %z) {
+; CHECK-LABEL: @double_negative_division(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[DIV21:%.*]] = sdiv i32 [[X:%.*]], [[SUB1:%.*]]
+; CHECK-NEXT:    ret i32 [[DIV21]]
+;
+entry:
+  %sub2 = sub nsw i32 0, %x
+  %sub1 = sub nsw i32 0, %z
+  %div2 = sdiv i32 %sub2, %sub1
+  ret i32 %div2
+}
+
+; Negative test
+
+define i32 @negative_divisior_only(i32 %x, i32 %z) {
+; CHECK-LABEL: @negative_divisior_only(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[SUB1:%.*]] = sub nsw i32 0, [[Z:%.*]]
+; CHECK-NEXT:    [[DIV2:%.*]] = sdiv i32 [[X:%.*]], [[SUB1]]
+; CHECK-NEXT:    ret i32 [[DIV2]]
+;
+entry:
+  %sub1 = sub nsw i32 0, %z
+  %div2 = sdiv i32 %x, %sub1
+  ret i32 %div2
+}
+
+
 ; exact propagates
 
 define i8 @sdiv_sdiv_mul_nsw_exact_exact(i8 %x, i8 %y, i8 %z) {

``````````

</details>


https://github.com/llvm/llvm-project/pull/88422


More information about the llvm-commits mailing list