[llvm] 1b24f35 - [InstCombine] improve demanded bits analysis of left-shifted operand

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Mon May 3 05:40:51 PDT 2021


Author: Sanjay Patel
Date: 2021-05-03T08:39:20-04:00
New Revision: 1b24f35f843cd58ea22ec3968d0d2589c5bdc2c9

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

LOG: [InstCombine] improve demanded bits analysis of left-shifted operand

If we don't demand high bits, then we also don't care about those
high bits of a left-shift operand regardless of shift amount.
I noticed the sext/trunc pattern in a motivating example.
It seems like there should be a low-bits with right-shift sibling,
but I haven't looked at that yet.

https://alive2.llvm.org/ce/z/JuS6jc
https://rise4fun.com/Alive/Trm (not sure how to use 'width' with Alive1)
https://alive2.llvm.org/ce/z/gRadbF

Differential Revision: https://reviews.llvm.org/D101489

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
    llvm/test/Transforms/InstCombine/rotate.ll
    llvm/test/Transforms/InstCombine/shl-demand.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index a97a50b887538..6175c921a06cd 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -559,6 +559,14 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
           return UndefValue::get(I->getType());
       }
     } else {
+      // This is a variable shift, so we can't shift the demand mask by a known
+      // amount. But if we are not demanding high bits, then we are not
+      // demanding those bits from the pre-shifted operand either.
+      if (unsigned CTLZ = DemandedMask.countLeadingZeros()) {
+        APInt DemandedFromOp(APInt::getLowBitsSet(BitWidth, BitWidth - CTLZ));
+        if (SimplifyDemandedBits(I, 0, DemandedFromOp, Known, Depth + 1))
+          return I;
+      }
       computeKnownBits(I, Known, Depth, CxtI);
     }
     break;

diff  --git a/llvm/test/Transforms/InstCombine/rotate.ll b/llvm/test/Transforms/InstCombine/rotate.ll
index 7a1066f02a94c..b0e80192809b7 100644
--- a/llvm/test/Transforms/InstCombine/rotate.ll
+++ b/llvm/test/Transforms/InstCombine/rotate.ll
@@ -443,7 +443,8 @@ define i8 @rotate_right_commute_8bit_unmasked_shl(i32 %v, i32 %shift) {
 ; CHECK-NEXT:    [[TMP1:%.*]] = trunc i32 [[SHIFT:%.*]] to i8
 ; CHECK-NEXT:    [[TMP2:%.*]] = and i8 [[TMP1]], 3
 ; CHECK-NEXT:    [[TMP3:%.*]] = trunc i32 [[V:%.*]] to i8
-; CHECK-NEXT:    [[CONV2:%.*]] = call i8 @llvm.fshr.i8(i8 [[TMP3]], i8 [[TMP3]], i8 [[TMP2]])
+; CHECK-NEXT:    [[TMP4:%.*]] = trunc i32 [[V]] to i8
+; CHECK-NEXT:    [[CONV2:%.*]] = call i8 @llvm.fshr.i8(i8 [[TMP3]], i8 [[TMP4]], i8 [[TMP2]])
 ; CHECK-NEXT:    ret i8 [[CONV2]]
 ;
   %and = and i32 %shift, 3

diff  --git a/llvm/test/Transforms/InstCombine/shl-demand.ll b/llvm/test/Transforms/InstCombine/shl-demand.ll
index 491ff09175961..f2e59a1c4fcc6 100644
--- a/llvm/test/Transforms/InstCombine/shl-demand.ll
+++ b/llvm/test/Transforms/InstCombine/shl-demand.ll
@@ -3,8 +3,8 @@
 
 define i16 @sext_shl_trunc_same_size(i16 %x, i32 %y) {
 ; CHECK-LABEL: @sext_shl_trunc_same_size(
-; CHECK-NEXT:    [[CONV:%.*]] = sext i16 [[X:%.*]] to i32
-; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[CONV]], [[Y:%.*]]
+; CHECK-NEXT:    [[CONV1:%.*]] = zext i16 [[X:%.*]] to i32
+; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[CONV1]], [[Y:%.*]]
 ; CHECK-NEXT:    [[T:%.*]] = trunc i32 [[SHL]] to i16
 ; CHECK-NEXT:    ret i16 [[T]]
 ;
@@ -16,8 +16,8 @@ define i16 @sext_shl_trunc_same_size(i16 %x, i32 %y) {
 
 define i5 @sext_shl_trunc_smaller(i16 %x, i32 %y) {
 ; CHECK-LABEL: @sext_shl_trunc_smaller(
-; CHECK-NEXT:    [[CONV:%.*]] = sext i16 [[X:%.*]] to i32
-; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[CONV]], [[Y:%.*]]
+; CHECK-NEXT:    [[CONV1:%.*]] = zext i16 [[X:%.*]] to i32
+; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[CONV1]], [[Y:%.*]]
 ; CHECK-NEXT:    [[T:%.*]] = trunc i32 [[SHL]] to i5
 ; CHECK-NEXT:    ret i5 [[T]]
 ;
@@ -27,6 +27,8 @@ define i5 @sext_shl_trunc_smaller(i16 %x, i32 %y) {
   ret i5 %t
 }
 
+; negative test - demanding 1 high-bit too many to change the extend
+
 define i17 @sext_shl_trunc_larger(i16 %x, i32 %y) {
 ; CHECK-LABEL: @sext_shl_trunc_larger(
 ; CHECK-NEXT:    [[CONV:%.*]] = sext i16 [[X:%.*]] to i32
@@ -42,8 +44,8 @@ define i17 @sext_shl_trunc_larger(i16 %x, i32 %y) {
 
 define i32 @sext_shl_mask(i16 %x, i32 %y) {
 ; CHECK-LABEL: @sext_shl_mask(
-; CHECK-NEXT:    [[CONV:%.*]] = sext i16 [[X:%.*]] to i32
-; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[CONV]], [[Y:%.*]]
+; CHECK-NEXT:    [[CONV1:%.*]] = zext i16 [[X:%.*]] to i32
+; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[CONV1]], [[Y:%.*]]
 ; CHECK-NEXT:    [[T:%.*]] = and i32 [[SHL]], 65535
 ; CHECK-NEXT:    ret i32 [[T]]
 ;
@@ -53,6 +55,8 @@ define i32 @sext_shl_mask(i16 %x, i32 %y) {
   ret i32 %t
 }
 
+; negative test - demanding a bit that could change with sext
+
 define i32 @sext_shl_mask_higher(i16 %x, i32 %y) {
 ; CHECK-LABEL: @sext_shl_mask_higher(
 ; CHECK-NEXT:    [[CONV:%.*]] = sext i16 [[X:%.*]] to i32
@@ -66,9 +70,11 @@ define i32 @sext_shl_mask_higher(i16 %x, i32 %y) {
   ret i32 %t
 }
 
+; May need some, but not all of the bits set by the 'or'.
+
 define i32 @set_shl_mask(i32 %x, i32 %y) {
 ; CHECK-LABEL: @set_shl_mask(
-; CHECK-NEXT:    [[Z:%.*]] = or i32 [[X:%.*]], 196609
+; CHECK-NEXT:    [[Z:%.*]] = or i32 [[X:%.*]], 65537
 ; CHECK-NEXT:    [[S:%.*]] = shl i32 [[Z]], [[Y:%.*]]
 ; CHECK-NEXT:    [[R:%.*]] = and i32 [[S]], 65536
 ; CHECK-NEXT:    ret i32 [[R]]


        


More information about the llvm-commits mailing list