Skip to content

Commit

Permalink
[InstCombine] combine mul(abs(x),abs(y)) to abs(mul(x,y)) (llvm#78395)
Browse files Browse the repository at this point in the history
  • Loading branch information
HerrCai0907 authored Jan 18, 2024
1 parent a48c1bd commit 64e9443
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 0 deletions.
13 changes: 13 additions & 0 deletions llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,19 @@ Instruction *InstCombinerImpl::visitMul(BinaryOperator &I) {
return BinaryOperator::CreateMul(X, X);
}

{
Value *X, *Y;
// abs(X) * abs(Y) -> abs(X * Y)
if (I.hasNoSignedWrap() &&
match(Op0,
m_OneUse(m_Intrinsic<Intrinsic::abs>(m_Value(X), m_One()))) &&
match(Op1, m_OneUse(m_Intrinsic<Intrinsic::abs>(m_Value(Y), m_One()))))
return replaceInstUsesWith(
I, Builder.CreateBinaryIntrinsic(Intrinsic::abs,
Builder.CreateNSWMul(X, Y),
Builder.getTrue()));
}

// -X * C --> X * -C
Value *X, *Y;
Constant *Op1C;
Expand Down
67 changes: 67 additions & 0 deletions llvm/test/Transforms/InstCombine/mul.ll
Original file line number Diff line number Diff line change
Expand Up @@ -1649,6 +1649,73 @@ define <vscale x 2 x i64> @mul_scalable_splat_zero(<vscale x 2 x i64> %z) {
ret <vscale x 2 x i64> %t3
}

; fold mul(abs(x),abs(y)) -> abs(mul(x,y))
define i32 @combine_mul_abs_x_abs_y(i32 %x, i32 %y) {
; CHECK-LABEL: @combine_mul_abs_x_abs_y(
; CHECK-NEXT: [[TMP1:%.*]] = mul nsw i32 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT: [[MUL:%.*]] = call i32 @llvm.abs.i32(i32 [[TMP1]], i1 true)
; CHECK-NEXT: ret i32 [[MUL]]
;
%abs_x = call i32 @llvm.abs.i32(i32 %x, i1 true)
%abs_y = call i32 @llvm.abs.i32(i32 %y, i1 true)
%mul = mul nsw i32 %abs_x, %abs_y
ret i32 %mul
}

define i32 @combine_mul_abs_x_abs_y_no_nsw(i32 %x, i32 %y) {
; CHECK-LABEL: @combine_mul_abs_x_abs_y_no_nsw(
; CHECK-NEXT: [[ABS_X:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 true)
; CHECK-NEXT: [[ABS_Y:%.*]] = call i32 @llvm.abs.i32(i32 [[Y:%.*]], i1 true)
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[ABS_X]], [[ABS_Y]]
; CHECK-NEXT: ret i32 [[MUL]]
;
%abs_x = call i32 @llvm.abs.i32(i32 %x, i1 true)
%abs_y = call i32 @llvm.abs.i32(i32 %y, i1 true)
%mul = mul i32 %abs_x, %abs_y
ret i32 %mul
}

define i32 @combine_mul_abs_x_abs_y_poison_1(i32 %x, i32 %y) {
; CHECK-LABEL: @combine_mul_abs_x_abs_y_poison_1(
; CHECK-NEXT: [[ABS_X:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 true)
; CHECK-NEXT: [[ABS_Y:%.*]] = call i32 @llvm.abs.i32(i32 [[Y:%.*]], i1 false)
; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[ABS_X]], [[ABS_Y]]
; CHECK-NEXT: ret i32 [[MUL]]
;
%abs_x = call i32 @llvm.abs.i32(i32 %x, i1 true)
%abs_y = call i32 @llvm.abs.i32(i32 %y, i1 false)
%mul = mul nsw i32 %abs_x, %abs_y
ret i32 %mul
}

define i32 @combine_mul_abs_x_abs_y_poison_2(i32 %x, i32 %y) {
; CHECK-LABEL: @combine_mul_abs_x_abs_y_poison_2(
; CHECK-NEXT: [[ABS_X:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 false)
; CHECK-NEXT: [[ABS_Y:%.*]] = call i32 @llvm.abs.i32(i32 [[Y:%.*]], i1 false)
; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[ABS_X]], [[ABS_Y]]
; CHECK-NEXT: ret i32 [[MUL]]
;
%abs_x = call i32 @llvm.abs.i32(i32 %x, i1 false)
%abs_y = call i32 @llvm.abs.i32(i32 %y, i1 false)
%mul = mul nsw i32 %abs_x, %abs_y
ret i32 %mul
}

define i32 @combine_mul_abs_x_abs_y_not_oneuse(i32 %x, i32 %y) {
; CHECK-LABEL: @combine_mul_abs_x_abs_y_not_oneuse(
; CHECK-NEXT: [[ABS_X:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 true)
; CHECK-NEXT: [[ABS_Y:%.*]] = call i32 @llvm.abs.i32(i32 [[Y:%.*]], i1 true)
; CHECK-NEXT: [[ABS_X1:%.*]] = add nuw i32 [[ABS_Y]], 1
; CHECK-NEXT: [[RET:%.*]] = mul i32 [[ABS_X]], [[ABS_X1]]
; CHECK-NEXT: ret i32 [[RET]]
;
%abs_x = call i32 @llvm.abs.i32(i32 %x, i1 true)
%abs_y = call i32 @llvm.abs.i32(i32 %y, i1 true)
%mul = mul nsw i32 %abs_x, %abs_y
%ret = add i32 %mul, %abs_x
ret i32 %ret
}

;
; fold mul(sub(x,y),negpow2) -> shl(sub(y,x),log2(pow2))
;
Expand Down

0 comments on commit 64e9443

Please sign in to comment.