https://github.com/Andres-Salamanca updated 
https://github.com/llvm/llvm-project/pull/168151

>From f370cf6048c10df86159d5272a2d3dc463247110 Mon Sep 17 00:00:00 2001
From: Andres Salamanca <[email protected]>
Date: Fri, 14 Nov 2025 18:30:22 -0500
Subject: [PATCH 1/2] [CIR] Upstream the initial BlockAddressOp implementation

---
 .../include/clang/CIR/Dialect/IR/CIRAttrs.td  | 25 ++++++
 clang/include/clang/CIR/Dialect/IR/CIROps.td  | 33 ++++++++
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp    |  9 +++
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp       | 29 ++++++-
 .../lib/CIR/Dialect/Transforms/GotoSolver.cpp | 17 ++++-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp |  6 ++
 clang/test/CIR/CodeGen/label-values.c         | 76 +++++++++++++++++++
 clang/test/CIR/IR/block-adress.cir            | 34 +++++++++
 clang/test/CIR/IR/invalid-block-address.cir   | 21 +++++
 clang/test/CIR/Transforms/goto_solver.cir     | 62 +++++++++++++++
 clang/tools/cir-opt/cir-opt.cpp               |  4 +
 11 files changed, 311 insertions(+), 5 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/label-values.c
 create mode 100644 clang/test/CIR/IR/block-adress.cir
 create mode 100644 clang/test/CIR/IR/invalid-block-address.cir
 create mode 100644 clang/test/CIR/Transforms/goto_solver.cir

diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td 
b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index 1e0fb038b19d8..47ff9389e8028 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -1026,4 +1026,29 @@ def CIR_UnwindAttr : CIR_UnitAttr<"Unwind", "unwind"> {
   let storageType = [{ CatchUnwind }];
 }
 
+//===----------------------------------------------------------------------===//
+// CIR_BlockAddrInfoAttr
+//===----------------------------------------------------------------------===//
+
+def CIR_BlockAddrInfoAttr : CIR_Attr<"BlockAddrInfo", "block_addr_info"> {
+  let summary = "Block Addres attribute";
+  let description = [{
+    This attribute is used to represent the address of a basic block
+    within a function. It combines the symbol reference to a function
+    with the name of a label inside that function.
+  }];
+  let parameters = (ins "mlir::FlatSymbolRefAttr":$func,
+                        "mlir::StringAttr":$label);
+
+  let assemblyFormat = "`<` $func `,` $label `>`";
+  let builders = [
+    AttrBuilder<(ins "llvm::StringRef":$func_name,
+                     "llvm::StringRef":$label_name
+                     ), [{
+      return $_get($_ctxt, mlir::FlatSymbolRefAttr::get($_ctxt, func_name),
+                   mlir::StringAttr::get($_ctxt, label_name));
+    }]>
+  ];
+}
+
 #endif // CLANG_CIR_DIALECT_IR_CIRATTRS_TD
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 16258513239d9..d7270bc81b68a 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -4800,4 +4800,37 @@ def CIR_AtomicClearOp : CIR_Op<"atomic.clear"> {
   }];
 }
 
+//===----------------------------------------------------------------------===//
+// BlockAddressOp
+//===----------------------------------------------------------------------===//
+
+def CIR_BlockAddressOp : CIR_Op<"blockaddress", [Pure]> {
+  let summary = "Get the address of a cir.label within a function";
+  let description = [{
+    The `cir.blockaddress` operation takes a function name and a label and
+    produces a pointer value that represents the address of that cir.label 
within
+    the specified function.
+
+    This operation models GCC's "labels as values" extension (`&&label`), which
+    allows taking the address of a local label and using it as a computed
+    jump target (e.g., with `goto *addr;`).
+
+    Example:
+    ```mlir
+    %1 = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr", init] 
{alignment = 8 : i64}
+    %addr = cir.blockaddress("foo", "label") -> !cir.ptr<!cir.void>
+    cir.store align(8) %addr, %1 : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
+    cir.br ^bb1
+   ^bb1:
+    cir.label "label"
+    ```
+  }];
+
+  let arguments = (ins CIR_BlockAddrInfoAttr:$blockAddrInfo);
+  let results = (outs CIR_VoidPtrType:$addr);
+  let assemblyFormat = [{
+    $blockAddrInfo `->` qualified(type($addr)) attr-dict
+  }];
+}
+
 #endif // CLANG_CIR_DIALECT_IR_CIROPS_TD
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 4461875fcf678..e3e8f2827d841 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -166,6 +166,15 @@ class ScalarExprEmitter : public 
StmtVisitor<ScalarExprEmitter, mlir::Value> {
     return emitLoadOfLValue(e);
   }
 
+  mlir::Value VisitAddrLabelExpr(const AddrLabelExpr *e) {
+    auto func = cast<cir::FuncOp>(cgf.curFn);
+    auto blockInfoAttr = cir::BlockAddrInfoAttr::get(
+        &cgf.getMLIRContext(), func.getSymName(), e->getLabel()->getName());
+    return cir::BlockAddressOp::create(builder, 
cgf.getLoc(e->getSourceRange()),
+                                       cgf.convertType(e->getType()),
+                                       blockInfoAttr);
+  }
+
   mlir::Value VisitIntegerLiteral(const IntegerLiteral *e) {
     mlir::Type type = cgf.convertType(e->getType());
     return cir::ConstantOp::create(builder, cgf.getLoc(e->getExprLoc()),
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp 
b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 7ba03ce40140c..95dfcc7ce1c13 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -1902,22 +1902,45 @@ mlir::LogicalResult cir::FuncOp::verify() {
 
   llvm::SmallSet<llvm::StringRef, 16> labels;
   llvm::SmallSet<llvm::StringRef, 16> gotos;
-
+  llvm::SmallSet<llvm::StringRef, 16> blockAddresses;
+  bool invalidBlockAddress = false;
   getOperation()->walk([&](mlir::Operation *op) {
     if (auto lab = dyn_cast<cir::LabelOp>(op)) {
       labels.insert(lab.getLabel());
     } else if (auto goTo = dyn_cast<cir::GotoOp>(op)) {
       gotos.insert(goTo.getLabel());
+    } else if (auto blkAdd = dyn_cast<cir::BlockAddressOp>(op)) {
+      if (blkAdd.getBlockAddrInfoAttr().getFunc().getAttr() != getSymName()) {
+        // Stop the walk early, no need to continue
+        invalidBlockAddress = true;
+        return mlir::WalkResult::interrupt();
+      }
+      blockAddresses.insert(blkAdd.getBlockAddrInfoAttr().getLabel());
     }
+    return mlir::WalkResult::advance();
   });
 
+  if (invalidBlockAddress)
+    return emitOpError() << "blockaddress references a different function";
+
+  llvm::SmallSet<llvm::StringRef, 16> mismatched;
   if (!labels.empty() || !gotos.empty()) {
-    llvm::SmallSet<llvm::StringRef, 16> mismatched =
-        llvm::set_difference(gotos, labels);
+    mismatched = llvm::set_difference(gotos, labels);
 
     if (!mismatched.empty())
       return emitOpError() << "goto/label mismatch";
   }
+
+  mismatched.clear();
+
+  if (!labels.empty() || !blockAddresses.empty()) {
+    mismatched = llvm::set_difference(blockAddresses, labels);
+
+    if (!mismatched.empty())
+      return emitOpError()
+             << "expects an existing label target in the referenced function";
+  }
+
   return success();
 }
 
diff --git a/clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp 
b/clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp
index 00972b6976295..d590ccce1f540 100644
--- a/clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/GotoSolver.cpp
@@ -8,6 +8,7 @@
 #include "PassDetail.h"
 #include "clang/CIR/Dialect/IR/CIRDialect.h"
 #include "clang/CIR/Dialect/Passes.h"
+#include "llvm/ADT/SmallSet.h"
 #include "llvm/Support/TimeProfiler.h"
 #include <memory>
 
@@ -30,17 +31,29 @@ static void process(cir::FuncOp func) {
   mlir::OpBuilder rewriter(func.getContext());
   llvm::StringMap<Block *> labels;
   llvm::SmallVector<cir::GotoOp, 4> gotos;
+  llvm::SmallSet<StringRef, 4> blockAddrLabel;
 
   func.getBody().walk([&](mlir::Operation *op) {
     if (auto lab = dyn_cast<cir::LabelOp>(op)) {
-      // Will construct a string copy inplace. Safely erase the label
       labels.try_emplace(lab.getLabel(), lab->getBlock());
-      lab.erase();
     } else if (auto goTo = dyn_cast<cir::GotoOp>(op)) {
       gotos.push_back(goTo);
+    } else if (auto blockAddr = dyn_cast<cir::BlockAddressOp>(op)) {
+      blockAddrLabel.insert(blockAddr.getBlockAddrInfo().getLabel());
     }
   });
 
+  for (auto &lab : labels) {
+    StringRef labelName = lab.getKey();
+    Block *block = lab.getValue();
+    if (!blockAddrLabel.contains(labelName)) {
+      // erase the LabelOp inside the block if safe
+      if (auto lab = dyn_cast<cir::LabelOp>(&block->front())) {
+        lab.erase();
+      }
+    }
+  }
+
   for (auto goTo : gotos) {
     mlir::OpBuilder::InsertionGuard guard(rewriter);
     rewriter.setInsertionPoint(goTo);
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index b4afed7019417..13835949789ce 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -3778,6 +3778,12 @@ mlir::LogicalResult 
CIRToLLVMVAArgOpLowering::matchAndRewrite(
   return mlir::success();
 }
 
+mlir::LogicalResult CIRToLLVMBlockAddressOpLowering::matchAndRewrite(
+    cir::BlockAddressOp op, OpAdaptor adaptor,
+    mlir::ConversionPatternRewriter &rewriter) const {
+  return mlir::failure();
+}
+
 std::unique_ptr<mlir::Pass> createConvertCIRToLLVMPass() {
   return std::make_unique<ConvertCIRToLLVMPass>();
 }
diff --git a/clang/test/CIR/CodeGen/label-values.c 
b/clang/test/CIR/CodeGen/label-values.c
new file mode 100644
index 0000000000000..20042ce1e6e8b
--- /dev/null
+++ b/clang/test/CIR/CodeGen/label-values.c
@@ -0,0 +1,76 @@
+// 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
+
+void A(void) {
+  void *ptr = &&A;
+A:
+  return;
+}
+// CIR:  cir.func dso_local @A
+// CIR:    [[PTR:%.*]] = cir.alloca !cir.ptr<!void>, 
!cir.ptr<!cir.ptr<!void>>, ["ptr", init] {alignment = 8 : i64}
+// CIR:    [[BLOCK:%.*]] = cir.blockaddress <@A, "A"> -> !cir.ptr<!void>
+// CIR:    cir.store align(8) [[BLOCK]], [[PTR]] : !cir.ptr<!void>, 
!cir.ptr<!cir.ptr<!void>>
+// CIR:    cir.br ^bb1
+// CIR:  ^bb1:  // pred: ^bb0
+// CIR:    cir.label "A"
+// CIR:    cir.return
+
+void B(void) {
+B:
+  void *ptr = &&B;
+}
+
+// CIR:  cir.func dso_local @B()
+// CIR:    [[PTR:%.*]] = cir.alloca !cir.ptr<!void>, 
!cir.ptr<!cir.ptr<!void>>, ["ptr", init] {alignment = 8 : i64}
+// CIR:    cir.br ^bb1
+// CIR:   ^bb1:
+// CIR:    cir.label "B"
+// CIR:    [[BLOCK:%.*]] = cir.blockaddress <@B, "B"> -> !cir.ptr<!void>
+// CIR:    cir.store align(8) [[BLOCK]], [[PTR]] : !cir.ptr<!void>, 
!cir.ptr<!cir.ptr<!void>>
+// CIR:    cir.return
+
+void C(int x) {
+    void *ptr = (x == 0) ? &&A : &&B;
+A:
+    return;
+B:
+    return;
+}
+
+// CIR:  cir.func dso_local @C
+// CIR:    [[BLOCK1:%.*]] = cir.blockaddress <@C, "A"> -> !cir.ptr<!void>
+// CIR:    [[BLOCK2:%.*]] = cir.blockaddress <@C, "B"> -> !cir.ptr<!void>
+// CIR:    [[COND:%.*]] = cir.select if [[CMP:%.*]] then [[BLOCK1]] else 
[[BLOCK2]] : (!cir.bool, !cir.ptr<!void>, !cir.ptr<!void>) -> !cir.ptr<!void>
+// CIR:    cir.store align(8) [[COND]], [[PTR:%.*]] : !cir.ptr<!void>, 
!cir.ptr<!cir.ptr<!void>>
+// CIR:    cir.br ^bb1
+// CIR:  ^bb1:  // pred: ^bb0
+// CIR:    cir.label "A"
+// CIR:    cir.br ^bb2
+// CIR:  ^bb2:  // 2 preds: ^bb1, ^bb3
+// CIR:    cir.return
+// CIR:  ^bb3:  // no predecessors
+// CIR:    cir.label "B"
+// CIR:    cir.br ^bb2
+
+void D(void) {
+  void *ptr = &&A;
+  void *ptr2 = &&A;
+A:
+  void *ptr3 = &&A;
+  return;
+}
+
+// CIR:  cir.func dso_local @D
+// CIR:    %[[PTR:.*]] = cir.alloca !cir.ptr<!void>, 
!cir.ptr<!cir.ptr<!void>>, ["ptr", init]
+// CIR:    %[[PTR2:.*]] = cir.alloca !cir.ptr<!void>, 
!cir.ptr<!cir.ptr<!void>>, ["ptr2", init]
+// CIR:    %[[PTR3:.*]] = cir.alloca !cir.ptr<!void>, 
!cir.ptr<!cir.ptr<!void>>, ["ptr3", init]
+// CIR:    %[[BLK1:.*]] = cir.blockaddress <@D, "A"> -> !cir.ptr<!void>
+// CIR:    cir.store align(8) %[[BLK1]], %[[PTR]] : !cir.ptr<!void>, 
!cir.ptr<!cir.ptr<!void>>
+// CIR:    %[[BLK2:.*]] = cir.blockaddress <@D, "A"> -> !cir.ptr<!void>
+// CIR:    cir.store align(8) %[[BLK2]], %[[PTR2]] : !cir.ptr<!void>, 
!cir.ptr<!cir.ptr<!void>>
+// CIR:    cir.br ^bb1
+// CIR:  ^bb1:  // pred: ^bb0
+// CIR:    cir.label "A"
+// CIR:    %[[BLK3:.*]] = cir.blockaddress <@D, "A"> -> !cir.ptr<!void>
+// CIR:    cir.store align(8) %[[BLK3]], %[[PTR3]] : !cir.ptr<!void>, 
!cir.ptr<!cir.ptr<!void>>
+// CIR:    cir.return
diff --git a/clang/test/CIR/IR/block-adress.cir 
b/clang/test/CIR/IR/block-adress.cir
new file mode 100644
index 0000000000000..ae9662461d08f
--- /dev/null
+++ b/clang/test/CIR/IR/block-adress.cir
@@ -0,0 +1,34 @@
+// RUN: cir-opt %s | cir-opt | FileCheck %s
+
+!void = !cir.void
+
+module {
+  cir.func @block_address(){
+    %0 = cir.blockaddress <@block_address, "label"> -> !cir.ptr<!void>
+    cir.br ^bb1
+  ^bb1:
+    cir.label "label"
+    cir.return
+  }
+// CHECK: cir.func @block_address
+// CHECK: %0 = cir.blockaddress <@block_address, "label"> -> !cir.ptr<!void>
+// CHECK:   cir.br ^bb1
+// CHECK: ^bb1:
+// CHECK:   cir.label "label"
+// CHECK:   cir.return
+
+cir.func @block_address_inside_scope() -> () {
+  cir.scope{
+    %0 = cir.blockaddress <@block_address_inside_scope, "label"> -> 
!cir.ptr<!void>
+  }
+  cir.br ^bb1
+^bb1:
+  cir.label "label"
+  cir.return
+}
+// CHECK: cir.func @block_address_inside_scope
+// CHECK: cir.scope
+// CHECK:  %0 = cir.blockaddress <@block_address_inside_scope, "label"> -> 
!cir.ptr<!void>
+// CHECK:  cir.label "label"
+// CHECK: cir.return
+}
diff --git a/clang/test/CIR/IR/invalid-block-address.cir 
b/clang/test/CIR/IR/invalid-block-address.cir
new file mode 100644
index 0000000000000..c3545406bfcff
--- /dev/null
+++ b/clang/test/CIR/IR/invalid-block-address.cir
@@ -0,0 +1,21 @@
+// RUN: cir-opt %s -verify-diagnostics -split-input-file
+
+!void = !cir.void
+
+// expected-error@+1 {{expects an existing label target in the referenced 
function}}
+cir.func @bad_block_address() -> () {
+    %0 = cir.blockaddress <@bad_block_address, "label"> -> !cir.ptr<!void>
+    cir.br ^bb1
+  ^bb1:
+    cir.label "wrong_label"
+    cir.return
+}
+
+// expected-error@+1 {{blockaddress references a different function}}
+cir.func @bad_block_func() -> () {
+    %0 = cir.blockaddress <@mismatch_func, "label"> -> !cir.ptr<!void>
+    cir.br ^bb1
+  ^bb1:
+    cir.label "label"
+    cir.return
+}
diff --git a/clang/test/CIR/Transforms/goto_solver.cir 
b/clang/test/CIR/Transforms/goto_solver.cir
new file mode 100644
index 0000000000000..13ec4b8d79006
--- /dev/null
+++ b/clang/test/CIR/Transforms/goto_solver.cir
@@ -0,0 +1,62 @@
+// RUN: cir-opt %s -cir-goto-solver -o - | FileCheck %s
+
+!void = !cir.void
+
+cir.func @a(){
+  %0 = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr", init] 
{alignment = 8 : i64}
+  %1 = cir.blockaddress <@a, "label1"> -> !cir.ptr<!void>
+  cir.store align(8) %1, %0 : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
+  cir.br ^bb1
+^bb1:
+  cir.label "label1"
+  cir.br ^bb2
+^bb2:
+  // This label is not referenced by any blockaddressOp, so it should be 
removed
+  cir.label "label2"
+  cir.return
+}
+
+// CHECK:  cir.func @a()
+// CHECK:   %1 = cir.blockaddress <@a, "label1"> -> !cir.ptr<!void>
+// CHECK: ^bb1:
+// CHECK:   cir.label "label1"
+// CHECK:   cir.br ^bb2
+// CHECK: ^bb2:
+// CHECK-NOT: cir.label "label2"
+
+cir.func @b(){
+  %0 = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr", init] 
{alignment = 8 : i64}
+  %1 = cir.blockaddress <@b, "label1"> -> !cir.ptr<!void>
+  cir.store align(8) %1, %0 : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
+  cir.goto "label2"
+^bb1:
+  cir.label "label1"
+  cir.br ^bb2
+^bb2:
+  // This label is not referenced by any blockaddressOp, so it should be 
removed
+  cir.label "label2"
+  cir.return
+}
+
+// CHECK: cir.func @b() {
+// CHECK:   %1 = cir.blockaddress <@b, "label1"> -> !cir.ptr<!void>
+// CHECK:   cir.store align(8) %1, {{.*}} : !cir.ptr<!void>, 
!cir.ptr<!cir.ptr<!void>>
+// CHECK:   cir.br ^bb2
+// CHECK: ^bb1:
+// CHECK:   cir.label "label1"
+// CHECK:   cir.br ^bb2
+// CHECK: ^bb2:
+// CHECK-NOT: cir.label "label2"
+
+cir.func @c() {
+  cir.label "label1"
+  %0 = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr", init] 
{alignment = 8 : i64}
+  %1 = cir.blockaddress <@c, "label1"> -> !cir.ptr<!void>
+  cir.store align(8) %1, %0 : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
+  cir.return
+}
+
+// CHECK: cir.func @c
+// CHECK:   cir.label "label1"
+// CHECK:   %1 = cir.blockaddress <@c, "label1"> -> !cir.ptr<!void>
+// CHECK:   cir.store align(8) %1, {{.*}} : !cir.ptr<!void>, 
!cir.ptr<!cir.ptr<!void>>
diff --git a/clang/tools/cir-opt/cir-opt.cpp b/clang/tools/cir-opt/cir-opt.cpp
index c4d29a2117c75..ee42015bb38e9 100644
--- a/clang/tools/cir-opt/cir-opt.cpp
+++ b/clang/tools/cir-opt/cir-opt.cpp
@@ -58,6 +58,10 @@ int main(int argc, char **argv) {
     return mlir::createHoistAllocasPass();
   });
 
+  ::mlir::registerPass([]() -> std::unique_ptr<::mlir::Pass> {
+    return mlir::createGotoSolverPass();
+  });
+
   mlir::registerTransformsPasses();
 
   return mlir::asMainReturnCode(MlirOptMain(

>From 1ba292553639ff83f3bc2c2a816987ebf4876c2c Mon Sep 17 00:00:00 2001
From: Andres Salamanca <[email protected]>
Date: Sat, 15 Nov 2025 17:59:15 -0500
Subject: [PATCH 2/2] Apply review

---
 clang/include/clang/CIR/Dialect/IR/CIROps.td | 15 ++++---
 clang/test/CIR/CodeGen/label-values.c        | 46 ++++++++++----------
 clang/test/CIR/IR/block-adress.cir           | 10 ++---
 clang/test/CIR/IR/invalid-block-address.cir  |  6 +--
 clang/test/CIR/Transforms/goto_solver.cir    | 14 +++---
 5 files changed, 46 insertions(+), 45 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index d7270bc81b68a..10c801c4762ea 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -4804,12 +4804,12 @@ def CIR_AtomicClearOp : CIR_Op<"atomic.clear"> {
 // BlockAddressOp
 
//===----------------------------------------------------------------------===//
 
-def CIR_BlockAddressOp : CIR_Op<"blockaddress", [Pure]> {
+def CIR_BlockAddressOp : CIR_Op<"block_address", [Pure]> {
   let summary = "Get the address of a cir.label within a function";
   let description = [{
     The `cir.blockaddress` operation takes a function name and a label and
-    produces a pointer value that represents the address of that cir.label 
within
-    the specified function.
+    produces a pointer value that represents the address of that cir.label
+    within the specified function.
 
     This operation models GCC's "labels as values" extension (`&&label`), which
     allows taking the address of a local label and using it as a computed
@@ -4817,8 +4817,9 @@ def CIR_BlockAddressOp : CIR_Op<"blockaddress", [Pure]> {
 
     Example:
     ```mlir
-    %1 = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr", init] 
{alignment = 8 : i64}
-    %addr = cir.blockaddress("foo", "label") -> !cir.ptr<!cir.void>
+    %1 = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr", init]
+                                                          {alignment = 8 : i64}
+    %addr = cir.block_address <@c, "label1"> : !cir.ptr<!cir.void>
     cir.store align(8) %addr, %1 : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
     cir.br ^bb1
    ^bb1:
@@ -4826,10 +4827,10 @@ def CIR_BlockAddressOp : CIR_Op<"blockaddress", [Pure]> 
{
     ```
   }];
 
-  let arguments = (ins CIR_BlockAddrInfoAttr:$blockAddrInfo);
+  let arguments = (ins CIR_BlockAddrInfoAttr:$block_addr_info);
   let results = (outs CIR_VoidPtrType:$addr);
   let assemblyFormat = [{
-    $blockAddrInfo `->` qualified(type($addr)) attr-dict
+    $block_addr_info `:` qualified(type($addr)) attr-dict
   }];
 }
 
diff --git a/clang/test/CIR/CodeGen/label-values.c 
b/clang/test/CIR/CodeGen/label-values.c
index 20042ce1e6e8b..41178e3f62f20 100644
--- a/clang/test/CIR/CodeGen/label-values.c
+++ b/clang/test/CIR/CodeGen/label-values.c
@@ -2,61 +2,61 @@
 // RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR
 
 void A(void) {
-  void *ptr = &&A;
-A:
+  void *ptr = &&LABEL_A;
+LABEL_A:
   return;
 }
 // CIR:  cir.func dso_local @A
 // CIR:    [[PTR:%.*]] = cir.alloca !cir.ptr<!void>, 
!cir.ptr<!cir.ptr<!void>>, ["ptr", init] {alignment = 8 : i64}
-// CIR:    [[BLOCK:%.*]] = cir.blockaddress <@A, "A"> -> !cir.ptr<!void>
+// CIR:    [[BLOCK:%.*]] = cir.block_address <@A, "LABEL_A"> : !cir.ptr<!void>
 // CIR:    cir.store align(8) [[BLOCK]], [[PTR]] : !cir.ptr<!void>, 
!cir.ptr<!cir.ptr<!void>>
 // CIR:    cir.br ^bb1
 // CIR:  ^bb1:  // pred: ^bb0
-// CIR:    cir.label "A"
+// CIR:    cir.label "LABEL_A"
 // CIR:    cir.return
 
 void B(void) {
-B:
-  void *ptr = &&B;
+LABEL_B:
+  void *ptr = &&LABEL_B;
 }
 
 // CIR:  cir.func dso_local @B()
 // CIR:    [[PTR:%.*]] = cir.alloca !cir.ptr<!void>, 
!cir.ptr<!cir.ptr<!void>>, ["ptr", init] {alignment = 8 : i64}
 // CIR:    cir.br ^bb1
 // CIR:   ^bb1:
-// CIR:    cir.label "B"
-// CIR:    [[BLOCK:%.*]] = cir.blockaddress <@B, "B"> -> !cir.ptr<!void>
+// CIR:    cir.label "LABEL_B"
+// CIR:    [[BLOCK:%.*]] = cir.block_address <@B, "LABEL_B"> : !cir.ptr<!void>
 // CIR:    cir.store align(8) [[BLOCK]], [[PTR]] : !cir.ptr<!void>, 
!cir.ptr<!cir.ptr<!void>>
 // CIR:    cir.return
 
 void C(int x) {
-    void *ptr = (x == 0) ? &&A : &&B;
-A:
+    void *ptr = (x == 0) ? &&LABEL_A : &&LABEL_B;
+LABEL_A:
     return;
-B:
+LABEL_B:
     return;
 }
 
 // CIR:  cir.func dso_local @C
-// CIR:    [[BLOCK1:%.*]] = cir.blockaddress <@C, "A"> -> !cir.ptr<!void>
-// CIR:    [[BLOCK2:%.*]] = cir.blockaddress <@C, "B"> -> !cir.ptr<!void>
+// CIR:    [[BLOCK1:%.*]] = cir.block_address <@C, "LABEL_A"> : !cir.ptr<!void>
+// CIR:    [[BLOCK2:%.*]] = cir.block_address <@C, "LABEL_B"> : !cir.ptr<!void>
 // CIR:    [[COND:%.*]] = cir.select if [[CMP:%.*]] then [[BLOCK1]] else 
[[BLOCK2]] : (!cir.bool, !cir.ptr<!void>, !cir.ptr<!void>) -> !cir.ptr<!void>
 // CIR:    cir.store align(8) [[COND]], [[PTR:%.*]] : !cir.ptr<!void>, 
!cir.ptr<!cir.ptr<!void>>
 // CIR:    cir.br ^bb1
 // CIR:  ^bb1:  // pred: ^bb0
-// CIR:    cir.label "A"
+// CIR:    cir.label "LABEL_A"
 // CIR:    cir.br ^bb2
 // CIR:  ^bb2:  // 2 preds: ^bb1, ^bb3
 // CIR:    cir.return
 // CIR:  ^bb3:  // no predecessors
-// CIR:    cir.label "B"
+// CIR:    cir.label "LABEL_B"
 // CIR:    cir.br ^bb2
 
 void D(void) {
-  void *ptr = &&A;
-  void *ptr2 = &&A;
-A:
-  void *ptr3 = &&A;
+  void *ptr = &&LABEL_A;
+  void *ptr2 = &&LABEL_A;
+LABEL_A:
+  void *ptr3 = &&LABEL_A;
   return;
 }
 
@@ -64,13 +64,13 @@ void D(void) {
 // CIR:    %[[PTR:.*]] = cir.alloca !cir.ptr<!void>, 
!cir.ptr<!cir.ptr<!void>>, ["ptr", init]
 // CIR:    %[[PTR2:.*]] = cir.alloca !cir.ptr<!void>, 
!cir.ptr<!cir.ptr<!void>>, ["ptr2", init]
 // CIR:    %[[PTR3:.*]] = cir.alloca !cir.ptr<!void>, 
!cir.ptr<!cir.ptr<!void>>, ["ptr3", init]
-// CIR:    %[[BLK1:.*]] = cir.blockaddress <@D, "A"> -> !cir.ptr<!void>
+// CIR:    %[[BLK1:.*]] = cir.block_address <@D, "LABEL_A"> : !cir.ptr<!void>
 // CIR:    cir.store align(8) %[[BLK1]], %[[PTR]] : !cir.ptr<!void>, 
!cir.ptr<!cir.ptr<!void>>
-// CIR:    %[[BLK2:.*]] = cir.blockaddress <@D, "A"> -> !cir.ptr<!void>
+// CIR:    %[[BLK2:.*]] = cir.block_address <@D, "LABEL_A"> : !cir.ptr<!void>
 // CIR:    cir.store align(8) %[[BLK2]], %[[PTR2]] : !cir.ptr<!void>, 
!cir.ptr<!cir.ptr<!void>>
 // CIR:    cir.br ^bb1
 // CIR:  ^bb1:  // pred: ^bb0
-// CIR:    cir.label "A"
-// CIR:    %[[BLK3:.*]] = cir.blockaddress <@D, "A"> -> !cir.ptr<!void>
+// CIR:    cir.label "LABEL_A"
+// CIR:    %[[BLK3:.*]] = cir.block_address <@D, "LABEL_A"> : !cir.ptr<!void>
 // CIR:    cir.store align(8) %[[BLK3]], %[[PTR3]] : !cir.ptr<!void>, 
!cir.ptr<!cir.ptr<!void>>
 // CIR:    cir.return
diff --git a/clang/test/CIR/IR/block-adress.cir 
b/clang/test/CIR/IR/block-adress.cir
index ae9662461d08f..9d6840819c2d4 100644
--- a/clang/test/CIR/IR/block-adress.cir
+++ b/clang/test/CIR/IR/block-adress.cir
@@ -1,17 +1,17 @@
-// RUN: cir-opt %s | cir-opt | FileCheck %s
+// RUN: cir-opt %s --verify-roundtrip | FileCheck %s
 
 !void = !cir.void
 
 module {
   cir.func @block_address(){
-    %0 = cir.blockaddress <@block_address, "label"> -> !cir.ptr<!void>
+    %0 = cir.block_address <@block_address, "label"> : !cir.ptr<!void>
     cir.br ^bb1
   ^bb1:
     cir.label "label"
     cir.return
   }
 // CHECK: cir.func @block_address
-// CHECK: %0 = cir.blockaddress <@block_address, "label"> -> !cir.ptr<!void>
+// CHECK: %0 = cir.block_address <@block_address, "label"> : !cir.ptr<!void>
 // CHECK:   cir.br ^bb1
 // CHECK: ^bb1:
 // CHECK:   cir.label "label"
@@ -19,7 +19,7 @@ module {
 
 cir.func @block_address_inside_scope() -> () {
   cir.scope{
-    %0 = cir.blockaddress <@block_address_inside_scope, "label"> -> 
!cir.ptr<!void>
+    %0 = cir.block_address <@block_address_inside_scope, "label"> : 
!cir.ptr<!void>
   }
   cir.br ^bb1
 ^bb1:
@@ -28,7 +28,7 @@ cir.func @block_address_inside_scope() -> () {
 }
 // CHECK: cir.func @block_address_inside_scope
 // CHECK: cir.scope
-// CHECK:  %0 = cir.blockaddress <@block_address_inside_scope, "label"> -> 
!cir.ptr<!void>
+// CHECK:  %0 = cir.block_address <@block_address_inside_scope, "label"> : 
!cir.ptr<!void>
 // CHECK:  cir.label "label"
 // CHECK: cir.return
 }
diff --git a/clang/test/CIR/IR/invalid-block-address.cir 
b/clang/test/CIR/IR/invalid-block-address.cir
index c3545406bfcff..fc9b4a902e2f4 100644
--- a/clang/test/CIR/IR/invalid-block-address.cir
+++ b/clang/test/CIR/IR/invalid-block-address.cir
@@ -1,10 +1,10 @@
-// RUN: cir-opt %s -verify-diagnostics -split-input-file
+// RUN: cir-opt %s -verify-diagnostics -split-input-file --verify-roundtrip
 
 !void = !cir.void
 
 // expected-error@+1 {{expects an existing label target in the referenced 
function}}
 cir.func @bad_block_address() -> () {
-    %0 = cir.blockaddress <@bad_block_address, "label"> -> !cir.ptr<!void>
+    %0 = cir.block_address <@bad_block_address, "label"> : !cir.ptr<!void>
     cir.br ^bb1
   ^bb1:
     cir.label "wrong_label"
@@ -13,7 +13,7 @@ cir.func @bad_block_address() -> () {
 
 // expected-error@+1 {{blockaddress references a different function}}
 cir.func @bad_block_func() -> () {
-    %0 = cir.blockaddress <@mismatch_func, "label"> -> !cir.ptr<!void>
+    %0 = cir.block_address <@mismatch_func, "label"> : !cir.ptr<!void>
     cir.br ^bb1
   ^bb1:
     cir.label "label"
diff --git a/clang/test/CIR/Transforms/goto_solver.cir 
b/clang/test/CIR/Transforms/goto_solver.cir
index 13ec4b8d79006..6ae019b44a39e 100644
--- a/clang/test/CIR/Transforms/goto_solver.cir
+++ b/clang/test/CIR/Transforms/goto_solver.cir
@@ -1,10 +1,10 @@
-// RUN: cir-opt %s -cir-goto-solver -o - | FileCheck %s
+// RUN: cir-opt %s -cir-goto-solver --verify-roundtrip -o - | FileCheck %s
 
 !void = !cir.void
 
 cir.func @a(){
   %0 = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr", init] 
{alignment = 8 : i64}
-  %1 = cir.blockaddress <@a, "label1"> -> !cir.ptr<!void>
+  %1 = cir.block_address <@a, "label1"> : !cir.ptr<!void>
   cir.store align(8) %1, %0 : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
   cir.br ^bb1
 ^bb1:
@@ -17,7 +17,7 @@ cir.func @a(){
 }
 
 // CHECK:  cir.func @a()
-// CHECK:   %1 = cir.blockaddress <@a, "label1"> -> !cir.ptr<!void>
+// CHECK:   %1 = cir.block_address <@a, "label1"> : !cir.ptr<!void>
 // CHECK: ^bb1:
 // CHECK:   cir.label "label1"
 // CHECK:   cir.br ^bb2
@@ -26,7 +26,7 @@ cir.func @a(){
 
 cir.func @b(){
   %0 = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr", init] 
{alignment = 8 : i64}
-  %1 = cir.blockaddress <@b, "label1"> -> !cir.ptr<!void>
+  %1 = cir.block_address <@b, "label1"> : !cir.ptr<!void>
   cir.store align(8) %1, %0 : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
   cir.goto "label2"
 ^bb1:
@@ -39,7 +39,7 @@ cir.func @b(){
 }
 
 // CHECK: cir.func @b() {
-// CHECK:   %1 = cir.blockaddress <@b, "label1"> -> !cir.ptr<!void>
+// CHECK:   %1 = cir.block_address <@b, "label1"> : !cir.ptr<!void>
 // CHECK:   cir.store align(8) %1, {{.*}} : !cir.ptr<!void>, 
!cir.ptr<!cir.ptr<!void>>
 // CHECK:   cir.br ^bb2
 // CHECK: ^bb1:
@@ -51,12 +51,12 @@ cir.func @b(){
 cir.func @c() {
   cir.label "label1"
   %0 = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr", init] 
{alignment = 8 : i64}
-  %1 = cir.blockaddress <@c, "label1"> -> !cir.ptr<!void>
+  %1 = cir.block_address <@c, "label1"> : !cir.ptr<!void>
   cir.store align(8) %1, %0 : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
   cir.return
 }
 
 // CHECK: cir.func @c
 // CHECK:   cir.label "label1"
-// CHECK:   %1 = cir.blockaddress <@c, "label1"> -> !cir.ptr<!void>
+// CHECK:   %1 = cir.block_address <@c, "label1"> : !cir.ptr<!void>
 // CHECK:   cir.store align(8) %1, {{.*}} : !cir.ptr<!void>, 
!cir.ptr<!cir.ptr<!void>>

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to