aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2008-08-06 07:35:52 +0000
committerChris Lattner <sabre@nondot.org>2008-08-06 07:35:52 +0000
commit46bbad217b9fe616cc9309e6ee6b507a118cd618 (patch)
treef5bf747f5901ee9092555ff9cee78c9b28e49866
parentbbe51362d53a532942997903a49faa7b5b50ad1f (diff)
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
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp32
-rw-r--r--test/Transforms/InstCombine/sext-misc.ll10
2 files changed, 41 insertions, 1 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index 44083bc2d0..3a74c7f73d 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<TruncInst>(A)) {
+ Value *I = cast<TruncInst>(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 69850025ac..58749666ea 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 ; <i8> [#uses=1]
+ %tmp16 = shl i8 %tmp12, 6 ; <i8> [#uses=1]
+ %a = ashr i8 %tmp16, 6 ; <i8> [#uses=1]
+ %b = sext i8 %a to i32 ; <i32> [#uses=1]
+ ret i32 %b
+}
+