Skip to content

Commit 64e9443

Browse files
authored
[InstCombine] combine mul(abs(x),abs(y)) to abs(mul(x,y)) (#78395)
Fixes: #78076 Alive2 Proof: https://alive2.llvm.org/ce/z/XEDy0f
1 parent a48c1bd commit 64e9443

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed

llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,19 @@ Instruction *InstCombinerImpl::visitMul(BinaryOperator &I) {
330330
return BinaryOperator::CreateMul(X, X);
331331
}
332332

333+
{
334+
Value *X, *Y;
335+
// abs(X) * abs(Y) -> abs(X * Y)
336+
if (I.hasNoSignedWrap() &&
337+
match(Op0,
338+
m_OneUse(m_Intrinsic<Intrinsic::abs>(m_Value(X), m_One()))) &&
339+
match(Op1, m_OneUse(m_Intrinsic<Intrinsic::abs>(m_Value(Y), m_One()))))
340+
return replaceInstUsesWith(
341+
I, Builder.CreateBinaryIntrinsic(Intrinsic::abs,
342+
Builder.CreateNSWMul(X, Y),
343+
Builder.getTrue()));
344+
}
345+
333346
// -X * C --> X * -C
334347
Value *X, *Y;
335348
Constant *Op1C;

llvm/test/Transforms/InstCombine/mul.ll

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1649,6 +1649,73 @@ define <vscale x 2 x i64> @mul_scalable_splat_zero(<vscale x 2 x i64> %z) {
16491649
ret <vscale x 2 x i64> %t3
16501650
}
16511651

1652+
; fold mul(abs(x),abs(y)) -> abs(mul(x,y))
1653+
define i32 @combine_mul_abs_x_abs_y(i32 %x, i32 %y) {
1654+
; CHECK-LABEL: @combine_mul_abs_x_abs_y(
1655+
; CHECK-NEXT: [[TMP1:%.*]] = mul nsw i32 [[X:%.*]], [[Y:%.*]]
1656+
; CHECK-NEXT: [[MUL:%.*]] = call i32 @llvm.abs.i32(i32 [[TMP1]], i1 true)
1657+
; CHECK-NEXT: ret i32 [[MUL]]
1658+
;
1659+
%abs_x = call i32 @llvm.abs.i32(i32 %x, i1 true)
1660+
%abs_y = call i32 @llvm.abs.i32(i32 %y, i1 true)
1661+
%mul = mul nsw i32 %abs_x, %abs_y
1662+
ret i32 %mul
1663+
}
1664+
1665+
define i32 @combine_mul_abs_x_abs_y_no_nsw(i32 %x, i32 %y) {
1666+
; CHECK-LABEL: @combine_mul_abs_x_abs_y_no_nsw(
1667+
; CHECK-NEXT: [[ABS_X:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 true)
1668+
; CHECK-NEXT: [[ABS_Y:%.*]] = call i32 @llvm.abs.i32(i32 [[Y:%.*]], i1 true)
1669+
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[ABS_X]], [[ABS_Y]]
1670+
; CHECK-NEXT: ret i32 [[MUL]]
1671+
;
1672+
%abs_x = call i32 @llvm.abs.i32(i32 %x, i1 true)
1673+
%abs_y = call i32 @llvm.abs.i32(i32 %y, i1 true)
1674+
%mul = mul i32 %abs_x, %abs_y
1675+
ret i32 %mul
1676+
}
1677+
1678+
define i32 @combine_mul_abs_x_abs_y_poison_1(i32 %x, i32 %y) {
1679+
; CHECK-LABEL: @combine_mul_abs_x_abs_y_poison_1(
1680+
; CHECK-NEXT: [[ABS_X:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 true)
1681+
; CHECK-NEXT: [[ABS_Y:%.*]] = call i32 @llvm.abs.i32(i32 [[Y:%.*]], i1 false)
1682+
; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[ABS_X]], [[ABS_Y]]
1683+
; CHECK-NEXT: ret i32 [[MUL]]
1684+
;
1685+
%abs_x = call i32 @llvm.abs.i32(i32 %x, i1 true)
1686+
%abs_y = call i32 @llvm.abs.i32(i32 %y, i1 false)
1687+
%mul = mul nsw i32 %abs_x, %abs_y
1688+
ret i32 %mul
1689+
}
1690+
1691+
define i32 @combine_mul_abs_x_abs_y_poison_2(i32 %x, i32 %y) {
1692+
; CHECK-LABEL: @combine_mul_abs_x_abs_y_poison_2(
1693+
; CHECK-NEXT: [[ABS_X:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 false)
1694+
; CHECK-NEXT: [[ABS_Y:%.*]] = call i32 @llvm.abs.i32(i32 [[Y:%.*]], i1 false)
1695+
; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[ABS_X]], [[ABS_Y]]
1696+
; CHECK-NEXT: ret i32 [[MUL]]
1697+
;
1698+
%abs_x = call i32 @llvm.abs.i32(i32 %x, i1 false)
1699+
%abs_y = call i32 @llvm.abs.i32(i32 %y, i1 false)
1700+
%mul = mul nsw i32 %abs_x, %abs_y
1701+
ret i32 %mul
1702+
}
1703+
1704+
define i32 @combine_mul_abs_x_abs_y_not_oneuse(i32 %x, i32 %y) {
1705+
; CHECK-LABEL: @combine_mul_abs_x_abs_y_not_oneuse(
1706+
; CHECK-NEXT: [[ABS_X:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 true)
1707+
; CHECK-NEXT: [[ABS_Y:%.*]] = call i32 @llvm.abs.i32(i32 [[Y:%.*]], i1 true)
1708+
; CHECK-NEXT: [[ABS_X1:%.*]] = add nuw i32 [[ABS_Y]], 1
1709+
; CHECK-NEXT: [[RET:%.*]] = mul i32 [[ABS_X]], [[ABS_X1]]
1710+
; CHECK-NEXT: ret i32 [[RET]]
1711+
;
1712+
%abs_x = call i32 @llvm.abs.i32(i32 %x, i1 true)
1713+
%abs_y = call i32 @llvm.abs.i32(i32 %y, i1 true)
1714+
%mul = mul nsw i32 %abs_x, %abs_y
1715+
%ret = add i32 %mul, %abs_x
1716+
ret i32 %ret
1717+
}
1718+
16521719
;
16531720
; fold mul(sub(x,y),negpow2) -> shl(sub(y,x),log2(pow2))
16541721
;

0 commit comments

Comments
 (0)