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

>From 8b9b35fac43c6fbdd082ab49b0a035cb5227a502 Mon Sep 17 00:00:00 2001
From: Andres Salamanca <[email protected]>
Date: Sun, 21 Dec 2025 21:22:21 -0500
Subject: [PATCH 1/3] [CIR] Add custom constructor declaration to CIR lowering
 TableGen

---
 clang/include/clang/CIR/Dialect/IR/CIROps.td  | 26 +++++-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 15 ++++
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h   | 42 +++++++++
 clang/utils/TableGen/CIRLoweringEmitter.cpp   | 87 ++++++++++++++++---
 4 files changed, 158 insertions(+), 12 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index e31024f7dfa84..0907939d124b6 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -77,6 +77,11 @@ class LLVMLoweringInfo {
   string llvmOp = "";
 }
 
+class loweringBuilders<dag p, code b = ""> {
+  dag dagParams = p;
+  code body = b;
+}
+
 class CIR_Op<string mnemonic, list<Trait> traits = []> :
     Op<CIR_Dialect, mnemonic, traits>, LLVMLoweringInfo {
   // Should we generate an ABI lowering pattern for this op?
@@ -88,6 +93,21 @@ class CIR_Op<string mnemonic, list<Trait> traits = []> :
   // Extra class declarations to be included in the generated LLVM lowering
   // pattern.
   code extraLLVMLoweringPatternDecl = "";
+  // Optional custom constructor for the generated LLVM lowering pattern.
+  //
+  // By default, CIR generates a standard lowering pattern constructor that
+  // receives the TypeConverter, MLIRContext, LowerModule, and DataLayout.
+  // Some operations require additional state or external context to be passed
+  // to the lowering pattern.
+  //
+  // This field allows an operation to define a single custom constructor for
+  // its LLVM lowering pattern. When specified, the default constructor is not
+  // generated, and only this custom constructor is emitted.
+  // NOTE: When providing a custom constructor, the corresponding lowering
+  // pattern is not automatically added to the RewritePatternSet. Users are
+  // responsible for manually registering the lowering pattern in the lowering
+  // pass.
+  loweringBuilders customLLVMLoweringConstructorDecl = ?;
 }
 
 
//===----------------------------------------------------------------------===//
@@ -1481,7 +1501,8 @@ def CIR_LabelOp : CIR_Op<"label", [AlwaysSpeculatable]> {
   let assemblyFormat = [{ $label attr-dict }];
   let hasVerifier = 1;
 
-  let hasLLVMLowering = false;
+  let customLLVMLoweringConstructorDecl =
+    loweringBuilders<(ins "LLVMBlockAddressInfo &":$blockInfoAddr)>;
 }
 
 
//===----------------------------------------------------------------------===//
@@ -6023,6 +6044,9 @@ def CIR_BlockAddressOp : CIR_Op<"block_address", [Pure]> {
   let assemblyFormat = [{
     $block_addr_info `:` qualified(type($addr)) attr-dict
   }];
+
+  let customLLVMLoweringConstructorDecl =
+    loweringBuilders<(ins "LLVMBlockAddressInfo &":$blockInfoAddr)>;
 }
 
 
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 7625bcccd520f..69daaf72b66e3 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -3230,7 +3230,16 @@ void ConvertCIRToLLVMPass::runOnOperation() {
   std::unique_ptr<cir::LowerModule> lowerModule = prepareLowerModule(module);
   prepareTypeConverter(converter, dl, lowerModule.get());
 
+  /// Tracks the state required to lower CIR `LabelOp` and `BlockAddressOp`.
+  /// Maps labels to their corresponding `BlockTagOp` and keeps bookkeeping
+  /// of unresolved `BlockAddressOp`s until they are matched with the
+  /// corresponding `BlockTagOp` in `resolveBlockAddressOp`.
+  LLVMBlockAddressInfo blockInfoAddr;
   mlir::RewritePatternSet patterns(&getContext());
+  patterns.add<CIRToLLVMBlockAddressOpLowering>(
+      converter, patterns.getContext(), lowerModule.get(), dl, blockInfoAddr);
+  patterns.add<CIRToLLVMLabelOpLowering>(converter, patterns.getContext(),
+                                         lowerModule.get(), dl, blockInfoAddr);
 
   patterns.add<
 #define GET_LLVM_LOWERING_PATTERNS_LIST
@@ -4279,6 +4288,12 @@ mlir::LogicalResult 
CIRToLLVMVAArgOpLowering::matchAndRewrite(
   return mlir::success();
 }
 
+mlir::LogicalResult CIRToLLVMLabelOpLowering::matchAndRewrite(
+    cir::LabelOp op, OpAdaptor adaptor,
+    mlir::ConversionPatternRewriter &rewriter) const {
+  return mlir::failure();
+}
+
 mlir::LogicalResult CIRToLLVMBlockAddressOpLowering::matchAndRewrite(
     cir::BlockAddressOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
index d32f8603ee0be..7235794c3f9b4 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
@@ -36,6 +36,48 @@ void convertSideEffectForCall(mlir::Operation *callOp, bool 
isNothrow,
                               mlir::LLVM::MemoryEffectsAttr &memoryEffect,
                               bool &noUnwind, bool &willReturn);
 
+struct LLVMBlockAddressInfo {
+  // Get the next tag index
+  uint32_t getTagIndex() { return blockTagOpIndex++; }
+
+  void mapBlockTag(cir::BlockAddrInfoAttr info, mlir::LLVM::BlockTagOp tagOp) {
+    auto result = blockInfoToTagOp.try_emplace(info, tagOp);
+    assert(result.second &&
+           "attempting to map a BlockTag operation that is already mapped");
+  }
+
+  // Lookup a BlockTagOp, may return nullptr if not yet registered.
+  mlir::LLVM::BlockTagOp lookupBlockTag(cir::BlockAddrInfoAttr info) const {
+    return blockInfoToTagOp.lookup(info);
+  }
+
+  // Record an unresolved BlockAddressOp that needs patching later.
+  void addUnresolvedBlockAddress(mlir::LLVM::BlockAddressOp op,
+                                 cir::BlockAddrInfoAttr info) {
+    unresolvedBlockAddressOp.try_emplace(op, info);
+  }
+
+  void clearUnresolvedMap() { unresolvedBlockAddressOp.clear(); }
+
+  llvm::DenseMap<mlir::LLVM::BlockAddressOp, cir::BlockAddrInfoAttr> &
+  getUnresolvedBlockAddress() {
+    return unresolvedBlockAddressOp;
+  }
+
+private:
+  // Maps a (function name, label name) pair to the corresponding BlockTagOp.
+  // Used to resolve CIR LabelOps into their LLVM BlockTagOp.
+  llvm::DenseMap<cir::BlockAddrInfoAttr, mlir::LLVM::BlockTagOp>
+      blockInfoToTagOp;
+  // Tracks BlockAddressOps that could not yet be fully resolved because
+  // their BlockTagOp was not available at the time of lowering. The map
+  // stores the unresolved BlockAddressOp along with its (function name, label
+  // name) pair so it can be patched later.
+  llvm::DenseMap<mlir::LLVM::BlockAddressOp, cir::BlockAddrInfoAttr>
+      unresolvedBlockAddressOp;
+  int32_t blockTagOpIndex;
+};
+
 #define GET_LLVM_LOWERING_PATTERNS
 #include "clang/CIR/Dialect/IR/CIRLowering.inc"
 #undef GET_LLVM_LOWERING_PATTERNS
diff --git a/clang/utils/TableGen/CIRLoweringEmitter.cpp 
b/clang/utils/TableGen/CIRLoweringEmitter.cpp
index a669f21aa1108..4af8026a559de 100644
--- a/clang/utils/TableGen/CIRLoweringEmitter.cpp
+++ b/clang/utils/TableGen/CIRLoweringEmitter.cpp
@@ -11,6 +11,7 @@
 
//===----------------------------------------------------------------------===//
 
 #include "TableGenBackends.h"
+#include "llvm/TableGen/Record.h"
 #include "llvm/TableGen/TableGenBackend.h"
 #include <string>
 #include <utility>
@@ -25,6 +26,16 @@ std::vector<std::string> CXXABILoweringPatternsList;
 std::vector<std::string> LLVMLoweringPatterns;
 std::vector<std::string> LLVMLoweringPatternsList;
 
+struct CustomLoweringCtor {
+  struct Param {
+    std::string Type;
+    std::string Name;
+  };
+
+  std::vector<Param> Params;
+  std::string Body;
+};
+
 // Adapted from mlir/lib/TableGen/Operator.cpp
 // Returns the C++ class name of the operation, which is the name of the
 // operation with the dialect prefix removed and the first underscore removed.
@@ -60,6 +71,34 @@ std::string GetOpLLVMLoweringPatternName(llvm::StringRef 
OpName) {
   Name += "Lowering";
   return Name;
 }
+std::optional<CustomLoweringCtor> parseCustomLoweringCtor(const Record *R) {
+  if (!R)
+    return std::nullopt;
+
+  CustomLoweringCtor Ctor;
+  const DagInit *Args = R->getValueAsDag("dagParams");
+  Ctor.Body = R->getValueAsString("body");
+
+  for (const auto &[Arg, Name] : Args->getArgAndNames()) {
+    Ctor.Params.push_back(
+        {Arg->getAsUnquotedString(), Name->getAsUnquotedString()});
+  }
+
+  return Ctor;
+}
+void emitCustomParamList(raw_ostream &Code,
+                         ArrayRef<CustomLoweringCtor::Param> Params) {
+  for (const auto &Param : Params) {
+    Code << ", ";
+    Code << Param.Type << " " << Param.Name;
+  }
+}
+
+void emitCustomInitList(raw_ostream &Code,
+                        ArrayRef<CustomLoweringCtor::Param> Params) {
+  for (auto &P : Params)
+    Code << ", " << P.Name << "(" << P.Name << ")";
+}
 
 void GenerateABILoweringPattern(llvm::StringRef OpName,
                                 llvm::StringRef PatternName) {
@@ -93,7 +132,9 @@ void GenerateABILoweringPattern(llvm::StringRef OpName,
 
 void GenerateLLVMLoweringPattern(llvm::StringRef OpName,
                                  llvm::StringRef PatternName, bool IsRecursive,
-                                 llvm::StringRef ExtraDecl) {
+                                 llvm::StringRef ExtraDecl,
+                                 const Record *CustomCtorRec) {
+  auto CustomCtor = parseCustomLoweringCtor(CustomCtorRec);
   std::string CodeBuffer;
   llvm::raw_string_ostream Code(CodeBuffer);
 
@@ -101,29 +142,46 @@ void GenerateLLVMLoweringPattern(llvm::StringRef OpName,
        << " : public mlir::OpConversionPattern<cir::" << OpName << "> {\n";
   Code << "  [[maybe_unused]] cir::LowerModule *lowerMod;\n";
   Code << "  [[maybe_unused]] mlir::DataLayout const &dataLayout;\n";
+
+  if (CustomCtor) {
+    for (auto &P : CustomCtor->Params)
+      Code << "  " << P.Type << " " << P.Name << ";\n";
+  }
+
   Code << "\n";
 
   Code << "public:\n";
   Code << "  using mlir::OpConversionPattern<cir::" << OpName
        << ">::OpConversionPattern;\n";
 
+  // Constructor
   Code << "  " << PatternName
        << "(mlir::TypeConverter const "
           "&typeConverter, mlir::MLIRContext *context, "
           "cir::LowerModule *lowerMod, mlir::DataLayout const "
-          "&dataLayout)\n";
+          "&dataLayout";
+
+  if (CustomCtor)
+    emitCustomParamList(Code, CustomCtor->Params);
+
+  Code << ")\n";
+
   Code << "    : OpConversionPattern<cir::" << OpName
        << ">(typeConverter, context), lowerMod(lowerMod), "
           "dataLayout(dataLayout)";
-  if (IsRecursive) {
-    Code << " {\n";
+
+  if (CustomCtor)
+    emitCustomInitList(Code, CustomCtor->Params);
+
+  Code << " {\n";
+
+  if (IsRecursive)
     Code << "    setHasBoundedRewriteRecursion();\n";
-    Code << "  }\n";
-  } else {
-    Code << " {}\n";
-  }
 
-  Code << "\n";
+  if (CustomCtor)
+    Code << CustomCtor->Body << "\n";
+
+  Code << "  }\n\n";
 
   Code << "  mlir::LogicalResult matchAndRewrite(cir::" << OpName
        << " op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) "
@@ -151,11 +209,18 @@ void Generate(const Record *OpRecord) {
   if (OpRecord->getValueAsBit("hasLLVMLowering")) {
     std::string PatternName = GetOpLLVMLoweringPatternName(OpName);
     bool IsRecursive = OpRecord->getValueAsBit("isLLVMLoweringRecursive");
+    const Record *CustomCtor =
+        OpRecord->getValueAsOptionalDef("customLLVMLoweringConstructorDecl");
     llvm::StringRef ExtraDecl =
         OpRecord->getValueAsString("extraLLVMLoweringPatternDecl");
 
-    GenerateLLVMLoweringPattern(OpName, PatternName, IsRecursive, ExtraDecl);
-    LLVMLoweringPatternsList.push_back(std::move(PatternName));
+    GenerateLLVMLoweringPattern(OpName, PatternName, IsRecursive, ExtraDecl,
+                                CustomCtor);
+    // Only automatically register patterns that use the default constructor.
+    // Patterns with a custom constructor must be manually registered by the
+    // lowering pass.
+    if (!CustomCtor)
+      LLVMLoweringPatternsList.push_back(std::move(PatternName));
   }
 }
 } // namespace

>From c9f602dc283f9cbaa8c6f68421f31f11db04d767 Mon Sep 17 00:00:00 2001
From: Andres Salamanca <[email protected]>
Date: Tue, 20 Jan 2026 21:03:48 -0500
Subject: [PATCH 2/3] Address review feedback

---
 clang/include/clang/CIR/Dialect/IR/CIROps.td |  9 ++++-----
 clang/utils/TableGen/CIRLoweringEmitter.cpp  | 15 ++++++---------
 2 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 0907939d124b6..33fadd0f762b5 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -77,9 +77,8 @@ class LLVMLoweringInfo {
   string llvmOp = "";
 }
 
-class loweringBuilders<dag p, code b = ""> {
+class LoweringBuilders<dag p> {
   dag dagParams = p;
-  code body = b;
 }
 
 class CIR_Op<string mnemonic, list<Trait> traits = []> :
@@ -107,7 +106,7 @@ class CIR_Op<string mnemonic, list<Trait> traits = []> :
   // pattern is not automatically added to the RewritePatternSet. Users are
   // responsible for manually registering the lowering pattern in the lowering
   // pass.
-  loweringBuilders customLLVMLoweringConstructorDecl = ?;
+  LoweringBuilders customLLVMLoweringConstructorDecl = ?;
 }
 
 
//===----------------------------------------------------------------------===//
@@ -1502,7 +1501,7 @@ def CIR_LabelOp : CIR_Op<"label", [AlwaysSpeculatable]> {
   let hasVerifier = 1;
 
   let customLLVMLoweringConstructorDecl =
-    loweringBuilders<(ins "LLVMBlockAddressInfo &":$blockInfoAddr)>;
+    LoweringBuilders<(ins "LLVMBlockAddressInfo &":$blockInfoAddr)>;
 }
 
 
//===----------------------------------------------------------------------===//
@@ -6046,7 +6045,7 @@ def CIR_BlockAddressOp : CIR_Op<"block_address", [Pure]> {
   }];
 
   let customLLVMLoweringConstructorDecl =
-    loweringBuilders<(ins "LLVMBlockAddressInfo &":$blockInfoAddr)>;
+    LoweringBuilders<(ins "LLVMBlockAddressInfo &":$blockInfoAddr)>;
 }
 
 
//===----------------------------------------------------------------------===//
diff --git a/clang/utils/TableGen/CIRLoweringEmitter.cpp 
b/clang/utils/TableGen/CIRLoweringEmitter.cpp
index 4af8026a559de..d50373bb8b5dc 100644
--- a/clang/utils/TableGen/CIRLoweringEmitter.cpp
+++ b/clang/utils/TableGen/CIRLoweringEmitter.cpp
@@ -33,7 +33,6 @@ struct CustomLoweringCtor {
   };
 
   std::vector<Param> Params;
-  std::string Body;
 };
 
 // Adapted from mlir/lib/TableGen/Operator.cpp
@@ -77,7 +76,6 @@ std::optional<CustomLoweringCtor> 
parseCustomLoweringCtor(const Record *R) {
 
   CustomLoweringCtor Ctor;
   const DagInit *Args = R->getValueAsDag("dagParams");
-  Ctor.Body = R->getValueAsString("body");
 
   for (const auto &[Arg, Name] : Args->getArgAndNames()) {
     Ctor.Params.push_back(
@@ -86,9 +84,10 @@ std::optional<CustomLoweringCtor> 
parseCustomLoweringCtor(const Record *R) {
 
   return Ctor;
 }
+
 void emitCustomParamList(raw_ostream &Code,
                          ArrayRef<CustomLoweringCtor::Param> Params) {
-  for (const auto &Param : Params) {
+  for (const CustomLoweringCtor::Param &Param : Params) {
     Code << ", ";
     Code << Param.Type << " " << Param.Name;
   }
@@ -96,7 +95,7 @@ void emitCustomParamList(raw_ostream &Code,
 
 void emitCustomInitList(raw_ostream &Code,
                         ArrayRef<CustomLoweringCtor::Param> Params) {
-  for (auto &P : Params)
+  for (const CustomLoweringCtor::Param &P : Params)
     Code << ", " << P.Name << "(" << P.Name << ")";
 }
 
@@ -134,7 +133,8 @@ void GenerateLLVMLoweringPattern(llvm::StringRef OpName,
                                  llvm::StringRef PatternName, bool IsRecursive,
                                  llvm::StringRef ExtraDecl,
                                  const Record *CustomCtorRec) {
-  auto CustomCtor = parseCustomLoweringCtor(CustomCtorRec);
+  std::optional<CustomLoweringCtor> CustomCtor =
+      parseCustomLoweringCtor(CustomCtorRec);
   std::string CodeBuffer;
   llvm::raw_string_ostream Code(CodeBuffer);
 
@@ -144,7 +144,7 @@ void GenerateLLVMLoweringPattern(llvm::StringRef OpName,
   Code << "  [[maybe_unused]] mlir::DataLayout const &dataLayout;\n";
 
   if (CustomCtor) {
-    for (auto &P : CustomCtor->Params)
+    for (const CustomLoweringCtor::Param &P : CustomCtor->Params)
       Code << "  " << P.Type << " " << P.Name << ";\n";
   }
 
@@ -178,9 +178,6 @@ void GenerateLLVMLoweringPattern(llvm::StringRef OpName,
   if (IsRecursive)
     Code << "    setHasBoundedRewriteRecursion();\n";
 
-  if (CustomCtor)
-    Code << CustomCtor->Body << "\n";
-
   Code << "  }\n\n";
 
   Code << "  mlir::LogicalResult matchAndRewrite(cir::" << OpName

>From fb738d470be82b517efb3011ab85a5bb8d59c9af Mon Sep 17 00:00:00 2001
From: Andres Salamanca <[email protected]>
Date: Sun, 25 Jan 2026 13:31:24 -0500
Subject: [PATCH 3/3] Add [[maybe_unused]] to LLVMBlockAddressInfo

---
 clang/include/clang/CIR/Dialect/IR/CIROps.td        | 4 ++--
 clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 4 +---
 2 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 33fadd0f762b5..6d4d7b313f6e3 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -1501,7 +1501,7 @@ def CIR_LabelOp : CIR_Op<"label", [AlwaysSpeculatable]> {
   let hasVerifier = 1;
 
   let customLLVMLoweringConstructorDecl =
-    LoweringBuilders<(ins "LLVMBlockAddressInfo &":$blockInfoAddr)>;
+    LoweringBuilders<(ins "[[maybe_unused]] LLVMBlockAddressInfo 
&":$blockInfoAddr)>;
 }
 
 
//===----------------------------------------------------------------------===//
@@ -6045,7 +6045,7 @@ def CIR_BlockAddressOp : CIR_Op<"block_address", [Pure]> {
   }];
 
   let customLLVMLoweringConstructorDecl =
-    LoweringBuilders<(ins "LLVMBlockAddressInfo &":$blockInfoAddr)>;
+    LoweringBuilders<(ins "[[maybe_unused]] LLVMBlockAddressInfo 
&":$blockInfoAddr)>;
 }
 
 
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 69daaf72b66e3..a45025430b961 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -3236,10 +3236,8 @@ void ConvertCIRToLLVMPass::runOnOperation() {
   /// corresponding `BlockTagOp` in `resolveBlockAddressOp`.
   LLVMBlockAddressInfo blockInfoAddr;
   mlir::RewritePatternSet patterns(&getContext());
-  patterns.add<CIRToLLVMBlockAddressOpLowering>(
+  patterns.add<CIRToLLVMBlockAddressOpLowering, CIRToLLVMLabelOpLowering>(
       converter, patterns.getContext(), lowerModule.get(), dl, blockInfoAddr);
-  patterns.add<CIRToLLVMLabelOpLowering>(converter, patterns.getContext(),
-                                         lowerModule.get(), dl, blockInfoAddr);
 
   patterns.add<
 #define GET_LLVM_LOWERING_PATTERNS_LIST

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

Reply via email to