Skip to content

Commit e142fec

Browse files
committed
feat(pipeline): add target options
1 parent d43a108 commit e142fec

4 files changed

Lines changed: 94 additions & 8 deletions

File tree

‎README.md‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,21 @@ These tools can be composed for debugging or inspecting intermediate stages:
8282
./build/bin/warpforth-translate --mlir-to-ptx
8383
```
8484

85+
The pipeline accepts standard MLIR pipeline options for its NVVM target and
86+
output format. For example, to target Ampere while retaining textual PTX
87+
output:
88+
89+
```bash
90+
./build/bin/warpforth-opt \
91+
--pass-pipeline='builtin.module(warpforth-pipeline{chip=sm_80 features=+ptx70 opt-level=3 compilation-target=isa})' \
92+
kernel.mlir
93+
```
94+
95+
Available options are `chip` (default `sm_70`), `features` (default `+ptx60`),
96+
`libdevice` (the configured libdevice path by default), `opt-level` (`0`, `1`,
97+
`2`, or `3`; default `2`), and `compilation-target` (`llvm`, `isa`, `bin`, or
98+
`fatbin`; default `isa`, textual PTX).
99+
85100
## Language Reference
86101

87102
WarpForth supports stack operations, integer and float arithmetic, control flow, global and shared memory access, reduced-width memory types, user-defined words with local variables, and GPU-specific operations.

‎include/warpforth/Conversion/Passes.h‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,37 @@
77
#ifndef WARPFORTH_CONVERSION_PASSES_H
88
#define WARPFORTH_CONVERSION_PASSES_H
99

10+
#include "mlir/Dialect/GPU/IR/CompilationInterfaces.h"
1011
#include "mlir/Pass/Pass.h"
12+
#include "mlir/Pass/PassOptions.h"
13+
#include "llvm/Support/CodeGen.h"
1114
#include <memory>
15+
#include <string>
1216

1317
namespace mlir {
1418
class OpPassManager;
1519

1620
namespace warpforth {
1721

22+
/// Target configuration for the WarpForth compilation pipeline.
23+
struct WarpForthPipelineOptions
24+
: public PassPipelineOptions<WarpForthPipelineOptions> {
25+
WarpForthPipelineOptions();
26+
27+
PassOptions::Option<std::string> chip;
28+
PassOptions::Option<std::string> features;
29+
PassOptions::Option<std::string> libdevicePath;
30+
PassOptions::Option<llvm::CodeGenOptLevel> optLevel;
31+
PassOptions::Option<gpu::CompilationTarget> compilationTarget;
32+
};
33+
1834
/// Register all conversion passes.
1935
void registerConversionPasses();
2036

2137
/// Build the WarpForth compilation pipeline (Forth to PTX).
2238
void buildWarpForthPipeline(OpPassManager &pm);
39+
void buildWarpForthPipeline(OpPassManager &pm,
40+
const WarpForthPipelineOptions &options);
2341

2442
} // namespace warpforth
2543
} // namespace mlir

‎lib/Conversion/Passes.cpp‎

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,40 @@
2222
namespace mlir {
2323
namespace warpforth {
2424

25-
void buildWarpForthPipeline(OpPassManager &pm) {
25+
WarpForthPipelineOptions::WarpForthPipelineOptions()
26+
: chip(*this, "chip", llvm::cl::desc("NVVM target chip"),
27+
llvm::cl::init("sm_70")),
28+
features(*this, "features", llvm::cl::desc("NVVM target features"),
29+
llvm::cl::init("+ptx60")),
30+
libdevicePath(*this, "libdevice",
31+
llvm::cl::desc("Path to the CUDA libdevice bitcode"),
32+
llvm::cl::init(WARPFORTH_LIBDEVICE_PATH)),
33+
optLevel(
34+
*this, "opt-level",
35+
llvm::cl::desc("NVVM target optimization level (0, 1, 2, or 3)"),
36+
llvm::cl::init(llvm::CodeGenOptLevel::Default),
37+
llvm::cl::values(
38+
clEnumValN(llvm::CodeGenOptLevel::None, "0", "No optimization"),
39+
clEnumValN(llvm::CodeGenOptLevel::Less, "1", "Less optimization"),
40+
clEnumValN(llvm::CodeGenOptLevel::Default, "2",
41+
"Default optimization"),
42+
clEnumValN(llvm::CodeGenOptLevel::Aggressive, "3",
43+
"Aggressive optimization"))),
44+
compilationTarget(
45+
*this, "compilation-target",
46+
llvm::cl::desc("GPU output format (llvm, isa, bin, or fatbin)"),
47+
llvm::cl::init(gpu::CompilationTarget::Assembly),
48+
llvm::cl::values(clEnumValN(gpu::CompilationTarget::Offload, "llvm",
49+
"LLVM bitcode"),
50+
clEnumValN(gpu::CompilationTarget::Assembly, "isa",
51+
"Target assembly"),
52+
clEnumValN(gpu::CompilationTarget::Binary, "bin",
53+
"Target binary"),
54+
clEnumValN(gpu::CompilationTarget::Fatbin, "fatbin",
55+
"Fat binary"))) {}
56+
57+
void buildWarpForthPipeline(OpPassManager &pm,
58+
const WarpForthPipelineOptions &options) {
2659
// Stage 1: Lower Forth to MemRef (CF ops pass through as-is)
2760
pm.addPass(createConvertForthToMemRefPass());
2861

@@ -32,10 +65,13 @@ void buildWarpForthPipeline(OpPassManager &pm) {
3265
// Stage 3: Normalize MemRefs for GPU
3366
pm.addPass(createCanonicalizerPass());
3467

35-
// Stage 4: Attach NVVM target to GPU modules (sm_70 = Volta architecture)
68+
// Stage 4: Attach the configured NVVM target to GPU modules
3669
GpuNVVMAttachTargetOptions nvvmOptions;
37-
nvvmOptions.chip = "sm_70";
38-
nvvmOptions.linkLibs.push_back(WARPFORTH_LIBDEVICE_PATH);
70+
nvvmOptions.chip = options.chip.getValue();
71+
nvvmOptions.features = options.features.getValue();
72+
nvvmOptions.optLevel = static_cast<unsigned>(options.optLevel.getValue());
73+
if (!options.libdevicePath.getValue().empty())
74+
nvvmOptions.linkLibs.push_back(options.libdevicePath.getValue());
3975
pm.addPass(createGpuNVVMAttachTarget(nvvmOptions));
4076

4177
// Stage 5: Lower GPU to NVVM with bare pointers
@@ -55,10 +91,15 @@ void buildWarpForthPipeline(OpPassManager &pm) {
5591

5692
// Stage 9: Compile GPU module to PTX binary
5793
GpuModuleToBinaryPassOptions binaryOptions;
58-
binaryOptions.compilationTarget = "isa"; // Output PTX assembly
94+
binaryOptions.compilationTarget =
95+
gpu::stringifyCompilationTarget(options.compilationTarget.getValue());
5996
pm.addPass(createGpuModuleToBinaryPass(binaryOptions));
6097
}
6198

99+
void buildWarpForthPipeline(OpPassManager &pm) {
100+
buildWarpForthPipeline(pm, WarpForthPipelineOptions());
101+
}
102+
62103
void registerConversionPasses() {
63104
registerPass([]() -> std::unique_ptr<Pass> {
64105
return createConvertForthToMemRefPass();
@@ -67,9 +108,11 @@ void registerConversionPasses() {
67108
[]() -> std::unique_ptr<Pass> { return createConvertForthToGPUPass(); });
68109

69110
// Register WarpForth pipeline
70-
PassPipelineRegistration<>("warpforth-pipeline",
71-
"WarpForth compilation pipeline (Forth to PTX)",
72-
buildWarpForthPipeline);
111+
PassPipelineRegistration<WarpForthPipelineOptions>(
112+
"warpforth-pipeline", "WarpForth compilation pipeline (Forth to PTX)",
113+
[](OpPassManager &pm, const WarpForthPipelineOptions &options) {
114+
buildWarpForthPipeline(pm, options);
115+
});
73116
}
74117

75118
} // namespace warpforth

‎test/Pipeline/target-options.forth‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
\ RUN: %warpforth-translate --forth-to-mlir %s | %warpforth-opt '--pass-pipeline=builtin.module(warpforth-pipeline{chip=sm_80 opt-level=3 compilation-target=isa})' --mlir-print-ir-after=nvvm-attach-target --mlir-disable-threading 2>&1 | %FileCheck %s
2+
\ RUN: %warpforth-translate --forth-to-mlir %s | %not %warpforth-opt '--pass-pipeline=builtin.module(warpforth-pipeline{opt-level=4})' 2>&1 | %FileCheck %s --check-prefix=BAD-OPT
3+
\ RUN: %warpforth-translate --forth-to-mlir %s | %not %warpforth-opt '--pass-pipeline=builtin.module(warpforth-pipeline{compilation-target=bogus})' 2>&1 | %FileCheck %s --check-prefix=BAD-FORMAT
4+
5+
\! kernel main
6+
42
7+
8+
\ CHECK: #nvvm.target<O = 3, chip = "sm_80"
9+
\ BAD-OPT: for the --opt-level option: Cannot find option named '4'!
10+
\ BAD-FORMAT: for the --compilation-target option: Cannot find option named 'bogus'!

0 commit comments

Comments
 (0)