[llvm] [SimplifyCFG] Support trunc nuw in chain of comparisons. (PR #155087)
Andreas Jonson via llvm-commits
llvm-commits at lists.llvm.org
Sat Aug 30 14:13:32 PDT 2025
https://github.com/andjo403 updated https://github.com/llvm/llvm-project/pull/155087
>From 3a67ccf3c8db1aafe8165dc232870384f629a348 Mon Sep 17 00:00:00 2001
From: Andreas Jonson <andjo403 at hotmail.com>
Date: Sun, 24 Aug 2025 17:27:08 +0200
Subject: [PATCH 1/2] [SimplifyCFG] Add test for trunc nuw in chain of
comparisons. (NFC)
---
.../Transforms/SimplifyCFG/switch_create.ll | 73 +++++++++++++++++++
1 file changed, 73 insertions(+)
diff --git a/llvm/test/Transforms/SimplifyCFG/switch_create.ll b/llvm/test/Transforms/SimplifyCFG/switch_create.ll
index a06e64f74b3ac..61f768cf98574 100644
--- a/llvm/test/Transforms/SimplifyCFG/switch_create.ll
+++ b/llvm/test/Transforms/SimplifyCFG/switch_create.ll
@@ -1192,3 +1192,76 @@ if.end:
ret void
}
+
+define void @and_chain_trunc_nuw_i1_condition(i8 %x) {
+; CHECK-LABEL: @and_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: [[AND:%.*]] = select i1 [[ICMP]], i1 [[TRUNC]], i1 false
+; CHECK-NEXT: br i1 [[AND]], 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
+ %and = select i1 %icmp, i1 %trunc, 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_i1_condition(i8 %x) {
+; CHECK-LABEL: @or_chain_trunc_nuw_i1_condition(
+; CHECK-NEXT: [[ICMP:%.*]] = icmp eq i8 [[X:%.*]], 2
+; CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw i8 [[X]] to i1
+; CHECK-NEXT: [[SWITCH:%.*]] = select i1 [[ICMP]], i1 true, i1 [[TRUNC]]
+; CHECK-NEXT: br i1 [[SWITCH]], 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
+ %or = select i1 %icmp, i1 true, i1 %trunc
+ br i1 %or, label %if.then, label %if.end
+if.then:
+ tail call void @foo1()
+ ret void
+if.end:
+ ret void
+}
+
+define void @neg_and_chain_trunc_i1_condition(i8 %x) {
+; CHECK-LABEL: @neg_and_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: [[AND:%.*]] = select i1 [[ICMP]], i1 [[TRUNC]], i1 false
+; CHECK-NEXT: br i1 [[AND]], 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
+ %and = select i1 %icmp, i1 %trunc, i1 false
+ br i1 %and, label %if.then, label %if.end
+if.then:
+ tail call void @foo1()
+ ret void
+if.end:
+ ret void
+}
>From c8ec9edec50fdb0e86fd95228e54c9e7eca8b971 Mon Sep 17 00:00:00 2001
From: Andreas Jonson <andjo403 at hotmail.com>
Date: Sun, 24 Aug 2025 17:27:38 +0200
Subject: [PATCH 2/2] [SimplifyCFG] Support trunc nuw in chain of comparisons.
---
llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 9 +++++++++
.../test/Transforms/SimplifyCFG/switch_create.ll | 16 ++++++++--------
2 files changed, 17 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 93ace4d50cbdc..84a838b48eadd 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 (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()), isEQ));
+ 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 61f768cf98574..6d2a404203d02 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 @and_chain_trunc_nuw_i1_condition(i8 %x) {
; CHECK-LABEL: @and_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: [[AND:%.*]] = select i1 [[ICMP]], i1 [[TRUNC]], i1 false
-; CHECK-NEXT: br i1 [[AND]], 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:
@@ -1220,9 +1221,8 @@ if.end:
define void @or_chain_trunc_nuw_i1_condition(i8 %x) {
; CHECK-LABEL: @or_chain_trunc_nuw_i1_condition(
-; CHECK-NEXT: [[ICMP:%.*]] = icmp eq i8 [[X:%.*]], 2
-; CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw i8 [[X]] to i1
-; CHECK-NEXT: [[SWITCH:%.*]] = select i1 [[ICMP]], i1 true, i1 [[TRUNC]]
+; CHECK-NEXT: [[X_OFF:%.*]] = add i8 [[X:%.*]], -1
+; CHECK-NEXT: [[SWITCH:%.*]] = icmp ult i8 [[X_OFF]], 2
; CHECK-NEXT: br i1 [[SWITCH]], label [[IF_THEN:%.*]], label [[COMMON_RET:%.*]]
; CHECK: common.ret:
; CHECK-NEXT: ret void
More information about the llvm-commits
mailing list