[llvm] r305190 - [InstCombine] lshr (sext iM X to iN), N-M --> zext (ashr X, min(N-M, M-1)) to iN

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 12 07:23:43 PDT 2017


Author: spatel
Date: Mon Jun 12 09:23:43 2017
New Revision: 305190

URL: http://llvm.org/viewvc/llvm-project?rev=305190&view=rev
Log:
[InstCombine] lshr (sext iM X to iN), N-M --> zext (ashr X, min(N-M, M-1)) to iN

This is a follow-up to https://reviews.llvm.org/D33879 / https://reviews.llvm.org/rL304939 ,
and was discussed in https://reviews.llvm.org/D33338.

We prefer this form because a narrower shift may be cheaper, and we can more easily fold a
zext than a sext.

http://rise4fun.com/Alive/slVe

Name: shz
%s = sext i8 %x to i12
%r = lshr i12 %s, 4
=>
%a = ashr i8 %x, 4
%r = zext i8 %a to i12 

Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp
    llvm/trunk/test/Transforms/InstCombine/lshr.ll

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp?rev=305190&r1=305189&r2=305190&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp Mon Jun 12 09:23:43 2017
@@ -682,11 +682,11 @@ Instruction *InstCombiner::visitLShr(Bin
       return BinaryOperator::CreateAnd(X, ConstantInt::get(Ty, Mask));
     }
 
-    if (match(Op0, m_SExt(m_Value(X)))) {
+    if (match(Op0, m_SExt(m_Value(X))) &&
+        (!Ty->isIntegerTy() || shouldChangeType(Ty, X->getType()))) {
       // Are we moving the sign bit to the low bit and widening with high zeros?
       unsigned SrcTyBitWidth = X->getType()->getScalarSizeInBits();
-      if (ShAmt == BitWidth - 1 &&
-          (!Ty->isIntegerTy() || shouldChangeType(Ty, X->getType()))) {
+      if (ShAmt == BitWidth - 1) {
         // lshr (sext i1 X to iN), N-1 --> zext X to iN
         if (SrcTyBitWidth == 1)
           return new ZExtInst(X, Ty);
@@ -698,7 +698,13 @@ Instruction *InstCombiner::visitLShr(Bin
         }
       }
 
-      // TODO: Convert to ashr+zext if the shift equals the extension amount.
+      // lshr (sext iM X to iN), N-M --> zext (ashr X, min(N-M, M-1)) to iN
+      if (ShAmt == BitWidth - SrcTyBitWidth && Op0->hasOneUse()) {
+        // The new shift amount can't be more than the narrow source type.
+        unsigned NewShAmt = std::min(ShAmt, SrcTyBitWidth - 1);
+        Value *AShr = Builder->CreateAShr(X, NewShAmt);
+        return new ZExtInst(AShr, Ty);
+      }
     }
 
     if (match(Op0, m_LShr(m_Value(X), m_APInt(ShOp1)))) {

Modified: llvm/trunk/test/Transforms/InstCombine/lshr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/lshr.ll?rev=305190&r1=305189&r2=305190&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/lshr.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/lshr.ll Mon Jun 12 09:23:43 2017
@@ -122,10 +122,19 @@ define <2 x i8> @bool_zext_splat(<2 x i1
   ret <2 x i8> %hibit
 }
 
-; FIXME: The replicated sign bits are all that's left. This could be ashr+zext.
-
-define i16 @smear_sign_and_widen(i4 %x) {
+define i32 @smear_sign_and_widen(i8 %x) {
 ; CHECK-LABEL: @smear_sign_and_widen(
+; CHECK-NEXT:    [[TMP1:%.*]] = ashr i8 %x, 7
+; CHECK-NEXT:    [[HIBIT:%.*]] = zext i8 [[TMP1]] to i32
+; CHECK-NEXT:    ret i32 [[HIBIT]]
+;
+  %sext = sext i8 %x to i32
+  %hibit = lshr i32 %sext, 24
+  ret i32 %hibit
+}
+
+define i16 @smear_sign_and_widen_should_not_change_type(i4 %x) {
+; CHECK-LABEL: @smear_sign_and_widen_should_not_change_type(
 ; CHECK-NEXT:    [[SEXT:%.*]] = sext i4 %x to i16
 ; CHECK-NEXT:    [[HIBIT:%.*]] = lshr i16 [[SEXT]], 12
 ; CHECK-NEXT:    ret i16 [[HIBIT]]
@@ -137,8 +146,8 @@ define i16 @smear_sign_and_widen(i4 %x)
 
 define <2 x i8> @smear_sign_and_widen_splat(<2 x i6> %x) {
 ; CHECK-LABEL: @smear_sign_and_widen_splat(
-; CHECK-NEXT:    [[SEXT:%.*]] = sext <2 x i6> %x to <2 x i8>
-; CHECK-NEXT:    [[HIBIT:%.*]] = lshr <2 x i8> [[SEXT]], <i8 2, i8 2>
+; CHECK-NEXT:    [[TMP1:%.*]] = ashr <2 x i6> %x, <i6 2, i6 2>
+; CHECK-NEXT:    [[HIBIT:%.*]] = zext <2 x i6> [[TMP1]] to <2 x i8>
 ; CHECK-NEXT:    ret <2 x i8> [[HIBIT]]
 ;
   %sext = sext <2 x i6> %x to <2 x i8>




More information about the llvm-commits mailing list