diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2009-07-13 22:46:01 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2009-07-13 22:46:01 +0000 |
commit | 070a981ab7c9b1ba82af9acf5c3b94da8af48646 (patch) | |
tree | 1f27029d09615a6927994790194d23959c48cf5f | |
parent | a43c3aca851b10329f756b084d897e9dfb2d0729 (diff) | |
download | external_llvm-070a981ab7c9b1ba82af9acf5c3b94da8af48646.zip external_llvm-070a981ab7c9b1ba82af9acf5c3b94da8af48646.tar.gz external_llvm-070a981ab7c9b1ba82af9acf5c3b94da8af48646.tar.bz2 |
PR4548: optimize zext+udiv+trunc to udiv.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@75539 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Transforms/Scalar/InstructionCombining.cpp | 21 | ||||
-rw-r--r-- | test/Transforms/InstCombine/udivrem-change-width.ll | 19 |
2 files changed, 39 insertions, 1 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index c93994f..838b33c 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -7974,6 +7974,23 @@ bool InstCombiner::CanEvaluateInDifferentType(Value *V, const Type *Ty, CanEvaluateInDifferentType(I->getOperand(1), Ty, CastOpc, NumCastsRemoved); + case Instruction::UDiv: + case Instruction::URem: { + // UDiv and URem can be truncated if all the truncated bits are zero. + uint32_t OrigBitWidth = OrigTy->getScalarSizeInBits(); + uint32_t BitWidth = Ty->getScalarSizeInBits(); + if (BitWidth < OrigBitWidth) { + APInt Mask = APInt::getHighBitsSet(OrigBitWidth, OrigBitWidth-BitWidth); + if (MaskedValueIsZero(I->getOperand(0), Mask) && + MaskedValueIsZero(I->getOperand(1), Mask)) { + return CanEvaluateInDifferentType(I->getOperand(0), Ty, CastOpc, + NumCastsRemoved) && + CanEvaluateInDifferentType(I->getOperand(1), Ty, CastOpc, + NumCastsRemoved); + } + } + break; + } case Instruction::Shl: // If we are truncating the result of this SHL, and if it's a shift of a // constant amount, we can always perform a SHL in a smaller type. @@ -8060,7 +8077,9 @@ Value *InstCombiner::EvaluateInDifferentType(Value *V, const Type *Ty, case Instruction::Xor: case Instruction::AShr: case Instruction::LShr: - case Instruction::Shl: { + case Instruction::Shl: + case Instruction::UDiv: + case Instruction::URem: { Value *LHS = EvaluateInDifferentType(I->getOperand(0), Ty, isSigned); Value *RHS = EvaluateInDifferentType(I->getOperand(1), Ty, isSigned); Res = BinaryOperator::Create((Instruction::BinaryOps)Opc, LHS, RHS); diff --git a/test/Transforms/InstCombine/udivrem-change-width.ll b/test/Transforms/InstCombine/udivrem-change-width.ll new file mode 100644 index 0000000..eb4ba66 --- /dev/null +++ b/test/Transforms/InstCombine/udivrem-change-width.ll @@ -0,0 +1,19 @@ +; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep zext +; PR4548 + +define i8 @udiv_i8(i8 %a, i8 %b) nounwind { + %conv = zext i8 %a to i32 + %conv2 = zext i8 %b to i32 + %div = udiv i32 %conv, %conv2 + %conv3 = trunc i32 %div to i8 + ret i8 %conv3 +} + +define i8 @urem_i8(i8 %a, i8 %b) nounwind { + %conv = zext i8 %a to i32 + %conv2 = zext i8 %b to i32 + %div = urem i32 %conv, %conv2 + %conv3 = trunc i32 %div to i8 + ret i8 %conv3 +} + |