Skip to content

Commit 3267d11

Browse files
Auto merge of #149170 - ZuseZ4:automate-offload-packager, r=<try>
automate gpu offloading - part 1 try-job: dist-ohos-aarch64
2 parents 94b49fd + 8d313e3 commit 3267d11

File tree

11 files changed

+99
-12
lines changed

11 files changed

+99
-12
lines changed

compiler/rustc/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ check_only = ['rustc_driver_impl/check_only']
3838
jemalloc = ['dep:tikv-jemalloc-sys']
3939
llvm = ['rustc_driver_impl/llvm']
4040
llvm_enzyme = ['rustc_driver_impl/llvm_enzyme']
41+
llvm_offload = ['rustc_driver_impl/llvm_offload']
4142
max_level_info = ['rustc_driver_impl/max_level_info']
4243
rustc_randomized_layouts = ['rustc_driver_impl/rustc_randomized_layouts']
4344
# tidy-alphabetical-end

compiler/rustc_codegen_llvm/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,6 @@ tracing = "0.1"
4747
# tidy-alphabetical-start
4848
check_only = ["rustc_llvm/check_only"]
4949
llvm_enzyme = []
50+
llvm_offload = []
5051
# tidy-alphabetical-end
5152

compiler/rustc_codegen_llvm/src/back/write.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,13 @@ pub(crate) unsafe fn llvm_optimize(
771771
llvm_plugins.len(),
772772
)
773773
};
774+
775+
if cgcx.target_is_like_gpu && config.offload.contains(&config::Offload::Enable) {
776+
unsafe {
777+
llvm::LLVMRustBundleImages(module.module_llvm.llmod(), module.module_llvm.tm.raw());
778+
}
779+
}
780+
774781
result.into_result().unwrap_or_else(|()| llvm_err(dcx, LlvmError::RunLlvmPasses))
775782
}
776783

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1718,6 +1718,20 @@ unsafe extern "C" {
17181718
) -> &'a Value;
17191719
}
17201720

1721+
#[cfg(feature = "llvm_offload")]
1722+
unsafe extern "C" {
1723+
/// Processes the module and writes it in an offload compatible way into a "host.out" file.
1724+
pub(crate) fn LLVMRustBundleImages<'a>(M: &'a Module, TM: &'a TargetMachine) -> bool;
1725+
}
1726+
1727+
#[cfg(not(feature = "llvm_offload"))]
1728+
#[allow(unused_unsafe)]
1729+
/// Processes the module and writes it in an offload compatible way into a "host.out" file.
1730+
/// Marked as unsafe to match the real offload wrapper which is unsafe due to FFI.
1731+
pub(crate) unsafe fn LLVMRustBundleImages<'a>(_M: &'a Module, _TM: &'a TargetMachine) -> bool {
1732+
unimplemented!("This rustc version was not built with LLVM Offload support!");
1733+
}
1734+
17211735
// FFI bindings for `DIBuilder` functions in the LLVM-C API.
17221736
// Try to keep these in the same order as in `llvm/include/llvm-c/DebugInfo.h`.
17231737
//

compiler/rustc_driver_impl/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ ctrlc = "3.4.4"
7575
check_only = ['rustc_interface/check_only']
7676
llvm = ['rustc_interface/llvm']
7777
llvm_enzyme = ['rustc_interface/llvm_enzyme']
78+
llvm_offload = ['rustc_interface/llvm_offload']
7879
max_level_info = ['rustc_log/max_level_info']
7980
rustc_randomized_layouts = [
8081
'rustc_index/rustc_randomized_layouts',

compiler/rustc_interface/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,5 @@ rustc_abi = { path = "../rustc_abi" }
5959
check_only = ['rustc_codegen_llvm?/check_only']
6060
llvm = ['dep:rustc_codegen_llvm']
6161
llvm_enzyme = ['rustc_builtin_macros/llvm_enzyme', 'rustc_codegen_llvm/llvm_enzyme']
62+
llvm_offload = ['rustc_codegen_llvm/llvm_offload']
6263
# tidy-alphabetical-end

compiler/rustc_llvm/build.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,10 @@ fn main() {
214214
cfg.define("ENZYME", None);
215215
}
216216

217+
if tracked_env_var_os("LLVM_OFFLOAD").is_some() {
218+
cfg.define("OFFLOAD", None);
219+
}
220+
217221
if tracked_env_var_os("LLVM_RUSTLLVM").is_some() {
218222
cfg.define("LLVM_RUSTLLVM", None);
219223
}

compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,14 @@
3939
#include "llvm/Transforms/Utils/ValueMapper.h"
4040
#include <iostream>
4141

42+
// Some of the functions below rely on LLVM modules that may not always be
43+
// available. As such, we only try to build it in the first place, if
44+
// llvm.offload is enabled.
45+
#ifdef OFFLOAD
46+
#include "llvm/Object/OffloadBinary.h"
47+
#include "llvm/Target/TargetMachine.h"
48+
#endif
49+
4250
// for raw `write` in the bad-alloc handler
4351
#ifdef _MSC_VER
4452
#include <io.h>
@@ -144,6 +152,55 @@ extern "C" void LLVMRustPrintStatistics(RustStringRef OutBuf) {
144152
llvm::PrintStatistics(OS);
145153
}
146154

155+
// Some of the functions here rely on LLVM modules that may not always be
156+
// available. As such, we only try to build it in the first place, if
157+
// llvm.offload is enabled.
158+
#ifdef OFFLOAD
159+
static Error writeFile(StringRef Filename, StringRef Data) {
160+
Expected<std::unique_ptr<FileOutputBuffer>> OutputOrErr =
161+
FileOutputBuffer::create(Filename, Data.size());
162+
if (!OutputOrErr)
163+
return OutputOrErr.takeError();
164+
std::unique_ptr<FileOutputBuffer> Output = std::move(*OutputOrErr);
165+
llvm::copy(Data, Output->getBufferStart());
166+
if (Error E = Output->commit())
167+
return E;
168+
return Error::success();
169+
}
170+
171+
// This is the first of many steps in creating a binary using llvm offload,
172+
// to run code on the gpu. Concrete, it replaces the following binary use:
173+
// clang-offload-packager -o host.out
174+
// --image=file=device.bc,triple=amdgcn-amd-amdhsa,arch=gfx90a,kind=openmp
175+
// The input module is the rust code compiled for a gpu target like amdgpu.
176+
// Based on clang/tools/clang-offload-packager/ClangOffloadPackager.cpp
177+
extern "C" bool LLVMRustBundleImages(LLVMModuleRef M, TargetMachine &TM) {
178+
std::string Storage;
179+
llvm::raw_string_ostream OS1(Storage);
180+
llvm::WriteBitcodeToFile(*unwrap(M), OS1);
181+
OS1.flush();
182+
auto MB = llvm::MemoryBuffer::getMemBufferCopy(Storage, "module.bc");
183+
184+
SmallVector<char, 1024> BinaryData;
185+
raw_svector_ostream OS2(BinaryData);
186+
187+
OffloadBinary::OffloadingImage ImageBinary{};
188+
ImageBinary.TheImageKind = object::IMG_Bitcode;
189+
ImageBinary.Image = std::move(MB);
190+
ImageBinary.TheOffloadKind = object::OFK_OpenMP;
191+
ImageBinary.StringData["triple"] = TM.getTargetTriple().str();
192+
ImageBinary.StringData["arch"] = TM.getTargetCPU();
193+
llvm::SmallString<0> Buffer = OffloadBinary::write(ImageBinary);
194+
if (Buffer.size() % OffloadBinary::getAlignment() != 0)
195+
// Offload binary has invalid size alignment
196+
return false;
197+
OS2 << Buffer;
198+
if (Error E = writeFile("host.out",
199+
StringRef(BinaryData.begin(), BinaryData.size())))
200+
return false;
201+
return true;
202+
}
203+
147204
extern "C" void LLVMRustOffloadMapper(LLVMValueRef OldFn, LLVMValueRef NewFn) {
148205
llvm::Function *oldFn = llvm::unwrap<llvm::Function>(OldFn);
149206
llvm::Function *newFn = llvm::unwrap<llvm::Function>(NewFn);
@@ -163,6 +220,7 @@ extern "C" void LLVMRustOffloadMapper(LLVMValueRef OldFn, LLVMValueRef NewFn) {
163220
llvm::CloneFunctionChangeType::LocalChangesOnly,
164221
returns);
165222
}
223+
#endif
166224

167225
extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M, const char *Name,
168226
size_t NameLen) {

src/bootstrap/src/core/build_steps/compile.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1436,6 +1436,9 @@ fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelect
14361436
if builder.config.llvm_enzyme {
14371437
cargo.env("LLVM_ENZYME", "1");
14381438
}
1439+
if builder.config.llvm_offload {
1440+
cargo.env("LLVM_OFFLOAD", "1");
1441+
}
14391442
let llvm::LlvmResult { host_llvm_config, .. } = builder.ensure(llvm::Llvm { target });
14401443
cargo.env("LLVM_CONFIG", &host_llvm_config);
14411444

src/bootstrap/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -850,6 +850,10 @@ impl Build {
850850
features.insert("llvm_enzyme");
851851
}
852852

853+
//if self.config.llvm_offload {
854+
// features.insert("llvm_offload");
855+
//}
856+
853857
features.into_iter().collect::<Vec<_>>().join(" ")
854858
}
855859

@@ -873,6 +877,9 @@ impl Build {
873877
if self.config.llvm_enzyme {
874878
features.push("llvm_enzyme");
875879
}
880+
if self.config.llvm_offload {
881+
features.push("llvm_offload");
882+
}
876883
// keep in sync with `bootstrap/compile.rs:rustc_cargo_env`
877884
if self.config.rust_randomize_layout && check("rustc_randomized_layouts") {
878885
features.push("rustc_randomized_layouts");

0 commit comments

Comments
 (0)