MLIR 24.0.0git
LLVMToLLVMIRTranslation.cpp
Go to the documentation of this file.
1//===- LLVMToLLVMIRTranslation.cpp - Translate LLVM dialect to LLVM IR ----===//
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 a translation between the MLIR LLVM dialect and LLVM IR.
10//
11//===----------------------------------------------------------------------===//
12
16#include "mlir/IR/Operation.h"
18#include "mlir/Support/LLVM.h"
20
21#include "llvm/ADT/TypeSwitch.h"
22#include "llvm/Analysis/ConstantFolding.h"
23#include "llvm/IR/ConstantRange.h"
24#include "llvm/IR/Constants.h"
25#include "llvm/IR/DIBuilder.h"
26#include "llvm/IR/IRBuilder.h"
27#include "llvm/IR/InlineAsm.h"
28#include "llvm/IR/Instructions.h"
29#include "llvm/IR/MDBuilder.h"
30#include "llvm/IR/MatrixBuilder.h"
31#include "llvm/IR/MemoryModelRelaxationAnnotations.h"
32#include "llvm/Support/LogicalResult.h"
33
34using namespace mlir;
35using namespace mlir::LLVM;
37
38#include "mlir/Dialect/LLVMIR/LLVMConversionEnumsToLLVM.inc"
39
40static llvm::FastMathFlags getFastmathFlags(FastmathFlagsInterface &op) {
41 using llvmFMF = llvm::FastMathFlags;
42 using FuncT = void (llvmFMF::*)(bool);
43 const std::pair<FastmathFlags, FuncT> handlers[] = {
44 // clang-format off
45 {FastmathFlags::nnan, &llvmFMF::setNoNaNs},
46 {FastmathFlags::ninf, &llvmFMF::setNoInfs},
47 {FastmathFlags::nsz, &llvmFMF::setNoSignedZeros},
48 {FastmathFlags::arcp, &llvmFMF::setAllowReciprocal},
49 {FastmathFlags::contract, &llvmFMF::setAllowContract},
50 {FastmathFlags::afn, &llvmFMF::setApproxFunc},
51 {FastmathFlags::reassoc, &llvmFMF::setAllowReassoc},
52 // clang-format on
53 };
54 llvm::FastMathFlags ret;
55 ::mlir::LLVM::FastmathFlags fmfMlir = op.getFastmathAttr().getValue();
56 for (auto it : handlers)
57 if (bitEnumContainsAll(fmfMlir, it.first))
58 (ret.*(it.second))(true);
59 return ret;
60}
61
62/// Convert the value of a DenseI64ArrayAttr to a vector of unsigned indices.
64 SmallVector<unsigned> position;
65 llvm::append_range(position, indices);
66 return position;
67}
68
69/// Convert an LLVM type to a string for printing in diagnostics.
70static std::string diagStr(const llvm::Type *type) {
71 std::string str;
72 llvm::raw_string_ostream os(str);
73 type->print(os);
74 return str;
75}
76
77/// Get the declaration of an overloaded llvm intrinsic. First we get the
78/// overloaded argument types and/or result type from the CallIntrinsicOp, and
79/// then use those to get the correct declaration of the overloaded intrinsic.
80static FailureOr<llvm::Function *>
81getOverloadedDeclaration(CallIntrinsicOp op, llvm::Intrinsic::ID id,
82 llvm::Module *module,
83 LLVM::ModuleTranslation &moduleTranslation) {
85 for (Type type : op->getOperandTypes())
86 allArgTys.push_back(moduleTranslation.convertType(type));
87
88 llvm::Type *resTy;
89 if (op.getNumResults() == 0)
90 resTy = llvm::Type::getVoidTy(module->getContext());
91 else
92 resTy = moduleTranslation.convertType(op.getResult(0).getType());
93
94 // ATM we do not support variadic intrinsics.
95 llvm::FunctionType *ft = llvm::FunctionType::get(resTy, allArgTys, false);
96
97 std::string errorMsg;
98 llvm::raw_string_ostream errorOS(errorMsg);
99 SmallVector<llvm::Type *, 8> overloadedTys;
100 if (!llvm::Intrinsic::isSignatureValid(id, ft, overloadedTys, errorOS)) {
101 return mlir::emitError(op.getLoc(), "call intrinsic signature ")
102 << diagStr(ft) << " to overloaded intrinsic " << op.getIntrinAttr()
103 << " does not match any of the overloads: " << errorMsg;
104 }
105
106 return llvm::Intrinsic::getOrInsertDeclaration(module, id, overloadedTys);
107}
108
109static llvm::OperandBundleDef
110convertOperandBundle(OperandRange bundleOperands, StringRef bundleTag,
111 LLVM::ModuleTranslation &moduleTranslation) {
112 std::vector<llvm::Value *> operands;
113 operands.reserve(bundleOperands.size());
114 for (Value bundleArg : bundleOperands)
115 operands.push_back(moduleTranslation.lookupValue(bundleArg));
116 return llvm::OperandBundleDef(bundleTag.str(), std::move(operands));
117}
118
121 LLVM::ModuleTranslation &moduleTranslation) {
123 bundles.reserve(bundleOperands.size());
124
125 for (auto [operands, tagAttr] : llvm::zip_equal(bundleOperands, bundleTags)) {
126 StringRef tag = cast<StringAttr>(tagAttr).getValue();
127 bundles.push_back(convertOperandBundle(operands, tag, moduleTranslation));
128 }
129 return bundles;
130}
131
134 std::optional<ArrayAttr> bundleTags,
135 LLVM::ModuleTranslation &moduleTranslation) {
136 if (!bundleTags)
137 return {};
138 return convertOperandBundles(bundleOperands, *bundleTags, moduleTranslation);
139}
140
141/// Builder for LLVM_CallIntrinsicOp
142static LogicalResult
143convertCallLLVMIntrinsicOp(CallIntrinsicOp op, llvm::IRBuilderBase &builder,
144 LLVM::ModuleTranslation &moduleTranslation) {
145 llvm::Module *module = builder.GetInsertBlock()->getModule();
146 llvm::Intrinsic::ID id =
147 llvm::Intrinsic::lookupIntrinsicID(op.getIntrinAttr());
148 if (!id)
149 return mlir::emitError(op.getLoc(), "could not find LLVM intrinsic: ")
150 << op.getIntrinAttr();
151
152 llvm::Function *fn = nullptr;
153 if (llvm::Intrinsic::isOverloaded(id)) {
154 auto fnOrFailure =
155 getOverloadedDeclaration(op, id, module, moduleTranslation);
156 if (failed(fnOrFailure))
157 return failure();
158 fn = *fnOrFailure;
159 } else {
160 fn = llvm::Intrinsic::getOrInsertDeclaration(module, id, {});
161 }
162
163 // Check the result type of the call.
164 const llvm::Type *intrinType =
165 op.getNumResults() == 0
166 ? llvm::Type::getVoidTy(module->getContext())
167 : moduleTranslation.convertType(op.getResultTypes().front());
168 if (intrinType != fn->getReturnType()) {
169 return mlir::emitError(op.getLoc(), "intrinsic call returns ")
170 << diagStr(intrinType) << " but " << op.getIntrinAttr()
171 << " actually returns " << diagStr(fn->getReturnType());
172 }
173
174 // Check the argument types of the call. If the function is variadic, check
175 // the subrange of required arguments.
176 if (!fn->getFunctionType()->isVarArg() &&
177 op.getArgs().size() != fn->arg_size()) {
178 return mlir::emitError(op.getLoc(), "intrinsic call has ")
179 << op.getArgs().size() << " operands but " << op.getIntrinAttr()
180 << " expects " << fn->arg_size();
181 }
182 if (fn->getFunctionType()->isVarArg() &&
183 op.getArgs().size() < fn->arg_size()) {
184 return mlir::emitError(op.getLoc(), "intrinsic call has ")
185 << op.getArgs().size() << " operands but variadic "
186 << op.getIntrinAttr() << " expects at least " << fn->arg_size();
187 }
188 // Check the arguments up to the number the function requires.
189 for (unsigned i = 0, e = fn->arg_size(); i != e; ++i) {
190 const llvm::Type *expected = fn->getArg(i)->getType();
191 const llvm::Type *actual =
192 moduleTranslation.convertType(op.getOperandTypes()[i]);
193 if (actual != expected) {
194 return mlir::emitError(op.getLoc(), "intrinsic call operand #")
195 << i << " has type " << diagStr(actual) << " but "
196 << op.getIntrinAttr() << " expects " << diagStr(expected);
197 }
198 }
199
200 FastmathFlagsInterface itf = op;
201 builder.setFastMathFlags(getFastmathFlags(itf));
202
203 auto *inst = builder.CreateCall(
204 fn, moduleTranslation.lookupValues(op.getArgs()),
205 convertOperandBundles(op.getOpBundleOperands(), op.getOpBundleTags(),
206 moduleTranslation));
207
208 if (failed(moduleTranslation.convertArgAndResultAttrs(op, inst)))
209 return failure();
210
211 if (op.getNumResults() == 1)
212 moduleTranslation.mapValue(op->getResults().front()) = inst;
213 return success();
214}
215
216static LogicalResult
217convertNamedMetadataOp(NamedMetadataOp op,
218 LLVM::ModuleTranslation &moduleTranslation) {
219 llvm::Module *llvmModule = moduleTranslation.getLLVMModule();
220 llvm::NamedMDNode *namedMD =
221 llvmModule->getOrInsertNamedMetadata(op.getMetadataName());
222 for (Attribute nodeAttr : op.getNodes()) {
223 FailureOr<llvm::Metadata *> md =
224 moduleTranslation.convertMetadataAttr(nodeAttr, [&]() {
225 return op.emitError() << "failed to convert named metadata '"
226 << op.getMetadataName() << "': ";
227 });
228 if (failed(md))
229 return failure();
230 auto *mdNode = llvm::dyn_cast_if_present<llvm::MDNode>(*md);
231 if (!mdNode) {
232 return op.emitError() << "failed to convert named metadata '"
233 << op.getMetadataName() << "'";
234 }
235 namedMD->addOperand(mdNode);
236 }
237 return success();
238}
239
240/// Translate `llvm.getelementptr`. `inrange` is only representable on LLVM
241/// constant GEP expressions.
242static LogicalResult convertGEPOp(GEPOp op, llvm::IRBuilderBase &builder,
243 LLVM::ModuleTranslation &moduleTranslation) {
245 indices.reserve(op.getRawConstantIndices().size());
246 for (PointerUnion<IntegerAttr, Value> valueOrAttr : op.getIndices()) {
247 if (Value value = dyn_cast_if_present<Value>(valueOrAttr))
248 indices.push_back(moduleTranslation.lookupValue(value));
249 else
250 indices.push_back(
251 builder.getInt32(cast<IntegerAttr>(valueOrAttr).getInt()));
252 }
253
254 llvm::Type *elementType = moduleTranslation.convertType(op.getElemType());
255 llvm::GEPNoWrapFlags nwFlags =
256 llvm::GEPNoWrapFlags::fromRaw(static_cast<unsigned>(op.getNoWrapFlags()));
257 ConstantRangeAttr inrangeAttr = op.getInrangeAttr();
258 llvm::Value *base = moduleTranslation.lookupValue(op.getBase());
259 llvm::Value *res;
260 if (inrangeAttr || !builder.GetInsertPoint().isValid()) {
261 StringRef WhyConstExpr =
262 inrangeAttr ? "'inrange' GEP" : "global initializer GEP";
263 auto *baseConst = dyn_cast<llvm::Constant>(base);
264 if (!baseConst || !llvm::all_of(indices, [](llvm::Value *value) {
265 return isa<llvm::Constant>(value);
266 }))
267 return op.emitError(WhyConstExpr + " requires the base and indices to "
268 "translate to LLVM constants");
269
270 std::optional<llvm::ConstantRange> inrangeCR;
271 if (inrangeAttr)
272 inrangeCR = llvm::ConstantRange::getNonEmpty(inrangeAttr.getLower(),
273 inrangeAttr.getUpper());
274
276 constIndices.reserve(indices.size());
277 for (llvm::Value *value : indices)
278 constIndices.push_back(cast<llvm::Constant>(value));
279 const llvm::DataLayout &dataLayout =
280 moduleTranslation.getLLVMModule()->getDataLayout();
281 res = llvm::ConstantExpr::getGetElementPtr(
282 dataLayout, elementType, baseConst, constIndices, nwFlags, inrangeCR);
283 if (!res)
284 return op.emitError("failed to lower " + WhyConstExpr +
285 " to a constant byte offset");
286 // Fold the constant as CreateGEP did through the TargetFolder. This also
287 // infers inbounds and nuw when the offset stays within the global.
288 res = llvm::ConstantFoldConstant(cast<llvm::Constant>(res), dataLayout);
289 } else {
290 res = builder.CreateGEP(elementType, base, indices, "", nwFlags);
291 }
292 moduleTranslation.mapValue(op.getRes()) = res;
293 return success();
294}
295
297 llvm::IRBuilderBase &builder,
298 LLVM::ModuleTranslation &moduleTranslation) {
299 llvm::Module *llvmModule = moduleTranslation.getLLVMModule();
300 llvm::LLVMContext &context = llvmModule->getContext();
301 llvm::NamedMDNode *linkerMDNode =
302 llvmModule->getOrInsertNamedMetadata("llvm.linker.options");
304 mdNodes.reserve(options.size());
305 for (auto s : options.getAsRange<StringAttr>()) {
306 auto *mdNode = llvm::MDString::get(context, s.getValue());
307 mdNodes.push_back(mdNode);
308 }
309
310 auto *listMDNode = llvm::MDTuple::get(context, mdNodes);
311 linkerMDNode->addOperand(listMDNode);
312}
313
314static llvm::Metadata *
315convertModuleFlagValue(StringRef key, ArrayAttr arrayAttr,
316 llvm::IRBuilderBase &builder,
317 LLVM::ModuleTranslation &moduleTranslation) {
318 llvm::LLVMContext &context = builder.getContext();
319 llvm::MDBuilder mdb(context);
321
322 if (key == LLVMDialect::getModuleFlagKeyCGProfileName()) {
323 for (auto entry : arrayAttr.getAsRange<ModuleFlagCGProfileEntryAttr>()) {
324 auto getFuncMetadata = [&](FlatSymbolRefAttr sym) -> llvm::Metadata * {
325 if (!sym)
326 return nullptr;
327 if (llvm::Function *fn =
328 moduleTranslation.lookupFunction(sym.getValue()))
329 return llvm::ValueAsMetadata::get(fn);
330 return nullptr;
331 };
332 llvm::Metadata *fromMetadata = getFuncMetadata(entry.getFrom());
333 llvm::Metadata *toMetadata = getFuncMetadata(entry.getTo());
334
335 llvm::Metadata *vals[] = {
336 fromMetadata, toMetadata,
337 mdb.createConstant(llvm::ConstantInt::get(
338 llvm::Type::getInt64Ty(context), entry.getCount()))};
339 nodes.push_back(llvm::MDNode::get(context, vals));
340 }
341 return llvm::MDTuple::getDistinct(context, nodes);
342 }
343 // Handle ArrayAttr of StringAttrs (e.g. "riscv-isa") by converting back to
344 // an MDTuple of MDStrings for a lossless round-trip.
345 if (llvm::all_of(arrayAttr, [](Attribute a) { return isa<StringAttr>(a); })) {
346 assert(!arrayAttr.empty() &&
347 "empty string-array is invalid per ModuleFlagAttr::verify");
348 for (StringAttr strAttr : arrayAttr.getAsRange<StringAttr>())
349 nodes.push_back(llvm::MDString::get(context, strAttr.getValue()));
350 return llvm::MDTuple::get(context, nodes);
351 }
352 return nullptr;
353}
354
356 StringRef key, ModuleFlagProfileSummaryAttr summaryAttr,
357 llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation) {
358 llvm::LLVMContext &context = builder.getContext();
359 llvm::MDBuilder mdb(context);
360
361 auto getIntTuple = [&](StringRef key, uint64_t val) -> llvm::MDTuple * {
363 mdb.createString(key), mdb.createConstant(llvm::ConstantInt::get(
364 llvm::Type::getInt64Ty(context), val))};
365 return llvm::MDTuple::get(context, tupleNodes);
366 };
367
369 mdb.createString("ProfileFormat"),
370 mdb.createString(
371 stringifyProfileSummaryFormatKind(summaryAttr.getFormat()))};
372
374 llvm::MDTuple::get(context, fmtNode),
375 getIntTuple("TotalCount", summaryAttr.getTotalCount()),
376 getIntTuple("MaxCount", summaryAttr.getMaxCount()),
377 getIntTuple("MaxInternalCount", summaryAttr.getMaxInternalCount()),
378 getIntTuple("MaxFunctionCount", summaryAttr.getMaxFunctionCount()),
379 getIntTuple("NumCounts", summaryAttr.getNumCounts()),
380 getIntTuple("NumFunctions", summaryAttr.getNumFunctions()),
381 };
382
383 if (summaryAttr.getIsPartialProfile())
384 vals.push_back(
385 getIntTuple("IsPartialProfile", *summaryAttr.getIsPartialProfile()));
386
387 if (summaryAttr.getPartialProfileRatio()) {
389 mdb.createString("PartialProfileRatio"),
390 mdb.createConstant(llvm::ConstantFP::get(
391 llvm::Type::getDoubleTy(context),
392 summaryAttr.getPartialProfileRatio().getValue()))};
393 vals.push_back(llvm::MDTuple::get(context, tupleNodes));
394 }
395
396 SmallVector<llvm::Metadata *> detailedEntries;
397 llvm::Type *llvmInt64Type = llvm::Type::getInt64Ty(context);
398 for (ModuleFlagProfileSummaryDetailedAttr detailedEntry :
399 summaryAttr.getDetailedSummary()) {
401 mdb.createConstant(
402 llvm::ConstantInt::get(llvmInt64Type, detailedEntry.getCutOff())),
403 mdb.createConstant(
404 llvm::ConstantInt::get(llvmInt64Type, detailedEntry.getMinCount())),
405 mdb.createConstant(llvm::ConstantInt::get(
406 llvmInt64Type, detailedEntry.getNumCounts()))};
407 detailedEntries.push_back(llvm::MDTuple::get(context, tupleNodes));
408 }
409 SmallVector<llvm::Metadata *> detailedSummary{
410 mdb.createString("DetailedSummary"),
411 llvm::MDTuple::get(context, detailedEntries)};
412 vals.push_back(llvm::MDTuple::get(context, detailedSummary));
413
414 return llvm::MDNode::get(context, vals);
415}
416
417static void convertModuleFlagsOp(ArrayAttr flags, llvm::IRBuilderBase &builder,
418 LLVM::ModuleTranslation &moduleTranslation) {
419 llvm::Module *llvmModule = moduleTranslation.getLLVMModule();
420 auto convertIntegerAttr = [&](IntegerAttr intAttr) -> llvm::Metadata * {
421 return llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
422 llvm::Type::getInt32Ty(builder.getContext()), intAttr.getInt()));
423 };
424 for (auto flagAttr : flags.getAsRange<ModuleFlagAttrInterface>()) {
425 llvm::Metadata *valueMetadata =
427 flagAttr.getModuleFlagValue())
428 .Case([&](StringAttr strAttr) {
429 return llvm::MDString::get(builder.getContext(),
430 strAttr.getValue());
431 })
432 .Case([&](IntegerAttr intAttr) {
433 return convertIntegerAttr(intAttr);
434 })
435 .Case([&](IntrinsicIntegerAttrInterface intAttr) {
436 return convertIntegerAttr(intAttr.getIntegerAttr());
437 })
438 .Case([&](ArrayAttr arrayAttr) {
440 flagAttr.getModuleFlagKey().getValue(), arrayAttr, builder,
441 moduleTranslation);
442 })
443 .Case([&](ModuleFlagProfileSummaryAttr summaryAttr) {
445 flagAttr.getModuleFlagKey().getValue(), summaryAttr, builder,
446 moduleTranslation);
447 })
448 .Default([](auto) { return nullptr; });
449
450 assert(valueMetadata && "expected valid metadata");
451 llvmModule->addModuleFlag(
452 convertModFlagBehaviorToLLVM(flagAttr.getModuleFlagBehavior()),
453 flagAttr.getModuleFlagKey().getValue(), valueMetadata);
454 }
455}
456
457/// Looks up the GlobalValue and FunctionType for a callee symbol that is not a
458/// regular LLVM function (i.e. an alias or ifunc). Returns the lowered
459/// GlobalValue and FunctionType derived from \p calleeFuncType.
460static std::pair<llvm::GlobalValue *, llvm::FunctionType *>
462 Operation &opInst,
463 LLVM::ModuleTranslation &moduleTranslation) {
464 Operation *moduleOp = parentLLVMModule(&opInst);
465 Operation *calleeOp =
466 moduleTranslation.symbolTable().lookupSymbolIn(moduleOp, attr);
467 llvm::FunctionType *calleeType = llvm::cast<llvm::FunctionType>(
468 moduleTranslation.convertType(calleeFuncType));
469 llvm::GlobalValue *calleeGV;
470 if (isa<LLVM::AliasOp>(calleeOp))
471 calleeGV = moduleTranslation.lookupAlias(calleeOp);
472 else
473 calleeGV = moduleTranslation.lookupIFunc(calleeOp);
474 return {calleeGV, calleeType};
475}
476
477static llvm::DILocalScope *
478getLocalScopeFromLoc(llvm::IRBuilderBase &builder, Location loc,
479 LLVM::ModuleTranslation &moduleTranslation) {
480 if (auto scopeLoc =
482 if (auto *localScope = llvm::dyn_cast<llvm::DILocalScope>(
483 moduleTranslation.translateDebugInfo(scopeLoc.getMetadata())))
484 return localScope;
485 return builder.GetInsertBlock()->getParent()->getSubprogram();
486}
487
488static LogicalResult
489convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
490 LLVM::ModuleTranslation &moduleTranslation) {
491
492 llvm::IRBuilder<>::FastMathFlagGuard fmfGuard(builder);
493 if (auto fmf = dyn_cast<FastmathFlagsInterface>(opInst))
494 builder.setFastMathFlags(getFastmathFlags(fmf));
495
496#include "mlir/Dialect/LLVMIR/LLVMConversions.inc"
497#include "mlir/Dialect/LLVMIR/LLVMIntrinsicConversions.inc"
498
499 // Emit function calls. If the "callee" attribute is present, this is a
500 // direct function call and we also need to look up the remapped function
501 // itself. Otherwise, this is an indirect call and the callee is the first
502 // operand, look it up as a normal value.
503 if (auto callOp = dyn_cast<LLVM::CallOp>(opInst)) {
504 auto operands = moduleTranslation.lookupValues(callOp.getCalleeOperands());
506 convertOperandBundles(callOp.getOpBundleOperands(),
507 callOp.getOpBundleTags(), moduleTranslation);
508 ArrayRef<llvm::Value *> operandsRef(operands);
509 llvm::CallInst *call;
510 if (auto attr = callOp.getCalleeAttr()) {
511 if (llvm::Function *function =
512 moduleTranslation.lookupFunction(attr.getValue())) {
513 call = builder.CreateCall(function, operandsRef, opBundles);
514 } else {
515 auto [calleeGV, calleeType] = lookupNonFunctionSymbolCallee(
516 attr, callOp.getCalleeFunctionType(), opInst, moduleTranslation);
517 call = builder.CreateCall(calleeType, calleeGV, operandsRef, opBundles);
518 }
519 } else {
520 llvm::FunctionType *calleeType = llvm::cast<llvm::FunctionType>(
521 moduleTranslation.convertType(callOp.getCalleeFunctionType()));
522 call = builder.CreateCall(calleeType, operandsRef.front(),
523 operandsRef.drop_front(), opBundles);
524 }
525 call->setCallingConv(convertCConvToLLVM(callOp.getCConv()));
526 call->setTailCallKind(convertTailCallKindToLLVM(callOp.getTailCallKind()));
527 if (callOp.getConvergentAttr())
528 call->addFnAttr(llvm::Attribute::Convergent);
529 if (callOp.getNoUnwindAttr())
530 call->addFnAttr(llvm::Attribute::NoUnwind);
531 if (callOp.getWillReturnAttr())
532 call->addFnAttr(llvm::Attribute::WillReturn);
533 if (callOp.getNoreturnAttr())
534 call->addFnAttr(llvm::Attribute::NoReturn);
535 if (callOp.getOptsizeAttr())
536 call->addFnAttr(llvm::Attribute::OptimizeForSize);
537 if (callOp.getMinsizeAttr())
538 call->addFnAttr(llvm::Attribute::MinSize);
539 if (callOp.getSaveRegParamsAttr())
540 call->addFnAttr(llvm::Attribute::get(moduleTranslation.getLLVMContext(),
541 "save-reg-params"));
542 if (callOp.getBuiltinAttr())
543 call->addFnAttr(llvm::Attribute::Builtin);
544 if (callOp.getNobuiltinAttr())
545 call->addFnAttr(llvm::Attribute::NoBuiltin);
546 if (callOp.getReturnsTwiceAttr())
547 call->addFnAttr(llvm::Attribute::ReturnsTwice);
548 if (callOp.getColdAttr())
549 call->addFnAttr(llvm::Attribute::Cold);
550 if (callOp.getHotAttr())
551 call->addFnAttr(llvm::Attribute::Hot);
552 if (callOp.getNoduplicateAttr())
553 call->addFnAttr(llvm::Attribute::NoDuplicate);
554 if (callOp.getNoInlineAttr())
555 call->addFnAttr(llvm::Attribute::NoInline);
556 if (callOp.getAlwaysInlineAttr())
557 call->addFnAttr(llvm::Attribute::AlwaysInline);
558 if (callOp.getInlineHintAttr())
559 call->addFnAttr(llvm::Attribute::InlineHint);
560 if (callOp.getNoCallerSavedRegistersAttr())
561 call->addFnAttr(llvm::Attribute::get(moduleTranslation.getLLVMContext(),
562 "no_caller_saved_registers"));
563 if (callOp.getNocallbackAttr())
564 call->addFnAttr(llvm::Attribute::NoCallback);
565 if (StringAttr modFormat = callOp.getModularFormatAttr())
566 call->addFnAttr(llvm::Attribute::get(moduleTranslation.getLLVMContext(),
567 "modular-format",
568 modFormat.getValue()));
569 if (StringAttr zcsr = callOp.getZeroCallUsedRegsAttr())
570 call->addFnAttr(llvm::Attribute::get(moduleTranslation.getLLVMContext(),
571 "zero-call-used-regs",
572 zcsr.getValue()));
573 if (callOp.getUniformWorkGroupSizeAttr())
574 call->addFnAttr(llvm::Attribute::get(moduleTranslation.getLLVMContext(),
575 "uniform-work-group-size"));
576 if (StringAttr trapFunc = callOp.getTrapFuncNameAttr())
577 call->addFnAttr(llvm::Attribute::get(moduleTranslation.getLLVMContext(),
578 "trap-func-name",
579 trapFunc.getValue()));
580
581 if (ArrayAttr noBuiltins = callOp.getNobuiltinsAttr()) {
582 if (noBuiltins.empty())
583 call->addFnAttr(llvm::Attribute::get(moduleTranslation.getLLVMContext(),
584 "no-builtins"));
585
586 moduleTranslation.convertFunctionAttrCollection(
587 noBuiltins, call, ModuleTranslation::convertNoBuiltin);
588 }
589
590 moduleTranslation.convertFunctionAttrCollection(
591 callOp.getDefaultFuncAttrsAttr(), call,
593
594 if (llvm::Attribute attr =
595 moduleTranslation.convertAllocsizeAttr(callOp.getAllocsizeAttr());
596 attr.isValid())
597 call->addFnAttr(attr);
598
599 if (failed(moduleTranslation.convertArgAndResultAttrs(callOp, call)))
600 return failure();
601
602 if (MemoryEffectsAttr memAttr = callOp.getMemoryEffectsAttr()) {
603 llvm::MemoryEffects memEffects =
604 llvm::MemoryEffects(llvm::MemoryEffects::Location::ArgMem,
605 convertModRefInfoToLLVM(memAttr.getArgMem())) |
606 llvm::MemoryEffects(
607 llvm::MemoryEffects::Location::InaccessibleMem,
608 convertModRefInfoToLLVM(memAttr.getInaccessibleMem())) |
609 llvm::MemoryEffects(llvm::MemoryEffects::Location::Other,
610 convertModRefInfoToLLVM(memAttr.getOther())) |
611 llvm::MemoryEffects(llvm::MemoryEffects::Location::ErrnoMem,
612 convertModRefInfoToLLVM(memAttr.getErrnoMem())) |
613 llvm::MemoryEffects(
614 llvm::MemoryEffects::Location::TargetMem0,
615 convertModRefInfoToLLVM(memAttr.getTargetMem0())) |
616 llvm::MemoryEffects(llvm::MemoryEffects::Location::TargetMem1,
617 convertModRefInfoToLLVM(memAttr.getTargetMem1()));
618 call->setMemoryEffects(memEffects);
619 }
620
621 moduleTranslation.setAccessGroupsMetadata(callOp, call);
622 moduleTranslation.setAliasScopeMetadata(callOp, call);
623 moduleTranslation.setTBAAMetadata(callOp, call);
624 // If the called function has a result, remap the corresponding value. Note
625 // that LLVM IR dialect CallOp has either 0 or 1 result.
626 if (opInst.getNumResults() != 0)
627 moduleTranslation.mapValue(opInst.getResult(0), call);
628 // Check that LLVM call returns void for 0-result functions.
629 else if (!call->getType()->isVoidTy())
630 return failure();
631 moduleTranslation.mapCall(callOp, call);
632 return success();
633 }
634
635 if (auto inlineAsmOp = dyn_cast<LLVM::InlineAsmOp>(opInst)) {
636 // TODO: refactor function type creation which usually occurs in std-LLVM
637 // conversion.
638 SmallVector<Type, 8> operandTypes;
639 llvm::append_range(operandTypes, inlineAsmOp.getOperands().getTypes());
640
641 Type resultType;
642 if (inlineAsmOp.getNumResults() == 0) {
643 resultType = LLVM::LLVMVoidType::get(&moduleTranslation.getContext());
644 } else {
645 assert(inlineAsmOp.getNumResults() == 1);
646 resultType = inlineAsmOp.getResultTypes()[0];
647 }
648 auto ft = LLVM::LLVMFunctionType::get(resultType, operandTypes);
649 llvm::InlineAsm *inlineAsmInst =
650 inlineAsmOp.getAsmDialect()
651 ? llvm::InlineAsm::get(
652 static_cast<llvm::FunctionType *>(
653 moduleTranslation.convertType(ft)),
654 inlineAsmOp.getAsmString(), inlineAsmOp.getConstraints(),
655 inlineAsmOp.getHasSideEffects(),
656 inlineAsmOp.getIsAlignStack(),
657 convertAsmDialectToLLVM(*inlineAsmOp.getAsmDialect()))
658 : llvm::InlineAsm::get(static_cast<llvm::FunctionType *>(
659 moduleTranslation.convertType(ft)),
660 inlineAsmOp.getAsmString(),
661 inlineAsmOp.getConstraints(),
662 inlineAsmOp.getHasSideEffects(),
663 inlineAsmOp.getIsAlignStack());
664 llvm::CallInst *inst = builder.CreateCall(
665 inlineAsmInst,
666 moduleTranslation.lookupValues(inlineAsmOp.getOperands()));
667 inst->setTailCallKind(convertTailCallKindToLLVM(
668 inlineAsmOp.getTailCallKindAttr().getTailCallKind()));
669 if (inlineAsmOp.getConvergent())
670 inst->addFnAttr(llvm::Attribute::Convergent);
671 if (auto maybeOperandAttrs = inlineAsmOp.getOperandAttrs()) {
672 llvm::AttributeList attrList;
673 for (const auto &it : llvm::enumerate(*maybeOperandAttrs)) {
674 Attribute attr = it.value();
675 if (!attr)
676 continue;
677 DictionaryAttr dAttr = cast<DictionaryAttr>(attr);
678 if (dAttr.empty())
679 continue;
680 TypeAttr tAttr =
681 cast<TypeAttr>(dAttr.get(InlineAsmOp::getElementTypeAttrName()));
682 llvm::AttrBuilder b(moduleTranslation.getLLVMContext());
683 llvm::Type *ty = moduleTranslation.convertType(tAttr.getValue());
684 b.addTypeAttr(llvm::Attribute::ElementType, ty);
685 // shift to account for the returned value (this is always 1 aggregate
686 // value in LLVM).
687 int shift = (opInst.getNumResults() > 0) ? 1 : 0;
688 attrList = attrList.addAttributesAtIndex(
689 moduleTranslation.getLLVMContext(), it.index() + shift, b);
690 }
691 inst->setAttributes(attrList);
692 }
693
694 if (opInst.getNumResults() != 0)
695 moduleTranslation.mapValue(opInst.getResult(0), inst);
696 return success();
697 }
698
699 if (auto invOp = dyn_cast<LLVM::InvokeOp>(opInst)) {
700 auto operands = moduleTranslation.lookupValues(invOp.getCalleeOperands());
702 convertOperandBundles(invOp.getOpBundleOperands(),
703 invOp.getOpBundleTags(), moduleTranslation);
704 ArrayRef<llvm::Value *> operandsRef(operands);
705 llvm::InvokeInst *result;
706 if (auto attr = invOp.getCalleeAttr()) {
707 if (llvm::Function *function =
708 moduleTranslation.lookupFunction(attr.getValue())) {
709 result = builder.CreateInvoke(
710 function, moduleTranslation.lookupBlock(invOp.getSuccessor(0)),
711 moduleTranslation.lookupBlock(invOp.getSuccessor(1)), operandsRef,
712 opBundles);
713 } else {
714 auto [calleeGV, calleeType] = lookupNonFunctionSymbolCallee(
715 attr, invOp.getCalleeFunctionType(), opInst, moduleTranslation);
716 result = builder.CreateInvoke(
717 calleeType, calleeGV,
718 moduleTranslation.lookupBlock(invOp.getSuccessor(0)),
719 moduleTranslation.lookupBlock(invOp.getSuccessor(1)), operandsRef,
720 opBundles);
721 }
722 } else {
723 llvm::FunctionType *calleeType = llvm::cast<llvm::FunctionType>(
724 moduleTranslation.convertType(invOp.getCalleeFunctionType()));
725 result = builder.CreateInvoke(
726 calleeType, operandsRef.front(),
727 moduleTranslation.lookupBlock(invOp.getSuccessor(0)),
728 moduleTranslation.lookupBlock(invOp.getSuccessor(1)),
729 operandsRef.drop_front(), opBundles);
730 }
731 result->setCallingConv(convertCConvToLLVM(invOp.getCConv()));
732 if (invOp.getUniformWorkGroupSizeAttr())
733 result->addFnAttr(llvm::Attribute::get(moduleTranslation.getLLVMContext(),
734 "uniform-work-group-size"));
735 moduleTranslation.convertFunctionAttrCollection(
736 invOp.getDefaultFuncAttrsAttr(), result,
738 if (failed(moduleTranslation.convertArgAndResultAttrs(invOp, result)))
739 return failure();
740 moduleTranslation.mapBranch(invOp, result);
741 // InvokeOp can only have 0 or 1 result
742 if (invOp->getNumResults() != 0) {
743 moduleTranslation.mapValue(opInst.getResult(0), result);
744 return success();
745 }
746 return success(result->getType()->isVoidTy());
747 }
748
749 if (auto lpOp = dyn_cast<LLVM::LandingpadOp>(opInst)) {
750 llvm::Type *ty = moduleTranslation.convertType(lpOp.getType());
751 llvm::LandingPadInst *lpi =
752 builder.CreateLandingPad(ty, lpOp.getNumOperands());
753 lpi->setCleanup(lpOp.getCleanup());
754
755 // Add clauses
756 for (llvm::Value *operand :
757 moduleTranslation.lookupValues(lpOp.getOperands())) {
758 // All operands should be constant - checked by verifier
759 if (auto *constOperand = dyn_cast<llvm::Constant>(operand))
760 lpi->addClause(constOperand);
761 }
762 moduleTranslation.mapValue(lpOp.getResult(), lpi);
763 return success();
764 }
765
766 // Emit branches. We need to look up the remapped blocks and ignore the
767 // block arguments that were transformed into PHI nodes.
768 if (auto brOp = dyn_cast<LLVM::BrOp>(opInst)) {
769 llvm::UncondBrInst *branch =
770 builder.CreateBr(moduleTranslation.lookupBlock(brOp.getSuccessor()));
771 moduleTranslation.mapBranch(&opInst, branch);
772 moduleTranslation.setLoopMetadata(&opInst, branch);
773 return success();
774 }
775 if (auto condbrOp = dyn_cast<LLVM::CondBrOp>(opInst)) {
776 llvm::CondBrInst *branch = builder.CreateCondBr(
777 moduleTranslation.lookupValue(condbrOp.getOperand(0)),
778 moduleTranslation.lookupBlock(condbrOp.getSuccessor(0)),
779 moduleTranslation.lookupBlock(condbrOp.getSuccessor(1)));
780 moduleTranslation.mapBranch(&opInst, branch);
781 moduleTranslation.setLoopMetadata(&opInst, branch);
782 return success();
783 }
784 if (auto switchOp = dyn_cast<LLVM::SwitchOp>(opInst)) {
785 llvm::SwitchInst *switchInst = builder.CreateSwitch(
786 moduleTranslation.lookupValue(switchOp.getValue()),
787 moduleTranslation.lookupBlock(switchOp.getDefaultDestination()),
788 switchOp.getCaseDestinations().size());
789
790 // Handle switch with zero cases.
791 if (!switchOp.getCaseValues())
792 return success();
793
794 auto *ty = llvm::cast<llvm::IntegerType>(
795 moduleTranslation.convertType(switchOp.getValue().getType()));
796 for (auto i :
797 llvm::zip(llvm::cast<DenseIntElementsAttr>(*switchOp.getCaseValues()),
798 switchOp.getCaseDestinations()))
799 switchInst->addCase(
800 llvm::ConstantInt::get(ty, std::get<0>(i).getLimitedValue()),
801 moduleTranslation.lookupBlock(std::get<1>(i)));
802
803 moduleTranslation.mapBranch(&opInst, switchInst);
804 return success();
805 }
806 if (auto indBrOp = dyn_cast<LLVM::IndirectBrOp>(opInst)) {
807 llvm::IndirectBrInst *indBr = builder.CreateIndirectBr(
808 moduleTranslation.lookupValue(indBrOp.getAddr()),
809 indBrOp->getNumSuccessors());
810 for (auto *succ : indBrOp.getSuccessors())
811 indBr->addDestination(moduleTranslation.lookupBlock(succ));
812 moduleTranslation.mapBranch(&opInst, indBr);
813 return success();
814 }
815
816 // Emit addressof. We need to look up the global value referenced by the
817 // operation and store it in the MLIR-to-LLVM value mapping. This does not
818 // emit any LLVM instruction.
819 if (auto addressOfOp = dyn_cast<LLVM::AddressOfOp>(opInst)) {
820 LLVM::GlobalOp global =
821 addressOfOp.getGlobal(moduleTranslation.symbolTable());
822 LLVM::LLVMFuncOp function =
823 addressOfOp.getFunction(moduleTranslation.symbolTable());
824 LLVM::AliasOp alias = addressOfOp.getAlias(moduleTranslation.symbolTable());
825 LLVM::IFuncOp ifunc = addressOfOp.getIFunc(moduleTranslation.symbolTable());
826
827 // The verifier should not have allowed this.
828 assert((global || function || alias || ifunc) &&
829 "referencing an undefined global, function, alias, or ifunc");
830
831 llvm::Value *llvmValue = nullptr;
832 if (global)
833 llvmValue = moduleTranslation.lookupGlobal(global);
834 else if (alias)
835 llvmValue = moduleTranslation.lookupAlias(alias);
836 else if (function)
837 llvmValue = moduleTranslation.lookupFunction(function.getName());
838 else
839 llvmValue = moduleTranslation.lookupIFunc(ifunc);
840
841 moduleTranslation.mapValue(addressOfOp.getResult(), llvmValue);
842 return success();
843 }
844
845 // Emit dso_local_equivalent. We need to look up the global value referenced
846 // by the operation and store it in the MLIR-to-LLVM value mapping.
847 if (auto dsoLocalEquivalentOp =
848 dyn_cast<LLVM::DSOLocalEquivalentOp>(opInst)) {
849 LLVM::LLVMFuncOp function =
850 dsoLocalEquivalentOp.getFunction(moduleTranslation.symbolTable());
851 LLVM::AliasOp alias =
852 dsoLocalEquivalentOp.getAlias(moduleTranslation.symbolTable());
853
854 // The verifier should not have allowed this.
855 assert((function || alias) &&
856 "referencing an undefined function, or alias");
857
858 llvm::Value *llvmValue = nullptr;
859 if (alias)
860 llvmValue = moduleTranslation.lookupAlias(alias);
861 else
862 llvmValue = moduleTranslation.lookupFunction(function.getName());
863
864 moduleTranslation.mapValue(
865 dsoLocalEquivalentOp.getResult(),
866 llvm::DSOLocalEquivalent::get(cast<llvm::GlobalValue>(llvmValue)));
867 return success();
868 }
869
870 // Emit blockaddress. We first need to find the LLVM block referenced by this
871 // operation and then create a LLVM block address for it.
872 if (auto blockAddressOp = dyn_cast<LLVM::BlockAddressOp>(opInst)) {
873 BlockAddressAttr blockAddressAttr = blockAddressOp.getBlockAddr();
874 llvm::BasicBlock *llvmBlock =
875 moduleTranslation.lookupBlockAddress(blockAddressAttr);
876
877 llvm::Value *llvmValue = nullptr;
878 StringRef fnName = blockAddressAttr.getFunction().getValue();
879 if (llvmBlock) {
880 llvm::Function *llvmFn = moduleTranslation.lookupFunction(fnName);
881 llvmValue = llvm::BlockAddress::get(llvmFn, llvmBlock);
882 } else {
883 // The matching LLVM block is not yet emitted, a placeholder is created
884 // in its place. When the LLVM block is emitted later in translation,
885 // the llvmValue is replaced with the actual llvm::BlockAddress.
886 // A GlobalVariable is chosen as placeholder because in general LLVM
887 // constants are uniqued and are not proper for RAUW, since that could
888 // harm unrelated uses of the constant.
889 llvmValue = new llvm::GlobalVariable(
890 *moduleTranslation.getLLVMModule(),
891 llvm::PointerType::getUnqual(moduleTranslation.getLLVMContext()),
892 /*isConstant=*/true, llvm::GlobalValue::LinkageTypes::ExternalLinkage,
893 /*Initializer=*/nullptr,
894 Twine("__mlir_block_address_")
895 .concat(Twine(fnName))
896 .concat(Twine((uint64_t)blockAddressOp.getOperation())));
897 moduleTranslation.mapUnresolvedBlockAddress(blockAddressOp, llvmValue);
898 }
899
900 moduleTranslation.mapValue(blockAddressOp.getResult(), llvmValue);
901 return success();
902 }
903
904 // Emit block label. If this label is seen before BlockAddressOp is
905 // translated, go ahead and already map it.
906 if (auto blockTagOp = dyn_cast<LLVM::BlockTagOp>(opInst)) {
907 auto funcOp = blockTagOp->getParentOfType<LLVMFuncOp>();
908 BlockAddressAttr blockAddressAttr = BlockAddressAttr::get(
909 &moduleTranslation.getContext(),
910 FlatSymbolRefAttr::get(&moduleTranslation.getContext(),
911 funcOp.getName()),
912 blockTagOp.getTag());
913 moduleTranslation.mapBlockAddress(blockAddressAttr,
914 builder.GetInsertBlock());
915 return success();
916 }
917
918 return failure();
919}
920
921static LogicalResult
923 NamedAttribute attribute,
924 LLVM::ModuleTranslation &moduleTranslation) {
925 StringRef name = attribute.getName();
926 if (name == LLVMDialect::getMmraAttrName()) {
928 if (auto oneTag = dyn_cast<LLVM::MMRATagAttr>(attribute.getValue())) {
929 tags.emplace_back(oneTag.getPrefix(), oneTag.getSuffix());
930 } else if (auto manyTags = dyn_cast<ArrayAttr>(attribute.getValue())) {
931 for (Attribute attr : manyTags) {
932 auto tag = dyn_cast<MMRATagAttr>(attr);
933 if (!tag)
934 return op.emitOpError(
935 "MMRA annotations array contains value that isn't an MMRA tag");
936 tags.emplace_back(tag.getPrefix(), tag.getSuffix());
937 }
938 } else {
939 return op.emitOpError(
940 "llvm.mmra is something other than an MMRA tag or an array of them");
941 }
942 llvm::MDTuple *mmraMd =
943 llvm::MMRAMetadata::getMD(moduleTranslation.getLLVMContext(), tags);
944 if (!mmraMd) {
945 // Empty list, canonicalizes to nothing
946 return success();
947 }
948 for (llvm::Instruction *inst : instructions)
949 inst->setMetadata(llvm::LLVMContext::MD_mmra, mmraMd);
950 return success();
951 }
952 return success();
953}
954
955namespace {
956/// Implementation of the dialect interface that converts operations belonging
957/// to the LLVM dialect to LLVM IR.
958class LLVMDialectLLVMIRTranslationInterface
959 : public LLVMTranslationDialectInterface {
960public:
961 using LLVMTranslationDialectInterface::LLVMTranslationDialectInterface;
962
963 /// Translates the given operation to LLVM IR using the provided IR builder
964 /// and saving the state in `moduleTranslation`.
965 LogicalResult
966 convertOperation(Operation *op, llvm::IRBuilderBase &builder,
967 LLVM::ModuleTranslation &moduleTranslation) const final {
968 return convertOperationImpl(*op, builder, moduleTranslation);
969 }
970
971 /// Handle some metadata that is represented as a discardable attribute.
972 LogicalResult
973 amendOperation(Operation *op, ArrayRef<llvm::Instruction *> instructions,
974 NamedAttribute attribute,
975 LLVM::ModuleTranslation &moduleTranslation) const final {
976 return amendOperationImpl(*op, instructions, attribute, moduleTranslation);
977 }
978};
979} // namespace
980
982 registry.insert<LLVM::LLVMDialect>();
983 registry.addExtension(+[](MLIRContext *ctx, LLVM::LLVMDialect *dialect) {
984 dialect->addInterfaces<LLVMDialectLLVMIRTranslationInterface>();
985 });
986}
987
989 DialectRegistry registry;
991 context.appendDialectRegistry(registry);
992}
return success()
static IntegerAttr convertIntegerAttr(IntegerAttr srcAttr, IntegerType dstType, Builder builder)
Converts the given srcAttr to a new attribute of the given dstType.
static std::string diagStr(const llvm::Type *type)
Convert an LLVM type to a string for printing in diagnostics.
static llvm::Metadata * convertModuleFlagValue(StringRef key, ArrayAttr arrayAttr, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static SmallVector< llvm::OperandBundleDef > convertOperandBundles(OperandRangeRange bundleOperands, ArrayAttr bundleTags, LLVM::ModuleTranslation &moduleTranslation)
static LogicalResult convertNamedMetadataOp(NamedMetadataOp op, LLVM::ModuleTranslation &moduleTranslation)
static std::pair< llvm::GlobalValue *, llvm::FunctionType * > lookupNonFunctionSymbolCallee(FlatSymbolRefAttr attr, mlir::Type calleeFuncType, Operation &opInst, LLVM::ModuleTranslation &moduleTranslation)
Looks up the GlobalValue and FunctionType for a callee symbol that is not a regular LLVM function (i....
static FailureOr< llvm::Function * > getOverloadedDeclaration(CallIntrinsicOp op, llvm::Intrinsic::ID id, llvm::Module *module, LLVM::ModuleTranslation &moduleTranslation)
Get the declaration of an overloaded llvm intrinsic.
static void convertModuleFlagsOp(ArrayAttr flags, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static LogicalResult convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static LogicalResult convertCallLLVMIntrinsicOp(CallIntrinsicOp op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Builder for LLVM_CallIntrinsicOp.
static LogicalResult amendOperationImpl(Operation &op, ArrayRef< llvm::Instruction * > instructions, NamedAttribute attribute, LLVM::ModuleTranslation &moduleTranslation)
static LogicalResult convertGEPOp(GEPOp op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Translate llvm.getelementptr.
static llvm::FastMathFlags getFastmathFlags(FastmathFlagsInterface &op)
static llvm::OperandBundleDef convertOperandBundle(OperandRange bundleOperands, StringRef bundleTag, LLVM::ModuleTranslation &moduleTranslation)
static SmallVector< unsigned > extractPosition(ArrayRef< int64_t > indices)
Convert the value of a DenseI64ArrayAttr to a vector of unsigned indices.
static llvm::DILocalScope * getLocalScopeFromLoc(llvm::IRBuilderBase &builder, Location loc, LLVM::ModuleTranslation &moduleTranslation)
static llvm::Metadata * convertModuleFlagProfileSummaryAttr(StringRef key, ModuleFlagProfileSummaryAttr summaryAttr, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static void convertLinkerOptionsOp(ArrayAttr options, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
b
Return true if permutation is a valid permutation of the outer_dims_perm (case OuterOrInnerPerm::Oute...
ArrayAttr()
static llvm::ManagedStatic< PassManagerOptions > options
Attributes are known-constant values of operations.
Definition Attributes.h:25
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
bool addExtension(TypeID extensionID, std::unique_ptr< DialectExtensionBase > extension)
Add the given extension to the registry.
A symbol reference with a reference path containing a single element.
static FlatSymbolRefAttr get(StringAttr value)
Construct a symbol reference for the given value name.
This class represents a fused location whose metadata is known to be an instance of the given type.
Definition Location.h:149
Implementation class for module translation.
void mapUnresolvedBlockAddress(BlockAddressOp op, llvm::Value *cst)
Maps a blockaddress operation to its corresponding placeholder LLVM value.
void mapCall(Operation *mlir, llvm::CallInst *llvm)
Stores a mapping between an MLIR call operation and a corresponding LLVM call instruction.
llvm::BasicBlock * lookupBlock(Block *block) const
Finds an LLVM IR basic block that corresponds to the given MLIR block.
llvm::Attribute convertAllocsizeAttr(DenseI32ArrayAttr allocsizeAttr)
MLIRContext & getContext()
Returns the MLIR context of the module being translated.
void mapBranch(Operation *mlir, llvm::Instruction *llvm)
Stores the mapping between an MLIR operation with successors and a corresponding LLVM IR instruction.
SmallVector< llvm::Value * > lookupValues(ValueRange values)
Looks up remapped a list of remapped values.
void convertFunctionAttrCollection(AttrsTy attrs, Operation *op, const Converter &conv)
A template that takes a collection-like attribute, and converts it via a user provided callback,...
llvm::Value * lookupValue(Value value) const
Finds an LLVM IR value corresponding to the given MLIR value.
LogicalResult convertArgAndResultAttrs(ArgAndResultAttrsOpInterface attrsOp, llvm::CallBase *call, ArrayRef< unsigned > immArgPositions={})
Converts argument and result attributes from attrsOp to LLVM IR attributes on the call instruction.
static std::optional< llvm::Attribute > convertNoBuiltin(llvm::LLVMContext &ctx, mlir::Attribute a)
SymbolTableCollection & symbolTable()
llvm::Type * convertType(Type type)
Converts the type from MLIR LLVM dialect to LLVM.
void setTBAAMetadata(AliasAnalysisOpInterface op, llvm::Instruction *inst)
Sets LLVM TBAA metadata for memory operations that have TBAA attributes.
llvm::GlobalValue * lookupGlobal(Operation *op)
Finds an LLVM IR global value that corresponds to the given MLIR operation defining a global value.
FailureOr< llvm::Metadata * > convertMetadataAttr(Attribute attr, function_ref< InFlightDiagnostic()> emitError)
Converts an LLVM dialect metadata attribute to LLVM IR metadata.
llvm::BasicBlock * lookupBlockAddress(BlockAddressAttr attr) const
Finds the LLVM basic block that corresponds to the given BlockAddressAttr.
llvm::GlobalValue * lookupIFunc(Operation *op)
Finds an LLVM IR global value that corresponds to the given MLIR operation defining an IFunc.
llvm::Metadata * translateDebugInfo(LLVM::DINodeAttr attr)
Translates the given LLVM debug info metadata.
llvm::GlobalValue * lookupAlias(Operation *op)
Finds an LLVM IR global value that corresponds to the given MLIR operation defining a global alias va...
llvm::Function * lookupFunction(StringRef name) const
Finds an LLVM IR function by its name.
llvm::Module * getLLVMModule()
Returns the LLVM module in which the IR is being constructed.
static std::optional< llvm::Attribute > convertDefaultFuncAttr(llvm::LLVMContext &ctx, mlir::NamedAttribute namedAttr)
void setAliasScopeMetadata(AliasAnalysisOpInterface op, llvm::Instruction *inst)
void setAccessGroupsMetadata(AccessGroupOpInterface op, llvm::Instruction *inst)
void mapValue(Value mlir, llvm::Value *llvm)
Stores the mapping between an MLIR value and its LLVM IR counterpart.
llvm::LLVMContext & getLLVMContext() const
Returns the LLVM context in which the IR is being constructed.
void mapBlockAddress(BlockAddressAttr attr, llvm::BasicBlock *block)
Maps a BlockAddressAttr to its corresponding LLVM basic block.
void setLoopMetadata(Operation *op, llvm::Instruction *inst)
Sets LLVM loop metadata for branch operations that have a loop annotation attribute.
T findInstanceOf()
Return an instance of the given location type if one is nested under the current location.
Definition Location.h:45
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition Location.h:76
MLIRContext is the top-level object for a collection of MLIR operations.
Definition MLIRContext.h:63
void appendDialectRegistry(const DialectRegistry &registry)
Append the contents of the given dialect registry to the registry associated with this context.
NamedAttribute represents a combination of a name and an Attribute value.
Definition Attributes.h:164
StringAttr getName() const
Return the name of the attribute.
Attribute getValue() const
Return the value of the attribute.
Definition Attributes.h:179
This class represents a contiguous range of operand ranges, e.g.
Definition ValueRange.h:85
This class implements the operand iterators for the Operation class.
Definition ValueRange.h:44
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Definition Operation.h:432
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
unsigned getNumResults()
Return the number of results held by this operation.
Definition Operation.h:429
virtual Operation * lookupSymbolIn(Operation *symbolTableOp, StringAttr symbol)
Look up a symbol with the specified name within the specified symbol table operation,...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
llvm::Constant * getLLVMConstant(llvm::Type *llvmType, Attribute attr, Location loc, const ModuleTranslation &moduleTranslation)
Create an LLVM IR constant of llvmType from the MLIR attribute attr.
Operation * parentLLVMModule(Operation *op)
Lookup parent Module satisfying LLVM conditions on the Module Operation.
Include the generated interface declarations.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
void registerLLVMDialectTranslation(DialectRegistry &registry)
Register the LLVM dialect and the translation from it to the LLVM IR in the given registry;.