https://github.com/koparasy updated https://github.com/llvm/llvm-project/pull/227128
>From 4bb7a653c254c1d09ae1c107b6a6cde251089ada Mon Sep 17 00:00:00 2001 From: Konstantinos Parasyris <[email protected]> Date: Mon, 28 Sep 2026 14:35:01 -0700 Subject: [PATCH 1/2] [CIR] Make runCIRToCIRPasses independent of ASTContext Read the triple and the new cir.target_abi attribute from the module instead of the ASTContext, erroring if either is missing, so the CIR-to-CIR pipeline can run without a live AST. Co-Authored-By: Claude Opus 5.5 <[email protected]> --- clang/include/clang/CIR/CIRToCIRPasses.h | 11 ++--- .../clang/CIR/Dialect/IR/CIRDialect.td | 2 + clang/include/clang/CIR/Dialect/Passes.h | 6 --- clang/lib/CIR/CodeGen/CIRGenModule.cpp | 2 + .../Dialect/Transforms/LoweringPrepare.cpp | 16 ------- clang/lib/CIR/FrontendAction/CIRGenAction.cpp | 2 +- clang/lib/CIR/Lowering/CIRPasses.cpp | 43 +++++++++++-------- .../CodeGen/call-conv-lowering-x86_64-avx.c | 6 +++ 8 files changed, 40 insertions(+), 48 deletions(-) diff --git a/clang/include/clang/CIR/CIRToCIRPasses.h b/clang/include/clang/CIR/CIRToCIRPasses.h index 6e60614f8e9de..e4d2eff5baded 100644 --- a/clang/include/clang/CIR/CIRToCIRPasses.h +++ b/clang/include/clang/CIR/CIRToCIRPasses.h @@ -17,10 +17,6 @@ #include <memory> -namespace clang { -class ASTContext; -} - namespace mlir { class MLIRContext; class ModuleOp; @@ -31,10 +27,9 @@ namespace cir { // Run set of cleanup/prepare/etc passes CIR <-> CIR. mlir::LogicalResult runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirCtx, - clang::ASTContext &astCtx, bool enableVerifier, - bool enableIdiomRecognizer, bool enableCIRSimplify, - bool enableLibOpt, llvm::StringRef libOptOptions, - bool enableCallConvLowering); + bool enableVerifier, bool enableIdiomRecognizer, + bool enableCIRSimplify, bool enableLibOpt, + llvm::StringRef libOptOptions, bool enableCallConvLowering); } // namespace cir diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td index 93d020251f2a8..a0a1b391ee9f2 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td @@ -41,6 +41,8 @@ def CIR_Dialect : Dialect { let extraClassDeclaration = [{ static llvm::StringRef getSourceLanguageAttrName() { return "cir.lang"; } static llvm::StringRef getTripleAttrName() { return "cir.triple"; } + // TargetInfo::getABI(), e.g. "avx512" on x86 or "aapcs" on ARM. + static llvm::StringRef getTargetABIAttrName() { return "cir.target_abi"; } static llvm::StringRef getSizeTypeWidthAttrName() { return "cir.size_type_width"; } static llvm::StringRef getIntTypeWidthAttrName() { return "cir.int_type_width"; } static llvm::StringRef getOptInfoAttrName() { return "cir.opt_info"; } diff --git a/clang/include/clang/CIR/Dialect/Passes.h b/clang/include/clang/CIR/Dialect/Passes.h index 42dd338306456..dedfc9fa35179 100644 --- a/clang/include/clang/CIR/Dialect/Passes.h +++ b/clang/include/clang/CIR/Dialect/Passes.h @@ -23,10 +23,6 @@ namespace cir { enum class CallConvTarget { None, Test, X86_64 }; } // namespace cir -namespace clang { -class ASTContext; -} - namespace mlir { std::unique_ptr<Pass> createCIRCanonicalizePass(); @@ -43,11 +39,9 @@ createCallConvLoweringPass(cir::CallConvTarget target, const llvm::abi::X86ABICompatInfo &x86AbiCompat); std::unique_ptr<Pass> createHoistAllocasPass(); std::unique_ptr<Pass> createLoweringPreparePass(); -std::unique_ptr<Pass> createLoweringPreparePass(clang::ASTContext *astCtx); std::unique_ptr<Pass> createGotoSolverPass(); std::unique_ptr<Pass> createIdiomRecognizerPass(); std::unique_ptr<Pass> createLibOptPass(); -std::unique_ptr<Pass> createLibOptPass(clang::ASTContext *astCtx); void populateCIRPreLoweringPasses(mlir::OpPassManager &pm); diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index 007788d7e27c7..429ca18c08f04 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -148,6 +148,8 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext, } theModule->setAttr(cir::CIRDialect::getTripleAttrName(), builder.getStringAttr(getTriple().str())); + theModule->setAttr(cir::CIRDialect::getTargetABIAttrName(), + builder.getStringAttr(getTarget().getABI())); if (llvm::VersionTuple sdkVersion = getTarget().getSDKVersion(); !sdkVersion.empty()) theModule->setAttr(cir::CIRDialect::getSDKVersionAttrName(), diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp index 9a3c9c9745eaa..41f253e7147e0 100644 --- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp +++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp @@ -13,7 +13,6 @@ #include "mlir/IR/IRMapping.h" #include "mlir/IR/Location.h" #include "mlir/IR/Value.h" -#include "clang/AST/ASTContext.h" #include "clang/Basic/Cuda.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/Specifiers.h" @@ -290,12 +289,6 @@ struct LoweringPreparePass return guard; } - /// - /// AST related - /// ----------- - - clang::ASTContext *astCtx = nullptr; - /// Target/ABI facts sourced from the module's own attributes. std::unique_ptr<cir::LowerModule> lowerModule; @@ -578,8 +571,6 @@ struct LoweringPreparePass builder.createYield(loc); // Outermost IfOp } - - void setASTContext(clang::ASTContext *c) { astCtx = c; } }; } // namespace @@ -3111,10 +3102,3 @@ void LoweringPreparePass::runOnOperation() { std::unique_ptr<Pass> mlir::createLoweringPreparePass() { return std::make_unique<LoweringPreparePass>(); } - -std::unique_ptr<Pass> -mlir::createLoweringPreparePass(clang::ASTContext *astCtx) { - auto pass = std::make_unique<LoweringPreparePass>(); - pass->setASTContext(astCtx); - return std::move(pass); -} diff --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp index 240601f9834e5..a588ab2b67e5a 100644 --- a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp +++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp @@ -157,7 +157,7 @@ class CIRGenConsumer : public clang::ASTConsumer { const bool EnableLibOpt = FEOptions.ClangIRLibOptEnabled && (CGO.OptimizationLevel > 0); if (runCIRToCIRPasses( - MlirModule, MlirCtx, C, !FEOptions.ClangIRDisableCIRVerifier, + MlirModule, MlirCtx, !FEOptions.ClangIRDisableCIRVerifier, FEOptions.ClangIREnableIdiomRecognizer, CGO.OptimizationLevel > 0, EnableLibOpt, LibOptOptions, FEOptions.ClangIRCallConvLowering) .failed()) { diff --git a/clang/lib/CIR/Lowering/CIRPasses.cpp b/clang/lib/CIR/Lowering/CIRPasses.cpp index b612b64b71476..6e75ce03d14ff 100644 --- a/clang/lib/CIR/Lowering/CIRPasses.cpp +++ b/clang/lib/CIR/Lowering/CIRPasses.cpp @@ -12,9 +12,7 @@ #include "mlir/IR/BuiltinOps.h" #include "mlir/Pass/PassManager.h" -#include "clang/AST/ASTContext.h" #include "clang/Basic/LangOptions.h" -#include "clang/Basic/TargetInfo.h" #include "clang/CIR/Dialect/IR/CIRDialect.h" #include "clang/CIR/Dialect/Passes.h" #include "llvm/Support/TimeProfiler.h" @@ -44,10 +42,9 @@ static llvm::abi::X86AVXABILevel getX86AVXABILevel(llvm::StringRef abi) { /// Whether `__attribute__((target(...)))` on a function may raise its AVX ABI /// level above the command line's. A target that opts out, and any ABI older /// than the rule, stay at the module level. -static bool allowsX86TargetAttrAvx(const clang::ASTContext &astContext, +static bool allowsX86TargetAttrAvx(const llvm::Triple &triple, clang::LangOptions::ClangABI compat) { - return !astContext.getTargetInfo().getTriple().isPS() && - compat > clang::LangOptions::ClangABI::Ver23; + return !triple.isPS() && compat > clang::LangOptions::ClangABI::Ver23; } /// The x86_64 ABI-compatibility flags, derived from the target and the @@ -56,9 +53,8 @@ static bool allowsX86TargetAttrAvx(const clang::ASTContext &astContext, /// modern Linux target, so leaving it at the default classifies a union larger /// than an eightbyte as though every member spanned its size. static llvm::abi::X86ABICompatInfo -getX86ABICompatInfo(const clang::ASTContext &astContext, +getX86ABICompatInfo(const llvm::Triple &triple, clang::LangOptions::ClangABI compat) { - const llvm::Triple &triple = astContext.getTargetInfo().getTriple(); llvm::abi::X86ABICompatInfo abiCompat; abiCompat.HonorsRevision98 = !triple.isOSDarwin(); abiCompat.ClassifyIntegerMMXAsSSE = @@ -76,13 +72,27 @@ getX86ABICompatInfo(const clang::ASTContext &astContext, mlir::LogicalResult runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirContext, - clang::ASTContext &astContext, bool enableVerifier, - bool enableIdiomRecognizer, bool enableCIRSimplify, - bool enableLibOpt, llvm::StringRef libOptOptions, - bool enableCallConvLowering) { + bool enableVerifier, bool enableIdiomRecognizer, + bool enableCIRSimplify, bool enableLibOpt, + llvm::StringRef libOptOptions, bool enableCallConvLowering) { llvm::TimeTraceScope scope("CIR To CIR Passes"); + auto tripleAttr = theModule->getAttrOfType<mlir::StringAttr>( + cir::CIRDialect::getTripleAttrName()); + if (!tripleAttr) + return theModule.emitError() + << "missing '" << cir::CIRDialect::getTripleAttrName() + << "' attribute"; + llvm::Triple triple(tripleAttr.getValue()); + + auto abiAttr = theModule->getAttrOfType<mlir::StringAttr>( + cir::CIRDialect::getTargetABIAttrName()); + if (!abiAttr) + return theModule.emitError() + << "missing '" << cir::CIRDialect::getTargetABIAttrName() + << "' attribute"; + mlir::PassManager pm(&mlirContext); pm.addPass(mlir::createCIRCanonicalizePass()); @@ -111,15 +121,14 @@ runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirContext, // outlines dynamic global initializers into functions. It must run before // CallConvLowering so the classifier sees them, otherwise their signatures // go unclassified and caller and callee disagree on the ABI. - pm.addPass(mlir::createLoweringPreparePass(&astContext)); + pm.addPass(mlir::createLoweringPreparePass()); if (enableCallConvLowering) { // CallConvLowering rewrites signatures and call sites using the classifier, // so it must run after CXXABILowering has lowered C++ ABI types to plain // records the classifier can handle. Only the x86_64 System V classifier // is implemented; other targets are left unchanged. - const clang::TargetInfo &targetInfo = astContext.getTargetInfo(); - CallConvTarget target = getCallConvTarget(targetInfo.getTriple()); + CallConvTarget target = getCallConvTarget(triple); if (target != CallConvTarget::None) { // Source the ABI-compatibility version from the module's serialized // #cir.lowering_lang_options so a reloaded .cir classifies the same way @@ -133,9 +142,9 @@ runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirContext, compat = static_cast<clang::LangOptions::ClangABI>( loweringLangOpts.getClangAbiCompat()); pm.addPass(mlir::createCallConvLoweringPass( - target, getX86AVXABILevel(targetInfo.getABI()), - allowsX86TargetAttrAvx(astContext, compat), - getX86ABICompatInfo(astContext, compat))); + target, getX86AVXABILevel(abiAttr.getValue()), + allowsX86TargetAttrAvx(triple, compat), + getX86ABICompatInfo(triple, compat))); } } diff --git a/clang/test/CIR/CodeGen/call-conv-lowering-x86_64-avx.c b/clang/test/CIR/CodeGen/call-conv-lowering-x86_64-avx.c index 7b0fb4d4cb5b1..0ef03a867fa6a 100644 --- a/clang/test/CIR/CodeGen/call-conv-lowering-x86_64-avx.c +++ b/clang/test/CIR/CodeGen/call-conv-lowering-x86_64-avx.c @@ -12,6 +12,8 @@ // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -target-feature +avx -emit-llvm %s -o %t-avx.ll // RUN: FileCheck --check-prefixes=LLVM,LLVM-AVX,LLVM-OGCG-AVX --input-file=%t-avx.ll %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -target-feature +avx512f -fclangir -emit-cir %s -o %t-avx512.cir +// RUN: FileCheck --check-prefix=CIR-AVX512 --input-file=%t-avx512.cir %s // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -target-feature +avx512f -fclangir -emit-llvm %s -o %t-avx512-cir.ll // RUN: FileCheck --check-prefixes=LLVM,LLVM-AVX512 --input-file=%t-avx512-cir.ll %s // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -target-feature +avx512f -emit-llvm %s -o %t-avx512.ll @@ -31,6 +33,10 @@ typedef float v4f __attribute__((vector_size(16))); typedef float v8f __attribute__((vector_size(32))); typedef float v16f __attribute__((vector_size(64))); +// CIR-SSE: module {{.*}}cir.target_abi = "" +// CIR-AVX: module {{.*}}cir.target_abi = "avx" +// CIR-AVX512: module {{.*}}cir.target_abi = "avx512" + // A 128-bit vector is at or below the native vector size at every AVX level, // so it always passes in a register. void take_v128(v4f v) { (void)v; } >From 4016c442e512734cf27c902e7651f365517a463f Mon Sep 17 00:00:00 2001 From: Konstantinos Parasyris <[email protected]> Date: Mon, 28 Sep 2026 16:53:52 -0700 Subject: [PATCH 2/2] Bring ast context back --- clang/include/clang/CIR/CIRToCIRPasses.h | 12 +++++++++--- clang/include/clang/CIR/Dialect/Passes.h | 5 +++++ .../CIR/Dialect/Transforms/LoweringPrepare.cpp | 16 ++++++++++++++++ clang/lib/CIR/FrontendAction/CIRGenAction.cpp | 2 +- clang/lib/CIR/Lowering/CIRPasses.cpp | 9 +++++---- 5 files changed, 36 insertions(+), 8 deletions(-) diff --git a/clang/include/clang/CIR/CIRToCIRPasses.h b/clang/include/clang/CIR/CIRToCIRPasses.h index e4d2eff5baded..96ca97566ea40 100644 --- a/clang/include/clang/CIR/CIRToCIRPasses.h +++ b/clang/include/clang/CIR/CIRToCIRPasses.h @@ -17,6 +17,10 @@ #include <memory> +namespace clang { +class ASTContext; +} + namespace mlir { class MLIRContext; class ModuleOp; @@ -25,11 +29,13 @@ class ModuleOp; namespace cir { // Run set of cleanup/prepare/etc passes CIR <-> CIR. +// `astCtx` may be null; the pipeline reads its target facts from the module. mlir::LogicalResult runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirCtx, - bool enableVerifier, bool enableIdiomRecognizer, - bool enableCIRSimplify, bool enableLibOpt, - llvm::StringRef libOptOptions, bool enableCallConvLowering); + clang::ASTContext *astCtx, bool enableVerifier, + bool enableIdiomRecognizer, bool enableCIRSimplify, + bool enableLibOpt, llvm::StringRef libOptOptions, + bool enableCallConvLowering); } // namespace cir diff --git a/clang/include/clang/CIR/Dialect/Passes.h b/clang/include/clang/CIR/Dialect/Passes.h index dedfc9fa35179..dea8c4304a51a 100644 --- a/clang/include/clang/CIR/Dialect/Passes.h +++ b/clang/include/clang/CIR/Dialect/Passes.h @@ -23,6 +23,10 @@ namespace cir { enum class CallConvTarget { None, Test, X86_64 }; } // namespace cir +namespace clang { +class ASTContext; +} + namespace mlir { std::unique_ptr<Pass> createCIRCanonicalizePass(); @@ -39,6 +43,7 @@ createCallConvLoweringPass(cir::CallConvTarget target, const llvm::abi::X86ABICompatInfo &x86AbiCompat); std::unique_ptr<Pass> createHoistAllocasPass(); std::unique_ptr<Pass> createLoweringPreparePass(); +std::unique_ptr<Pass> createLoweringPreparePass(clang::ASTContext *astCtx); std::unique_ptr<Pass> createGotoSolverPass(); std::unique_ptr<Pass> createIdiomRecognizerPass(); std::unique_ptr<Pass> createLibOptPass(); diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp index 41f253e7147e0..9a3c9c9745eaa 100644 --- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp +++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp @@ -13,6 +13,7 @@ #include "mlir/IR/IRMapping.h" #include "mlir/IR/Location.h" #include "mlir/IR/Value.h" +#include "clang/AST/ASTContext.h" #include "clang/Basic/Cuda.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/Specifiers.h" @@ -289,6 +290,12 @@ struct LoweringPreparePass return guard; } + /// + /// AST related + /// ----------- + + clang::ASTContext *astCtx = nullptr; + /// Target/ABI facts sourced from the module's own attributes. std::unique_ptr<cir::LowerModule> lowerModule; @@ -571,6 +578,8 @@ struct LoweringPreparePass builder.createYield(loc); // Outermost IfOp } + + void setASTContext(clang::ASTContext *c) { astCtx = c; } }; } // namespace @@ -3102,3 +3111,10 @@ void LoweringPreparePass::runOnOperation() { std::unique_ptr<Pass> mlir::createLoweringPreparePass() { return std::make_unique<LoweringPreparePass>(); } + +std::unique_ptr<Pass> +mlir::createLoweringPreparePass(clang::ASTContext *astCtx) { + auto pass = std::make_unique<LoweringPreparePass>(); + pass->setASTContext(astCtx); + return std::move(pass); +} diff --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp index a588ab2b67e5a..f15fb274092c4 100644 --- a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp +++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp @@ -157,7 +157,7 @@ class CIRGenConsumer : public clang::ASTConsumer { const bool EnableLibOpt = FEOptions.ClangIRLibOptEnabled && (CGO.OptimizationLevel > 0); if (runCIRToCIRPasses( - MlirModule, MlirCtx, !FEOptions.ClangIRDisableCIRVerifier, + MlirModule, MlirCtx, &C, !FEOptions.ClangIRDisableCIRVerifier, FEOptions.ClangIREnableIdiomRecognizer, CGO.OptimizationLevel > 0, EnableLibOpt, LibOptOptions, FEOptions.ClangIRCallConvLowering) .failed()) { diff --git a/clang/lib/CIR/Lowering/CIRPasses.cpp b/clang/lib/CIR/Lowering/CIRPasses.cpp index 6e75ce03d14ff..933b98896b44e 100644 --- a/clang/lib/CIR/Lowering/CIRPasses.cpp +++ b/clang/lib/CIR/Lowering/CIRPasses.cpp @@ -72,9 +72,10 @@ getX86ABICompatInfo(const llvm::Triple &triple, mlir::LogicalResult runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirContext, - bool enableVerifier, bool enableIdiomRecognizer, - bool enableCIRSimplify, bool enableLibOpt, - llvm::StringRef libOptOptions, bool enableCallConvLowering) { + clang::ASTContext *astContext, bool enableVerifier, + bool enableIdiomRecognizer, bool enableCIRSimplify, + bool enableLibOpt, llvm::StringRef libOptOptions, + bool enableCallConvLowering) { llvm::TimeTraceScope scope("CIR To CIR Passes"); @@ -121,7 +122,7 @@ runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirContext, // outlines dynamic global initializers into functions. It must run before // CallConvLowering so the classifier sees them, otherwise their signatures // go unclassified and caller and callee disagree on the ABI. - pm.addPass(mlir::createLoweringPreparePass()); + pm.addPass(mlir::createLoweringPreparePass(astContext)); if (enableCallConvLowering) { // CallConvLowering rewrites signatures and call sites using the classifier, _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
