Skip to content

Commit 211c975

Browse files
committed
[mlir][NVVM] Adds the NVVM target attribute.
**For an explanation of these patches see D154153.** Commit message: This patch adds the NVVM target attribute for serializing GPU modules into strings containing cubin. Depends on D154113 and D154100 and D154097 Reviewed By: mehdi_amini Differential Revision: https://reviews.llvm.org/D154117
1 parent a3e9d3c commit 211c975

File tree

13 files changed

+970
-1
lines changed

13 files changed

+970
-1
lines changed

mlir/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ endif()
9797

9898
# Build the CUDA conversions and run according tests if the NVPTX backend
9999
# is available
100-
if ("NVPTX" IN_LIST LLVM_TARGETS_TO_BUILD AND MLIR_ENABLE_EXECUTION_ENGINE)
100+
if ("NVPTX" IN_LIST LLVM_TARGETS_TO_BUILD)
101101
set(MLIR_ENABLE_CUDA_CONVERSIONS 1)
102102
else()
103103
set(MLIR_ENABLE_CUDA_CONVERSIONS 0)
@@ -118,6 +118,9 @@ set(MLIR_ENABLE_CUDA_RUNNER 0 CACHE BOOL "Enable building the mlir CUDA runner")
118118
set(MLIR_ENABLE_ROCM_RUNNER 0 CACHE BOOL "Enable building the mlir ROCm runner")
119119
set(MLIR_ENABLE_SPIRV_CPU_RUNNER 0 CACHE BOOL "Enable building the mlir SPIR-V cpu runner")
120120
set(MLIR_ENABLE_VULKAN_RUNNER 0 CACHE BOOL "Enable building the mlir Vulkan runner")
121+
set(MLIR_ENABLE_NVPTXCOMPILER 0 CACHE BOOL
122+
"Statically link the nvptxlibrary instead of calling ptxas as a subprocess \
123+
for compiling PTX to cubin")
121124

122125
option(MLIR_INCLUDE_TESTS
123126
"Generate build targets for the MLIR unit tests."

mlir/include/mlir/Dialect/LLVMIR/NVVMDialect.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#define MLIR_DIALECT_LLVMIR_NVVMDIALECT_H_
1616

1717
#include "mlir/Bytecode/BytecodeOpInterface.h"
18+
#include "mlir/Dialect/GPU/IR/CompilationInterfaces.h"
1819
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
1920
#include "mlir/IR/Dialect.h"
2021
#include "mlir/IR/OpDefinition.h"

mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define NVVMIR_OPS
1515

1616
include "mlir/IR/EnumAttr.td"
17+
include "mlir/Dialect/GPU/IR/CompilationAttrInterfaces.td"
1718
include "mlir/Dialect/LLVMIR/LLVMOpBase.td"
1819
include "mlir/Interfaces/SideEffectInterfaces.td"
1920

@@ -1472,4 +1473,72 @@ def NVVM_WgmmaWaitGroupSyncOp : NVVM_Op<"wgmma.wait.group.sync.aligned",
14721473
}];
14731474
}
14741475

1476+
//===----------------------------------------------------------------------===//
1477+
// NVVM target attribute.
1478+
//===----------------------------------------------------------------------===//
1479+
1480+
def NVVM_TargettAttr : NVVM_Attr<"NVVMTarget", "target"> {
1481+
let description = [{
1482+
GPU target attribute for controlling compilation of NVIDIA targets. All
1483+
parameters decay into default values if not present.
1484+
1485+
Examples:
1486+
1487+
1. Target with default values.
1488+
```
1489+
gpu.module @mymodule [#nvvm.target] attributes {...} {
1490+
...
1491+
}
1492+
```
1493+
1494+
2. Target with `sm_90` chip and fast math.
1495+
```
1496+
gpu.module @mymodule [#nvvm.target<chip = "sm_90", flags = {fast}>] {
1497+
...
1498+
}
1499+
```
1500+
}];
1501+
let parameters = (ins
1502+
DefaultValuedParameter<"int", "2", "Optimization level to apply.">:$O,
1503+
StringRefParameter<"Target triple.", "\"nvptx64-nvidia-cuda\"">:$triple,
1504+
StringRefParameter<"Target chip.", "\"sm_50\"">:$chip,
1505+
StringRefParameter<"Target chip features.", "\"+ptx60\"">:$features,
1506+
OptionalParameter<"DictionaryAttr", "Target specific flags.">:$flags,
1507+
OptionalParameter<"ArrayAttr", "Files to link to the LLVM module.">:$link
1508+
);
1509+
let assemblyFormat = [{
1510+
(`<` struct($O, $triple, $chip, $features, $flags, $link)^ `>`)?
1511+
}];
1512+
let builders = [
1513+
AttrBuilder<(ins CArg<"int", "2">:$optLevel,
1514+
CArg<"StringRef", "\"nvptx64-nvidia-cuda\"">:$triple,
1515+
CArg<"StringRef", "\"sm_50\"">:$chip,
1516+
CArg<"StringRef", "\"+ptx60\"">:$features,
1517+
CArg<"DictionaryAttr", "nullptr">:$targetFlags,
1518+
CArg<"ArrayAttr", "nullptr">:$linkFiles), [{
1519+
return Base::get($_ctxt, optLevel, triple, chip, features, targetFlags, linkFiles);
1520+
}]>
1521+
];
1522+
let skipDefaultBuilders = 1;
1523+
let genVerifyDecl = 1;
1524+
let extraClassDeclaration = [{
1525+
bool hasFlag(StringRef flag) const;
1526+
bool hasFastMath() const;
1527+
bool hasFtz() const;
1528+
}];
1529+
let extraClassDefinition = [{
1530+
bool $cppClass::hasFlag(StringRef flag) const {
1531+
if (DictionaryAttr flags = getFlags())
1532+
return flags.get(flag) != nullptr;
1533+
return false;
1534+
}
1535+
bool $cppClass::hasFastMath() const {
1536+
return hasFlag("fast");
1537+
}
1538+
bool $cppClass::hasFtz() const {
1539+
return hasFlag("ftz");
1540+
}
1541+
}];
1542+
}
1543+
14751544
#endif // NVVMIR_OPS

mlir/include/mlir/InitAllExtensions.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include "mlir/Conversion/NVVMToLLVM/NVVMToLLVM.h"
1818
#include "mlir/Dialect/Func/Extensions/AllExtensions.h"
19+
#include "mlir/Target/LLVM/NVVM/Target.h"
1920

2021
#include <cstdlib>
2122

@@ -29,6 +30,7 @@ namespace mlir {
2930
inline void registerAllExtensions(DialectRegistry &registry) {
3031
func::registerAllExtensions(registry);
3132
registerConvertNVVMToLLVMInterface(registry);
33+
registerNVVMTarget(registry);
3234
}
3335

3436
} // namespace mlir
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//===- Target.h - MLIR NVVM target registration -----------------*- C++ -*-===//
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 provides registration calls for attaching the NVVM target interface.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef MLIR_TARGET_LLVM_NVVM_TARGET_H
14+
#define MLIR_TARGET_LLVM_NVVM_TARGET_H
15+
16+
namespace mlir {
17+
class DialectRegistry;
18+
class MLIRContext;
19+
/// Registers the `TargetAttrInterface` for the `#nvvm.target` attribute in the
20+
/// given registry.
21+
void registerNVVMTarget(DialectRegistry &registry);
22+
23+
/// Registers the `TargetAttrInterface` for the `#nvvm.target` attribute in the
24+
/// registry associated with the given context.
25+
void registerNVVMTarget(MLIRContext &context);
26+
} // namespace mlir
27+
28+
#endif // MLIR_TARGET_LLVM_NVVM_TARGET_H
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
//===- Utils.h - MLIR NVVM target utils -------------------------*- C++ -*-===//
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 files declares NVVM target related utility classes and functions.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef MLIR_TARGET_LLVM_NVVM_UTILS_H
14+
#define MLIR_TARGET_LLVM_NVVM_UTILS_H
15+
16+
#include "mlir/Dialect/GPU/IR/CompilationInterfaces.h"
17+
#include "mlir/Dialect/LLVMIR/NVVMDialect.h"
18+
#include "mlir/Target/LLVM/ModuleToObject.h"
19+
20+
namespace mlir {
21+
namespace NVVM {
22+
/// Searches & returns the path CUDA toolkit path, the search order is:
23+
/// 1. The `CUDA_ROOT` environment variable.
24+
/// 2. The `CUDA_HOME` environment variable.
25+
/// 3. The `CUDA_PATH` environment variable.
26+
/// 4. The CUDA toolkit path detected by CMake.
27+
/// 5. Returns an empty string.
28+
StringRef getCUDAToolkitPath();
29+
30+
/// Base class for all NVVM serializations from GPU modules into binary strings.
31+
/// By default this class serializes into LLVM bitcode.
32+
class SerializeGPUModuleBase : public LLVM::ModuleToObject {
33+
public:
34+
/// Initializes the `toolkitPath` with the path in `targetOptions` or if empty
35+
/// with the path in `getCUDAToolkitPath`.
36+
SerializeGPUModuleBase(Operation &module, NVVMTargetAttr target,
37+
const gpu::TargetOptions &targetOptions = {});
38+
39+
/// Initializes the LLVM NVPTX target by safely calling `LLVMInitializeNVPTX*`
40+
/// methods if available.
41+
static void init();
42+
43+
/// Returns the target attribute.
44+
NVVMTargetAttr getTarget() const;
45+
46+
/// Returns the CUDA toolkit path.
47+
StringRef getToolkitPath() const;
48+
49+
/// Returns the bitcode files to be loaded.
50+
ArrayRef<std::string> getFileList() const;
51+
52+
/// Appends `nvvm/libdevice.bc` into `fileList`. Returns failure if the
53+
/// library couldn't be found.
54+
LogicalResult appendStandardLibs();
55+
56+
/// Loads the bitcode files in `fileList`.
57+
virtual std::optional<SmallVector<std::unique_ptr<llvm::Module>>>
58+
loadBitcodeFiles(llvm::Module &module,
59+
llvm::TargetMachine &targetMachine) override;
60+
61+
protected:
62+
/// NVVM target attribute.
63+
NVVMTargetAttr target;
64+
65+
/// CUDA toolkit path.
66+
std::string toolkitPath;
67+
68+
/// List of LLVM bitcode files to link to.
69+
SmallVector<std::string> fileList;
70+
};
71+
} // namespace NVVM
72+
} // namespace mlir
73+
74+
#endif // MLIR_TARGET_LLVM_NVVM_UTILS_H

mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "mlir/Dialect/LLVMIR/NVVMDialect.h"
1818

1919
#include "mlir/Conversion/ConvertToLLVM/ToLLVMInterface.h"
20+
#include "mlir/Dialect/GPU/IR/GPUDialect.h"
2021
#include "mlir/Dialect/Utils/StaticValueUtils.h"
2122
#include "mlir/IR/Builders.h"
2223
#include "mlir/IR/BuiltinAttributes.h"
@@ -723,6 +724,7 @@ void NVVMDialect::initialize() {
723724
// registered.
724725
allowUnknownOperations();
725726
declarePromisedInterface<ConvertToLLVMPatternInterface>();
727+
declarePromisedInterface<gpu::TargetAttrInterface>();
726728
}
727729

728730
LogicalResult NVVMDialect::verifyOperationAttribute(Operation *op,
@@ -761,6 +763,35 @@ LogicalResult NVVMDialect::verifyOperationAttribute(Operation *op,
761763
return success();
762764
}
763765

766+
//===----------------------------------------------------------------------===//
767+
// NVVM target attribute.
768+
//===----------------------------------------------------------------------===//
769+
LogicalResult
770+
NVVMTargetAttr::verify(function_ref<InFlightDiagnostic()> emitError,
771+
int optLevel, StringRef triple, StringRef chip,
772+
StringRef features, DictionaryAttr flags,
773+
ArrayAttr files) {
774+
if (optLevel < 0 || optLevel > 3) {
775+
emitError() << "The optimization level must be a number between 0 and 3.";
776+
return failure();
777+
}
778+
if (triple.empty()) {
779+
emitError() << "The target triple cannot be empty.";
780+
return failure();
781+
}
782+
if (chip.empty()) {
783+
emitError() << "The target chip cannot be empty.";
784+
return failure();
785+
}
786+
if (files && !llvm::all_of(files, [](::mlir::Attribute attr) {
787+
return attr && mlir::isa<StringAttr>(attr);
788+
})) {
789+
emitError() << "All the elements in the `link` array must be strings.";
790+
return failure();
791+
}
792+
return success();
793+
}
794+
764795
#define GET_OP_CLASSES
765796
#include "mlir/Dialect/LLVMIR/NVVMOps.cpp.inc"
766797

mlir/lib/Target/LLVM/CMakeLists.txt

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,80 @@ add_mlir_library(MLIRTargetLLVM
2020
MLIRExecutionEngineUtils
2121
MLIRTargetLLVMIRExport
2222
)
23+
24+
if (MLIR_ENABLE_CUDA_CONVERSIONS)
25+
set(NVPTX_LIBS
26+
NVPTXCodeGen
27+
NVPTXDesc
28+
NVPTXInfo
29+
)
30+
endif()
31+
32+
add_mlir_dialect_library(MLIRNVVMTarget
33+
NVVM/Target.cpp
34+
35+
ADDITIONAL_HEADER_DIRS
36+
${MLIR_MAIN_INCLUDE_DIR}/mlir/Dialect/LLVMIR
37+
38+
LINK_COMPONENTS
39+
${NVPTX_LIBS}
40+
41+
LINK_LIBS PUBLIC
42+
MLIRIR
43+
MLIRExecutionEngineUtils
44+
MLIRSupport
45+
MLIRGPUDialect
46+
MLIRTargetLLVM
47+
MLIRNVVMToLLVMIRTranslation
48+
)
49+
50+
if(MLIR_ENABLE_CUDA_CONVERSIONS)
51+
# Find the CUDA toolkit.
52+
find_package(CUDAToolkit)
53+
54+
if(CUDAToolkit_FOUND)
55+
# Get the CUDA toolkit path. The path is needed for detecting `libdevice.bc`.
56+
# These extra steps are needed because of a bug on CMake.
57+
# See: https://gitlab.kitware.com/cmake/cmake/-/issues/24858
58+
# TODO: Bump the MLIR CMake version to 3.26.4 and switch to
59+
# ${CUDAToolkit_LIBRARY_ROOT}
60+
if(NOT DEFINED ${CUDAToolkit_LIBRARY_ROOT})
61+
get_filename_component(MLIR_CUDAToolkit_ROOT ${CUDAToolkit_BIN_DIR}
62+
DIRECTORY ABSOLUTE)
63+
else()
64+
set(MLIR_CUDAToolkit_ROOT ${CUDAToolkit_LIBRARY_ROOT})
65+
endif()
66+
67+
# Add the `nvptxcompiler` library.
68+
if(MLIR_ENABLE_NVPTXCOMPILER)
69+
# Find the `nvptxcompiler` library.
70+
# TODO: Bump the MLIR CMake version to 3.25 and use `CUDA::nvptxcompiler_static`.
71+
find_library(MLIR_NVPTXCOMPILER_LIB nvptxcompiler_static
72+
PATHS ${CUDAToolkit_LIBRARY_DIR} NO_DEFAULT_PATH)
73+
74+
# Fail if `nvptxcompiler_static` couldn't be found.
75+
if(MLIR_NVPTXCOMPILER_LIB STREQUAL "MLIR_NVPTXCOMPILER_LIB-NOTFOUND")
76+
message(FATAL_ERROR
77+
"Requested using the `nvptxcompiler` library backend but it couldn't be found.")
78+
endif()
79+
80+
# Link against `nvptxcompiler_static`. TODO: use `CUDA::nvptxcompiler_static`.
81+
target_link_libraries(MLIRNVVMTarget PRIVATE ${MLIR_NVPTXCOMPILER_LIB})
82+
target_include_directories(obj.MLIRNVVMTarget PUBLIC ${CUDAToolkit_INCLUDE_DIRS})
83+
endif()
84+
else()
85+
# Fail if `MLIR_ENABLE_NVPTXCOMPILER` is enabled and the toolkit couldn't be found.
86+
if(MLIR_ENABLE_NVPTXCOMPILER)
87+
message(FATAL_ERROR
88+
"Requested using the `nvptxcompiler` library backend but it couldn't be found.")
89+
endif()
90+
endif()
91+
message(VERBOSE "MLIR default CUDA toolkit path: ${MLIR_CUDAToolkit_ROOT}")
92+
93+
# Define the `CUDAToolkit` path.
94+
target_compile_definitions(obj.MLIRNVVMTarget
95+
PRIVATE
96+
MLIR_NVPTXCOMPILER_ENABLED=${MLIR_ENABLE_NVPTXCOMPILER}
97+
__DEFAULT_CUDATOOLKIT_PATH__="${MLIR_CUDAToolkit_ROOT}"
98+
)
99+
endif()

0 commit comments

Comments
 (0)