[llvm] [InstCombine] abs(X) * abs(X) and nabs(X) * nabs(X) should preserve flags (PR #88662)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Apr 14 09:02:58 PDT 2024
https://github.com/AtariDreams updated https://github.com/llvm/llvm-project/pull/88662
>From 7dffc520e1020dcdbfd8668811474b4a923da72b Mon Sep 17 00:00:00 2001
From: Rose <gfunni234 at gmail.com>
Date: Sun, 14 Apr 2024 11:50:44 -0400
Subject: [PATCH 1/2] [InstCombine] Pre-commit tests (NFC)
---
llvm/test/Transforms/InstCombine/mul.ll | 73 ++++++++++++++++++++++++-
1 file changed, 72 insertions(+), 1 deletion(-)
diff --git a/llvm/test/Transforms/InstCombine/mul.ll b/llvm/test/Transforms/InstCombine/mul.ll
index d4a689c60786e0..f9bc756eb05999 100644
--- a/llvm/test/Transforms/InstCombine/mul.ll
+++ b/llvm/test/Transforms/InstCombine/mul.ll
@@ -1605,6 +1605,31 @@ define i32 @combine_mul_nabs_i32(i32 %0) {
ret i32 %m
}
+define i32 @combine_mul_nabs_i32_unsigned_wrap(i32 %0) {
+; CHECK-LABEL: @combine_mul_nabs_i32_unsigned_wrap(
+; CHECK-NEXT: [[M:%.*]] = mul i32 [[TMP0:%.*]], [[TMP0]]
+; CHECK-NEXT: ret i32 [[M]]
+;
+ %c = icmp slt i32 %0, 0
+ %s = sub nsw i32 0, %0
+ %r = select i1 %c, i32 %0, i32 %s
+ %m = mul nuw i32 %r, %r
+ ret i32 %m
+}
+
+define i32 @combine_mul_nabs_i32_signed_wrap(i32 %0) {
+; CHECK-LABEL: @combine_mul_nabs_i32_signed_wrap(
+; CHECK-NEXT: [[M:%.*]] = mul i32 [[TMP0:%.*]], [[TMP0]]
+; CHECK-NEXT: ret i32 [[M]]
+;
+ %c = icmp slt i32 %0, 0
+ %s = sub nsw i32 0, %0
+ %r = select i1 %c, i32 %0, i32 %s
+ %m = mul nsw i32 %r, %r
+ ret i32 %m
+}
+
+
define <4 x i32> @combine_mul_nabs_v4i32(<4 x i32> %0) {
; CHECK-LABEL: @combine_mul_nabs_v4i32(
; CHECK-NEXT: [[M:%.*]] = mul <4 x i32> [[TMP0:%.*]], [[TMP0]]
@@ -1617,13 +1642,37 @@ define <4 x i32> @combine_mul_nabs_v4i32(<4 x i32> %0) {
ret <4 x i32> %m
}
+define <4 x i32> @combine_mul_nabs_v4i32_unsigned_wrap(<4 x i32> %0) {
+; CHECK-LABEL: @combine_mul_nabs_v4i32_unsigned_wrap(
+; CHECK-NEXT: [[M:%.*]] = mul <4 x i32> [[TMP0:%.*]], [[TMP0]]
+; CHECK-NEXT: ret <4 x i32> [[M]]
+;
+ %c = icmp slt <4 x i32> %0, zeroinitializer
+ %s = sub nsw <4 x i32> zeroinitializer, %0
+ %r = select <4 x i1> %c, <4 x i32> %0, <4 x i32> %s
+ %m = mul nuw <4 x i32> %r, %r
+ ret <4 x i32> %m
+}
+
+define <4 x i32> @combine_mul_nabs_v4i32_signed_wrap(<4 x i32> %0) {
+; CHECK-LABEL: @combine_mul_nabs_v4i32_signed_wrap(
+; CHECK-NEXT: [[M:%.*]] = mul <4 x i32> [[TMP0:%.*]], [[TMP0]]
+; CHECK-NEXT: ret <4 x i32> [[M]]
+;
+ %c = icmp slt <4 x i32> %0, zeroinitializer
+ %s = sub nsw <4 x i32> zeroinitializer, %0
+ %r = select <4 x i1> %c, <4 x i32> %0, <4 x i32> %s
+ %m = mul nsw <4 x i32> %r, %r
+ ret <4 x i32> %m
+}
+
define i32 @combine_mul_abs_intrin(i32 %x) {
; CHECK-LABEL: @combine_mul_abs_intrin(
; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], [[X]]
; CHECK-NEXT: ret i32 [[MUL]]
;
%abs = call i32 @llvm.abs.i32(i32 %x, i1 false)
- %mul = mul i32 %abs, %abs
+ %mul = mul nuw i32 %abs, %abs
ret i32 %mul
}
@@ -1638,6 +1687,28 @@ define i32 @combine_mul_nabs_intrin(i32 %x) {
ret i32 %mul
}
+define i32 @combine_mul_nabs_intrin_unsigned_flags(i32 %x) {
+; CHECK-LABEL: @combine_mul_nabs_intrin_unsigned_flags(
+; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], [[X]]
+; CHECK-NEXT: ret i32 [[MUL]]
+;
+ %abs = call i32 @llvm.abs.i32(i32 %x, i1 false)
+ %neg = sub i32 0, %abs
+ %mul = mul nuw i32 %neg, %neg
+ ret i32 %mul
+}
+
+define i32 @combine_mul_nabs_intrin_signed_flags(i32 %x) {
+; CHECK-LABEL: @combine_mul_nabs_intrin_signed_flags(
+; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], [[X]]
+; CHECK-NEXT: ret i32 [[MUL]]
+;
+ %abs = call i32 @llvm.abs.i32(i32 %x, i1 false)
+ %neg = sub i32 0, %abs
+ %mul = mul nsw i32 %neg, %neg
+ ret i32 %mul
+}
+
; z * splat(0) = splat(0), even for scalable vectors
define <vscale x 2 x i64> @mul_scalable_splat_zero(<vscale x 2 x i64> %z) {
; CHECK-LABEL: @mul_scalable_splat_zero(
>From 9db57c50398a05666e8e39dfe3802b346f4f74d3 Mon Sep 17 00:00:00 2001
From: Rose <gfunni234 at gmail.com>
Date: Sun, 14 Apr 2024 11:31:02 -0400
Subject: [PATCH 2/2] [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
---
.../InstCombine/InstCombineMulDivRem.cpp | 17 +++++++++++++----
llvm/test/Transforms/InstCombine/mul.ll | 12 ++++++------
2 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index 4dc1319f1c437f..ee092add097771 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -323,11 +323,20 @@ Instruction *InstCombinerImpl::visitMul(BinaryOperator &I) {
if (Op0 == Op1) {
Value *X, *Y;
SelectPatternFlavor SPF = matchSelectPattern(Op0, X, Y).Flavor;
- if (SPF == SPF_ABS || SPF == SPF_NABS)
- return BinaryOperator::CreateMul(X, X);
+ if (SPF == SPF_NABS ||
+ match(Op0, m_Neg(m_Intrinsic<Intrinsic::abs>(m_Value(X))))) {
+ if (I.hasNoUnsignedWrap()) {
+ Instruction *NewMul = BinaryOperator::CreateNUWMul(X, X);
+ NewMul->setHasNoSignedWrap(true);
+ return NewMul;
+ }
+ return I.hasNoSignedWrap() ? BinaryOperator::CreateNSWMul(X, X)
+ : BinaryOperator::CreateMul(X, X);
+ }
- if (match(Op0, m_Intrinsic<Intrinsic::abs>(m_Value(X))))
- return BinaryOperator::CreateMul(X, X);
+ if (SPF == SPF_ABS || match(Op0, m_Intrinsic<Intrinsic::abs>(m_Value(X))))
+ return I.hasNoSignedWrap() ? BinaryOperator::CreateNSWMul(X, X)
+ : BinaryOperator::CreateMul(X, X);
}
{
diff --git a/llvm/test/Transforms/InstCombine/mul.ll b/llvm/test/Transforms/InstCombine/mul.ll
index f9bc756eb05999..e478e34ddd4859 100644
--- a/llvm/test/Transforms/InstCombine/mul.ll
+++ b/llvm/test/Transforms/InstCombine/mul.ll
@@ -1607,7 +1607,7 @@ define i32 @combine_mul_nabs_i32(i32 %0) {
define i32 @combine_mul_nabs_i32_unsigned_wrap(i32 %0) {
; CHECK-LABEL: @combine_mul_nabs_i32_unsigned_wrap(
-; CHECK-NEXT: [[M:%.*]] = mul i32 [[TMP0:%.*]], [[TMP0]]
+; CHECK-NEXT: [[M:%.*]] = mul nuw nsw i32 [[TMP0:%.*]], [[TMP0]]
; CHECK-NEXT: ret i32 [[M]]
;
%c = icmp slt i32 %0, 0
@@ -1619,7 +1619,7 @@ define i32 @combine_mul_nabs_i32_unsigned_wrap(i32 %0) {
define i32 @combine_mul_nabs_i32_signed_wrap(i32 %0) {
; CHECK-LABEL: @combine_mul_nabs_i32_signed_wrap(
-; CHECK-NEXT: [[M:%.*]] = mul i32 [[TMP0:%.*]], [[TMP0]]
+; CHECK-NEXT: [[M:%.*]] = mul nsw i32 [[TMP0:%.*]], [[TMP0]]
; CHECK-NEXT: ret i32 [[M]]
;
%c = icmp slt i32 %0, 0
@@ -1644,7 +1644,7 @@ define <4 x i32> @combine_mul_nabs_v4i32(<4 x i32> %0) {
define <4 x i32> @combine_mul_nabs_v4i32_unsigned_wrap(<4 x i32> %0) {
; CHECK-LABEL: @combine_mul_nabs_v4i32_unsigned_wrap(
-; CHECK-NEXT: [[M:%.*]] = mul <4 x i32> [[TMP0:%.*]], [[TMP0]]
+; CHECK-NEXT: [[M:%.*]] = mul nuw nsw <4 x i32> [[TMP0:%.*]], [[TMP0]]
; CHECK-NEXT: ret <4 x i32> [[M]]
;
%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) {
define <4 x i32> @combine_mul_nabs_v4i32_signed_wrap(<4 x i32> %0) {
; CHECK-LABEL: @combine_mul_nabs_v4i32_signed_wrap(
-; CHECK-NEXT: [[M:%.*]] = mul <4 x i32> [[TMP0:%.*]], [[TMP0]]
+; CHECK-NEXT: [[M:%.*]] = mul nsw <4 x i32> [[TMP0:%.*]], [[TMP0]]
; CHECK-NEXT: ret <4 x i32> [[M]]
;
%c = icmp slt <4 x i32> %0, zeroinitializer
@@ -1689,7 +1689,7 @@ define i32 @combine_mul_nabs_intrin(i32 %x) {
define i32 @combine_mul_nabs_intrin_unsigned_flags(i32 %x) {
; CHECK-LABEL: @combine_mul_nabs_intrin_unsigned_flags(
-; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], [[X]]
+; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i32 [[X:%.*]], [[X]]
; CHECK-NEXT: ret i32 [[MUL]]
;
%abs = call i32 @llvm.abs.i32(i32 %x, i1 false)
@@ -1700,7 +1700,7 @@ define i32 @combine_mul_nabs_intrin_unsigned_flags(i32 %x) {
define i32 @combine_mul_nabs_intrin_signed_flags(i32 %x) {
; CHECK-LABEL: @combine_mul_nabs_intrin_signed_flags(
-; CHECK-NEXT: [[MUL:%.*]] = mul i32 [[X:%.*]], [[X]]
+; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[X:%.*]], [[X]]
; CHECK-NEXT: ret i32 [[MUL]]
;
%abs = call i32 @llvm.abs.i32(i32 %x, i1 false)
More information about the llvm-commits
mailing list