[llvm] f2898de - [InstCombine] Don't mix X << Y / Z << Y with X << Y / X << Z (#69302)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 17 03:47:53 PDT 2023
Author: XChy
Date: 2023-10-17T18:47:49+08:00
New Revision: f2898def693a8ba8a017fcceab4260d7fe2faeb1
URL: https://github.com/llvm/llvm-project/commit/f2898def693a8ba8a017fcceab4260d7fe2faeb1
DIFF: https://github.com/llvm/llvm-project/commit/f2898def693a8ba8a017fcceab4260d7fe2faeb1.diff
LOG: [InstCombine] Don't mix X << Y / Z << Y with X << Y / X << Z (#69302)
Fixes #69291.
This patch improve the logic handling different patterns to avoid mixing these
pattern.
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 26e0a6700042ef0..518f8aa51c0cd29 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -923,8 +923,7 @@ static bool isMultiple(const APInt &C1, const APInt &C2, APInt &Quotient,
return Remainder.isMinValue();
}
-static Instruction *foldIDivShl(BinaryOperator &I,
- InstCombiner::BuilderTy &Builder) {
+static Value *foldIDivShl(BinaryOperator &I, InstCombiner::BuilderTy &Builder) {
assert((I.getOpcode() == Instruction::SDiv ||
I.getOpcode() == Instruction::UDiv) &&
"Expected integer divide");
@@ -933,7 +932,6 @@ static Instruction *foldIDivShl(BinaryOperator &I,
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
Type *Ty = I.getType();
- Instruction *Ret = nullptr;
Value *X, *Y, *Z;
// With appropriate no-wrap constraints, remove a common factor in the
@@ -948,12 +946,12 @@ static Instruction *foldIDivShl(BinaryOperator &I,
// (X * Y) u/ (X << Z) --> Y u>> Z
if (!IsSigned && HasNUW)
- Ret = BinaryOperator::CreateLShr(Y, Z);
+ return Builder.CreateLShr(Y, Z, "", I.isExact());
// (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 Builder.CreateSDiv(Y, Shl, "", I.isExact());
}
}
@@ -971,13 +969,13 @@ static Instruction *foldIDivShl(BinaryOperator &I,
((Shl0->hasNoUnsignedWrap() && Shl1->hasNoUnsignedWrap()) ||
(Shl0->hasNoUnsignedWrap() && Shl0->hasNoSignedWrap() &&
Shl1->hasNoSignedWrap())))
- Ret = BinaryOperator::CreateUDiv(X, Y);
+ return Builder.CreateUDiv(X, Y, "", I.isExact());
// For signed div, we need 'nsw' on both shifts + 'nuw' on the divisor.
// (X << Z) / (Y << Z) --> X / Y
if (IsSigned && Shl0->hasNoSignedWrap() && Shl1->hasNoSignedWrap() &&
Shl1->hasNoUnsignedWrap())
- Ret = BinaryOperator::CreateSDiv(X, Y);
+ return Builder.CreateSDiv(X, Y, "", I.isExact());
}
// If X << Y and X << Z does not overflow, then:
@@ -998,15 +996,11 @@ static Instruction *foldIDivShl(BinaryOperator &I,
/*HasNSW*/
IsSigned ? (Shl0->hasNoUnsignedWrap() || Shl1->hasNoUnsignedWrap())
: Shl0->hasNoSignedWrap());
- Ret = BinaryOperator::CreateLShr(Dividend, Z);
+ return Builder.CreateLShr(Dividend, Z, "", I.isExact());
}
}
- if (!Ret)
- return nullptr;
-
- Ret->setIsExact(I.isExact());
- return Ret;
+ return nullptr;
}
/// This function implements the transforms common to both integer division
@@ -1183,8 +1177,8 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
return NewDiv;
}
- if (Instruction *R = foldIDivShl(I, Builder))
- return R;
+ if (Value *R = foldIDivShl(I, Builder))
+ return replaceInstUsesWith(I, R);
// With the appropriate no-wrap constraint, remove a multiply by the divisor
// after peeking through another divide:
diff --git a/llvm/test/Transforms/InstCombine/div-shift.ll b/llvm/test/Transforms/InstCombine/div-shift.ll
index 635c01d84441d8a..d208837f04594ab 100644
--- a/llvm/test/Transforms/InstCombine/div-shift.ll
+++ b/llvm/test/Transforms/InstCombine/div-shift.ll
@@ -1280,3 +1280,17 @@ entry:
%div = sdiv i32 %lhs, %rhs
ret i32 %div
}
+
+ at a = external global i32
+define i32 @pr69291() {
+; CHECK-LABEL: @pr69291(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: ret i32 1
+;
+entry:
+ %conv = load i32, ptr @a, align 1
+ %add = shl nuw nsw i32 %conv, 1
+ %add2 = shl nuw nsw i32 %conv, 1
+ %div = sdiv i32 %add, %add2
+ ret i32 %div
+}
More information about the llvm-commits
mailing list