[llvm] [InstCombine] Allow overflowing selects to work on cumulative arguments (PR #90812)
via llvm-commits
llvm-commits at lists.llvm.org
Thu May 2 06:35:44 PDT 2024
https://github.com/AtariDreams updated https://github.com/llvm/llvm-project/pull/90812
>From 5309763532698bc993d2196fcb64ef73c35668e5 Mon Sep 17 00:00:00 2001
From: Rose <gfunni234 at gmail.com>
Date: Wed, 1 May 2024 21:46:20 -0400
Subject: [PATCH 1/3] [InstCombine] Pre-commit test (NFC)
---
.../Transforms/InstCombine/overflow_to_sat.ll | 35 ++++++++++++++++++-
1 file changed, 34 insertions(+), 1 deletion(-)
diff --git a/llvm/test/Transforms/InstCombine/overflow_to_sat.ll b/llvm/test/Transforms/InstCombine/overflow_to_sat.ll
index 568ac77d6b88dd..a6c344fc018142 100644
--- a/llvm/test/Transforms/InstCombine/overflow_to_sat.ll
+++ b/llvm/test/Transforms/InstCombine/overflow_to_sat.ll
@@ -13,6 +13,21 @@ define i32 @uadd(i32 %x, i32 %y) {
ret i32 %s
}
+define i32 @uadd_cumm(i32 %x, i32 %y) {
+; CHECK-LABEL: @uadd_cumm(
+; CHECK-NEXT: [[AO:%.*]] = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
+; CHECK-NEXT: [[O:%.*]] = extractvalue { i32, i1 } [[AO]], 1
+; CHECK-NEXT: [[A:%.*]] = add i32 [[Y]], [[X]]
+; CHECK-NEXT: [[S:%.*]] = select i1 [[O]], i32 -1, i32 [[A]]
+; CHECK-NEXT: ret i32 [[S]]
+;
+ %ao = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 %y)
+ %o = extractvalue { i32, i1 } %ao, 1
+ %a = add i32 %y, %x
+ %s = select i1 %o, i32 -1, i32 %a
+ ret i32 %s
+}
+
define i32 @usub(i32 %x, i32 %y) {
; CHECK-LABEL: @usub(
; CHECK-NEXT: [[S:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
@@ -25,7 +40,6 @@ define i32 @usub(i32 %x, i32 %y) {
ret i32 %s
}
-
define i8 @sadd_x_lt_min(i8 %x, i8 %y) {
; CHECK-LABEL: @sadd_x_lt_min(
; CHECK-NEXT: [[AO:%.*]] = tail call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
@@ -650,6 +664,25 @@ define i32 @sadd_i32(i32 %x, i32 %y) {
ret i32 %r
}
+define i32 @sadd_i32_no_extract(i32 %x, i32 %y) {
+; CHECK-LABEL: @sadd_i32_no_extract(
+; CHECK-NEXT: [[AO:%.*]] = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
+; CHECK-NEXT: [[O:%.*]] = extractvalue { i32, i1 } [[AO]], 1
+; CHECK-NEXT: [[A:%.*]] = sub i32 [[X]], [[Y]]
+; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[X]], 0
+; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i32 -2147483648, i32 2147483647
+; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i32 [[S]], i32 [[A]]
+; CHECK-NEXT: ret i32 [[R]]
+;
+ %ao = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %x, i32 %y)
+ %o = extractvalue { i32, i1 } %ao, 1
+ %a = sub i32 %x, %y
+ %c = icmp slt i32 %x, 0
+ %s = select i1 %c, i32 -2147483648, i32 2147483647
+ %r = select i1 %o, i32 %s, i32 %a
+ ret i32 %r
+}
+
define i32 @ssub_i32(i32 %x, i32 %y) {
; CHECK-LABEL: @ssub_i32(
; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.ssub.sat.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
>From 9a83dc4a5a2ba6e020529c9568c5bdecbd3bc81f Mon Sep 17 00:00:00 2001
From: Rose <gfunni234 at gmail.com>
Date: Wed, 1 May 2024 21:47:02 -0400
Subject: [PATCH 2/3] [InstCombine] Allow overflowing selects to work on
cumulative arguments
This came up when working on a patch for systemd, where the code would not simplify because instead of using the actual result, someone decided to instead put "return x + y"
---
.../Transforms/InstCombine/InstCombineSelect.cpp | 15 +++++++++++++--
.../Transforms/InstCombine/overflow_to_sat.ll | 12 ++----------
2 files changed, 15 insertions(+), 12 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 8818369e79452b..1f01728c507d48 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -2075,12 +2075,23 @@ foldOverflowingAddSubSelect(SelectInst &SI, InstCombiner::BuilderTy &Builder) {
Value *FalseVal = SI.getFalseValue();
WithOverflowInst *II;
- if (!match(CondVal, m_ExtractValue<1>(m_WithOverflowInst(II))) ||
- !match(FalseVal, m_ExtractValue<0>(m_Specific(II))))
+ if (!match(CondVal, m_ExtractValue<1>(m_WithOverflowInst(II))))
return nullptr;
Value *X = II->getLHS();
Value *Y = II->getRHS();
+ if (!match(FalseVal, m_ExtractValue<0>(m_Specific(II)))) {
+ // Communinative adds can get missed, so check for X and Y being swapped
+ switch (II->getIntrinsicID()) {
+ case Intrinsic::uadd_with_overflow:
+ case Intrinsic::sadd_with_overflow:
+ if (!match(FalseVal, m_Add(m_Specific(Y), m_Specific(X))))
+ return nullptr;
+ break;
+ default:
+ return nullptr;
+ }
+ }
auto IsSignedSaturateLimit = [&](Value *Limit, bool IsAdd) {
Type *Ty = Limit->getType();
diff --git a/llvm/test/Transforms/InstCombine/overflow_to_sat.ll b/llvm/test/Transforms/InstCombine/overflow_to_sat.ll
index a6c344fc018142..4794d1ce113cca 100644
--- a/llvm/test/Transforms/InstCombine/overflow_to_sat.ll
+++ b/llvm/test/Transforms/InstCombine/overflow_to_sat.ll
@@ -15,10 +15,7 @@ define i32 @uadd(i32 %x, i32 %y) {
define i32 @uadd_cumm(i32 %x, i32 %y) {
; CHECK-LABEL: @uadd_cumm(
-; CHECK-NEXT: [[AO:%.*]] = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
-; CHECK-NEXT: [[O:%.*]] = extractvalue { i32, i1 } [[AO]], 1
-; CHECK-NEXT: [[A:%.*]] = add i32 [[Y]], [[X]]
-; CHECK-NEXT: [[S:%.*]] = select i1 [[O]], i32 -1, i32 [[A]]
+; CHECK-NEXT: [[S:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
; CHECK-NEXT: ret i32 [[S]]
;
%ao = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 %y)
@@ -666,12 +663,7 @@ define i32 @sadd_i32(i32 %x, i32 %y) {
define i32 @sadd_i32_no_extract(i32 %x, i32 %y) {
; CHECK-LABEL: @sadd_i32_no_extract(
-; CHECK-NEXT: [[AO:%.*]] = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
-; CHECK-NEXT: [[O:%.*]] = extractvalue { i32, i1 } [[AO]], 1
-; CHECK-NEXT: [[A:%.*]] = sub i32 [[X]], [[Y]]
-; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[X]], 0
-; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i32 -2147483648, i32 2147483647
-; CHECK-NEXT: [[R:%.*]] = select i1 [[O]], i32 [[S]], i32 [[A]]
+; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
; CHECK-NEXT: ret i32 [[R]]
;
%ao = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %x, i32 %y)
>From 85b26f6accbe7e8a474c538708f94dea2b23674a Mon Sep 17 00:00:00 2001
From: AtariDreams <gfunni234 at gmail.com>
Date: Thu, 2 May 2024 09:35:35 -0400
Subject: [PATCH 3/3] Fix typo
---
llvm/test/Transforms/InstCombine/overflow_to_sat.ll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/test/Transforms/InstCombine/overflow_to_sat.ll b/llvm/test/Transforms/InstCombine/overflow_to_sat.ll
index 4794d1ce113cca..649a0a1440f7b4 100644
--- a/llvm/test/Transforms/InstCombine/overflow_to_sat.ll
+++ b/llvm/test/Transforms/InstCombine/overflow_to_sat.ll
@@ -668,7 +668,7 @@ define i32 @sadd_i32_no_extract(i32 %x, i32 %y) {
;
%ao = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %x, i32 %y)
%o = extractvalue { i32, i1 } %ao, 1
- %a = sub i32 %x, %y
+ %a = add i32 %y, %x
%c = icmp slt i32 %x, 0
%s = select i1 %c, i32 -2147483648, i32 2147483647
%r = select i1 %o, i32 %s, i32 %a
More information about the llvm-commits
mailing list