Skip to content

Commit 204cabc

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 d87d8e3 commit 204cabc

File tree

3 files changed

+22
-13
lines changed

3 files changed

+22
-13
lines changed

llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -323,11 +323,20 @@ Instruction *InstCombinerImpl::visitMul(BinaryOperator &I) {
323323
if (Op0 == Op1) {
324324
Value *X, *Y;
325325
SelectPatternFlavor SPF = matchSelectPattern(Op0, X, Y).Flavor;
326-
if (SPF == SPF_ABS || SPF == SPF_NABS)
327-
return BinaryOperator::CreateMul(X, X);
326+
if (SPF == SPF_NABS ||
327+
match(Op0, m_Neg(m_Intrinsic<Intrinsic::abs>(m_Value(X))))) {
328+
if (I.hasNoUnsignedWrap()) {
329+
Instruction *NewMul = BinaryOperator::CreateNUWMul(X, X);
330+
NewMul->setHasNoSignedWrap(true);
331+
return NewMul;
332+
}
333+
return I.hasNoSignedWrap() ? BinaryOperator::CreateNSWMul(X, X)
334+
: BinaryOperator::CreateMul(X, X);
335+
}
328336

329-
if (match(Op0, m_Intrinsic<Intrinsic::abs>(m_Value(X))))
330-
return BinaryOperator::CreateMul(X, X);
337+
if (SPF == SPF_ABS || match(Op0, m_Intrinsic<Intrinsic::abs>(m_Value(X))))
338+
return I.hasNoSignedWrap() ? BinaryOperator::CreateNSWMul(X, X)
339+
: BinaryOperator::CreateMul(X, X);
331340
}
332341

333342
{

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)