[llvm] [InstCombine] Propagate NSW/NUW flags for `(X - Y) - Z -> X - (Y + Z)` (PR #72693)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Sun Nov 19 01:30:11 PST 2023


https://github.com/dtcxzyw updated https://github.com/llvm/llvm-project/pull/72693

>From ef55640eaf596c669a7560fe7118d53c2f331e3d Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sun, 19 Nov 2023 17:19:07 +0800
Subject: [PATCH 1/2] [InstCombine] Add extra pre-commit tests. NFC.

---
 .../Transforms/InstCombine/sub-from-sub.ll    | 70 ++++++++++++++++++-
 1 file changed, 69 insertions(+), 1 deletion(-)

diff --git a/llvm/test/Transforms/InstCombine/sub-from-sub.ll b/llvm/test/Transforms/InstCombine/sub-from-sub.ll
index 7976cdc970b9c5b..723fb7a1024026f 100644
--- a/llvm/test/Transforms/InstCombine/sub-from-sub.ll
+++ b/llvm/test/Transforms/InstCombine/sub-from-sub.ll
@@ -17,7 +17,7 @@ define i8 @t0(i8 %x, i8 %y, i8 %z) {
   ret i8 %r
 }
 
-; No flags are propagated
+; NSW/NUW flags are propagated
 define i8 @t1_flags(i8 %x, i8 %y, i8 %z) {
 ; CHECK-LABEL: @t1_flags(
 ; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]]
@@ -29,6 +29,74 @@ define i8 @t1_flags(i8 %x, i8 %y, i8 %z) {
   ret i8 %r
 }
 
+; NUW flags are propagated
+define i8 @t1_flags_nuw_only(i8 %x, i8 %y, i8 %z) {
+; CHECK-LABEL: @t1_flags_nuw_only(
+; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %o0 = sub nuw i8 %x, %y
+  %r = sub nuw i8 %o0, %z
+  ret i8 %r
+}
+
+; Negative tests
+define i8 @t1_flags_sub_nsw_sub(i8 %x, i8 %y, i8 %z) {
+; CHECK-LABEL: @t1_flags_sub_nsw_sub(
+; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %o0 = sub nsw i8 %x, %y
+  %r = sub i8 %o0, %z
+  ret i8 %r
+}
+
+define i8 @t1_flags_nuw_first(i8 %x, i8 %y, i8 %z) {
+; CHECK-LABEL: @t1_flags_nuw_first(
+; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %o0 = sub nuw i8 %x, %y
+  %r = sub i8 %o0, %z
+  ret i8 %r
+}
+
+define i8 @t1_flags_nuw_second(i8 %x, i8 %y, i8 %z) {
+; CHECK-LABEL: @t1_flags_nuw_second(
+; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %o0 = sub i8 %x, %y
+  %r = sub nuw i8 %o0, %z
+  ret i8 %r
+}
+
+define i8 @t1_flags_nuw_nsw_first(i8 %x, i8 %y, i8 %z) {
+; CHECK-LABEL: @t1_flags_nuw_nsw_first(
+; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %o0 = sub nuw nsw i8 %x, %y
+  %r = sub i8 %o0, %z
+  ret i8 %r
+}
+
+define i8 @t1_flags_nuw_nsw_second(i8 %x, i8 %y, i8 %z) {
+; CHECK-LABEL: @t1_flags_nuw_nsw_second(
+; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %o0 = sub i8 %x, %y
+  %r = sub nuw nsw i8 %o0, %z
+  ret i8 %r
+}
+
 ; The inner sub must have single use.
 define i8 @n2(i8 %x, i8 %y, i8 %z) {
 ; CHECK-LABEL: @n2(

>From 5585be4f8d2b84596a5e96668f61cbe822d39bd3 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sun, 19 Nov 2023 17:29:26 +0800
Subject: [PATCH 2/2] [InstCombine] Propagate NSW/NUW flags for `(X - Y) - Z ->
 X - (Y + Z)`

---
 llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp | 11 +++++++++--
 llvm/test/Transforms/InstCombine/sub-from-sub.ll      |  8 ++++----
 2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index 318992b55e4f9f8..90b1c133461a408 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2191,8 +2191,15 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
 
   // ((X - Y) - Op1)  -->  X - (Y + Op1)
   if (match(Op0, m_OneUse(m_Sub(m_Value(X), m_Value(Y))))) {
-    Value *Add = Builder.CreateAdd(Y, Op1);
-    return BinaryOperator::CreateSub(X, Add);
+    OverflowingBinaryOperator *LHSSub = cast<OverflowingBinaryOperator>(Op0);
+    bool HasNUW = I.hasNoUnsignedWrap() && LHSSub->hasNoUnsignedWrap();
+    bool HasNSW = HasNUW && I.hasNoSignedWrap() && LHSSub->hasNoSignedWrap();
+    Value *Add = Builder.CreateAdd(Y, Op1, "", /* HasNUW */ HasNUW,
+                                   /* HasNSW */ HasNSW);
+    BinaryOperator *Sub = BinaryOperator::CreateSub(X, Add);
+    Sub->setHasNoUnsignedWrap(HasNUW);
+    Sub->setHasNoSignedWrap(HasNSW);
+    return Sub;
   }
 
   // (~X) - (~Y) --> Y - X
diff --git a/llvm/test/Transforms/InstCombine/sub-from-sub.ll b/llvm/test/Transforms/InstCombine/sub-from-sub.ll
index 723fb7a1024026f..7b9e2fe4e6cdf2d 100644
--- a/llvm/test/Transforms/InstCombine/sub-from-sub.ll
+++ b/llvm/test/Transforms/InstCombine/sub-from-sub.ll
@@ -20,8 +20,8 @@ define i8 @t0(i8 %x, i8 %y, i8 %z) {
 ; NSW/NUW flags are propagated
 define i8 @t1_flags(i8 %x, i8 %y, i8 %z) {
 ; CHECK-LABEL: @t1_flags(
-; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = add nuw nsw i8 [[Y:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = sub nuw nsw i8 [[X:%.*]], [[TMP1]]
 ; CHECK-NEXT:    ret i8 [[R]]
 ;
   %o0 = sub nuw nsw i8 %x, %y
@@ -32,8 +32,8 @@ define i8 @t1_flags(i8 %x, i8 %y, i8 %z) {
 ; NUW flags are propagated
 define i8 @t1_flags_nuw_only(i8 %x, i8 %y, i8 %z) {
 ; CHECK-LABEL: @t1_flags_nuw_only(
-; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]]
-; CHECK-NEXT:    [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = add nuw i8 [[Y:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = sub nuw i8 [[X:%.*]], [[TMP1]]
 ; CHECK-NEXT:    ret i8 [[R]]
 ;
   %o0 = sub nuw i8 %x, %y



More information about the llvm-commits mailing list