MLIR 23.0.0git
LLVMIRToNVVMTranslation.cpp
Go to the documentation of this file.
1//===- LLVMIRToNVVMTranslation.cpp - Translate LLVM IR to NVVM dialect ----===//
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 LLVM IR and the MLIR NVVM dialect.
10//
11//===----------------------------------------------------------------------===//
12
16#include "llvm/IR/ConstantRange.h"
17
18using namespace mlir;
19using namespace mlir::NVVM;
20
21/// LLVM intrinsic IDs of the four `bar.sync` variants imported into
22/// `nvvm.barrier`.
23static constexpr llvm::Intrinsic::ID kBarrierSyncIntrinsics[] = {
24 llvm::Intrinsic::nvvm_barrier_cta_sync_all,
25 llvm::Intrinsic::nvvm_barrier_cta_sync_aligned_all,
26 llvm::Intrinsic::nvvm_barrier_cta_sync_count,
27 llvm::Intrinsic::nvvm_barrier_cta_sync_aligned_count,
28};
29
30/// Returns true if `id` is one of the `bar.sync` intrinsic IDs imported into
31/// `nvvm.barrier`.
32static bool isBarrierSyncIntrinsic(llvm::Intrinsic::ID id) {
33 return llvm::is_contained(kBarrierSyncIntrinsics, id);
34}
35
36/// Imports one of the four `bar.sync` LLVM intrinsic variants into a single
37/// `nvvm.barrier` op, deriving the `aligned` attribute and the optional
38/// `numberOfThreads` operand from the specific intrinsic ID.
39static LogicalResult
40convertBarrierSyncIntrinsic(OpBuilder &odsBuilder, llvm::CallInst *inst,
41 LLVM::ModuleImport &moduleImport,
42 ArrayRef<llvm::Value *> llvmOperands,
44 llvm::Intrinsic::ID id = inst->getIntrinsicID();
45 bool aligned = (id == llvm::Intrinsic::nvvm_barrier_cta_sync_aligned_all ||
46 id == llvm::Intrinsic::nvvm_barrier_cta_sync_aligned_count);
47 bool hasCount = (id == llvm::Intrinsic::nvvm_barrier_cta_sync_count ||
48 id == llvm::Intrinsic::nvvm_barrier_cta_sync_aligned_count);
49
50 SmallVector<Value> mlirOperands;
52 if (failed(moduleImport.convertIntrinsicArguments(
53 llvmOperands, llvmOpBundles, /*requiresOpBundles=*/false, {}, {},
54 mlirOperands, mlirAttrs)))
55 return failure();
56
57 auto op = NVVM::BarrierOp::create(
58 odsBuilder, moduleImport.translateLoc(inst->getDebugLoc()),
59 mlirOperands.front(), hasCount ? mlirOperands.back() : Value{},
60 odsBuilder.getBoolAttr(aligned));
61 moduleImport.mapNoResultOp(inst, op);
62 return success();
63}
64
65/// Returns true if the LLVM intrinsic `id` has a corresponding MLIR NVVM op.
66static bool isConvertibleIntrinsic(llvm::Intrinsic::ID id) {
67 static const DenseSet<unsigned> convertibleIntrinsics = {
68#include "mlir/Dialect/LLVMIR/NVVMConvertibleLLVMIRIntrinsics.inc"
69 };
70 return convertibleIntrinsics.contains(id) || isBarrierSyncIntrinsic(id);
71}
72
73/// Returns the LLVM intrinsic IDs that have a corresponding MLIR NVVM op.
75 static const SmallVector<unsigned> convertibleIntrinsics = []() {
77#include "mlir/Dialect/LLVMIR/NVVMConvertibleLLVMIRIntrinsics.inc"
78 };
79 ids.append(std::begin(kBarrierSyncIntrinsics),
80 std::end(kBarrierSyncIntrinsics));
81 return ids;
82 }();
83 return convertibleIntrinsics;
84}
85
86/// Converts the LLVM intrinsic to an MLIR NVVM dialect operation if a
87/// conversion exits. Returns failure otherwise.
88static LogicalResult convertIntrinsicImpl(OpBuilder &odsBuilder,
89 llvm::CallInst *inst,
90 LLVM::ModuleImport &moduleImport) {
91 llvm::Intrinsic::ID intrinsicID = inst->getIntrinsicID();
92
93 // Check if the intrinsic is convertible to an MLIR dialect counterpart and
94 // copy the arguments to an an LLVM operands array reference for conversion.
95 if (isConvertibleIntrinsic(intrinsicID)) {
96 SmallVector<llvm::Value *> args(inst->args());
97 ArrayRef<llvm::Value *> llvmOperands(args);
98
100 llvmOpBundles.reserve(inst->getNumOperandBundles());
101 for (unsigned i = 0; i < inst->getNumOperandBundles(); ++i)
102 llvmOpBundles.push_back(inst->getOperandBundleAt(i));
103
104 // Route `bar.sync` intrinsics to `nvvm.barrier`.
105 if (isBarrierSyncIntrinsic(intrinsicID))
106 return convertBarrierSyncIntrinsic(odsBuilder, inst, moduleImport,
107 llvmOperands, llvmOpBundles);
108
109#include "mlir/Dialect/LLVMIR/NVVMFromLLVMIRConversions.inc"
110 }
111
112 return failure();
113}
114
115namespace {
116
117/// Implementation of the dialect interface that converts operations belonging
118/// to the NVVM dialect.
119class NVVMDialectLLVMIRImportInterface : public LLVMImportDialectInterface {
120public:
121 using LLVMImportDialectInterface::LLVMImportDialectInterface;
122
123 /// Converts the LLVM intrinsic to an MLIR NVVM dialect operation if a
124 /// conversion exits. Returns failure otherwise.
125 LogicalResult convertIntrinsic(OpBuilder &builder, llvm::CallInst *inst,
126 LLVM::ModuleImport &moduleImport) const final {
127 return convertIntrinsicImpl(builder, inst, moduleImport);
128 }
129
130 /// Returns the list of LLVM IR intrinsic identifiers that are convertible to
131 /// MLIR NVVM dialect intrinsics.
132 ArrayRef<unsigned> getSupportedIntrinsics() const final {
134 }
135};
136
137} // namespace
138
140 registry.insert<NVVM::NVVMDialect>();
141 registry.addExtension(+[](MLIRContext *ctx, NVVM::NVVMDialect *dialect) {
142 dialect->addInterfaces<NVVMDialectLLVMIRImportInterface>();
143 });
144}
145
147 DialectRegistry registry;
149 context.appendDialectRegistry(registry);
150}
return success()
static ArrayRef< unsigned > getSupportedIntrinsicsImpl()
Returns the LLVM intrinsic IDs that have a corresponding MLIR NVVM op.
static bool isBarrierSyncIntrinsic(llvm::Intrinsic::ID id)
Returns true if id is one of the bar.sync intrinsic IDs imported into nvvm.barrier.
static bool isConvertibleIntrinsic(llvm::Intrinsic::ID id)
Returns true if the LLVM intrinsic id has a corresponding MLIR NVVM op.
static LogicalResult convertIntrinsicImpl(OpBuilder &odsBuilder, llvm::CallInst *inst, LLVM::ModuleImport &moduleImport)
Converts the LLVM intrinsic to an MLIR NVVM dialect operation if a conversion exits.
static constexpr llvm::Intrinsic::ID kBarrierSyncIntrinsics[]
LLVM intrinsic IDs of the four bar.sync variants imported into nvvm.barrier.
static LogicalResult convertBarrierSyncIntrinsic(OpBuilder &odsBuilder, llvm::CallInst *inst, LLVM::ModuleImport &moduleImport, ArrayRef< llvm::Value * > llvmOperands, ArrayRef< llvm::OperandBundleUse > llvmOpBundles)
Imports one of the four bar.sync LLVM intrinsic variants into a single nvvm.barrier op,...
BoolAttr getBoolAttr(bool value)
Definition Builders.cpp:104
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.
Module import implementation class that provides methods to import globals and functions from an LLVM...
LogicalResult convertIntrinsicArguments(ArrayRef< llvm::Value * > values, ArrayRef< llvm::OperandBundleUse > opBundles, bool requiresOpBundles, ArrayRef< unsigned > immArgPositions, ArrayRef< StringLiteral > immArgAttrNames, SmallVectorImpl< Value > &valuesOut, SmallVectorImpl< NamedAttribute > &attrsOut)
Converts the LLVM values for an intrinsic to mixed MLIR values and attributes for LLVM_IntrOpBase.
Location translateLoc(llvm::DILocation *loc)
Translates the debug location.
void mapNoResultOp(llvm::Instruction *llvm, Operation *mlir)
Stores a mapping between an LLVM instruction and the imported MLIR operation if the operation returns...
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.
This class helps build Operations.
Definition Builders.h:209
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
Include the generated interface declarations.
llvm::DenseSet< ValueT, ValueInfoT > DenseSet
Definition LLVM.h:122
void registerNVVMDialectImport(DialectRegistry &registry)
Registers the NVVM dialect and its import from LLVM IR in the given registry.