From 46bbad217b9fe616cc9309e6ee6b507a118cd618 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 6 Aug 2008 07:35:52 +0000 Subject: [PATCH 1/1] optimize a common idiom generated by clang for bitfield access, PR2638. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@54408 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Scalar/InstructionCombining.cpp | 32 ++++++++++++++++++- test/Transforms/InstCombine/sext-misc.ll | 10 ++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 44083bc2d00..3a74c7f73d0 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -7666,7 +7666,37 @@ Instruction *InstCombiner::visitSExt(SExtInst &CI) { return new TruncInst(Op, CI.getType(), "tmp"); } } - + + // If the input is a shl/ashr pair of a same constant, then this is a sign + // extension from a smaller value. If we could trust arbitrary bitwidth + // integers, we could turn this into a truncate to the smaller bit and then + // use a sext for the whole extension. Since we don't, look deeper and check + // for a truncate. If the source and dest are the same type, eliminate the + // trunc and extend and just do shifts. For example, turn: + // %a = trunc i32 %i to i8 + // %b = shl i8 %a, 6 + // %c = ashr i8 %b, 6 + // %d = sext i8 %c to i32 + // into: + // %a = shl i32 %i, 30 + // %d = ashr i32 %a, 30 + Value *A = 0; + ConstantInt *BA = 0, *CA = 0; + if (match(Src, m_AShr(m_Shl(m_Value(A), m_ConstantInt(BA)), + m_ConstantInt(CA))) && + BA == CA && isa(A)) { + Value *I = cast(A)->getOperand(0); + if (I->getType() == CI.getType()) { + unsigned MidSize = Src->getType()->getPrimitiveSizeInBits(); + unsigned SrcDstSize = CI.getType()->getPrimitiveSizeInBits(); + unsigned ShAmt = CA->getZExtValue()+SrcDstSize-MidSize; + Constant *ShAmtV = ConstantInt::get(CI.getType(), ShAmt); + I = InsertNewInstBefore(BinaryOperator::CreateShl(I, ShAmtV, + CI.getName()), CI); + return BinaryOperator::CreateAShr(I, ShAmtV); + } + } + return 0; } diff --git a/test/Transforms/InstCombine/sext-misc.ll b/test/Transforms/InstCombine/sext-misc.ll index 69850025aca..58749666ea1 100644 --- a/test/Transforms/InstCombine/sext-misc.ll +++ b/test/Transforms/InstCombine/sext-misc.ll @@ -63,3 +63,13 @@ F: ret i16 %W } +; PR2638 +define i32 @test2(i32 %i) nounwind { +entry: + %tmp12 = trunc i32 %i to i8 ; [#uses=1] + %tmp16 = shl i8 %tmp12, 6 ; [#uses=1] + %a = ashr i8 %tmp16, 6 ; [#uses=1] + %b = sext i8 %a to i32 ; [#uses=1] + ret i32 %b +} + -- 2.34.1