[PATCH] D12520: [InstCombineCasts] Cast elimination for sext->lshr->trunc patterns
Jakub Kuderski via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 1 02:00:53 PDT 2015
kuhar created this revision.
kuhar added a subscriber: llvm-commits.
kuhar set the repository for this revision to rL LLVM.
There is a `trunc(lshr (zext A), Cst)` optimization in InstCombineCasts that removes cast by performing the lshr on smaller types. However, currently there is no `trunc(lshr (sext A), Cst)` variant.
This patch add such optimization by transforming `trunc(lshr (sext A), Cst)` to ashr A, Cst.
Repository:
rL LLVM
http://reviews.llvm.org/D12520
Files:
lib/Transforms/InstCombine/InstCombineCasts.cpp
test/Transforms/InstCombine/cast.ll
Index: test/Transforms/InstCombine/cast.ll
===================================================================
--- test/Transforms/InstCombine/cast.ll
+++ test/Transforms/InstCombine/cast.ll
@@ -1062,6 +1062,43 @@
; CHECK: [[CST:%.*]] = trunc i32 [[SHR]] to i8
}
+define i16 @test86(i16 %v) {
+ %a = sext i16 %v to i32
+ %s = ashr i32 %a, 4
+ %t = trunc i32 %s to i16
+ ret i16 %t
+
+; CHECK-LABEL: @test86(
+; CHECK: %s.1 = ashr i16 %v, 4
+; CHECK-NEXT: ret i16 %s.1
+}
+
+define i16 @test87(i16 %v) {
+ %c = sext i16 %v to i32
+ %m = mul nsw i32 %c, 16
+ %a = ashr i32 %m, 16
+ %t = trunc i32 %a to i16
+ ret i16 %t
+
+; CHECK-LABEL: @test87(
+; CHECK: %a.1 = ashr i16 %v, 12
+; CHECK-NEXT: ret i16 %a.1
+}
+
+define i16 @test88(i16 %v) {
+ %a = sext i16 %v to i32
+ %s = ashr i32 %a, 18
+ %t = trunc i32 %s to i16
+ ret i16 %t
+
+; Do not optimize to ashr i16 (shift by 18)
+; CHECK-LABEL: @test88(
+; CHECK: %a = sext i16 %v to i32
+; CHECK-NEXT: %s = ashr i32 %a, 18
+; CHECK-NEXT: %t = trunc i32 %s to i16
+; CHECK-NEXT: ret i16 %t
+}
+
; Overflow on a float to int or int to float conversion is undefined (PR21130).
define i8 @overflow_fptosi() {
Index: lib/Transforms/InstCombine/InstCombineCasts.cpp
===================================================================
--- lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -499,6 +499,28 @@
return CastInst::CreateIntegerCast(Shift, CI.getType(), false);
}
+ // Transform trunc(lshr (sext A), Cst) to ashr A, Cst to eliminate type
+ // conversion.
+ // It works because bits comming from sign extension have the same value as
+ // sign bit of the original value; performing ashr instead of lshr
+ // generates bits of the same value as the sign bit.
+ if (Src->hasOneUse() &&
+ match(Src, m_LShr(m_SExt(m_Value(A)), m_ConstantInt(Cst))) &&
+ cast<Instruction>(Src)->getOperand(0)->hasOneUse()) {
+ const unsigned ASize = A->getType()->getPrimitiveSizeInBits();
+ // This optimization can be only performed when zero bits generated by
+ // the original lshr aren't pulled into the value after truncation, so we
+ // can only shift by values smaller then the size of destanation type (in
+ // bits).
+ if (Cst->getValue().ult(ASize)) {
+ // We can safely zero extend the result of ashr, since it'll get
+ // truncated.
+ Value *Shift = Builder->CreateAShr(A, Cst->getZExtValue());
+ Shift->takeName(Src);
+ return CastInst::CreateIntegerCast(Shift, CI.getType(), false);
+ }
+ }
+
// Transform "trunc (and X, cst)" -> "and (trunc X), cst" so long as the dest
// type isn't non-native.
if (Src->hasOneUse() && isa<IntegerType>(Src->getType()) &&
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D12520.33669.patch
Type: text/x-patch
Size: 2760 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150901/df812fbb/attachment.bin>
More information about the llvm-commits
mailing list