From a84f47c3e7bd1ba161ca46b64bd2469d49593320 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 17 Feb 2009 20:47:23 +0000 Subject: [PATCH] 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 --- .../Scalar/InstructionCombining.cpp | 55 ++++++++++--------- 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 8bdeb7f514c..bca6abc6051 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(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(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(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 ceb8deb6775..c0fa3771cc1 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 ; [#uses=1] + %tmp7 = lshr i64 %tmp, 8 ; [#uses=1] + %tmp8 = trunc i64 %tmp7 to i8 ; [#uses=1] + %tmp10 = lshr i64 %tmp, 16 ; [#uses=1] + %tmp11 = trunc i64 %tmp10 to i8 ; [#uses=1] + %tmp13 = lshr i64 %tmp, 24 ; [#uses=1] + %tmp14 = trunc i64 %tmp13 to i8 ; [#uses=1] + %tmp1 = zext i8 %tmp5 to i32 ; [#uses=1] + %tmp2 = zext i8 %tmp8 to i32 ; [#uses=1] + %tmp3 = shl i32 %tmp2, 8 ; [#uses=1] + %tmp4 = zext i8 %tmp11 to i32 ; [#uses=1] + %tmp6 = shl i32 %tmp4, 16 ; [#uses=1] + %tmp9 = zext i8 %tmp14 to i32 ; [#uses=1] + %tmp12 = shl i32 %tmp9, 24 ; [#uses=1] + %tmp15 = or i32 %tmp12, %tmp1 ; [#uses=1] + %tmp16 = or i32 %tmp15, %tmp6 ; [#uses=1] + %tmp17 = or i32 %tmp16, %tmp3 ; [#uses=1] + ret i32 %tmp17 +} +