[llvm] [SimplifyCFG] Support not in chain of comparisons. (PR #156497)

Andreas Jonson via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 2 10:19:43 PDT 2025


https://github.com/andjo403 created https://github.com/llvm/llvm-project/pull/156497

Proof: https://alive2.llvm.org/ce/z/cpXuCb

>From 8b1ce7bdfc2365008f0f9c1e8017fc8fe8e8e8ff Mon Sep 17 00:00:00 2001
From: Andreas Jonson <andjo403 at hotmail.com>
Date: Tue, 2 Sep 2025 19:16:37 +0200
Subject: [PATCH 1/2] [SimplifyCFG] Add test for not in chain of comparisons.
 (NFC)

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

diff --git a/llvm/test/Transforms/SimplifyCFG/switch_create.ll b/llvm/test/Transforms/SimplifyCFG/switch_create.ll
index 6d2a404203d02..ae7e97d23d774 100644
--- a/llvm/test/Transforms/SimplifyCFG/switch_create.ll
+++ b/llvm/test/Transforms/SimplifyCFG/switch_create.ll
@@ -1265,3 +1265,55 @@ if.then:
 if.end:
   ret void
 }
+
+define void @and_chain_trunc_nuw_not_i1_condition(i8 %x) {
+; CHECK-LABEL: @and_chain_trunc_nuw_not_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:    [[NOT:%.*]] = xor i1 [[TRUNC]], true
+; CHECK-NEXT:    [[SWITCH:%.*]] = select i1 [[ICMP]], i1 [[NOT]], i1 false
+; CHECK-NEXT:    br i1 [[SWITCH]], label [[COMMON_RET:%.*]], label [[IF_THEN:%.*]]
+; CHECK:       common.ret:
+; CHECK-NEXT:    ret void
+; CHECK:       if.then:
+; CHECK-NEXT:    tail call void @foo1()
+; CHECK-NEXT:    br label [[IF_THEN]]
+;
+  %add = add nsw i8 %x, -2
+  %icmp = icmp ugt i8 %add, 2
+  %trunc = trunc nuw i8 %x to i1
+  %not = xor i1 %trunc, true
+  %and = select i1 %icmp, i1 %not, i1 false
+  br i1 %and, label %if.then, label %if.end
+if.then:
+  tail call void @foo1()
+  ret void
+if.end:
+  ret void
+}
+
+define void @or_chain_trunc_nuw_not_i1_condition(i8 %x) {
+; CHECK-LABEL: @or_chain_trunc_nuw_not_i1_condition(
+; CHECK-NEXT:    [[ICMP:%.*]] = icmp eq i8 [[X:%.*]], 2
+; CHECK-NEXT:    [[TRUNC:%.*]] = trunc nuw i8 [[X]] to i1
+; CHECK-NEXT:    [[NOT:%.*]] = xor i1 [[TRUNC]], true
+; CHECK-NEXT:    [[OR:%.*]] = select i1 [[ICMP]], i1 true, i1 [[NOT]]
+; CHECK-NEXT:    br i1 [[OR]], 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]]
+;
+  %icmp = icmp eq i8 %x, 2
+  %trunc = trunc nuw i8 %x to i1
+  %not = xor i1 %trunc, true
+  %or = select i1 %icmp, i1 true, i1 %not
+  br i1 %or, label %if.then, label %if.end
+if.then:
+  tail call void @foo1()
+  ret void
+if.end:
+  ret void
+}

>From e1a749e4008e5e088bdb772bf8175e6e0c4ba90e Mon Sep 17 00:00:00 2001
From: Andreas Jonson <andjo403 at hotmail.com>
Date: Tue, 2 Sep 2025 19:17:52 +0200
Subject: [PATCH 2/2] [SimplifyCFG] Support not in chain of comparisons.

---
 llvm/lib/Transforms/Utils/SimplifyCFG.cpp      |  3 +++
 .../Transforms/SimplifyCFG/switch_create.ll    | 18 +++++++-----------
 2 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 02d6393dd5815..7b385f22348fa 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -612,6 +612,9 @@ 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) {
+    if (match(I, m_Not(m_Instruction(I))))
+      isEQ = !isEQ;
+
     Value *Val;
     if (match(I, m_NUWTrunc(m_Value(Val)))) {
       // If we already have a value for the switch, it has to match!
diff --git a/llvm/test/Transforms/SimplifyCFG/switch_create.ll b/llvm/test/Transforms/SimplifyCFG/switch_create.ll
index ae7e97d23d774..18c4ade46162c 100644
--- a/llvm/test/Transforms/SimplifyCFG/switch_create.ll
+++ b/llvm/test/Transforms/SimplifyCFG/switch_create.ll
@@ -1268,17 +1268,14 @@ if.end:
 
 define void @and_chain_trunc_nuw_not_i1_condition(i8 %x) {
 ; CHECK-LABEL: @and_chain_trunc_nuw_not_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:    [[NOT:%.*]] = xor i1 [[TRUNC]], true
-; CHECK-NEXT:    [[SWITCH:%.*]] = select i1 [[ICMP]], i1 [[NOT]], i1 false
+; CHECK-NEXT:    [[X_OFF:%.*]] = add i8 [[X:%.*]], -1
+; CHECK-NEXT:    [[SWITCH:%.*]] = icmp ult i8 [[X_OFF]], 4
 ; CHECK-NEXT:    br i1 [[SWITCH]], label [[COMMON_RET:%.*]], label [[IF_THEN:%.*]]
 ; CHECK:       common.ret:
 ; CHECK-NEXT:    ret void
 ; CHECK:       if.then:
 ; CHECK-NEXT:    tail call void @foo1()
-; CHECK-NEXT:    br label [[IF_THEN]]
+; CHECK-NEXT:    br label [[COMMON_RET]]
 ;
   %add = add nsw i8 %x, -2
   %icmp = icmp ugt i8 %add, 2
@@ -1295,11 +1292,10 @@ if.end:
 
 define void @or_chain_trunc_nuw_not_i1_condition(i8 %x) {
 ; CHECK-LABEL: @or_chain_trunc_nuw_not_i1_condition(
-; CHECK-NEXT:    [[ICMP:%.*]] = icmp eq i8 [[X:%.*]], 2
-; CHECK-NEXT:    [[TRUNC:%.*]] = trunc nuw i8 [[X]] to i1
-; CHECK-NEXT:    [[NOT:%.*]] = xor i1 [[TRUNC]], true
-; CHECK-NEXT:    [[OR:%.*]] = select i1 [[ICMP]], i1 true, i1 [[NOT]]
-; CHECK-NEXT:    br i1 [[OR]], label [[IF_THEN:%.*]], label [[COMMON_RET:%.*]]
+; CHECK-NEXT:    switch i8 [[X:%.*]], label [[COMMON_RET:%.*]] [
+; CHECK-NEXT:      i8 2, label [[IF_THEN:%.*]]
+; CHECK-NEXT:      i8 0, label [[IF_THEN]]
+; CHECK-NEXT:    ]
 ; CHECK:       common.ret:
 ; CHECK-NEXT:    ret void
 ; CHECK:       if.then:



More information about the llvm-commits mailing list