clang 24.0.0git
CIRPasses.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements machinery for any CIR <-> CIR passes used by clang.
10//
11//===----------------------------------------------------------------------===//
12
13#include "mlir/IR/BuiltinOps.h"
14#include "mlir/Pass/PassManager.h"
18#include "llvm/Support/TimeProfiler.h"
19#include "llvm/TargetParser/Triple.h"
20
21namespace cir {
22
23/// Map a target triple to the ABI target that drives CallConvLowering.
24/// Returns None for targets whose calling convention is not yet implemented.
25static CallConvTarget getCallConvTarget(const llvm::Triple &triple) {
26 // Windows is not supported. UEFI shares its convention.
27 if (triple.getArch() == llvm::Triple::x86_64 && !triple.isOSWindowsOrUEFI())
30}
31
32/// The AVX level the classifier uses to size a native vector, read from the
33/// target ABI name.
34static llvm::abi::X86AVXABILevel getX86AVXABILevel(llvm::StringRef abi) {
35 if (abi == "avx512")
36 return llvm::abi::X86AVXABILevel::AVX512;
37 if (abi == "avx")
38 return llvm::abi::X86AVXABILevel::AVX;
39 return llvm::abi::X86AVXABILevel::None;
40}
41
42/// Whether `__attribute__((target(...)))` on a function may raise its AVX ABI
43/// level above the command line's. A target that opts out, and any ABI older
44/// than the rule, stay at the module level.
45static bool allowsX86TargetAttrAvx(const llvm::Triple &triple,
47 return !triple.isPS() && compat > clang::LangOptions::ClangABI::Ver23;
48}
49
50/// The x86_64 ABI-compatibility flags, derived from the target and the
51/// requested compatibility version. Every flag defaults to true in the ABI
52/// library, which is not what any target computes: Clang11Compat is false for a
53/// modern Linux target, so leaving it at the default classifies a union larger
54/// than an eightbyte as though every member spanned its size.
55static llvm::abi::X86ABICompatInfo
56getX86ABICompatInfo(const llvm::Triple &triple,
58 llvm::abi::X86ABICompatInfo abiCompat;
59 abiCompat.HonorsRevision98 = !triple.isOSDarwin();
60 abiCompat.ClassifyIntegerMMXAsSSE =
61 compat > clang::LangOptions::ClangABI::Ver3_8 && !triple.isOSDarwin() &&
62 !triple.isPS() && !triple.isOSFreeBSD();
63 abiCompat.PassInt128VectorsInMem =
64 compat > clang::LangOptions::ClangABI::Ver9 &&
65 (triple.isOSLinux() || triple.isOSNetBSD());
66 abiCompat.ReturnCXXRecordGreaterThan128InMem =
67 compat > clang::LangOptions::ClangABI::Ver20 && !triple.isPS();
68 abiCompat.Clang11Compat =
69 compat <= clang::LangOptions::ClangABI::Ver11 || triple.isPS();
70 return abiCompat;
71}
72
73mlir::LogicalResult
74runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirContext,
75 bool enableVerifier, bool enableIdiomRecognizer,
76 bool enableCIRSimplify, bool enableLibOpt,
77 llvm::StringRef libOptOptions, bool enableCallConvLowering) {
78
79 llvm::TimeTraceScope scope("CIR To CIR Passes");
80
81 auto tripleAttr = theModule->getAttrOfType<mlir::StringAttr>(
82 cir::CIRDialect::getTripleAttrName());
83 if (!tripleAttr)
84 return theModule.emitError()
85 << "missing '" << cir::CIRDialect::getTripleAttrName()
86 << "' attribute";
87 llvm::Triple triple(tripleAttr.getValue());
88
89 auto abiAttr = theModule->getAttrOfType<mlir::StringAttr>(
90 cir::CIRDialect::getTargetABIAttrName());
91 if (!abiAttr)
92 return theModule.emitError()
93 << "missing '" << cir::CIRDialect::getTargetABIAttrName()
94 << "' attribute";
95
96 mlir::PassManager pm(&mlirContext);
98
99 if (enableCIRSimplify)
100 pm.addPass(mlir::createCIRSimplifyPass());
101
102 if (enableIdiomRecognizer)
104
105 if (enableLibOpt) {
106 auto libOptPass = mlir::createLibOptPass();
107 auto errorHandler = [](const llvm::Twine &) -> mlir::LogicalResult {
108 return mlir::LogicalResult::failure();
109 };
110
111 if (libOptPass->initializeOptions(libOptOptions, errorHandler).failed())
112 return mlir::failure();
113
114 pm.addPass(std::move(libOptPass));
115 }
116
117 pm.addPass(mlir::createTargetLoweringPass());
118 pm.addPass(mlir::createCXXABILoweringPass());
119
120 // LoweringPrepare synthesizes calls to runtime helpers such as __divsc3, and
121 // outlines dynamic global initializers into functions. It must run before
122 // CallConvLowering so the classifier sees them, otherwise their signatures
123 // go unclassified and caller and callee disagree on the ABI.
125
126 if (enableCallConvLowering) {
127 // CallConvLowering rewrites signatures and call sites using the classifier,
128 // so it must run after CXXABILowering has lowered C++ ABI types to plain
129 // records the classifier can handle. Only the x86_64 System V classifier
130 // is implemented; other targets are left unchanged.
131 CallConvTarget target = getCallConvTarget(triple);
132 if (target != CallConvTarget::None) {
133 // Source the ABI-compatibility version from the module's serialized
134 // #cir.lowering_lang_options so a reloaded .cir classifies the same way
135 // it was compiled, without a live clang::LangOptions. CIRGen sets this
136 // attribute at module construction; if it is absent fall back to the
137 // LangOptions default, matching how LowerModule reads the same attribute.
138 auto compat = clang::LangOptions::ClangABI::Latest;
139 if (auto loweringLangOpts =
140 theModule->getAttrOfType<cir::LoweringLangOptionsAttr>(
141 cir::CIRDialect::getLoweringLangOptionsAttrName()))
142 compat = static_cast<clang::LangOptions::ClangABI>(
143 loweringLangOpts.getClangAbiCompat());
145 target, getX86AVXABILevel(abiAttr.getValue()),
146 allowsX86TargetAttrAvx(triple, compat),
147 getX86ABICompatInfo(triple, compat)));
148 }
149 }
150
151 pm.enableVerifier(enableVerifier);
152 (void)mlir::applyPassManagerCLOptions(pm);
153 return pm.run(theModule);
154}
155
156} // namespace cir
157
158namespace mlir {
159
160void populateCIRPreLoweringPasses(OpPassManager &pm) {
161 pm.addPass(createHoistAllocasPass());
162 pm.addPass(createCIRFlattenCFGPass());
163 pm.addPass(createCIREHABILoweringPass());
164 pm.addPass(createGotoSolverPass());
165}
166
167} // namespace mlir
Defines the clang::LangOptions interface.
ClangABI
Clang versions with different platform ABI conformance.
static bool allowsX86TargetAttrAvx(const llvm::Triple &triple, clang::LangOptions::ClangABI compat)
Whether __attribute__((target(...))) on a function may raise its AVX ABI level above the command line...
Definition CIRPasses.cpp:45
static CallConvTarget getCallConvTarget(const llvm::Triple &triple)
Map a target triple to the ABI target that drives CallConvLowering.
Definition CIRPasses.cpp:25
mlir::LogicalResult runCIRToCIRPasses(mlir::ModuleOp theModule, mlir::MLIRContext &mlirCtx, bool enableVerifier, bool enableIdiomRecognizer, bool enableCIRSimplify, bool enableLibOpt, llvm::StringRef libOptOptions, bool enableCallConvLowering)
Definition CIRPasses.cpp:74
static llvm::abi::X86AVXABILevel getX86AVXABILevel(llvm::StringRef abi)
The AVX level the classifier uses to size a native vector, read from the target ABI name.
Definition CIRPasses.cpp:34
static llvm::abi::X86ABICompatInfo getX86ABICompatInfo(const llvm::Triple &triple, clang::LangOptions::ClangABI compat)
The x86_64 ABI-compatibility flags, derived from the target and the requested compatibility version.
Definition CIRPasses.cpp:56
CallConvTarget
The ABI target whose calling-convention rules drive CallConvLowering.
Definition Passes.h:23
std::unique_ptr< Pass > createCallConvLoweringPass()
std::unique_ptr< Pass > createCIREHABILoweringPass()
std::unique_ptr< Pass > createCIRCanonicalizePass()
std::unique_ptr< Pass > createCIRFlattenCFGPass()
std::unique_ptr< Pass > createLibOptPass()
Definition LibOpt.cpp:73
std::unique_ptr< Pass > createIdiomRecognizerPass()
void populateCIRPreLoweringPasses(mlir::OpPassManager &pm)
std::unique_ptr< Pass > createTargetLoweringPass()
std::unique_ptr< Pass > createGotoSolverPass()
std::unique_ptr< Pass > createLoweringPreparePass()
std::unique_ptr< Pass > createCIRSimplifyPass()
std::unique_ptr< Pass > createCXXABILoweringPass()
std::unique_ptr< Pass > createHoistAllocasPass()