[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