17#include "mlir/IR/AttrTypeSubElements.h"
18#include "mlir/IR/PatternMatch.h"
19#include "mlir/Support/LLVM.h"
20#include "mlir/Transforms/DialectConversion.h"
31#define GEN_PASS_DEF_TARGETLOWERING
32#include "clang/CIR/Dialect/Passes.h.inc"
37struct TargetLoweringPass
38 :
public impl::TargetLoweringBase<TargetLoweringPass> {
39 TargetLoweringPass() =
default;
40 void runOnOperation()
override;
47 TargetLoweringTypeConverter(mlir::MLIRContext &ctx,
48 const cir::TargetLoweringInfo &targetInfo)
49 : RecordRewritingTypeConverter(ctx), targetInfo(targetInfo) {
50 addConversion([
this](cir::PointerType type) -> mlir::Type {
51 mlir::Type pointee = convertType(
type.getPointee());
54 mlir::ptr::MemorySpaceAttrInterface addrSpace =
type.getAddrSpace();
56 mlir::dyn_cast_if_present<cir::LangAddressSpaceAttr>(addrSpace))
57 addrSpace = lowerAddrSpace(
type.getContext(), langAS);
58 return cir::PointerType::get(
type.getContext(), pointee, addrSpace);
62 mlir::ptr::MemorySpaceAttrInterface
63 lowerAddrSpace(mlir::MLIRContext *ctx,
64 cir::LangAddressSpaceAttr langAS)
const {
66 targetInfo.getTargetAddrSpaceFromCIRAddrSpace(langAS.getValue());
69 return cir::TargetAddressSpaceAttr::get(ctx, targetAS);
73 mlir::Attribute convertAttr(mlir::Attribute attr)
const {
74 return attrReplacer.replace(attr);
78 bool typeMayChange(mlir::Type type)
const override {
79 auto ptrTy = mlir::dyn_cast<cir::PointerType>(type);
80 return ptrTy && mlir::isa_and_present<cir::LangAddressSpaceAttr>(
81 ptrTy.getAddrSpace());
85 const cir::TargetLoweringInfo &targetInfo;
86 mutable mlir::AttrTypeReplacer attrReplacer = [
this] {
87 mlir::AttrTypeReplacer replacer;
88 replacer.addReplacement(
89 [
this](mlir::Type type)
90 -> std::optional<std::pair<mlir::Type, mlir::WalkResult>> {
91 mlir::Type converted = convertType(type);
95 return std::make_pair(converted, mlir::WalkResult::skip());
104class CIRGenericTargetLoweringPattern :
public mlir::ConversionPattern {
106 CIRGenericTargetLoweringPattern(
107 mlir::MLIRContext *context,
108 const TargetLoweringTypeConverter &typeConverter)
109 : mlir::ConversionPattern(typeConverter, MatchAnyOpTypeTag(),
113 matchAndRewrite(mlir::Operation *op, llvm::ArrayRef<mlir::Value> operands,
114 mlir::ConversionPatternRewriter &rewriter)
const override {
116 if (llvm::isa<cir::FuncOp, cir::GlobalOp>(op))
117 return mlir::failure();
119 const mlir::TypeConverter *typeConverter = getTypeConverter();
120 assert(typeConverter &&
121 "CIRGenericTargetLoweringPattern requires a type converter");
122 bool operandsAndResultsLegal = typeConverter->isLegal(op);
124 std::all_of(op->getRegions().begin(), op->getRegions().end(),
125 [typeConverter](mlir::Region ®ion) {
126 return typeConverter->isLegal(®ion);
128 if (operandsAndResultsLegal && regionsLegal)
129 return mlir::failure();
131 assert(op->getNumRegions() == 0 &&
"CIRGenericTargetLoweringPattern cannot "
132 "deal with operations with regions");
134 mlir::OperationState loweredOpState(op->getLoc(), op->getName());
135 loweredOpState.addOperands(operands);
138 loweredOpState.propertiesAttr = op->getPropertiesAsAttribute();
139 loweredOpState.addAttributes(op->getDiscardableAttrDictionary().getValue());
141 loweredOpState.addSuccessors(op->getSuccessors());
143 llvm::SmallVector<mlir::Type> loweredResultTypes;
144 loweredResultTypes.reserve(op->getNumResults());
145 for (mlir::Type result : op->getResultTypes())
146 loweredResultTypes.push_back(typeConverter->convertType(result));
147 loweredOpState.addTypes(loweredResultTypes);
149 for (mlir::Region ®ion : op->getRegions()) {
150 mlir::Region *loweredRegion = loweredOpState.addRegion();
151 rewriter.inlineRegionBefore(region, *loweredRegion, loweredRegion->end());
153 rewriter.convertRegionTypes(loweredRegion, *getTypeConverter())))
154 return mlir::failure();
157 mlir::Operation *loweredOp = rewriter.create(loweredOpState);
160 const auto *tlTypeConverter =
161 static_cast<const TargetLoweringTypeConverter *
>(typeConverter);
162 loweredOp->getName().walkInherentAttrs(
163 loweredOp, [&](llvm::StringRef, mlir::Attribute &attr) {
164 attr = tlTypeConverter->convertAttr(attr);
166 rewriter.replaceOp(op, loweredOp);
167 return mlir::success();
174class CIRGlobalOpTargetLowering
175 :
public mlir::OpConversionPattern<cir::GlobalOp> {
177 CIRGlobalOpTargetLowering(mlir::MLIRContext *context,
178 const TargetLoweringTypeConverter &typeConverter)
179 : mlir::OpConversionPattern<cir::GlobalOp>(typeConverter, context,
183 matchAndRewrite(cir::GlobalOp op, OpAdaptor adaptor,
184 mlir::ConversionPatternRewriter &rewriter)
const override {
185 const auto *typeConverter =
186 static_cast<const TargetLoweringTypeConverter *
>(getTypeConverter());
187 mlir::Type loweredSymTy = typeConverter->convertType(op.getSymType());
189 return mlir::failure();
192 mlir::ptr::MemorySpaceAttrInterface addrSpace = op.getAddrSpaceAttr();
194 mlir::dyn_cast_if_present<cir::LangAddressSpaceAttr>(addrSpace))
195 addrSpace = typeConverter->lowerAddrSpace(op.getContext(), langAS);
198 if (loweredSymTy == op.getSymType() && addrSpace == op.getAddrSpaceAttr())
199 return mlir::failure();
201 auto newOp = mlir::cast<cir::GlobalOp>(rewriter.clone(*op.getOperation()));
202 newOp.setSymType(loweredSymTy);
203 newOp.setAddrSpaceAttr(addrSpace);
204 if (mlir::Attribute init = newOp.getInitialValueAttr())
205 newOp.setInitialValueAttr(typeConverter->convertAttr(init));
206 rewriter.replaceOp(op, newOp);
207 return mlir::success();
212class CIRFuncOpTargetLowering :
public mlir::OpConversionPattern<cir::FuncOp> {
214 using mlir::OpConversionPattern<cir::FuncOp>::OpConversionPattern;
217 matchAndRewrite(cir::FuncOp op, OpAdaptor adaptor,
218 mlir::ConversionPatternRewriter &rewriter)
const override {
219 cir::FuncType opFuncType = op.getFunctionType();
220 mlir::TypeConverter::SignatureConversion signatureConversion(
221 opFuncType.getNumInputs());
223 for (
const auto &[i, argType] : llvm::enumerate(opFuncType.getInputs())) {
224 mlir::Type loweredArgType = getTypeConverter()->convertType(argType);
226 return mlir::failure();
227 signatureConversion.addInputs(i, loweredArgType);
230 mlir::Type loweredReturnType =
231 getTypeConverter()->convertType(opFuncType.getReturnType());
232 if (!loweredReturnType)
233 return mlir::failure();
235 auto loweredFuncType = cir::FuncType::get(
236 signatureConversion.getConvertedTypes(), loweredReturnType,
237 opFuncType.getVarArg());
240 if (loweredFuncType == opFuncType)
241 return mlir::failure();
243 cir::FuncOp loweredFuncOp = rewriter.cloneWithoutRegions(op);
244 loweredFuncOp.setFunctionType(loweredFuncType);
245 rewriter.inlineRegionBefore(op.getBody(), loweredFuncOp.getBody(),
246 loweredFuncOp.end());
247 if (mlir::failed(rewriter.convertRegionTypes(&loweredFuncOp.getBody(),
249 &signatureConversion)))
250 return mlir::failure();
252 rewriter.eraseOp(op);
253 return mlir::success();
262 mlir::cast_if_present<cir::SyncScopeKindAttr>(op->getAttr(
"sync_scope"));
264 cir::SyncScopeKind convertedSyncScope =
266 syncScopeAttr.getValue());
267 op->setAttr(
"sync_scope", cir::SyncScopeKindAttr::get(op->getContext(),
268 convertedSyncScope));
274 const mlir::TypeConverter &tc) {
275 target.addLegalOp<mlir::ModuleOp>();
277 target.addDynamicallyLegalDialect<cir::CIRDialect>(
278 [&tc](mlir::Operation *op) {
282 op->getRegions().begin(), op->getRegions().end(),
283 [&tc](mlir::Region ®ion) { return tc.isLegal(®ion); });
286 target.addDynamicallyLegalOp<cir::FuncOp>(
287 [&tc](cir::FuncOp op) {
return tc.isLegal(op.getFunctionType()); });
289 target.addDynamicallyLegalOp<cir::GlobalOp>([&tc](cir::GlobalOp op) {
290 if (!tc.isLegal(op.getSymType()))
292 return !mlir::isa_and_present<cir::LangAddressSpaceAttr>(
293 op.getAddrSpaceAttr());
297void TargetLoweringPass::runOnOperation() {
298 auto mod = mlir::cast<mlir::ModuleOp>(getOperation());
302 mod.emitWarning(
"Cannot create a CIR lower module, skipping the ")
307 const auto &targetInfo = lowerModule->getTargetLoweringInfo();
309 mod->walk([&](mlir::Operation *op) {
310 if (mlir::isa<cir::LoadOp, cir::StoreOp, cir::AtomicXchgOp,
311 cir::AtomicCmpXchgOp, cir::AtomicFetchOp>(op))
316 TargetLoweringTypeConverter typeConverter(*mod.getContext(), targetInfo);
318 mlir::RewritePatternSet patterns(mod.getContext());
319 patterns.add<CIRGlobalOpTargetLowering>(mod.getContext(), typeConverter);
320 patterns.add<CIRFuncOpTargetLowering>(typeConverter, mod.getContext());
321 patterns.add<CIRGenericTargetLoweringPattern>(mod.getContext(),
324 mlir::ConversionTarget target(*mod.getContext());
327 llvm::SmallVector<mlir::Operation *> ops;
331 if (failed(mlir::applyPartialConversion(ops, target, std::move(patterns))))
334 typeConverter.restoreRecordTypeNames();
338 return std::make_unique<TargetLoweringPass>();
static void populateTargetLoweringConversionTarget(mlir::ConversionTarget &target, const mlir::TypeConverter &tc)
static void convertSyncScopeIfPresent(mlir::Operation *op, cir::LowerModule &lowerModule)
const TargetLoweringInfo & getTargetLoweringInfo()
A type converter that converts the types nested in pointers, arrays, functions and records.
virtual cir::SyncScopeKind convertSyncScope(cir::SyncScopeKind syncScope) const
void collectUnreachable(mlir::Operation *parent, llvm::SmallVectorImpl< mlir::Operation * > &ops)
Collect ops in blocks that are unreachable from their region's entry, appending them to ops.
std::unique_ptr< LowerModule > createLowerModule(mlir::ModuleOp module)
const internal::VariadicAllOfMatcher< Attr > attr
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
StringRef getName(const HeaderType T)
std::unique_ptr< Pass > createTargetLoweringPass()