[llvm] [InstCombine] Reducing multiplications means we can have nsw and nuw tags. (PR #92980)
via llvm-commits
llvm-commits at lists.llvm.org
Tue May 21 18:51:30 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: AtariDreams (AtariDreams)
<details>
<summary>Changes</summary>
Alive2 Proofs:
https://alive2.llvm.org/ce/z/-36zkQ
https://alive2.llvm.org/ce/z/H4vGV7
https://alive2.llvm.org/ce/z/aRosSr
https://alive2.llvm.org/ce/z/2wWpyv
https://alive2.llvm.org/ce/z/oMsBg9
https://alive2.llvm.org/ce/z/xnoYh_
---
Full diff: https://github.com/llvm/llvm-project/pull/92980.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp (+32-8)
- (modified) llvm/test/Transforms/InstCombine/div.ll (+12-1)
``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index ca1b1921404d8..cceda67a45987 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -1057,8 +1057,11 @@ static Value *foldIDivShl(BinaryOperator &I, InstCombiner::BuilderTy &Builder) {
// (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 Builder.CreateSDiv(Y, Shl, "", I.isExact());
+ // These operands are intentionally swapped. See:
+ // https://alive2.llvm.org/ce/z/H4vGV7
+ Value *NewShl = Builder.CreateShl(ConstantInt::get(Ty, 1), Z, "", true,
+ Shl->hasNoUnsignedWrap());
+ return Builder.CreateSDiv(Y, NewShl, "", I.isExact());
}
}
@@ -1172,8 +1175,9 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
auto *Mul = BinaryOperator::Create(Instruction::Mul, X,
ConstantInt::get(Ty, Quotient));
auto *OBO = cast<OverflowingBinaryOperator>(Op0);
- Mul->setHasNoUnsignedWrap(!IsSigned && OBO->hasNoUnsignedWrap());
- Mul->setHasNoSignedWrap(OBO->hasNoSignedWrap());
+ Mul->setHasNoUnsignedWrap(
+ !IsSigned || (OBO->hasNoUnsignedWrap() && OBO->hasNoSignedWrap()));
+ Mul->setHasNoSignedWrap(IsSigned || OBO->hasNoSignedWrap());
return Mul;
}
}
@@ -1198,8 +1202,8 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
auto *Mul = BinaryOperator::Create(Instruction::Mul, X,
ConstantInt::get(Ty, Quotient));
auto *OBO = cast<OverflowingBinaryOperator>(Op0);
- Mul->setHasNoUnsignedWrap(!IsSigned && OBO->hasNoUnsignedWrap());
- Mul->setHasNoSignedWrap(OBO->hasNoSignedWrap());
+ Mul->setHasNoUnsignedWrap(OBO->hasNoUnsignedWrap());
+ Mul->setHasNoSignedWrap(!IsSigned || OBO->hasNoSignedWrap());
return Mul;
}
}
@@ -1273,17 +1277,37 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
}
// (X << Z) / (X * Y) -> (1 << Z) / Y
- // TODO: Handle sdiv.
if (!IsSigned && Op1->hasOneUse() &&
match(Op0, m_NUWShl(m_Value(X), m_Value(Z))) &&
match(Op1, m_c_Mul(m_Specific(X), m_Value(Y))))
if (cast<OverflowingBinaryOperator>(Op1)->hasNoUnsignedWrap()) {
Instruction *NewDiv = BinaryOperator::CreateUDiv(
- Builder.CreateShl(ConstantInt::get(Ty, 1), Z, "", /*NUW*/ true), Y);
+ Builder.CreateShl(
+ ConstantInt::get(Ty, 1), Z, "", /*NUW*/ true,
+ /*NSW*/ cast<OverflowingBinaryOperator>(Op0)->hasNoSignedWrap()),
+ Y);
NewDiv->setIsExact(I.isExact());
return NewDiv;
}
+ // (X << Z) / (X * Y) -> (1 << Z) / Y
+ if (IsSigned && Op1->hasOneUse() &&
+ match(Op0, m_NSWShl(m_Value(X), m_Value(Z))) &&
+ match(Op1, m_c_Mul(m_Specific(X), m_Value(Y))))
+ if (cast<OverflowingBinaryOperator>(Op1)->hasNoSignedWrap()) {
+ if (cast<OverflowingBinaryOperator>(Op0)->hasNoUnsignedWrap()) {
+ if (cast<OverflowingBinaryOperator>(Op1)->hasNoUnsignedWrap()) {
+ Instruction *NewDiv = BinaryOperator::CreateSDiv(
+ Builder.CreateShl(ConstantInt::get(Ty, 1), Z, "",
+ /*NUW*/ true,
+ /*NSW*/ true),
+ Y);
+ NewDiv->setIsExact(I.isExact());
+ return NewDiv;
+ }
+ }
+ }
+
if (Value *R = foldIDivShl(I, Builder))
return replaceInstUsesWith(I, R);
diff --git a/llvm/test/Transforms/InstCombine/div.ll b/llvm/test/Transforms/InstCombine/div.ll
index e8a25ff44d029..325d94cb72ffe 100644
--- a/llvm/test/Transforms/InstCombine/div.ll
+++ b/llvm/test/Transforms/InstCombine/div.ll
@@ -380,7 +380,7 @@ define i32 @test26(i32 %a) {
define i32 @test27(i32 %a) {
; CHECK-LABEL: @test27(
-; CHECK-NEXT: [[DIV:%.*]] = shl nuw i32 [[A:%.*]], 1
+; CHECK-NEXT: [[DIV:%.*]] = shl nuw nsw i32 [[A:%.*]], 1
; CHECK-NEXT: ret i32 [[DIV]]
;
%shl = shl nuw i32 %a, 2
@@ -1678,6 +1678,17 @@ define i32 @sdiv_sdiv_mul_nsw_exact_use(i32 %x, i32 %y, i32 %z) {
ret i32 %r
}
+define i32 @x_times_150_over_100(i32 %x) {
+; CHECK-LABEL: @x_times_150_over_100(
+; CHECK-NEXT: [[M:%.*]] = mul nuw nsw i32 [[X:%.*]], 150
+; CHECK-NEXT: [[D:%.*]] = udiv i32 [[M]], 100
+; CHECK-NEXT: ret i32 [[D]]
+;
+ %m = mul nuw nsw i32 %x, 150
+ %d = udiv i32 %m, 100
+ ret i32 %d
+}
+
; negative test - must have nsw
define i8 @sdiv_sdiv_mul_nuw(i8 %x, i8 %y, i8 %z) {
``````````
</details>
https://github.com/llvm/llvm-project/pull/92980
More information about the llvm-commits
mailing list