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

>From ed1eff3ca0fda93935fe8f43f9f230be38d3a2cd Mon Sep 17 00:00:00 2001
From: Andres Salamanca <[email protected]>
Date: Mon, 26 Jan 2026 21:11:09 -0500
Subject: [PATCH 1/2] [CIR] Add lowering for BlockAddressOp, IndirectBrOp and
 LabelOp

---
 clang/include/clang/CIR/Dialect/IR/CIROps.td  |  4 +-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 98 ++++++++++++++++++-
 clang/test/CIR/CodeGen/label-values.c         | 78 ++++++++++++++-
 3 files changed, 171 insertions(+), 9 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 35fd624b89743..3c2fc3facf2a3 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -1503,7 +1503,7 @@ def CIR_LabelOp : CIR_Op<"label", [AlwaysSpeculatable]> {
   let hasVerifier = 1;
 
   let customLLVMLoweringConstructorDecl =
-    LoweringBuilders<(ins "[[maybe_unused]] LLVMBlockAddressInfo 
&":$blockInfoAddr)>;
+    LoweringBuilders<(ins "LLVMBlockAddressInfo &":$blockInfoAddr)>;
 }
 
 
//===----------------------------------------------------------------------===//
@@ -6075,7 +6075,7 @@ def CIR_BlockAddressOp : CIR_Op<"block_address", [Pure]> {
   }];
 
   let customLLVMLoweringConstructorDecl =
-    LoweringBuilders<(ins "[[maybe_unused]] LLVMBlockAddressInfo 
&":$blockInfoAddr)>;
+    LoweringBuilders<(ins "LLVMBlockAddressInfo &":$blockInfoAddr)>;
 }
 
 
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 769a053c4e586..692b098912529 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -703,6 +703,8 @@ struct ConvertCIRToLLVMPass
 
   void processCIRAttrs(mlir::ModuleOp module);
 
+  void resolveBlockAddressOp(LLVMBlockAddressInfo &blockInfoAddr);
+
   StringRef getDescription() const override {
     return "Convert the prepared CIR dialect module to LLVM dialect";
   }
@@ -3249,6 +3251,24 @@ mlir::LogicalResult 
CIRToLLVMObjSizeOpLowering::matchAndRewrite(
   return mlir::LogicalResult::success();
 }
 
+void ConvertCIRToLLVMPass::resolveBlockAddressOp(
+    LLVMBlockAddressInfo &blockInfoAddr) {
+
+  mlir::ModuleOp module = getOperation();
+  mlir::OpBuilder opBuilder(module.getContext());
+  for (auto &[blockAddOp, blockInfo] :
+       blockInfoAddr.getUnresolvedBlockAddress()) {
+    mlir::LLVM::BlockTagOp resolvedLabel =
+        blockInfoAddr.lookupBlockTag(blockInfo);
+    assert(resolvedLabel && "expected BlockTagOp to already be emitted");
+    auto fnSym = blockInfo.getFunc();
+    auto blkAddTag = mlir::LLVM::BlockAddressAttr::get(
+        opBuilder.getContext(), fnSym, resolvedLabel.getTagAttr());
+    blockAddOp.setBlockAddrAttr(blkAddTag);
+  }
+  blockInfoAddr.clearUnresolvedMap();
+}
+
 void ConvertCIRToLLVMPass::processCIRAttrs(mlir::ModuleOp module) {
   // Lower the module attributes to LLVM equivalents.
   if (mlir::Attribute tripleAttr =
@@ -3315,6 +3335,7 @@ void ConvertCIRToLLVMPass::runOnOperation() {
                       return std::make_pair(dtorAttr.getName(),
                                             dtorAttr.getPriority());
                     });
+  resolveBlockAddressOp(blockInfoAddr);
 }
 
 mlir::LogicalResult CIRToLLVMBrOpLowering::matchAndRewrite(
@@ -4330,19 +4351,90 @@ mlir::LogicalResult 
CIRToLLVMVAArgOpLowering::matchAndRewrite(
 mlir::LogicalResult CIRToLLVMLabelOpLowering::matchAndRewrite(
     cir::LabelOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
-  return mlir::failure();
+  mlir::MLIRContext *ctx = rewriter.getContext();
+  mlir::Block *block = op->getBlock();
+  // A BlockTagOp cannot reside in the entry block. The address of the entry
+  // block cannot be taken
+  if (block->isEntryBlock()) {
+    mlir::Block *newBlock =
+        rewriter.splitBlock(op->getBlock(), mlir::Block::iterator(op));
+    rewriter.setInsertionPointToEnd(block);
+    mlir::LLVM::BrOp::create(rewriter, op.getLoc(), newBlock);
+  }
+  auto tagAttr =
+      mlir::LLVM::BlockTagAttr::get(ctx, blockInfoAddr.getTagIndex());
+  rewriter.setInsertionPoint(op);
+
+  auto blockTagOp =
+      mlir::LLVM::BlockTagOp::create(rewriter, op->getLoc(), tagAttr);
+  mlir::LLVM::LLVMFuncOp func = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
+  auto blockInfoAttr =
+      cir::BlockAddrInfoAttr::get(ctx, func.getSymName(), op.getLabel());
+  blockInfoAddr.mapBlockTag(blockInfoAttr, blockTagOp);
+  rewriter.eraseOp(op);
+
+  return mlir::success();
 }
 
 mlir::LogicalResult CIRToLLVMBlockAddressOpLowering::matchAndRewrite(
     cir::BlockAddressOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
-  return mlir::failure();
+  mlir::MLIRContext *ctx = rewriter.getContext();
+
+  mlir::LLVM::BlockTagOp matchLabel =
+      blockInfoAddr.lookupBlockTag(op.getBlockAddrInfoAttr());
+  mlir::LLVM::BlockTagAttr tagAttr;
+  if (!matchLabel)
+    // If the BlockTagOp has not been emitted yet, use  a placeholder.
+    // This will later be replaced with the correct tag index during
+    // `resolveBlockAddressOp`.
+    tagAttr = {};
+  else
+    tagAttr = matchLabel.getTag();
+
+  auto blkAddr = mlir::LLVM::BlockAddressAttr::get(
+      rewriter.getContext(), op.getBlockAddrInfoAttr().getFunc(), tagAttr);
+  rewriter.setInsertionPoint(op);
+  auto newOp = mlir::LLVM::BlockAddressOp::create(
+      rewriter, op.getLoc(), mlir::LLVM::LLVMPointerType::get(ctx), blkAddr);
+  if (!matchLabel)
+    blockInfoAddr.addUnresolvedBlockAddress(newOp, op.getBlockAddrInfoAttr());
+  rewriter.replaceOp(op, newOp);
+  return mlir::success();
 }
 
 mlir::LogicalResult CIRToLLVMIndirectBrOpLowering::matchAndRewrite(
     cir::IndirectBrOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
-  return mlir::failure();
+
+  llvm::SmallVector<mlir::Block *, 8> successors;
+  llvm::SmallVector<mlir::ValueRange, 8> succOperands;
+  bool poison = op.getPoison();
+  for (mlir::Block *succ : op->getSuccessors()) {
+    successors.push_back(succ);
+  }
+
+  for (mlir::ValueRange operand : op.getSuccOperands()) {
+    succOperands.push_back(operand);
+  }
+
+  auto llvmPtrType = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
+  mlir::Value targetAddr;
+  if (!poison) {
+    targetAddr = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(),
+                                               llvmPtrType, adaptor.getAddr());
+  } else {
+    targetAddr =
+        mlir::LLVM::PoisonOp::create(rewriter, op->getLoc(), llvmPtrType);
+    // Remove the block argument to avoid generating an empty PHI during
+    // lowering.
+    op->getBlock()->eraseArgument(0);
+  }
+
+  auto newOp = mlir::LLVM::IndirectBrOp::create(
+      rewriter, op.getLoc(), targetAddr, succOperands, successors);
+  rewriter.replaceOp(op, newOp);
+  return mlir::success();
 }
 
 mlir::LogicalResult CIRToLLVMAwaitOpLowering::matchAndRewrite(
diff --git a/clang/test/CIR/CodeGen/label-values.c 
b/clang/test/CIR/CodeGen/label-values.c
index 750ef1f6889bf..8ba0dd72f9ef5 100644
--- a/clang/test/CIR/CodeGen/label-values.c
+++ b/clang/test/CIR/CodeGen/label-values.c
@@ -1,5 +1,7 @@
 // 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
 
@@ -23,6 +25,17 @@ void A(void) {
 // CIR:    cir.label "LABEL_A"
 // CIR:    cir.return
 
+// LLVM: define dso_local void @A()
+// LLVM:   [[PTR:%.*]] = alloca ptr, i64 1, align 8
+// LLVM:   store ptr blockaddress(@A, %[[LABEL_A:.*]]), ptr [[PTR]], align 8
+// LLVM:   [[BLOCKADD:%.*]] = load ptr, ptr [[PTR]], align 8
+// LLVM:   br label %[[indirectgoto:.*]]
+// LLVM: [[indirectgoto]]:                                                ; 
preds = %[[ENTRY:.*]]
+// LLVM:  [[PHI:%.*]] = phi ptr [ [[BLOCKADD]], %[[ENTRY]] ]
+// LLVM:  indirectbr ptr [[PHI]], [label %[[LABEL_A]]]
+// LLVM: [[LABEL_A]]:                                                ; preds = 
%[[indirectgoto]]
+// LLVM:   ret void
+
 // OGCG: define dso_local void @A()
 // OGCG:   [[PTR:%.*]] = alloca ptr, align 8
 // OGCG:   store ptr blockaddress(@A, %LABEL_A), ptr [[PTR]], align 8
@@ -54,6 +67,17 @@ void B(void) {
 // CIR-NEXT:    ^bb1
 // CIR:    ]
 
+// LLVM: define dso_local void @B
+// LLVM:   %[[PTR:.*]] = alloca ptr, i64 1, align 8
+// LLVM:   br label %[[LABEL_B:.*]]
+// LLVM: [[LABEL_B]]:
+// LLVM:   store ptr blockaddress(@B, %[[LABEL_B]]), ptr %[[PTR]], align 8
+// LLVM:   [[BLOCKADD:%.*]] = load ptr, ptr %[[PTR]], align 8
+// LLVM:   br label %[[indirectgoto:.*]]
+// LLVM: [[indirectgoto]]:
+// LLVM:   [[PHI:%.*]] = phi ptr [ [[BLOCKADD]], %[[LABEL_B]] ]
+// LLVM:   indirectbr ptr [[PHI]], [label %[[LABEL_B]]]
+
 // OGCG: define dso_local void @B
 // OGCG:   [[PTR:%.*]] = alloca ptr, align 8
 // OGCG:   br label %LABEL_B
@@ -95,6 +119,21 @@ void C(int x) {
 // CIR:    cir.label "LABEL_B"
 // CIR:    cir.br ^bb3
 
+// LLVM: define dso_local void @C(i32 %0)
+// LLVM:   [[COND:%.*]] = select i1 [[CMP:%.*]], ptr blockaddress(@C, 
%[[LABEL_A:.*]]), ptr blockaddress(@C, %[[LABEL_B:.*]])
+// LLVM:   store ptr [[COND]], ptr [[PTR:%.*]], align 8
+// LLVM:   [[BLOCKADD:%.*]] = load ptr, ptr [[PTR]], align 8
+// LLVM:   br label %[[indirectgoto:.*]]
+// LLVM: [[indirectgoto]]:
+// LLVM:   [[PHI:%.*]] = phi ptr [ [[BLOCKADD]], %[[ENTRY:.*]] ]
+// LLVM:   indirectbr ptr [[PHI]], [label %[[LABEL_A]], label %[[LABEL_B]]]
+// LLVM: [[LABEL_A]]:
+// LLVM:   br label %[[RET:.*]]
+// LLVM: [[RET]]:
+// LLVM:   ret void
+// LLVM: [[LABEL_B]]:
+// LLVM:   br label %[[RET]]
+
 // OGCG: define dso_local void @C
 // OGCG:   [[COND:%.*]] = select i1 [[CMP:%.*]], ptr blockaddress(@C, 
%LABEL_A), ptr blockaddress(@C, %LABEL_B)
 // OGCG:   store ptr [[COND]], ptr [[PTR:%.*]], align 8
@@ -140,6 +179,21 @@ void D(void) {
 // CIR:    cir.store align(8) %[[BLK3]], %[[PTR3]] : !cir.ptr<!void>, 
!cir.ptr<!cir.ptr<!void>>
 // CIR:    cir.return
 
+// LLVM: define dso_local void @D
+// LLVM:   %[[PTR:.*]] = alloca ptr, i64 1, align 8
+// LLVM:   %[[PTR2:.*]] = alloca ptr, i64 1, align 8
+// LLVM:   %[[PTR3:.*]] = alloca ptr, i64 1, align 8
+// LLVM:   store ptr blockaddress(@D, %[[LABEL_A:.*]]), ptr %[[PTR]], align 8
+// LLVM:   store ptr blockaddress(@D, %[[LABEL_A]]), ptr %[[PTR2]], align 8
+// LLVM:   %[[BLOCKADD:.*]] = load ptr, ptr %[[PTR2]], align 8
+// LLVM:   br label %[[indirectgoto:.*]]
+// LLVM: [[indirectgoto]]:
+// LLVM:   [[PHI:%.*]] = phi ptr [ %[[BLOCKADD]], %[[ENTRY:.*]] ]
+// LLVM:   indirectbr ptr [[PHI]], [label %[[LABEL_A]], label %[[LABEL_A]], 
label %[[LABEL_A]]]
+// LLVM: [[LABEL_A]]:
+// LLVM:   store ptr blockaddress(@D, %[[LABEL_A]]), ptr %[[PTR3]], align 8
+// LLVM:   ret void
+
 // OGCG: define dso_local void @D
 // OGCG:   %[[PTR:.*]] = alloca ptr, align 8
 // OGCG:   %[[PTR2:.*]] = alloca ptr, align 8
@@ -186,19 +240,35 @@ void E(void) {
 //CIR:  ^bb5:  // 2 preds: ^bb1, ^bb4
 //CIR:    cir.label "LABEL_D"
 
+// LLVM: define dso_local void @E()
+// LLVM:   store ptr blockaddress(@E, %[[LABEL_D:.*]])
+// LLVM:   store ptr blockaddress(@E, %[[LABEL_C:.*]])
+// LLVM:   br label %[[LABEL_A:.*]]
+// LLVM: [[indirectgoto:.*]]:                                                ; 
No predecessors!
+// LLVM:   indirectbr ptr poison, [label %[[LABEL_D]], label %[[LABEL_C]], 
label %[[LABEL_B:.*]], label %[[LABEL_A]]]
+// LLVM: [[LABEL_A]]:
+// LLVM:   br label %[[LABEL_B]]
+// LLVM: [[LABEL_B]]:
+// LLVM:   store ptr blockaddress(@E, %[[LABEL_B]])
+// LLVM:   store ptr blockaddress(@E, %[[LABEL_A]])
+// LLVM:   br label %[[LABEL_C]]
+// LLVM: [[LABEL_C]]:
+// LLVM:   br label %[[LABEL_D]]
+// LLVM: [[LABEL_D]]:
+
 // OGCG: define dso_local void @E() #0 {
 // OGCG:   store ptr blockaddress(@E, %LABEL_D), ptr %ptr, align 8
 // OGCG:   store ptr blockaddress(@E, %LABEL_C), ptr %ptr2, align 8
 // OGCG:   br label %LABEL_A
-// OGCG: A:                                                ; preds = 
%indirectgoto, %entry
+// OGCG: LABEL_A:                                                ; preds = 
%indirectgoto, %entry
 // OGCG:   br label %LABEL_B
-// OGCG: B:                                                ; preds = 
%indirectgoto, %LABEL_A
+// OGCG: LABEL_B:                                                ; preds = 
%indirectgoto, %LABEL_A
 // OGCG:   store ptr blockaddress(@E, %LABEL_B), ptr %ptr3, align 8
 // OGCG:   store ptr blockaddress(@E, %LABEL_A), ptr %ptr4, align 8
 // OGCG:   br label %LABEL_C
-// OGCG: C:                                                ; preds = %LABEL_B, 
%indirectgoto
+// OGCG: LABEL_C:                                                ; preds = 
%LABEL_B, %indirectgoto
 // OGCG:   br label %LABEL_D
-// OGCG: D:                                                ; preds = %LABEL_C, 
%indirectgoto
+// OGCG: LABEL_D:                                                ; preds = 
%LABEL_C, %indirectgoto
 // OGCG:   ret void
 // OGCG: indirectgoto:                                     ; No predecessors!
 // OGCG:   indirectbr ptr poison, [label %LABEL_D, label %LABEL_C, label 
%LABEL_B, label %LABEL_A]

>From 33ce9c18351e41024aa863cd4f93f08d1a786a73 Mon Sep 17 00:00:00 2001
From: Andres Salamanca <[email protected]>
Date: Tue, 27 Jan 2026 18:48:24 -0500
Subject: [PATCH 2/2] Address review feedback

---
 clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 692b098912529..b5e11051de5e7 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -3261,7 +3261,7 @@ void ConvertCIRToLLVMPass::resolveBlockAddressOp(
     mlir::LLVM::BlockTagOp resolvedLabel =
         blockInfoAddr.lookupBlockTag(blockInfo);
     assert(resolvedLabel && "expected BlockTagOp to already be emitted");
-    auto fnSym = blockInfo.getFunc();
+    mlir::FlatSymbolRefAttr fnSym = blockInfo.getFunc();
     auto blkAddTag = mlir::LLVM::BlockAddressAttr::get(
         opBuilder.getContext(), fnSym, resolvedLabel.getTagAttr());
     blockAddOp.setBlockAddrAttr(blkAddTag);
@@ -4410,9 +4410,8 @@ mlir::LogicalResult 
CIRToLLVMIndirectBrOpLowering::matchAndRewrite(
   llvm::SmallVector<mlir::Block *, 8> successors;
   llvm::SmallVector<mlir::ValueRange, 8> succOperands;
   bool poison = op.getPoison();
-  for (mlir::Block *succ : op->getSuccessors()) {
+  for (mlir::Block *succ : op->getSuccessors())
     successors.push_back(succ);
-  }
 
   for (mlir::ValueRange operand : op.getSuccOperands()) {
     succOperands.push_back(operand);

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

Reply via email to