[llvm] [InstCombine]: Handle known negative variables with KnownBits (PR #89682)

via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 22 15:14:37 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: AtariDreams (AtariDreams)

<details>
<summary>Changes</summary>



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


2 Files Affected:

- (modified) llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp (+7-1) 
- (modified) llvm/test/Transforms/InstCombine/udiv-simplify.ll (+12) 


``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index 4ed4c36e21e016..f03c31e613d601 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -1491,12 +1491,18 @@ Instruction *InstCombinerImpl::visitUDiv(BinaryOperator &I) {
   }
 
   // Op0 / C where C is large (negative) --> zext (Op0 >= C)
-  // TODO: Could use isKnownNegative() to handle non-constant values.
   Type *Ty = I.getType();
   if (match(Op1, m_Negative())) {
     Value *Cmp = Builder.CreateICmpUGE(Op0, Op1);
     return CastInst::CreateZExtOrBitCast(Cmp, Ty);
   }
+
+  KnownBits Known = computeKnownBits(Op1, 0, &I);
+  if (Known.isNegative()) {
+    Value *Cmp = Builder.CreateICmpUGE(Op0, Op1);
+    return CastInst::CreateZExtOrBitCast(Cmp, Ty);
+  }
+
   // Op0 / (sext i1 X) --> zext (Op0 == -1) (if X is 0, the div is undefined)
   if (match(Op1, m_SExt(m_Value(X))) && X->getType()->isIntOrIntVectorTy(1)) {
     Value *Cmp = Builder.CreateICmpEQ(Op0, ConstantInt::getAllOnesValue(Ty));
diff --git a/llvm/test/Transforms/InstCombine/udiv-simplify.ll b/llvm/test/Transforms/InstCombine/udiv-simplify.ll
index bd6e5efc05f187..82532e3e6ff8c9 100644
--- a/llvm/test/Transforms/InstCombine/udiv-simplify.ll
+++ b/llvm/test/Transforms/InstCombine/udiv-simplify.ll
@@ -98,6 +98,18 @@ define i8 @udiv_demanded_low_bits_set(i8 %a) {
   ret i8 %u
 }
 
+define i8 @udiv_large_value(i8 %a) {
+; CHECK-LABEL: @udiv_large_value(
+; CHECK-NEXT:    [[TMP1:%.*]] = and i8 [[A:%.*]], -76
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[TMP1]], -76
+; CHECK-NEXT:    [[U:%.*]] = zext i1 [[TMP2]] to i8
+; CHECK-NEXT:    ret i8 [[U]]
+;
+  %o = or i8 %a, 180
+  %u = udiv i8 %a, %o
+  ret i8 %u
+}
+
 ; This can't divide evenly, so it is poison.
 
 define i8 @udiv_exact_demanded_low_bits_set(i8 %a) {

``````````

</details>


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


More information about the llvm-commits mailing list