diff options
author | Chris Lattner <sabre@nondot.org> | 2009-02-17 20:47:23 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2009-02-17 20:47:23 +0000 |
commit | a84f47c3e7bd1ba161ca46b64bd2469d49593320 (patch) | |
tree | 0c415987b9f976d0bf4685e89ffe9353acbdd486 | |
parent | 189c6357a1a1d09b8b0c5cf6f1cd561a47ccec18 (diff) | |
download | llvm-a84f47c3e7bd1ba161ca46b64bd2469d49593320.tar.gz llvm-a84f47c3e7bd1ba161ca46b64bd2469d49593320.tar.bz2 llvm-a84f47c3e7bd1ba161ca46b64bd2469d49593320.tar.xz |
commit a tweaked version of Daniel's patch for PR3599. We now
eliminate all the extensions and all but the one required truncate
from the testcase, but the or/and/shift stuff still isn't zapped.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@64809 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Transforms/Scalar/InstructionCombining.cpp | 55 | ||||
-rw-r--r-- | test/Transforms/InstCombine/zext.ll | 23 |
2 files changed, 52 insertions, 26 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 8bdeb7f514..bca6abc605 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -8271,32 +8271,35 @@ Instruction *InstCombiner::visitZExt(ZExtInst &CI) { Value *Src = CI.getOperand(0); - // If this is a cast of a cast - if (CastInst *CSrc = dyn_cast<CastInst>(Src)) { // A->B->C cast - // If this is a TRUNC followed by a ZEXT then we are dealing with integral - // types and if the sizes are just right we can convert this into a logical - // 'and' which will be much cheaper than the pair of casts. - if (isa<TruncInst>(CSrc)) { - // Get the sizes of the types involved - Value *A = CSrc->getOperand(0); - uint32_t SrcSize = A->getType()->getPrimitiveSizeInBits(); - uint32_t MidSize = CSrc->getType()->getPrimitiveSizeInBits(); - uint32_t DstSize = CI.getType()->getPrimitiveSizeInBits(); - // If we're actually extending zero bits and the trunc is a no-op - if (MidSize < DstSize && SrcSize == DstSize) { - // Replace both of the casts with an And of the type mask. - APInt AndValue(APInt::getLowBitsSet(SrcSize, MidSize)); - Constant *AndConst = ConstantInt::get(AndValue); - Instruction *And = - BinaryOperator::CreateAnd(CSrc->getOperand(0), AndConst); - // Unfortunately, if the type changed, we need to cast it back. - if (And->getType() != CI.getType()) { - And->setName(CSrc->getName()+".mask"); - InsertNewInstBefore(And, CI); - And = CastInst::CreateIntegerCast(And, CI.getType(), false/*ZExt*/); - } - return And; - } + // If this is a TRUNC followed by a ZEXT then we are dealing with integral + // types and if the sizes are just right we can convert this into a logical + // 'and' which will be much cheaper than the pair of casts. + if (TruncInst *CSrc = dyn_cast<TruncInst>(Src)) { // A->B->C cast + // Get the sizes of the types involved. We know that the intermediate type + // will be smaller than A or C, but don't know the relation between A and C. + Value *A = CSrc->getOperand(0); + unsigned SrcSize = A->getType()->getPrimitiveSizeInBits(); + unsigned MidSize = CSrc->getType()->getPrimitiveSizeInBits(); + unsigned DstSize = CI.getType()->getPrimitiveSizeInBits(); + // If we're actually extending zero bits, then if + // SrcSize < DstSize: zext(a & mask) + // SrcSize == DstSize: a & mask + // SrcSize > DstSize: trunc(a) & mask + if (SrcSize < DstSize) { + APInt AndValue(APInt::getLowBitsSet(SrcSize, MidSize)); + Constant *AndConst = ConstantInt::get(AndValue); + Instruction *And = + BinaryOperator::CreateAnd(A, AndConst, CSrc->getName()+".mask"); + InsertNewInstBefore(And, CI); + return new ZExtInst(And, CI.getType()); + } else if (SrcSize == DstSize) { + APInt AndValue(APInt::getLowBitsSet(SrcSize, MidSize)); + return BinaryOperator::CreateAnd(A, ConstantInt::get(AndValue)); + } else if (SrcSize > DstSize) { + Instruction *Trunc = new TruncInst(A, CI.getType(), "tmp"); + InsertNewInstBefore(Trunc, CI); + APInt AndValue(APInt::getLowBitsSet(DstSize, MidSize)); + return BinaryOperator::CreateAnd(Trunc, ConstantInt::get(AndValue)); } } diff --git a/test/Transforms/InstCombine/zext.ll b/test/Transforms/InstCombine/zext.ll index ceb8deb677..c0fa3771cc 100644 --- a/test/Transforms/InstCombine/zext.ll +++ b/test/Transforms/InstCombine/zext.ll @@ -8,3 +8,26 @@ define i64 @test_sext_zext(i16 %A) { ret i64 %c2 } +; PR3599 +define i32 @test2(i64 %tmp) nounwind readnone { +entry: + %tmp5 = trunc i64 %tmp to i8 ; <i8> [#uses=1] + %tmp7 = lshr i64 %tmp, 8 ; <i64> [#uses=1] + %tmp8 = trunc i64 %tmp7 to i8 ; <i8> [#uses=1] + %tmp10 = lshr i64 %tmp, 16 ; <i64> [#uses=1] + %tmp11 = trunc i64 %tmp10 to i8 ; <i8> [#uses=1] + %tmp13 = lshr i64 %tmp, 24 ; <i64> [#uses=1] + %tmp14 = trunc i64 %tmp13 to i8 ; <i8> [#uses=1] + %tmp1 = zext i8 %tmp5 to i32 ; <i32> [#uses=1] + %tmp2 = zext i8 %tmp8 to i32 ; <i32> [#uses=1] + %tmp3 = shl i32 %tmp2, 8 ; <i32> [#uses=1] + %tmp4 = zext i8 %tmp11 to i32 ; <i32> [#uses=1] + %tmp6 = shl i32 %tmp4, 16 ; <i32> [#uses=1] + %tmp9 = zext i8 %tmp14 to i32 ; <i32> [#uses=1] + %tmp12 = shl i32 %tmp9, 24 ; <i32> [#uses=1] + %tmp15 = or i32 %tmp12, %tmp1 ; <i32> [#uses=1] + %tmp16 = or i32 %tmp15, %tmp6 ; <i32> [#uses=1] + %tmp17 = or i32 %tmp16, %tmp3 ; <i32> [#uses=1] + ret i32 %tmp17 +} + |