[clang] [Clang][CodeGen] Fold forwarding blocks after nested else control flow (PR #207129)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 2 05:14:37 PDT 2026
https://github.com/firmiana402 updated https://github.com/llvm/llvm-project/pull/207129
>From ba7fc7db1b7986fa976e738ffb6801e0aae143ee Mon Sep 17 00:00:00 2001
From: firmiana402 <firmiana402 at gmail.com>
Date: Thu, 2 Jul 2026 14:09:03 +0800
Subject: [PATCH 1/3] [Clang][CodeGen] Fold forwarding blocks after nested else
control flow
---
clang/lib/CodeGen/CGStmt.cpp | 6 ++
.../else-nested-control-flow-forwarding.c | 56 +++++++++++++++++++
2 files changed, 62 insertions(+)
create mode 100644 clang/test/DebugInfo/Generic/else-nested-control-flow-forwarding.c
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 232094777f233..1e79138ed8f82 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -987,9 +987,15 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
EmitStmt(Else);
}
{
+ llvm::BasicBlock *ElseExitBlock = Builder.GetInsertBlock();
// There is no need to emit line number for an unconditional branch.
auto NL = ApplyDebugLocation::CreateEmpty(*this);
EmitBranch(ContBlock);
+
+ // If nested control flow in the else body left behind a synthetic
+ // continuation, fold it into this if's continuation when possible.
+ if (ElseExitBlock && ElseExitBlock != ElseBlock)
+ SimplifyForwardingBlocks(ElseExitBlock);
}
} else if (HasSkip) {
EmitBlock(ElseBlock);
diff --git a/clang/test/DebugInfo/Generic/else-nested-control-flow-forwarding.c b/clang/test/DebugInfo/Generic/else-nested-control-flow-forwarding.c
new file mode 100644
index 0000000000000..39d19233763fc
--- /dev/null
+++ b/clang/test/DebugInfo/Generic/else-nested-control-flow-forwarding.c
@@ -0,0 +1,56 @@
+// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple x86_64-unknown-linux-gnu %s -o - | FileCheck %s
+
+// Nested control flow at the end of an else body can leave behind an empty
+// continuation block that only forwards to the outer if continuation. Avoid
+// emitting that extra block.
+
+// CHECK-LABEL: define {{.*}} @else_if_chain(
+// CHECK: if.end:
+// CHECK-NOT: if.end{{[0-9]+}}:
+// CHECK: ret
+
+int else_if_chain(int i, int *arr) {
+ int x = 0;
+ if (i == 1) {
+ x = i + 1;
+ } else if (i == 2) {
+ arr[i] = 42;
+ }
+ return x;
+}
+
+// CHECK-LABEL: define {{.*}} @nested_if_in_else(
+// CHECK: if.end:
+// CHECK-NOT: if.end{{[0-9]+}}:
+// CHECK: ret
+
+int nested_if_in_else(int i, int *arr) {
+ int x = 0;
+ if (i == 1) {
+ x = i + 1;
+ } else {
+ if (i == 2) {
+ arr[i] = 42;
+ }
+ }
+ return x;
+}
+
+// CHECK-LABEL: define {{.*}} @else_if_chain_with_final_else(
+// CHECK: if.end:
+// CHECK-NOT: if.end{{[0-9]+}}:
+// CHECK: ret
+
+int else_if_chain_with_final_else(int i) {
+ int x = 0;
+ if (i == 1) {
+ x = 1;
+ } else if (i == 2) {
+ x = 2;
+ } else if (i == 3) {
+ x = 3;
+ } else {
+ x = 4;
+ }
+ return x;
+}
>From 6e6673f9b8db8928089a88ee45453236ed8cbb61 Mon Sep 17 00:00:00 2001
From: firmiana402 <firmiana402 at gmail.com>
Date: Thu, 2 Jul 2026 14:23:37 +0800
Subject: [PATCH 2/3] [Clang][test] Update CPU supports CFG checks
---
clang/test/CodeGen/builtin-cpu-supports.c | 32 ++---------------------
1 file changed, 2 insertions(+), 30 deletions(-)
diff --git a/clang/test/CodeGen/builtin-cpu-supports.c b/clang/test/CodeGen/builtin-cpu-supports.c
index 1ace52b7de8f1..6e56b72c99dc6 100644
--- a/clang/test/CodeGen/builtin-cpu-supports.c
+++ b/clang/test/CodeGen/builtin-cpu-supports.c
@@ -196,25 +196,9 @@ int v4() { return __builtin_cpu_supports("x86-64-v4"); }
// CHECK-PPC-NEXT: store i32 [[SUB27]], ptr [[RETVAL]], align 4
// CHECK-PPC-NEXT: br label [[RETURN]]
// CHECK-PPC: if.end:
-// CHECK-PPC-NEXT: br label [[IF_END28:%.*]]
-// CHECK-PPC: if.end28:
-// CHECK-PPC-NEXT: br label [[IF_END29:%.*]]
-// CHECK-PPC: if.end29:
-// CHECK-PPC-NEXT: br label [[IF_END30:%.*]]
-// CHECK-PPC: if.end30:
-// CHECK-PPC-NEXT: br label [[IF_END31:%.*]]
-// CHECK-PPC: if.end31:
-// CHECK-PPC-NEXT: br label [[IF_END32:%.*]]
-// CHECK-PPC: if.end32:
-// CHECK-PPC-NEXT: br label [[IF_END33:%.*]]
-// CHECK-PPC: if.end33:
-// CHECK-PPC-NEXT: br label [[IF_END34:%.*]]
-// CHECK-PPC: if.end34:
-// CHECK-PPC-NEXT: br label [[IF_END35:%.*]]
-// CHECK-PPC: if.end35:
// CHECK-PPC-NEXT: [[TMP21:%.*]] = load i32, ptr [[A_ADDR]], align 4
-// CHECK-PPC-NEXT: [[ADD36:%.*]] = add nsw i32 [[TMP21]], 5
-// CHECK-PPC-NEXT: store i32 [[ADD36]], ptr [[RETVAL]], align 4
+// CHECK-PPC-NEXT: [[ADD28:%.*]] = add nsw i32 [[TMP21]], 5
+// CHECK-PPC-NEXT: store i32 [[ADD28]], ptr [[RETVAL]], align 4
// CHECK-PPC-NEXT: br label [[RETURN]]
// CHECK-PPC: return:
// CHECK-PPC-NEXT: [[TMP22:%.*]] = load i32, ptr [[RETVAL]], align 4
@@ -283,12 +267,6 @@ int test_ppc(int a) {
// CHECK-RV32-NEXT: store i32 13, ptr [[RETVAL]], align 4
// CHECK-RV32-NEXT: br label [[RETURN]]
// CHECK-RV32: if.end:
-// CHECK-RV32-NEXT: br label [[IF_END6:%.*]]
-// CHECK-RV32: if.end6:
-// CHECK-RV32-NEXT: br label [[IF_END7:%.*]]
-// CHECK-RV32: if.end7:
-// CHECK-RV32-NEXT: br label [[IF_END8:%.*]]
-// CHECK-RV32: if.end8:
// CHECK-RV32-NEXT: store i32 0, ptr [[RETVAL]], align 4
// CHECK-RV32-NEXT: br label [[RETURN]]
// CHECK-RV32: return:
@@ -334,12 +312,6 @@ int test_ppc(int a) {
// CHECK-RV64-NEXT: store i32 13, ptr [[RETVAL]], align 4
// CHECK-RV64-NEXT: br label [[RETURN]]
// CHECK-RV64: if.end:
-// CHECK-RV64-NEXT: br label [[IF_END6:%.*]]
-// CHECK-RV64: if.end6:
-// CHECK-RV64-NEXT: br label [[IF_END7:%.*]]
-// CHECK-RV64: if.end7:
-// CHECK-RV64-NEXT: br label [[IF_END8:%.*]]
-// CHECK-RV64: if.end8:
// CHECK-RV64-NEXT: store i32 0, ptr [[RETVAL]], align 4
// CHECK-RV64-NEXT: br label [[RETURN]]
// CHECK-RV64: return:
>From 82e63b482ad96893aaf566680979e224920e7234 Mon Sep 17 00:00:00 2001
From: firmiana402 <firmiana402 at gmail.com>
Date: Thu, 2 Jul 2026 20:13:40 +0800
Subject: [PATCH 3/3] [Clang][CodeGen] Avoid folding else label targets
Do not simplify an else-body forwarding block when the block is the destination of a source label. Such blocks may still be referenced by later gotos or address-of-label expressions, so they do not satisfy SimplifyForwardingBlocks' safety precondition.
---
clang/lib/CodeGen/CGStmt.cpp | 6 ++++--
clang/lib/CodeGen/CodeGenFunction.h | 10 ++++++++++
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 1e79138ed8f82..dce37c37a9b51 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -993,8 +993,10 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
EmitBranch(ContBlock);
// If nested control flow in the else body left behind a synthetic
- // continuation, fold it into this if's continuation when possible.
- if (ElseExitBlock && ElseExitBlock != ElseBlock)
+ // continuation, fold it into this if's continuation when possible. Do not
+ // fold source-label targets, as they may still be referenced.
+ if (ElseExitBlock && ElseExitBlock != ElseBlock &&
+ !isLabelTarget(ElseExitBlock))
SimplifyForwardingBlocks(ElseExitBlock);
}
} else if (HasSkip) {
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 6d0718c243812..337331269e5e6 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -427,6 +427,16 @@ class CodeGenFunction : public CodeGenTypeCache {
return !LabelMap.empty();
}
+ /// Return true if this basic block is the destination for a source label.
+ bool isLabelTarget(const llvm::BasicBlock *BB) const {
+ if (!BB)
+ return false;
+ for (const auto &LabelAndDest : LabelMap)
+ if (LabelAndDest.second.getBlock() == BB)
+ return true;
+ return false;
+ }
+
/// AllocaInsertPoint - This is an instruction in the entry block before which
/// we prefer to insert allocas.
llvm::AssertingVH<llvm::Instruction> AllocaInsertPt;
More information about the cfe-commits
mailing list