[clang] [CIR] Wire const goto labels into indirect branch (PR #201644)

Andy Kaylor via cfe-commits cfe-commits at lists.llvm.org
Wed Jun 24 17:21:00 PDT 2026


================
@@ -0,0 +1,127 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=LLVM
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG
+
+int f(int x) {
+  static const void *tbl[] = {&&L1, &&L2};
+  goto *tbl[x];
+L1:
+  return 1;
+L2:
+  return 2;
+}
+
+// A appears twice in g's table; both occurrences are kept as indirect-branch
+// successors, matching classic codegen.
+int g(int x) {
+  static const void *tbl[] = {&&A, &&A, &&B};
+  goto *tbl[x];
+A:
+  return 1;
+B:
+  return 2;
+}
+
+// A constant label address with no indirect goto reaching it: the indirect-goto
+// block is created but has no predecessors, so it is left poisoned.
+int h(int x) {
+  static const void *tbl[] = {&&L1};
+  (void)tbl;
+  return x;
+L1:
+  return 0;
+}
+
+// A's address comes from a constant table, B's from a runtime block-address op;
+// both feed the same indirect branch.
+int m(int sel) {
+  static const void *ctbl[] = {&&A2};
+  void *p = &&B2;
+  void *t = (void *)ctbl[0];
+  void *dest = sel ? t : p;
+  goto *dest;
+A2:
+  return 1;
+B2:
+  return 2;
+}
+
+// CIR-DAG: cir.global "private" internal dso_local @f.tbl = #cir.const_array<[#cir.block_addr_info<@f, "L1"> : !cir.ptr<!void>, #cir.block_addr_info<@f, "L2"> : !cir.ptr<!void>]> : !cir.array<!cir.ptr<!void> x 2>
+// CIR-DAG: cir.global "private" internal dso_local @g.tbl = #cir.const_array<[#cir.block_addr_info<@g, "A"> : !cir.ptr<!void>, #cir.block_addr_info<@g, "A"> : !cir.ptr<!void>, #cir.block_addr_info<@g, "B"> : !cir.ptr<!void>]> : !cir.array<!cir.ptr<!void> x 3>
+// CIR-DAG: cir.global "private" internal dso_local @h.tbl = #cir.const_array<[#cir.block_addr_info<@h, "L1"> : !cir.ptr<!void>]> : !cir.array<!cir.ptr<!void> x 1>
+// CIR-DAG: cir.global "private" internal dso_local @m.ctbl = #cir.const_array<[#cir.block_addr_info<@m, "A2"> : !cir.ptr<!void>]> : !cir.array<!cir.ptr<!void> x 1>
+
+// CIR: cir.func {{.*}} @f
----------------
andykaylor wrote:

Can you move these checks to below the corresponding functions and group them by function rather than having all the CIR checks, followed by all the LLVM checks, etc?

https://github.com/llvm/llvm-project/pull/201644


More information about the cfe-commits mailing list