[llvm] [SimplifyCFG] Support trunc nuw in chain of comparisons. (PR #155087)

Andreas Jonson via llvm-commits llvm-commits at lists.llvm.org
Sat Aug 23 03:47:22 PDT 2025


https://github.com/andjo403 updated https://github.com/llvm/llvm-project/pull/155087

>From 5de46031f54039028381c14a6640d4f20aca2da4 Mon Sep 17 00:00:00 2001
From: Andreas Jonson <andjo403 at hotmail.com>
Date: Sat, 23 Aug 2025 12:04:30 +0200
Subject: [PATCH 1/2] [SimplifyCFG] Add test for trunc nuw in chain of
 comparisons. (NFC)

---
 .../Transforms/SimplifyCFG/switch_create.ll   | 50 +++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/llvm/test/Transforms/SimplifyCFG/switch_create.ll b/llvm/test/Transforms/SimplifyCFG/switch_create.ll
index a06e64f74b3ac..49b3cb887e7a9 100644
--- a/llvm/test/Transforms/SimplifyCFG/switch_create.ll
+++ b/llvm/test/Transforms/SimplifyCFG/switch_create.ll
@@ -1192,3 +1192,53 @@ if.end:
   ret void
 
 }
+
+define void @chain_trunc_nuw_i1_condition(i8 %x) {
+; CHECK-LABEL: @chain_trunc_nuw_i1_condition(
+; CHECK-NEXT:    [[ADD:%.*]] = add nsw i8 [[X:%.*]], -2
+; CHECK-NEXT:    [[ICMP:%.*]] = icmp ugt i8 [[ADD]], 2
+; CHECK-NEXT:    [[TRUNC:%.*]] = trunc nuw i8 [[X]] to i1
+; CHECK-NEXT:    [[OR_COND_I:%.*]] = select i1 [[ICMP]], i1 [[TRUNC]], i1 false
+; CHECK-NEXT:    br i1 [[OR_COND_I]], label [[IF_THEN:%.*]], label [[COMMON_RET:%.*]]
+; CHECK:       common.ret:
+; CHECK-NEXT:    ret void
+; CHECK:       if.then:
+; CHECK-NEXT:    tail call void @foo1()
+; CHECK-NEXT:    br label [[COMMON_RET]]
+;
+  %add = add nsw i8 %x, -2
+  %icmp = icmp ugt i8 %add, 2
+  %trunc = trunc nuw i8 %x to i1
+  %or.cond.i = select i1 %icmp, i1 %trunc, i1 false
+  br i1 %or.cond.i, label %if.then, label %if.end
+if.then:
+  tail call void @foo1()
+  ret void
+if.end:
+  ret void
+}
+
+define void @neg_chain_trunc_i1_condition(i8 %x) {
+; CHECK-LABEL: @neg_chain_trunc_i1_condition(
+; CHECK-NEXT:    [[ADD:%.*]] = add nsw i8 [[X:%.*]], -2
+; CHECK-NEXT:    [[ICMP:%.*]] = icmp ugt i8 [[ADD]], 2
+; CHECK-NEXT:    [[TRUNC:%.*]] = trunc i8 [[X]] to i1
+; CHECK-NEXT:    [[OR_COND_I:%.*]] = select i1 [[ICMP]], i1 [[TRUNC]], i1 false
+; CHECK-NEXT:    br i1 [[OR_COND_I]], label [[IF_THEN:%.*]], label [[COMMON_RET:%.*]]
+; CHECK:       common.ret:
+; CHECK-NEXT:    ret void
+; CHECK:       if.then:
+; CHECK-NEXT:    tail call void @foo1()
+; CHECK-NEXT:    br label [[COMMON_RET]]
+;
+  %add = add nsw i8 %x, -2
+  %icmp = icmp ugt i8 %add, 2
+  %trunc = trunc i8 %x to i1
+  %or.cond.i = select i1 %icmp, i1 %trunc, i1 false
+  br i1 %or.cond.i, label %if.then, label %if.end
+if.then:
+  tail call void @foo1()
+  ret void
+if.end:
+  ret void
+}

>From 654bb71bbe5fe81eca22200d0419ace76b19f207 Mon Sep 17 00:00:00 2001
From: Andreas Jonson <andjo403 at hotmail.com>
Date: Sat, 23 Aug 2025 12:05:16 +0200
Subject: [PATCH 2/2] [SimplifyCFG] Support trunc nuw in chain of comparisons.

---
 llvm/lib/Transforms/Utils/SimplifyCFG.cpp         |  9 +++++++++
 llvm/test/Transforms/SimplifyCFG/switch_create.ll | 11 ++++++-----
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 48a99543d7083..7666d3d088fc2 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -612,6 +612,15 @@ struct ConstantComparesGatherer {
   /// If CompValue is already set, the function is expected to fail if a match
   /// is found but the value compared to is different.
   bool matchInstruction(Instruction *I, bool isEQ) {
+    Value *Val;
+    if (!isEQ && match(I, m_NUWTrunc(m_Value(Val)))) {
+      // If we already have a value for the switch, it has to match!
+      if (!setValueOnce(Val))
+        return false;
+      UsedICmps++;
+      Vals.push_back(ConstantInt::get(cast<IntegerType>(Val->getType()), 0));
+      return true;
+    }
     // If this is an icmp against a constant, handle this as one of the cases.
     ICmpInst *ICI;
     ConstantInt *C;
diff --git a/llvm/test/Transforms/SimplifyCFG/switch_create.ll b/llvm/test/Transforms/SimplifyCFG/switch_create.ll
index 49b3cb887e7a9..74e9731e0a3e6 100644
--- a/llvm/test/Transforms/SimplifyCFG/switch_create.ll
+++ b/llvm/test/Transforms/SimplifyCFG/switch_create.ll
@@ -1195,11 +1195,12 @@ if.end:
 
 define void @chain_trunc_nuw_i1_condition(i8 %x) {
 ; CHECK-LABEL: @chain_trunc_nuw_i1_condition(
-; CHECK-NEXT:    [[ADD:%.*]] = add nsw i8 [[X:%.*]], -2
-; CHECK-NEXT:    [[ICMP:%.*]] = icmp ugt i8 [[ADD]], 2
-; CHECK-NEXT:    [[TRUNC:%.*]] = trunc nuw i8 [[X]] to i1
-; CHECK-NEXT:    [[OR_COND_I:%.*]] = select i1 [[ICMP]], i1 [[TRUNC]], i1 false
-; CHECK-NEXT:    br i1 [[OR_COND_I]], label [[IF_THEN:%.*]], label [[COMMON_RET:%.*]]
+; CHECK-NEXT:    switch i8 [[X:%.*]], label [[IF_THEN:%.*]] [
+; CHECK-NEXT:      i8 4, label [[COMMON_RET:%.*]]
+; CHECK-NEXT:      i8 3, label [[COMMON_RET]]
+; CHECK-NEXT:      i8 2, label [[COMMON_RET]]
+; CHECK-NEXT:      i8 0, label [[COMMON_RET]]
+; CHECK-NEXT:    ]
 ; CHECK:       common.ret:
 ; CHECK-NEXT:    ret void
 ; CHECK:       if.then:



More information about the llvm-commits mailing list