[llvm] r310942 - [InstCombine] sink sext after ashr

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 15 11:25:52 PDT 2017


Author: spatel
Date: Tue Aug 15 11:25:52 2017
New Revision: 310942

URL: http://llvm.org/viewvc/llvm-project?rev=310942&view=rev
Log:
[InstCombine] sink sext after ashr

Narrow ops are better for bit-tracking, and in the case of vectors,
may enable better codegen.

As the trunc test shows, this can allow follow-on simplifications.

There's a block of code in visitTrunc that deals with shifted ops
with FIXME comments. It may be possible to remove some of that now,
but I want to make sure there are no problems with this step first.

http://rise4fun.com/Alive/Y3a

Name: hoist_ashr_ahead_of_sext_1
  %s = sext i8 %x to i32
  %r = ashr i32 %s, 3  ; shift value is < than source bit width
  =>
  %a = ashr i8 %x, 3
  %r = sext i8 %a to i32
  
Name: hoist_ashr_ahead_of_sext_2
  %s = sext i8 %x to i32
  %r = ashr i32 %s, 8  ; shift value is >= than source bit width
  =>
  %a = ashr i8 %x, 7   ; so clamp this shift value
  %r = sext i8 %a to i32
  
Name: junc_the_trunc  
  %a = sext i16 %v to i32
  %s = ashr i32 %a, 18
  %t = trunc i32 %s to i16
  =>
  %t = ashr i16 %v, 15



Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp
    llvm/trunk/test/Transforms/InstCombine/cast.ll
    llvm/trunk/test/Transforms/InstCombine/shift-sra.ll

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp?rev=310942&r1=310941&r2=310942&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp Tue Aug 15 11:25:52 2017
@@ -803,6 +803,15 @@ Instruction *InstCombiner::visitAShr(Bin
       return BinaryOperator::CreateAShr(X, ConstantInt::get(Ty, AmtSum));
     }
 
+    if (match(Op0, m_OneUse(m_SExt(m_Value(X)))) &&
+        (Ty->isVectorTy() || shouldChangeType(Ty, X->getType()))) {
+      // ashr (sext X), C --> sext (ashr X, C')
+      Type *SrcTy = X->getType();
+      ShAmt = std::min(ShAmt, SrcTy->getScalarSizeInBits() - 1);
+      Value *NewSh = Builder.CreateAShr(X, ConstantInt::get(SrcTy, ShAmt));
+      return new SExtInst(NewSh, Ty);
+    }
+
     // If the shifted-out value is known-zero, then this is an exact shift.
     if (!I.isExact() &&
         MaskedValueIsZero(Op0, APInt::getLowBitsSet(BitWidth, ShAmt), 0, &I)) {

Modified: llvm/trunk/test/Transforms/InstCombine/cast.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/cast.ll?rev=310942&r1=310941&r2=310942&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/cast.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/cast.ll Tue Aug 15 11:25:52 2017
@@ -1302,13 +1302,10 @@ define i16 @test87(i16 %v) {
   ret i16 %t
 }
 
-; Do not optimize to ashr i16 (shift by 18)
 define i16 @test88(i16 %v) {
 ; CHECK-LABEL: @test88(
-; CHECK-NEXT:    [[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]]
+; CHECK-NEXT:    [[TMP1:%.*]] = ashr i16 %v, 15
+; CHECK-NEXT:    ret i16 [[TMP1]]
 ;
   %a = sext i16 %v to i32
   %s = ashr i32 %a, 18

Modified: llvm/trunk/test/Transforms/InstCombine/shift-sra.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/shift-sra.ll?rev=310942&r1=310941&r2=310942&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/shift-sra.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/shift-sra.ll Tue Aug 15 11:25:52 2017
@@ -163,13 +163,12 @@ define <2 x i32> @ashr_overshift_splat_v
   ret <2 x i32> %sh2
 }
 
-; TODO: Prefer a narrow shift for better for bit-tracking.
 ; ashr (sext X), C --> sext (ashr X, C')
 
 define i32 @hoist_ashr_ahead_of_sext_1(i8 %x) {
 ; CHECK-LABEL: @hoist_ashr_ahead_of_sext_1(
-; CHECK-NEXT:    [[SEXT:%.*]] = sext i8 %x to i32
-; CHECK-NEXT:    [[R:%.*]] = ashr i32 [[SEXT]], 3
+; CHECK-NEXT:    [[TMP1:%.*]] = ashr i8 %x, 3
+; CHECK-NEXT:    [[R:%.*]] = sext i8 [[TMP1]] to i32
 ; CHECK-NEXT:    ret i32 [[R]]
 ;
   %sext = sext i8 %x to i32
@@ -177,13 +176,12 @@ define i32 @hoist_ashr_ahead_of_sext_1(i
   ret i32 %r
 }
 
-; TODO: Prefer a narrow shift for better for bit-tracking.
 ; ashr (sext X), C --> sext (ashr X, C')
 
 define <2 x i32> @hoist_ashr_ahead_of_sext_1_splat(<2 x i8> %x) {
 ; CHECK-LABEL: @hoist_ashr_ahead_of_sext_1_splat(
-; CHECK-NEXT:    [[SEXT:%.*]] = sext <2 x i8> %x to <2 x i32>
-; CHECK-NEXT:    [[R:%.*]] = ashr <2 x i32> [[SEXT]], <i32 3, i32 3>
+; CHECK-NEXT:    [[TMP1:%.*]] = ashr <2 x i8> %x, <i8 3, i8 3>
+; CHECK-NEXT:    [[R:%.*]] = sext <2 x i8> [[TMP1]] to <2 x i32>
 ; CHECK-NEXT:    ret <2 x i32> [[R]]
 ;
   %sext = sext <2 x i8> %x to <2 x i32>
@@ -191,13 +189,12 @@ define <2 x i32> @hoist_ashr_ahead_of_se
   ret <2 x i32> %r
 }
 
-; TODO: Prefer a narrow shift for better for bit-tracking.
 ; ashr (sext X), C --> sext (ashr X, C') -- the shift amount must be clamped
 
 define i32 @hoist_ashr_ahead_of_sext_2(i8 %x) {
 ; CHECK-LABEL: @hoist_ashr_ahead_of_sext_2(
-; CHECK-NEXT:    [[SEXT:%.*]] = sext i8 %x to i32
-; CHECK-NEXT:    [[R:%.*]] = ashr i32 [[SEXT]], 8
+; CHECK-NEXT:    [[TMP1:%.*]] = ashr i8 %x, 7
+; CHECK-NEXT:    [[R:%.*]] = sext i8 [[TMP1]] to i32
 ; CHECK-NEXT:    ret i32 [[R]]
 ;
   %sext = sext i8 %x to i32
@@ -205,13 +202,12 @@ define i32 @hoist_ashr_ahead_of_sext_2(i
   ret i32 %r
 }
 
-; TODO: Prefer a narrow shift for better for bit-tracking.
 ; ashr (sext X), C --> sext (ashr X, C') -- the shift amount must be clamped
 
 define <2 x i32> @hoist_ashr_ahead_of_sext_2_splat(<2 x i8> %x) {
 ; CHECK-LABEL: @hoist_ashr_ahead_of_sext_2_splat(
-; CHECK-NEXT:    [[SEXT:%.*]] = sext <2 x i8> %x to <2 x i32>
-; CHECK-NEXT:    [[R:%.*]] = ashr <2 x i32> [[SEXT]], <i32 8, i32 8>
+; CHECK-NEXT:    [[TMP1:%.*]] = ashr <2 x i8> %x, <i8 7, i8 7>
+; CHECK-NEXT:    [[R:%.*]] = sext <2 x i8> [[TMP1]] to <2 x i32>
 ; CHECK-NEXT:    ret <2 x i32> [[R]]
 ;
   %sext = sext <2 x i8> %x to <2 x i32>




More information about the llvm-commits mailing list