[llvm] cae993d - [InstCombine] [InstCombine] reduce left-shift-of-right-shifted constant via demanded bits

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 7 15:43:41 PDT 2022


Author: Sanjay Patel
Date: 2022-06-07T18:43:27-04:00
New Revision: cae993d4c87fa2d0664bb711f100ef7b563f77d9

URL: https://github.com/llvm/llvm-project/commit/cae993d4c87fa2d0664bb711f100ef7b563f77d9
DIFF: https://github.com/llvm/llvm-project/commit/cae993d4c87fa2d0664bb711f100ef7b563f77d9.diff

LOG: [InstCombine] [InstCombine] reduce left-shift-of-right-shifted constant via demanded bits

If we don't demand low bits and it is valid to pre-shift a constant:
(C2 >> X) << C1 --> (C2 << C1) >> X

https://alive2.llvm.org/ce/z/_UzTMP

This is the reverse-order shift sibling to 82040d414b3c ( D127122 ).
It seems likely that we would want to add this to the SDAG version of
the code too to keep it on par with IR.

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
    llvm/test/Transforms/InstCombine/shift-shift.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index b682caa9cc52..d801f4d50964 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -563,7 +563,23 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
       // TODO: If we only want bits that already match the signbit then we don't
       // need to shift.
 
+      // If we can pre-shift a right-shifted constant to the left without
+      // losing any high bits amd we don't demand the low bits, then eliminate
+      // the left-shift:
+      // (C >> X) << LeftShiftAmtC --> (C << RightShiftAmtC) >> X
       uint64_t ShiftAmt = SA->getLimitedValue(BitWidth-1);
+      Value *X;
+      Constant *C;
+      if (DemandedMask.countTrailingZeros() >= ShiftAmt &&
+          match(I->getOperand(0), m_LShr(m_ImmConstant(C), m_Value(X)))) {
+        Constant *LeftShiftAmtC = ConstantInt::get(VTy, ShiftAmt);
+        Constant *NewC = ConstantExpr::getShl(C, LeftShiftAmtC);
+        if (ConstantExpr::getLShr(NewC, LeftShiftAmtC) == C) {
+          Instruction *Lshr = BinaryOperator::CreateLShr(NewC, X);
+          return InsertNewInstWith(Lshr, *I);
+        }
+      }
+
       APInt DemandedMaskIn(DemandedMask.lshr(ShiftAmt));
 
       // If the shift is NUW/NSW, then it does demand the high bits.

diff  --git a/llvm/test/Transforms/InstCombine/shift-shift.ll b/llvm/test/Transforms/InstCombine/shift-shift.ll
index e26db2ae2257..1803a7f7b135 100644
--- a/llvm/test/Transforms/InstCombine/shift-shift.ll
+++ b/llvm/test/Transforms/InstCombine/shift-shift.ll
@@ -584,11 +584,12 @@ define i16 @shl_lshr_demand6(i16 %x) {
   ret i16 %r
 }
 
+; Pre-shift a constant to eliminate shl.
+
 define i8 @lshr_shl_demand1(i8 %x) {
 ; CHECK-LABEL: @lshr_shl_demand1(
-; CHECK-NEXT:    [[SHR:%.*]] = lshr i8 28, [[X:%.*]]
-; CHECK-NEXT:    [[SHL:%.*]] = shl nuw i8 [[SHR]], 3
-; CHECK-NEXT:    [[R:%.*]] = or i8 [[SHL]], 7
+; CHECK-NEXT:    [[TMP1:%.*]] = lshr i8 -32, [[X:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = or i8 [[TMP1]], 7
 ; CHECK-NEXT:    ret i8 [[R]]
 ;
   %shr = lshr i8 28, %x ; 0b0001_1100
@@ -597,12 +598,14 @@ define i8 @lshr_shl_demand1(i8 %x) {
   ret i8 %r
 }
 
+; Extra use on lshr is ok and 'and' is another demand limiter.
+
 define i8 @lshr_shl_demand2(i8 %x) {
 ; CHECK-LABEL: @lshr_shl_demand2(
 ; CHECK-NEXT:    [[SHR:%.*]] = lshr i8 28, [[X:%.*]]
 ; CHECK-NEXT:    call void @use8(i8 [[SHR]])
-; CHECK-NEXT:    [[SHL:%.*]] = shl nuw i8 [[SHR]], 3
-; CHECK-NEXT:    [[R:%.*]] = and i8 [[SHL]], -16
+; CHECK-NEXT:    [[TMP1:%.*]] = lshr i8 -32, [[X]]
+; CHECK-NEXT:    [[R:%.*]] = and i8 [[TMP1]], -16
 ; CHECK-NEXT:    ret i8 [[R]]
 ;
   %shr = lshr i8 28, %x ; 0b0001_1100
@@ -612,6 +615,8 @@ define i8 @lshr_shl_demand2(i8 %x) {
   ret i8 %r
 }
 
+; It is not safe to pre-shift because we demand an extra low bit.
+
 define i8 @lshr_shl_demand3(i8 %x) {
 ; CHECK-LABEL: @lshr_shl_demand3(
 ; CHECK-NEXT:    [[SHR:%.*]] = lshr i8 28, [[X:%.*]]
@@ -625,6 +630,8 @@ define i8 @lshr_shl_demand3(i8 %x) {
   ret i8 %r
 }
 
+; It is not valid to pre-shift because we lose the high bit of 60.
+
 define i8 @lshr_shl_demand4(i8 %x) {
 ; CHECK-LABEL: @lshr_shl_demand4(
 ; CHECK-NEXT:    [[SHR:%.*]] = lshr i8 60, [[X:%.*]]
@@ -638,11 +645,12 @@ define i8 @lshr_shl_demand4(i8 %x) {
   ret i8 %r
 }
 
+; Splat vectors work too.
+
 define <2 x i8> @lshr_shl_demand5(<2 x i8> %x) {
 ; CHECK-LABEL: @lshr_shl_demand5(
-; CHECK-NEXT:    [[SHR:%.*]] = lshr <2 x i8> <i8 45, i8 45>, [[X:%.*]]
-; CHECK-NEXT:    [[SHL:%.*]] = shl nuw <2 x i8> [[SHR]], <i8 2, i8 2>
-; CHECK-NEXT:    [[R:%.*]] = and <2 x i8> [[SHL]], <i8 108, i8 108>
+; CHECK-NEXT:    [[TMP1:%.*]] = lshr <2 x i8> <i8 -76, i8 -76>, [[X:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = and <2 x i8> [[TMP1]], <i8 108, i8 108>
 ; CHECK-NEXT:    ret <2 x i8> [[R]]
 ;
   %shr = lshr <2 x i8> <i8 45, i8 45>, %x ; 0b0010_1101
@@ -651,6 +659,8 @@ define <2 x i8> @lshr_shl_demand5(<2 x i8> %x) {
   ret <2 x i8> %r
 }
 
+; TODO: allow undef/poison elements for this transform.
+
 define <2 x i8> @lshr_shl_demand5_undef_left(<2 x i8> %x) {
 ; CHECK-LABEL: @lshr_shl_demand5_undef_left(
 ; CHECK-NEXT:    [[SHR:%.*]] = lshr <2 x i8> <i8 45, i8 45>, [[X:%.*]]
@@ -664,6 +674,8 @@ define <2 x i8> @lshr_shl_demand5_undef_left(<2 x i8> %x) {
   ret <2 x i8> %r
 }
 
+; TODO: allow undef/poison elements for this transform.
+
 define <2 x i8> @lshr_shl_demand5_undef_right(<2 x i8> %x) {
 ; CHECK-LABEL: @lshr_shl_demand5_undef_right(
 ; CHECK-NEXT:    [[SHR:%.*]] = lshr <2 x i8> <i8 undef, i8 45>, [[X:%.*]]
@@ -677,6 +689,8 @@ define <2 x i8> @lshr_shl_demand5_undef_right(<2 x i8> %x) {
   ret <2 x i8> %r
 }
 
+; TODO: allow non-splat vector constants.
+
 define <2 x i8> @lshr_shl_demand5_nonuniform_vec_left(<2 x i8> %x) {
 ; CHECK-LABEL: @lshr_shl_demand5_nonuniform_vec_left(
 ; CHECK-NEXT:    [[SHR:%.*]] = lshr <2 x i8> <i8 45, i8 45>, [[X:%.*]]
@@ -690,11 +704,12 @@ define <2 x i8> @lshr_shl_demand5_nonuniform_vec_left(<2 x i8> %x) {
   ret <2 x i8> %r
 }
 
+; non-splat lshr constant is ok.
+
 define <2 x i8> @lshr_shl_demand5_nonuniform_vec_right(<2 x i8> %x) {
 ; CHECK-LABEL: @lshr_shl_demand5_nonuniform_vec_right(
-; CHECK-NEXT:    [[SHR:%.*]] = lshr <2 x i8> <i8 45, i8 13>, [[X:%.*]]
-; CHECK-NEXT:    [[SHL:%.*]] = shl <2 x i8> [[SHR]], <i8 2, i8 2>
-; CHECK-NEXT:    [[R:%.*]] = and <2 x i8> [[SHL]], <i8 108, i8 108>
+; CHECK-NEXT:    [[TMP1:%.*]] = lshr <2 x i8> <i8 -76, i8 52>, [[X:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = and <2 x i8> [[TMP1]], <i8 108, i8 108>
 ; CHECK-NEXT:    ret <2 x i8> [[R]]
 ;
   %shr = lshr <2 x i8> <i8 45, i8 13>, %x ; 0b0010_1101. 0b0000_1101
@@ -703,6 +718,8 @@ define <2 x i8> @lshr_shl_demand5_nonuniform_vec_right(<2 x i8> %x) {
   ret <2 x i8> %r
 }
 
+; This is possible, but may require significant changes to the demanded bits framework.
+
 define <2 x i8> @lshr_shl_demand5_nonuniform_vec_both(<2 x i8> %x) {
 ; CHECK-LABEL: @lshr_shl_demand5_nonuniform_vec_both(
 ; CHECK-NEXT:    [[SHR:%.*]] = lshr <2 x i8> <i8 45, i8 13>, [[X:%.*]]


        


More information about the llvm-commits mailing list