Skip to content

Commit 295d6b1

Browse files
authored
[InstCombine] Fold (X * (Y << K)) u>> K -> X * Y when highbits are not demanded (#111151)
Alive2: https://alive2.llvm.org/ce/z/Z7QgjH
1 parent 877b934 commit 295d6b1

File tree

2 files changed

+71
-0
lines changed

2 files changed

+71
-0
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,15 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Instruction *I,
776776
return InsertNewInstWith(Shl, I->getIterator());
777777
}
778778
}
779+
780+
const APInt *Factor;
781+
if (match(I->getOperand(0),
782+
m_OneUse(m_Mul(m_Value(X), m_APInt(Factor)))) &&
783+
Factor->countr_zero() >= ShiftAmt) {
784+
BinaryOperator *Mul = BinaryOperator::CreateMul(
785+
X, ConstantInt::get(X->getType(), Factor->lshr(ShiftAmt)));
786+
return InsertNewInstWith(Mul, I->getIterator());
787+
}
779788
}
780789

781790
// Unsigned shift right.

llvm/test/Transforms/InstCombine/lshr.ll

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1523,3 +1523,65 @@ define <2 x i8> @bool_add_lshr_vec_wrong_shift_amt(<2 x i1> %a, <2 x i1> %b) {
15231523
%lshr = lshr <2 x i8> %add, <i8 1, i8 2>
15241524
ret <2 x i8> %lshr
15251525
}
1526+
1527+
define i32 @lowbits_of_lshr_mul(i64 %x) {
1528+
; CHECK-LABEL: @lowbits_of_lshr_mul(
1529+
; CHECK-NEXT: entry:
1530+
; CHECK-NEXT: [[TMP0:%.*]] = trunc i64 [[X:%.*]] to i32
1531+
; CHECK-NEXT: [[CONV:%.*]] = mul i32 [[TMP0]], 15
1532+
; CHECK-NEXT: ret i32 [[CONV]]
1533+
;
1534+
entry:
1535+
%mul = mul i64 %x, 64424509440
1536+
%shift = lshr i64 %mul, 32
1537+
%conv = trunc i64 %shift to i32
1538+
ret i32 %conv
1539+
}
1540+
1541+
define i32 @lowbits_of_lshr_mul_mask(i32 %x) {
1542+
; CHECK-LABEL: @lowbits_of_lshr_mul_mask(
1543+
; CHECK-NEXT: entry:
1544+
; CHECK-NEXT: [[TMP0:%.*]] = mul i32 [[X:%.*]], 1600
1545+
; CHECK-NEXT: [[CONV:%.*]] = and i32 [[TMP0]], 32704
1546+
; CHECK-NEXT: ret i32 [[CONV]]
1547+
;
1548+
entry:
1549+
%mul = mul i32 %x, 104857600
1550+
%shift = lshr i32 %mul, 16
1551+
%conv = and i32 %shift, 32767
1552+
ret i32 %conv
1553+
}
1554+
1555+
; Negative tests
1556+
1557+
define i32 @lowbits_of_lshr_mul_mask_multiuse(i32 %x) {
1558+
; CHECK-LABEL: @lowbits_of_lshr_mul_mask_multiuse(
1559+
; CHECK-NEXT: entry:
1560+
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], 104857600
1561+
; CHECK-NEXT: call void @use(i32 [[MUL]])
1562+
; CHECK-NEXT: [[SHIFT:%.*]] = lshr exact i32 [[MUL]], 16
1563+
; CHECK-NEXT: [[CONV:%.*]] = and i32 [[SHIFT]], 32704
1564+
; CHECK-NEXT: ret i32 [[CONV]]
1565+
;
1566+
entry:
1567+
%mul = mul i32 %x, 104857600
1568+
call void @use(i32 %mul)
1569+
%shift = lshr i32 %mul, 16
1570+
%conv = and i32 %shift, 32767
1571+
ret i32 %conv
1572+
}
1573+
1574+
define i32 @lowbits_of_lshr_mul_mask_indivisible(i32 %x) {
1575+
; CHECK-LABEL: @lowbits_of_lshr_mul_mask_indivisible(
1576+
; CHECK-NEXT: entry:
1577+
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], 25600
1578+
; CHECK-NEXT: [[SHIFT:%.*]] = lshr i32 [[MUL]], 16
1579+
; CHECK-NEXT: [[CONV:%.*]] = and i32 [[SHIFT]], 32767
1580+
; CHECK-NEXT: ret i32 [[CONV]]
1581+
;
1582+
entry:
1583+
%mul = mul i32 %x, 25600
1584+
%shift = lshr i32 %mul, 16
1585+
%conv = and i32 %shift, 32767
1586+
ret i32 %conv
1587+
}

0 commit comments

Comments
 (0)