From 15305ce91e34d8f65eeeb75ee49f67ed8d5d13df Mon Sep 17 00:00:00 2001 From: XChy Date: Tue, 17 Oct 2023 16:58:45 +0800 Subject: [PATCH] [InstCombine] Don't mix X << Y / Z << Y with X << Y / X << Z --- .../InstCombine/InstCombineMulDivRem.cpp | 24 +++++++------------ llvm/test/Transforms/InstCombine/div-shift.ll | 14 +++++++++++ 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index 26e0a6700042e..518f8aa51c0cd 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 635c01d84441d..d208837f04594 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 } + +@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 +}