[llvm] [ValueTracking] mul nuw nsw with factor sge 1 is non-negative (PR #110803)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 2 01:45:13 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Nikita Popov (nikic)
<details>
<summary>Changes</summary>
Proof: https://alive2.llvm.org/ce/z/6nRJMD
---
Full diff: https://github.com/llvm/llvm-project/pull/110803.diff
4 Files Affected:
- (modified) llvm/lib/Analysis/ValueTracking.cpp (+14-6)
- (modified) llvm/test/Transforms/InstCombine/ashr-lshr.ll (+2-2)
- (modified) llvm/test/Transforms/InstCombine/known-bits.ll (+44)
- (modified) llvm/test/Transforms/InstCombine/rem-mul-shl.ll (+1-1)
``````````diff
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 56eb3f99b39d2c..0d384c61f978ee 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -369,9 +369,9 @@ static void computeKnownBitsAddSub(bool Add, const Value *Op0, const Value *Op1,
}
static void computeKnownBitsMul(const Value *Op0, const Value *Op1, bool NSW,
- const APInt &DemandedElts, KnownBits &Known,
- KnownBits &Known2, unsigned Depth,
- const SimplifyQuery &Q) {
+ bool NUW, const APInt &DemandedElts,
+ KnownBits &Known, KnownBits &Known2,
+ unsigned Depth, const SimplifyQuery &Q) {
computeKnownBits(Op1, DemandedElts, Known, Depth + 1, Q);
computeKnownBits(Op0, DemandedElts, Known2, Depth + 1, Q);
@@ -390,6 +390,13 @@ static void computeKnownBitsMul(const Value *Op0, const Value *Op1, bool NSW,
// The product of two numbers with the same sign is non-negative.
isKnownNonNegative = (isKnownNegativeOp1 && isKnownNegativeOp0) ||
(isKnownNonNegativeOp1 && isKnownNonNegativeOp0);
+ if (!isKnownNonNegative && NUW) {
+ // mul nuw nsw with a factor > 1 is non-negative.
+ KnownBits One = KnownBits::makeConstant(APInt(Known.getBitWidth(), 1));
+ isKnownNonNegative = KnownBits::sgt(Known, One).value_or(false) ||
+ KnownBits::sgt(Known2, One).value_or(false);
+ }
+
// The product of a negative number and a non-negative number is either
// negative or zero.
if (!isKnownNonNegative)
@@ -1090,8 +1097,9 @@ static void computeKnownBitsFromOperator(const Operator *I,
break;
case Instruction::Mul: {
bool NSW = Q.IIQ.hasNoSignedWrap(cast<OverflowingBinaryOperator>(I));
- computeKnownBitsMul(I->getOperand(0), I->getOperand(1), NSW, DemandedElts,
- Known, Known2, Depth, Q);
+ bool NUW = Q.IIQ.hasNoUnsignedWrap(cast<OverflowingBinaryOperator>(I));
+ computeKnownBitsMul(I->getOperand(0), I->getOperand(1), NSW, NUW,
+ DemandedElts, Known, Known2, Depth, Q);
break;
}
case Instruction::UDiv: {
@@ -1961,7 +1969,7 @@ static void computeKnownBitsFromOperator(const Operator *I,
case Intrinsic::umul_with_overflow:
case Intrinsic::smul_with_overflow:
computeKnownBitsMul(II->getArgOperand(0), II->getArgOperand(1), false,
- DemandedElts, Known, Known2, Depth, Q);
+ false, DemandedElts, Known, Known2, Depth, Q);
break;
}
}
diff --git a/llvm/test/Transforms/InstCombine/ashr-lshr.ll b/llvm/test/Transforms/InstCombine/ashr-lshr.ll
index 49041906680b3a..1abf1be2cbedd9 100644
--- a/llvm/test/Transforms/InstCombine/ashr-lshr.ll
+++ b/llvm/test/Transforms/InstCombine/ashr-lshr.ll
@@ -741,7 +741,7 @@ define i32 @lshr_mul_times_5_div_4_exact_2(i32 %x) {
define i32 @ashr_mul_times_3_div_2(i32 %0) {
; CHECK-LABEL: @ashr_mul_times_3_div_2(
-; CHECK-NEXT: [[TMP2:%.*]] = ashr i32 [[TMP0:%.*]], 1
+; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP0:%.*]], 1
; CHECK-NEXT: [[ASHR:%.*]] = add nuw nsw i32 [[TMP0]], [[TMP2]]
; CHECK-NEXT: ret i32 [[ASHR]]
;
@@ -815,7 +815,7 @@ define i32 @ashr_mul_times_3_div_2_exact_2(i32 %x) {
define i32 @ashr_mul_times_5_div_4(i32 %0) {
; CHECK-LABEL: @ashr_mul_times_5_div_4(
-; CHECK-NEXT: [[TMP2:%.*]] = ashr i32 [[TMP0:%.*]], 2
+; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP0:%.*]], 2
; CHECK-NEXT: [[ASHR:%.*]] = add nuw nsw i32 [[TMP0]], [[TMP2]]
; CHECK-NEXT: ret i32 [[ASHR]]
;
diff --git a/llvm/test/Transforms/InstCombine/known-bits.ll b/llvm/test/Transforms/InstCombine/known-bits.ll
index 8cfb987e422f38..d5393492c31ff1 100644
--- a/llvm/test/Transforms/InstCombine/known-bits.ll
+++ b/llvm/test/Transforms/InstCombine/known-bits.ll
@@ -2051,6 +2051,50 @@ exit:
ret i16 %conv
}
+define i1 @mul_nuw_nsw_nonneg_const(i8 %x) {
+; CHECK-LABEL: @mul_nuw_nsw_nonneg_const(
+; CHECK-NEXT: ret i1 true
+;
+ %mul = mul nuw nsw i8 %x, 3
+ %cmp = icmp sgt i8 %mul, -1
+ ret i1 %cmp
+}
+
+define i1 @mul_nuw_nsw_nonneg_can_be_one(i8 %x, i8 %y) {
+; CHECK-LABEL: @mul_nuw_nsw_nonneg_can_be_one(
+; CHECK-NEXT: [[Y_NNEG:%.*]] = and i8 [[Y:%.*]], 127
+; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i8 [[X:%.*]], [[Y_NNEG]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[MUL]], -1
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %y.nneg = and i8 %y, 127
+ %mul = mul nuw nsw i8 %x, %y.nneg
+ %cmp = icmp sgt i8 %mul, -1
+ ret i1 %cmp
+}
+
+define i1 @mul_nuw_nsw_nonneg_cant_be_one(i8 %x, i8 %y) {
+; CHECK-LABEL: @mul_nuw_nsw_nonneg_cant_be_one(
+; CHECK-NEXT: ret i1 true
+;
+ %y.nneg = and i8 %y, 127
+ %y.nneg.not.one = or i8 %y.nneg, 2
+ %mul = mul nuw nsw i8 %x, %y.nneg.not.one
+ %cmp = icmp sgt i8 %mul, -1
+ ret i1 %cmp
+}
+
+define i1 @mul_nuw_nsw_nonneg_cant_be_one_commuted(i8 %x, i8 %y) {
+; CHECK-LABEL: @mul_nuw_nsw_nonneg_cant_be_one_commuted(
+; CHECK-NEXT: ret i1 true
+;
+ %y.nneg = and i8 %y, 127
+ %y.nneg.not.one = or i8 %y.nneg, 2
+ %mul = mul nuw nsw i8 %y.nneg.not.one, %x
+ %cmp = icmp sgt i8 %mul, -1
+ ret i1 %cmp
+}
+
declare void @dummy()
declare void @use(i1)
declare void @sink(i8)
diff --git a/llvm/test/Transforms/InstCombine/rem-mul-shl.ll b/llvm/test/Transforms/InstCombine/rem-mul-shl.ll
index 9e2df157c2c858..45db2cf6758524 100644
--- a/llvm/test/Transforms/InstCombine/rem-mul-shl.ll
+++ b/llvm/test/Transforms/InstCombine/rem-mul-shl.ll
@@ -8,7 +8,7 @@ define i8 @srem_non_matching(i8 %X, i8 %Y) {
; CHECK-LABEL: @srem_non_matching(
; CHECK-NEXT: [[BO0:%.*]] = mul nuw nsw i8 [[X:%.*]], 15
; CHECK-NEXT: [[BO1:%.*]] = mul nuw nsw i8 [[Y:%.*]], 5
-; CHECK-NEXT: [[R:%.*]] = srem i8 [[BO0]], [[BO1]]
+; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]]
; CHECK-NEXT: ret i8 [[R]]
;
%BO0 = mul nsw nuw i8 %X, 15
``````````
</details>
https://github.com/llvm/llvm-project/pull/110803
More information about the llvm-commits
mailing list