[llvm] [InstCombine] Allow overflowing selects to work on cumulative arguments (PR #90812)

via llvm-commits llvm-commits at lists.llvm.org
Wed May 1 19:27:11 PDT 2024


https://github.com/AtariDreams created https://github.com/llvm/llvm-project/pull/90812

This came up when working on a patch for systemd, where the code would not simplify because the code read:

```
unsigned int u(unsigned int x, unsigned int y)
{
    unsigned int z;
    if (__builtin_uadd_overflow(x, y, &z))
         return UINT_MAX; /* indicate overflow */
    return x + y;
}
```
Instead of:
```
unsigned int u(unsigned int x, unsigned int y)
{
    unsigned int z;
    if (__builtin_uadd_overflow(x, y, &z))
         return UINT_MAX; /* indicate overflow */
    return z;
}
```

>From 6e0b436b348b4c925c6168ecff30e513a05b7fb4 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/2] [InstCombine] Pre-commit test (NFC)

---
 .../Transforms/InstCombine/overflow_to_sat.ll     | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/overflow_to_sat.ll b/llvm/test/Transforms/InstCombine/overflow_to_sat.ll
index 568ac77d6b88dd..5d602c4834bc6c 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:%.*]])

>From 37c439df474d4550b75efbba614d6a1875814c62 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/2] [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"
---
 .../InstCombine/InstCombineSelect.cpp         | 19 +++++++++++++++++--
 .../Transforms/InstCombine/overflow_to_sat.ll |  5 +----
 2 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 8818369e79452b..d10adb1667c020 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -2075,12 +2075,27 @@ 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)))) {
+    switch (II->getIntrinsicID()) {
+    case Intrinsic::uadd_with_overflow:
+    case Intrinsic::sadd_with_overflow:
+      if (!match(FalseVal, m_c_Add(m_Specific(X), m_Specific(Y))))
+        return nullptr;
+      break;
+    case Intrinsic::usub_with_overflow:
+    case Intrinsic::ssub_with_overflow:
+      if (!match(FalseVal, m_Sub(m_Specific(X), m_Specific(Y))))
+        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 5d602c4834bc6c..eaa247b42a37b9 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)



More information about the llvm-commits mailing list