Skip to content

Commit ca3c98a

Browse files
committed
[InstCombine] Preserve flags for abs(X) * abs(X) and nabs(X) * nabs(X)
Alive2 Proofs: https://alive2.llvm.org/ce/z/CN9BP- https://alive2.llvm.org/ce/z/kq9vh6 https://alive2.llvm.org/ce/z/LtVSL5
1 parent ed886a9 commit ca3c98a

File tree

3 files changed

+29
-11
lines changed

3 files changed

+29
-11
lines changed

llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -320,8 +320,26 @@ Instruction *InstCombinerImpl::visitMul(BinaryOperator &I) {
320320

321321
// abs(X) * abs(X) -> X * X
322322
Value *X;
323-
if (Op0 == Op1 && match(Op0, m_Intrinsic<Intrinsic::abs>(m_Value(X))))
324-
return BinaryOperator::CreateMul(X, X);
323+
if (Op0 == Op1) {
324+
// nabs(X) * nabs(X) -> X * X
325+
if (match(Op0, m_Neg(m_Intrinsic<Intrinsic::abs>(m_Value(X))))) {
326+
Instruction *NewMul = BinaryOperator::CreateMul(X, X);
327+
if (I.hasNoUnsignedWrap()) {
328+
// (nabs * nabs) nuw in this case also implies nsw
329+
NewMul->setHasNoUnsignedWrap(true);
330+
NewMul->setHasNoSignedWrap(true);
331+
} else if (I.hasNoSignedWrap())
332+
NewMul->setHasNoSignedWrap(true);
333+
334+
return NewMul;
335+
}
336+
337+
if (match(Op0, m_Intrinsic<Intrinsic::abs>(m_Value(X)))) {
338+
Instruction *NewMul = BinaryOperator::CreateMul(X, X);
339+
NewMul->setHasNoSignedWrap(I.hasNoSignedWrap());
340+
return NewMul;
341+
}
342+
}
325343

326344
{
327345
Value *Y;

llvm/test/Transforms/InstCombine/mul-inseltpoison.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -927,7 +927,7 @@ define i32 @combine_mul_abs_intrin_nuw(i32 %x) {
927927

928928
define i32 @combine_mul_abs_intrin_nsw(i32 %x) {
929929
; CHECK-LABEL: @combine_mul_abs_intrin_nsw(
930-
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], [[X]]
930+
; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[X:%.*]], [[X]]
931931
; CHECK-NEXT: ret i32 [[MUL]]
932932
;
933933
%abs = call i32 @llvm.abs.i32(i32 %x, i1 false)
@@ -948,7 +948,7 @@ define i32 @combine_mul_nabs_intrin(i32 %x) {
948948

949949
define i32 @combine_mul_nabs_intrin_nuw(i32 %x) {
950950
; CHECK-LABEL: @combine_mul_nabs_intrin_nuw(
951-
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], [[X]]
951+
; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i32 [[X:%.*]], [[X]]
952952
; CHECK-NEXT: ret i32 [[MUL]]
953953
;
954954
%abs = call i32 @llvm.abs.i32(i32 %x, i1 false)
@@ -959,7 +959,7 @@ define i32 @combine_mul_nabs_intrin_nuw(i32 %x) {
959959

960960
define i32 @combine_mul_nabs_intrin_nsw(i32 %x) {
961961
; CHECK-LABEL: @combine_mul_nabs_intrin_nsw(
962-
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], [[X]]
962+
; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[X:%.*]], [[X]]
963963
; CHECK-NEXT: ret i32 [[MUL]]
964964
;
965965
%abs = call i32 @llvm.abs.i32(i32 %x, i1 false)

llvm/test/Transforms/InstCombine/mul.ll

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1607,7 +1607,7 @@ define i32 @combine_mul_nabs_i32(i32 %0) {
16071607

16081608
define i32 @combine_mul_nabs_i32_unsigned_wrap(i32 %0) {
16091609
; CHECK-LABEL: @combine_mul_nabs_i32_unsigned_wrap(
1610-
; CHECK-NEXT: [[M:%.*]] = mul i32 [[TMP0:%.*]], [[TMP0]]
1610+
; CHECK-NEXT: [[M:%.*]] = mul nuw nsw i32 [[TMP0:%.*]], [[TMP0]]
16111611
; CHECK-NEXT: ret i32 [[M]]
16121612
;
16131613
%c = icmp slt i32 %0, 0
@@ -1619,7 +1619,7 @@ define i32 @combine_mul_nabs_i32_unsigned_wrap(i32 %0) {
16191619

16201620
define i32 @combine_mul_nabs_i32_signed_wrap(i32 %0) {
16211621
; CHECK-LABEL: @combine_mul_nabs_i32_signed_wrap(
1622-
; CHECK-NEXT: [[M:%.*]] = mul i32 [[TMP0:%.*]], [[TMP0]]
1622+
; CHECK-NEXT: [[M:%.*]] = mul nsw i32 [[TMP0:%.*]], [[TMP0]]
16231623
; CHECK-NEXT: ret i32 [[M]]
16241624
;
16251625
%c = icmp slt i32 %0, 0
@@ -1644,7 +1644,7 @@ define <4 x i32> @combine_mul_nabs_v4i32(<4 x i32> %0) {
16441644

16451645
define <4 x i32> @combine_mul_nabs_v4i32_unsigned_wrap(<4 x i32> %0) {
16461646
; CHECK-LABEL: @combine_mul_nabs_v4i32_unsigned_wrap(
1647-
; CHECK-NEXT: [[M:%.*]] = mul <4 x i32> [[TMP0:%.*]], [[TMP0]]
1647+
; CHECK-NEXT: [[M:%.*]] = mul nuw nsw <4 x i32> [[TMP0:%.*]], [[TMP0]]
16481648
; CHECK-NEXT: ret <4 x i32> [[M]]
16491649
;
16501650
%c = icmp slt <4 x i32> %0, zeroinitializer
@@ -1656,7 +1656,7 @@ define <4 x i32> @combine_mul_nabs_v4i32_unsigned_wrap(<4 x i32> %0) {
16561656

16571657
define <4 x i32> @combine_mul_nabs_v4i32_signed_wrap(<4 x i32> %0) {
16581658
; CHECK-LABEL: @combine_mul_nabs_v4i32_signed_wrap(
1659-
; CHECK-NEXT: [[M:%.*]] = mul <4 x i32> [[TMP0:%.*]], [[TMP0]]
1659+
; CHECK-NEXT: [[M:%.*]] = mul nsw <4 x i32> [[TMP0:%.*]], [[TMP0]]
16601660
; CHECK-NEXT: ret <4 x i32> [[M]]
16611661
;
16621662
%c = icmp slt <4 x i32> %0, zeroinitializer
@@ -1689,7 +1689,7 @@ define i32 @combine_mul_nabs_intrin(i32 %x) {
16891689

16901690
define i32 @combine_mul_nabs_intrin_unsigned_flags(i32 %x) {
16911691
; CHECK-LABEL: @combine_mul_nabs_intrin_unsigned_flags(
1692-
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], [[X]]
1692+
; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i32 [[X:%.*]], [[X]]
16931693
; CHECK-NEXT: ret i32 [[MUL]]
16941694
;
16951695
%abs = call i32 @llvm.abs.i32(i32 %x, i1 false)
@@ -1700,7 +1700,7 @@ define i32 @combine_mul_nabs_intrin_unsigned_flags(i32 %x) {
17001700

17011701
define i32 @combine_mul_nabs_intrin_signed_flags(i32 %x) {
17021702
; CHECK-LABEL: @combine_mul_nabs_intrin_signed_flags(
1703-
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], [[X]]
1703+
; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[X:%.*]], [[X]]
17041704
; CHECK-NEXT: ret i32 [[MUL]]
17051705
;
17061706
%abs = call i32 @llvm.abs.i32(i32 %x, i1 false)

0 commit comments

Comments
 (0)