clang 24.0.0git
LowerToLLVMIR.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 lowering of CIR attributes and operations directly to
10// LLVMIR.
11//
12//===----------------------------------------------------------------------===//
13
14#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
15#include "mlir/IR/DialectRegistry.h"
16#include "mlir/Target/LLVMIR/LLVMTranslationInterface.h"
17#include "mlir/Target/LLVMIR/ModuleTranslation.h"
19#include "llvm/ADT/ArrayRef.h"
20#include "llvm/IR/Constant.h"
21#include "llvm/IR/Constants.h"
22#include "llvm/IR/GlobalVariable.h"
23#include "llvm/IR/Metadata.h"
24
25using namespace llvm;
26
27namespace cir {
28namespace direct {
29
30/// Implementation of the dialect interface that converts CIR attributes to LLVM
31/// IR metadata.
33 : public mlir::LLVMTranslationDialectInterface {
34public:
35 using LLVMTranslationDialectInterface::LLVMTranslationDialectInterface;
36
37 /// Translates the given operation to LLVM IR using the provided IR builder
38 /// and saving the state in `moduleTranslation`.
39 mlir::LogicalResult convertOperation(
40 mlir::Operation *op, llvm::IRBuilderBase &builder,
41 mlir::LLVM::ModuleTranslation &moduleTranslation) const final {
42
43 if (auto cirOp = llvm::dyn_cast<mlir::LLVM::ZeroOp>(op))
44 moduleTranslation.mapValue(cirOp.getResult()) =
45 llvm::Constant::getNullValue(
46 moduleTranslation.convertType(cirOp.getType()));
47
48 return mlir::success();
49 }
50
51 /// Any named attribute in the CIR dialect, i.e, with name started with
52 /// "cir.", will be handled here.
53 virtual mlir::LogicalResult amendOperation(
54 mlir::Operation *op, llvm::ArrayRef<llvm::Instruction *> instructions,
55 mlir::NamedAttribute attribute,
56 mlir::LLVM::ModuleTranslation &moduleTranslation) const override {
57 if (auto func = dyn_cast<mlir::LLVM::LLVMFuncOp>(op)) {
58 if (mlir::failed(
59 amendFunction(func, instructions, attribute, moduleTranslation)))
60 return mlir::failure();
61 } else if (auto mod = dyn_cast<mlir::ModuleOp>(op)) {
62 if (mlir::failed(amendModule(mod, attribute, moduleTranslation)))
63 return mlir::failure();
64 } else if (attribute.getName() == "cir.riscv_nontemporal_domain") {
65 if (mlir::failed(amendRISCVNontemporalDomain(op, instructions, attribute,
66 moduleTranslation)))
67 return mlir::failure();
68 }
69 return mlir::success();
70 }
71
72private:
73 mlir::LogicalResult amendRISCVNontemporalDomain(
74 mlir::Operation *op, llvm::ArrayRef<llvm::Instruction *> instructions,
75 mlir::NamedAttribute attribute,
76 mlir::LLVM::ModuleTranslation &moduleTranslation) const {
77 auto domain = mlir::dyn_cast<mlir::IntegerAttr>(attribute.getValue());
78 if (!domain)
79 return op->emitError()
80 << "expected cir.riscv_nontemporal_domain to be an integer";
81
82 llvm::LLVMContext &llvmContext = moduleTranslation.getLLVMContext();
83 llvm::MDNode *node = llvm::MDNode::get(
84 llvmContext, llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
85 llvm::Type::getInt32Ty(llvmContext),
86 domain.getValue().getZExtValue())));
87 for (llvm::Instruction *inst : instructions)
88 inst->setMetadata("riscv-nontemporal-domain", node);
89 return mlir::success();
90 }
91
92 // Translate CIR function attributes to LLVM function attributes.
93 mlir::LogicalResult
94 amendFunction(mlir::LLVM::LLVMFuncOp func,
96 mlir::NamedAttribute attribute,
97 mlir::LLVM::ModuleTranslation &moduleTranslation) const {
98 llvm::Function *llvmFunc = moduleTranslation.lookupFunction(func.getName());
99 llvm::StringRef attrName = attribute.getName().strref();
100
101 // Strip the "cir." prefix to get the LLVM attribute name.
102 llvm::StringRef llvmAttrName = attrName.substr(strlen("cir."));
103 if (auto strAttr = mlir::dyn_cast<mlir::StringAttr>(attribute.getValue()))
104 llvmFunc->addFnAttr(llvmAttrName, strAttr.getValue());
105 return mlir::success();
106 }
107
108 // Translate CIR's module attributes to LLVM's module metadata
109 mlir::LogicalResult
110 amendModule(mlir::ModuleOp mod, mlir::NamedAttribute attribute,
111 mlir::LLVM::ModuleTranslation &moduleTranslation) const {
112 llvm::Module *llvmModule = moduleTranslation.getLLVMModule();
113 llvm::LLVMContext &llvmContext = llvmModule->getContext();
114
115 if (attribute.getName() == "cir.amdhsa_code_object_version") {
116 if (auto intAttr =
117 mlir::dyn_cast<mlir::IntegerAttr>(attribute.getValue())) {
118 llvmModule->addModuleFlag(llvm::Module::Error,
119 "amdhsa_code_object_version",
120 static_cast<uint32_t>(intAttr.getInt()));
121 }
122 }
123
124 if (attribute.getName() == "cir.amdgpu_printf_kind") {
125 if (auto strAttr =
126 mlir::dyn_cast<mlir::StringAttr>(attribute.getValue())) {
127 llvm::MDString *mdStr =
128 llvm::MDString::get(llvmContext, strAttr.getValue());
129 llvmModule->addModuleFlag(llvm::Module::Error, "amdgpu_printf_kind",
130 mdStr);
131 }
132 }
133
134 if (attribute.getName() == "cir.amdgpu_xnack") {
135 if (auto intAttr =
136 mlir::dyn_cast<mlir::IntegerAttr>(attribute.getValue())) {
137 llvmModule->addModuleFlag(llvm::Module::Error, "amdgpu.xnack",
138 static_cast<uint32_t>(intAttr.getInt()));
139 }
140 }
141
142 if (attribute.getName() == "cir.amdgpu_sramecc") {
143 if (auto intAttr =
144 mlir::dyn_cast<mlir::IntegerAttr>(attribute.getValue())) {
145 llvmModule->addModuleFlag(llvm::Module::Error, "amdgpu.sramecc",
146 static_cast<uint32_t>(intAttr.getInt()));
147 }
148 }
149
150 return mlir::success();
151 }
152};
153
154void registerCIRDialectTranslation(mlir::DialectRegistry &registry) {
155 registry.insert<cir::CIRDialect>();
156 registry.addExtension(+[](mlir::MLIRContext *ctx, cir::CIRDialect *dialect) {
157 dialect->addInterfaces<CIRDialectLLVMIRTranslationInterface>();
158 });
159}
160
161} // namespace direct
162} // namespace cir
163
164namespace mlir {
165void registerCIRDialectTranslation(mlir::MLIRContext &context) {
166 mlir::DialectRegistry registry;
168 context.appendDialectRegistry(registry);
169}
170} // namespace mlir
Implementation of the dialect interface that converts CIR attributes to LLVM IR metadata.
mlir::LogicalResult convertOperation(mlir::Operation *op, llvm::IRBuilderBase &builder, mlir::LLVM::ModuleTranslation &moduleTranslation) const final
Translates the given operation to LLVM IR using the provided IR builder and saving the state in modul...
virtual mlir::LogicalResult amendOperation(mlir::Operation *op, llvm::ArrayRef< llvm::Instruction * > instructions, mlir::NamedAttribute attribute, mlir::LLVM::ModuleTranslation &moduleTranslation) const override
Any named attribute in the CIR dialect, i.e, with name started with "cir.", will be handled here.
void registerCIRDialectTranslation(mlir::DialectRegistry &registry)
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
void registerCIRDialectTranslation(mlir::MLIRContext &context)
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t