Skip to content

Commit 0c6979b

Browse files
committed
[InstCombine] fold opposite shifts around an add
((X << C) + Y) >>u C --> (X + (Y >>u C)) & (-1 >>u C) https://alive2.llvm.org/ce/z/DY9DPg This replaces a shift with an 'and', and in the case where the add has a constant operand, it eliminates both shifts. As noted in the TODO comment, we already have this fold when the shifts are in the opposite order (and that code handles bitwise logic ops too). Fixes #52851
1 parent fd9cd34 commit 0c6979b

File tree

3 files changed

+196
-188
lines changed

3 files changed

+196
-188
lines changed

llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1057,6 +1057,21 @@ Instruction *InstCombinerImpl::visitLShr(BinaryOperator &I) {
10571057
return BinaryOperator::CreateAnd(X, ConstantInt::get(Ty, Mask));
10581058
}
10591059

1060+
// ((X << C) + Y) >>u C --> (X + (Y >>u C)) & (-1 >>u C)
1061+
// TODO: Consolidate with the more general transform that starts from shl
1062+
// (the shifts are in the opposite order).
1063+
Value *Y;
1064+
if (match(Op0,
1065+
m_OneUse(m_c_Add(m_OneUse(m_Shl(m_Value(X), m_Specific(Op1))),
1066+
m_Value(Y))))) {
1067+
Value *NewLshr = Builder.CreateLShr(Y, Op1);
1068+
Value *NewAdd = Builder.CreateAdd(NewLshr, X);
1069+
unsigned Op1Val = C->getLimitedValue(BitWidth);
1070+
APInt Bits = APInt::getLowBitsSet(BitWidth, BitWidth - Op1Val);
1071+
Constant *Mask = ConstantInt::get(Ty, Bits);
1072+
return BinaryOperator::CreateAnd(NewAdd, Mask);
1073+
}
1074+
10601075
if (match(Op0, m_OneUse(m_ZExt(m_Value(X)))) &&
10611076
(!Ty->isIntegerTy() || shouldChangeType(Ty, X->getType()))) {
10621077
assert(ShAmtC < X->getType()->getScalarSizeInBits() &&
@@ -1094,7 +1109,6 @@ Instruction *InstCombinerImpl::visitLShr(BinaryOperator &I) {
10941109
}
10951110
}
10961111

1097-
Value *Y;
10981112
if (ShAmtC == BitWidth - 1) {
10991113
// lshr i32 or(X,-X), 31 --> zext (X != 0)
11001114
if (match(Op0, m_OneUse(m_c_Or(m_Neg(m_Value(X)), m_Deferred(X)))))

llvm/test/Transforms/InstCombine/lshr.ll

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,8 @@ define i8 @lshr_cttz_zero_is_undef_vec(<2 x i8> %x) {
138138

139139
define i8 @lshr_exact(i8 %x) {
140140
; CHECK-LABEL: @lshr_exact(
141-
; CHECK-NEXT: [[SHL:%.*]] = shl i8 [[X:%.*]], 2
142-
; CHECK-NEXT: [[ADD:%.*]] = add i8 [[SHL]], 4
143-
; CHECK-NEXT: [[LSHR:%.*]] = lshr exact i8 [[ADD]], 2
141+
; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[X:%.*]], 1
142+
; CHECK-NEXT: [[LSHR:%.*]] = and i8 [[TMP1]], 63
144143
; CHECK-NEXT: ret i8 [[LSHR]]
145144
;
146145
%shl = shl i8 %x, 2
@@ -151,9 +150,8 @@ define i8 @lshr_exact(i8 %x) {
151150

152151
define <2 x i8> @lshr_exact_splat_vec(<2 x i8> %x) {
153152
; CHECK-LABEL: @lshr_exact_splat_vec(
154-
; CHECK-NEXT: [[SHL:%.*]] = shl <2 x i8> [[X:%.*]], <i8 2, i8 2>
155-
; CHECK-NEXT: [[ADD:%.*]] = add <2 x i8> [[SHL]], <i8 4, i8 4>
156-
; CHECK-NEXT: [[LSHR:%.*]] = lshr exact <2 x i8> [[ADD]], <i8 2, i8 2>
153+
; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i8> [[X:%.*]], <i8 1, i8 1>
154+
; CHECK-NEXT: [[LSHR:%.*]] = and <2 x i8> [[TMP1]], <i8 63, i8 63>
157155
; CHECK-NEXT: ret <2 x i8> [[LSHR]]
158156
;
159157
%shl = shl <2 x i8> %x, <i8 2, i8 2>
@@ -164,9 +162,9 @@ define <2 x i8> @lshr_exact_splat_vec(<2 x i8> %x) {
164162

165163
define i8 @shl_add(i8 %x, i8 %y) {
166164
; CHECK-LABEL: @shl_add(
167-
; CHECK-NEXT: [[L:%.*]] = shl i8 [[X:%.*]], 2
168-
; CHECK-NEXT: [[A:%.*]] = add i8 [[L]], [[Y:%.*]]
169-
; CHECK-NEXT: [[R:%.*]] = lshr i8 [[A]], 2
165+
; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 [[Y:%.*]], 2
166+
; CHECK-NEXT: [[TMP2:%.*]] = add i8 [[TMP1]], [[X:%.*]]
167+
; CHECK-NEXT: [[R:%.*]] = and i8 [[TMP2]], 63
170168
; CHECK-NEXT: ret i8 [[R]]
171169
;
172170
%l = shl i8 %x, 2
@@ -178,9 +176,9 @@ define i8 @shl_add(i8 %x, i8 %y) {
178176
define <2 x i8> @shl_add_commute_vec(<2 x i8> %x, <2 x i8> %py) {
179177
; CHECK-LABEL: @shl_add_commute_vec(
180178
; CHECK-NEXT: [[Y:%.*]] = mul <2 x i8> [[PY:%.*]], [[PY]]
181-
; CHECK-NEXT: [[L:%.*]] = shl <2 x i8> [[X:%.*]], <i8 3, i8 3>
182-
; CHECK-NEXT: [[A:%.*]] = add <2 x i8> [[Y]], [[L]]
183-
; CHECK-NEXT: [[R:%.*]] = lshr <2 x i8> [[A]], <i8 3, i8 3>
179+
; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i8> [[Y]], <i8 3, i8 3>
180+
; CHECK-NEXT: [[TMP2:%.*]] = add <2 x i8> [[TMP1]], [[X:%.*]]
181+
; CHECK-NEXT: [[R:%.*]] = and <2 x i8> [[TMP2]], <i8 31, i8 31>
184182
; CHECK-NEXT: ret <2 x i8> [[R]]
185183
;
186184
%y = mul <2 x i8> %py, %py ; thwart complexity-based canonicalization

0 commit comments

Comments
 (0)