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
