[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