Skip to content

Commit c50742e

Browse files
authored
Rollup merge of #158032 - Sa4dUs:offload-device-selection, r=ZuseZ4
Offload expose device selection get amount of available devices with `omp_get_num_devices` and add arg to the intrinsic for device selection r? @ZuseZ4
2 parents 1228360 + 3777642 commit c50742e

25 files changed

Lines changed: 241 additions & 77 deletions

File tree

compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,20 @@ fn generate_launcher<'ll>(cx: &CodegenCx<'ll, '_>) -> (&'ll llvm::Value, &'ll ll
197197
(tgt_decl, tgt_fn_ty)
198198
}
199199

200+
/// Declares the `omp_get_num_devices` runtime function and returns the
201+
/// declaration together with its type.
202+
pub(crate) fn declare_omp_get_num_devices<'ll>(
203+
cx: &CodegenCx<'ll, '_>,
204+
) -> (&'ll llvm::Value, &'ll llvm::Type) {
205+
let ti32 = cx.type_i32();
206+
let tgt_fn_ty = cx.type_func(&[], ti32);
207+
let name = "omp_get_num_devices";
208+
let tgt_decl = declare_offload_fn(&cx, name, tgt_fn_ty);
209+
let nounwind = llvm::AttributeKind::NoUnwind.create_attr(cx.llcx);
210+
attributes::apply_to_llfn(tgt_decl, Function, &[nounwind]);
211+
(tgt_decl, tgt_fn_ty)
212+
}
213+
200214
// What is our @1 here? A magic global, used in our data_{begin/update/end}_mapper:
201215
// @0 = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00", align 1
202216
// @1 = private unnamed_addr constant %struct.ident_t { i32 0, i32 2, i32 0, i32 22, ptr @0 }, align 8
@@ -591,6 +605,7 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>(
591605
offload_globals: &OffloadGlobals<'ll>,
592606
offload_dims: &OffloadKernelDims<'ll>,
593607
dyn_cache: &'ll Value,
608+
device_id: &'ll Value,
594609
) {
595610
let cx = builder.cx;
596611
let OffloadKernelGlobals {
@@ -775,15 +790,8 @@ pub(crate) fn gen_call_handling<'ll, 'tcx>(
775790
builder.store(value.2, ptr, value.0);
776791
}
777792

778-
let args = vec![
779-
s_ident_t,
780-
// FIXME(offload) give users a way to select which GPU to use.
781-
cx.get_const_i64(u64::MAX), // MAX == -1.
782-
num_workgroups,
783-
threads_per_block,
784-
region_id,
785-
a5,
786-
];
793+
let device_id = builder.sext(device_id, cx.type_i64());
794+
let args = vec![s_ident_t, device_id, num_workgroups, threads_per_block, region_id, a5];
787795
builder.call(tgt_target_kernel_ty, None, None, tgt_decl, &args, None, None);
788796
// %41 = call i32 @__tgt_target_kernel(ptr @1, i64 -1, i32 2097152, i32 256, ptr @.kernel_1.region_id, ptr %kernel_args)
789797

compiler/rustc_codegen_llvm/src/intrinsic.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use crate::abi::FnAbiLlvmExt;
3737
use crate::builder::Builder;
3838
use crate::builder::autodiff::{adjust_activity_to_abi, generate_enzyme_call};
3939
use crate::builder::gpu_offload::{
40-
OffloadKernelDims, gen_call_handling, gen_define_handling, register_offload,
40+
self, OffloadKernelDims, declare_omp_get_num_devices, register_offload,
4141
};
4242
use crate::context::CodegenCx;
4343
use crate::declare::declare_raw_fn;
@@ -241,6 +241,13 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
241241
// offload *has* a return type, but somehow works without mentioning the place
242242
return IntrinsicResult::WroteIntoPlace;
243243
}
244+
sym::offload_get_num_devices => {
245+
let (fn_decl, fn_ty) = declare_omp_get_num_devices(self.cx);
246+
247+
let llval = self.call(fn_ty, None, None, fn_decl, &[], None, None);
248+
249+
return IntrinsicResult::Operand(OperandValue::Immediate(llval));
250+
},
244251
sym::is_val_statically_known => {
245252
if let OperandValue::Immediate(imm) = args[0].val {
246253
self.call_intrinsic(
@@ -1851,7 +1858,11 @@ fn codegen_offload<'ll, 'tcx>(
18511858
OperandValue::Immediate(val) => val,
18521859
_ => panic!("unparsable"),
18531860
};
1854-
let args = get_args_from_tuple(bx, args[4], fn_target);
1861+
let device_id = match args[4].val {
1862+
OperandValue::Immediate(val) => val,
1863+
_ => panic!("unparsable"),
1864+
};
1865+
let args = get_args_from_tuple(bx, args[5], fn_target);
18551866
let target_symbol = mangle_offload_export(tcx, fn_target);
18561867

18571868
let sig = tcx.fn_sig(fn_target.def_id()).instantiate(tcx, fn_target.args).skip_norm_wip();
@@ -1882,8 +1893,9 @@ fn codegen_offload<'ll, 'tcx>(
18821893
}
18831894
};
18841895
register_offload(cx);
1885-
let offload_data = gen_define_handling(&cx, &metadata, target_symbol, offload_globals);
1886-
gen_call_handling(
1896+
let offload_data =
1897+
gpu_offload::gen_define_handling(&cx, &metadata, target_symbol, offload_globals);
1898+
gpu_offload::gen_call_handling(
18871899
bx,
18881900
&offload_data,
18891901
&args,
@@ -1892,6 +1904,7 @@ fn codegen_offload<'ll, 'tcx>(
18921904
offload_globals,
18931905
&offload_dims,
18941906
&dyn_cache,
1907+
&device_id,
18951908
);
18961909
}
18971910

compiler/rustc_codegen_ssa/src/mir/intrinsic.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
135135
| sym::atomic_fence
136136
| sym::atomic_singlethreadfence
137137
| sym::caller_location
138+
| sym::offload_get_num_devices
138139
| sym::return_address => {}
139140
_ => {
140141
span_bug!(

compiler/rustc_hir_analysis/src/check/intrinsic.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi
168168
| sym::needs_drop
169169
| sym::non_exhaustive
170170
| sym::offload
171+
| sym::offload_get_num_devices
171172
| sym::offset_of
172173
| sym::overflow_checks
173174
| sym::powf16
@@ -384,10 +385,12 @@ pub(crate) fn check_intrinsic_type(
384385
Ty::new_array_with_const_len(tcx, tcx.types.u32, Const::from_target_usize(tcx, 3)),
385386
Ty::new_array_with_const_len(tcx, tcx.types.u32, Const::from_target_usize(tcx, 3)),
386387
tcx.types.u32,
388+
tcx.types.i32,
387389
param(1),
388390
],
389391
param(2),
390392
),
393+
sym::offload_get_num_devices => (0, 0, vec![], tcx.types.i32),
391394
sym::offset => (2, 0, vec![param(0), param(1)], param(0)),
392395
sym::arith_offset => (
393396
1,

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1471,6 +1471,7 @@ symbols! {
14711471
of,
14721472
off,
14731473
offload,
1474+
offload_get_num_devices,
14741475
offload_kernel,
14751476
offset,
14761477
offset_of,

library/core/src/intrinsics/mod.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3808,13 +3808,15 @@ pub const fn autodiff<F, G, T: crate::marker::Tuple, R>(f: F, df: G, args: T) ->
38083808
/// - `f`: The kernel function to offload.
38093809
/// - `workgroup_dim`: A 3D size specifying the number of workgroups to launch.
38103810
/// - `thread_dim`: A 3D size specifying the number of threads per workgroup.
3811+
/// - `dyn_cache`: The amount of dynamic shared memory to request for the kernel.
3812+
/// - `device_id`: The device to offload to. Use `-1` to select the default device.
38113813
/// - `args`: A tuple of arguments forwarded to `f`.
38123814
///
38133815
/// Example usage (pseudocode):
38143816
///
38153817
/// ```rust,ignore (pseudocode)
38163818
/// fn kernel(x: *mut [f64; 128]) {
3817-
/// core::intrinsics::offload(kernel_1, [256, 1, 1], [32, 1, 1], (x,))
3819+
/// core::intrinsics::offload(kernel_1, [256, 1, 1], [32, 1, 1], 0, -1, (x,))
38183820
/// }
38193821
///
38203822
/// #[cfg(target_os = "linux")]
@@ -3838,9 +3840,20 @@ pub const fn offload<F, T: crate::marker::Tuple, R>(
38383840
workgroup_dim: [u32; 3],
38393841
thread_dim: [u32; 3],
38403842
dyn_cache: u32,
3843+
device_id: i32,
38413844
args: T,
38423845
) -> R;
38433846

3847+
/// Returns the number of offload devices available on the system.
3848+
///
3849+
/// Use this to discover which `device_id` values are valid to pass to
3850+
/// [`offload`]. Devices are numbered from `0` to the returned value minus one.
3851+
///
3852+
/// Returns `0` if no offloading devices are present.
3853+
#[rustc_nounwind]
3854+
#[rustc_intrinsic]
3855+
pub const fn offload_get_num_devices() -> i32;
3856+
38443857
/// Inform Miri that a given pointer definitely has a certain alignment.
38453858
#[cfg(miri)]
38463859
#[rustc_allow_const_fn_unstable(const_eval_select)]

library/core/src/offload.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ fn kernel(x: *mut [f64; 256]) {
2121
```
2222

2323
To launch an offloaded kernel, use the `offload!` macro. It lets you specify the kernel, the
24-
workgroup and thread dimensions, and the arguments to forward to the device.
24+
workgroup and thread dimensions, the device to offload to, and the arguments to forward to the
25+
device.
2526

2627
```rust,ignore (optional component)
2728
let mut x = [0.0f64; 256];

library/core/src/offload/mod.rs

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ pub use crate::offload;
1919
/// Defaults to `[1, 1, 1]`.
2020
/// - `dyn_cache`: The amount of dynamic shared memory, in bytes, to allocate for the kernel.
2121
/// Defaults to `0`.
22+
/// - `device`: The index of the device to offload to. Must be `>= 0`. If omitted, the
23+
/// default device is used. Use [`crate::intrinsics::offload_get_num_devices`] to discover
24+
/// which device ids are valid.
2225
///
2326
/// Each argument may only be specified once.
2427
///
@@ -43,61 +46,82 @@ macro_rules! offload {
4346
workgroup_dim = ([1, 1, 1]);
4447
thread_dim = ([1, 1, 1]);
4548
dyn_cache = (0);
49+
device = NONE;
4650
args = NONE
4751
)
4852
};
4953

50-
(@munch [kernel = $val:expr $(, $rest_f:ident = $rest_v:expr)*]; kernel = NONE; workgroup_dim = $w:tt; thread_dim = $t:tt; dyn_cache = $d:tt; args = $a:tt) => {
51-
$crate::offload!(@munch [$($rest_f = $rest_v),*]; kernel = (SOME $val); workgroup_dim = $w; thread_dim = $t; dyn_cache = $d; args = $a)
54+
(@munch [kernel = $val:expr $(, $rest_f:ident = $rest_v:expr)*]; kernel = NONE; workgroup_dim = $w:tt; thread_dim = $t:tt; dyn_cache = $d:tt; device = $device:tt; args = $a:tt) => {
55+
$crate::offload!(@munch [$($rest_f = $rest_v),*]; kernel = (SOME $val); workgroup_dim = $w; thread_dim = $t; dyn_cache = $d; device = $device; args = $a)
5256
};
53-
(@munch [kernel = $val:expr $(, $rest_f:ident = $rest_v:expr)*]; kernel = (SOME $old:expr); workgroup_dim = $w:tt; thread_dim = $t:tt; dyn_cache = $d:tt; args = $a:tt) => {
57+
(@munch [kernel = $val:expr $(, $rest_f:ident = $rest_v:expr)*]; kernel = (SOME $old:expr); workgroup_dim = $w:tt; thread_dim = $t:tt; dyn_cache = $d:tt; device = $device:tt; args = $a:tt) => {
5458
compile_error!("duplicate field `kernel`")
5559
};
56-
(@munch [workgroup_dim = $val:expr $(, $rest_f:ident = $rest_v:expr)*]; kernel = $k:tt; workgroup_dim = ([1, 1, 1]); thread_dim = $t:tt; dyn_cache = $d:tt; args = $a:tt) => {
57-
$crate::offload!(@munch [$($rest_f = $rest_v),*]; kernel = $k; workgroup_dim = (SOME $val); thread_dim = $t; dyn_cache = $d; args = $a)
60+
(@munch [workgroup_dim = $val:expr $(, $rest_f:ident = $rest_v:expr)*]; kernel = $k:tt; workgroup_dim = ([1, 1, 1]); thread_dim = $t:tt; dyn_cache = $d:tt; device = $device:tt; args = $a:tt) => {
61+
$crate::offload!(@munch [$($rest_f = $rest_v),*]; kernel = $k; workgroup_dim = (SOME $val); thread_dim = $t; dyn_cache = $d; device = $device; args = $a)
5862
};
59-
(@munch [workgroup_dim = $val:expr $(, $rest_f:ident = $rest_v:expr)*]; kernel = $k:tt; workgroup_dim = (SOME $old:expr); thread_dim = $t:tt; dyn_cache = $d:tt; args = $a:tt) => {
63+
(@munch [workgroup_dim = $val:expr $(, $rest_f:ident = $rest_v:expr)*]; kernel = $k:tt; workgroup_dim = (SOME $old:expr); thread_dim = $t:tt; dyn_cache = $d:tt; device = $device:tt; args = $a:tt) => {
6064
compile_error!("duplicate field `workgroup_dim`")
6165
};
62-
(@munch [thread_dim = $val:expr $(, $rest_f:ident = $rest_v:expr)*]; kernel = $k:tt; workgroup_dim = $w:tt; thread_dim = ([1, 1, 1]); dyn_cache = $d:tt; args = $a:tt) => {
63-
$crate::offload!(@munch [$($rest_f = $rest_v),*]; kernel = $k; workgroup_dim = $w; thread_dim = (SOME $val); dyn_cache = $d; args = $a)
66+
(@munch [thread_dim = $val:expr $(, $rest_f:ident = $rest_v:expr)*]; kernel = $k:tt; workgroup_dim = $w:tt; thread_dim = ([1, 1, 1]); dyn_cache = $d:tt; device = $device:tt; args = $a:tt) => {
67+
$crate::offload!(@munch [$($rest_f = $rest_v),*]; kernel = $k; workgroup_dim = $w; thread_dim = (SOME $val); dyn_cache = $d; device = $device; args = $a)
6468
};
65-
(@munch [thread_dim = $val:expr $(, $rest_f:ident = $rest_v:expr)*]; kernel = $k:tt; workgroup_dim = $w:tt; thread_dim = (SOME $old:expr); dyn_cache = $d:tt; args = $a:tt) => {
69+
(@munch [thread_dim = $val:expr $(, $rest_f:ident = $rest_v:expr)*]; kernel = $k:tt; workgroup_dim = $w:tt; thread_dim = (SOME $old:expr); dyn_cache = $d:tt; device = $device:tt; args = $a:tt) => {
6670
compile_error!("duplicate field `thread_dim`")
6771
};
68-
(@munch [dyn_cache = $val:expr $(, $rest_f:ident = $rest_v:expr)*]; kernel = $k:tt; workgroup_dim = $w:tt; thread_dim = $t:tt; dyn_cache = (0); args = $a:tt) => {
69-
$crate::offload!(@munch [$($rest_f = $rest_v),*]; kernel = $k; workgroup_dim = $w; thread_dim = $t; dyn_cache = (SOME $val); args = $a)
72+
(@munch [dyn_cache = $val:expr $(, $rest_f:ident = $rest_v:expr)*]; kernel = $k:tt; workgroup_dim = $w:tt; thread_dim = $t:tt; dyn_cache = (0); device = $device:tt; args = $a:tt) => {
73+
$crate::offload!(@munch [$($rest_f = $rest_v),*]; kernel = $k; workgroup_dim = $w; thread_dim = $t; dyn_cache = (SOME $val); device = $device; args = $a)
7074
};
71-
(@munch [dyn_cache = $val:expr $(, $rest_f:ident = $rest_v:expr)*]; kernel = $k:tt; workgroup_dim = $w:tt; thread_dim = $t:tt; dyn_cache = (SOME $old:expr); args = $a:tt) => {
75+
(@munch [dyn_cache = $val:expr $(, $rest_f:ident = $rest_v:expr)*]; kernel = $k:tt; workgroup_dim = $w:tt; thread_dim = $t:tt; dyn_cache = (SOME $old:expr); device = $device:tt; args = $a:tt) => {
7276
compile_error!("duplicate field `dyn_cache`")
7377
};
74-
(@munch [args = $val:expr $(, $rest_f:ident = $rest_v:expr)*]; kernel = $k:tt; workgroup_dim = $w:tt; thread_dim = $t:tt; dyn_cache = $d:tt; args = NONE) => {
75-
$crate::offload!(@munch [$($rest_f = $rest_v),*]; kernel = $k; workgroup_dim = $w; thread_dim = $t; dyn_cache = $d; args = (SOME $val))
78+
(@munch [device = $val:expr $(, $rest_f:ident = $rest_v:expr)*]; kernel = $k:tt; workgroup_dim = $w:tt; thread_dim = $t:tt; dyn_cache = $d:tt; device = NONE; args = $a:tt) => {
79+
$crate::offload!(@munch [$($rest_f = $rest_v),*]; kernel = $k; workgroup_dim = $w; thread_dim = $t; dyn_cache = $d; device = (SOME $val); args = $a)
7680
};
77-
(@munch [args = $val:expr $(, $rest_f:ident = $rest_v:expr)*]; kernel = $k:tt; workgroup_dim = $w:tt; thread_dim = $t:tt; dyn_cache = $d:tt; args = (SOME $old:expr)) => {
81+
(@munch [device = $val:expr $(, $rest_f:ident = $rest_v:expr)*]; kernel = $k:tt; workgroup_dim = $w:tt; thread_dim = $t:tt; dyn_cache = $d:tt; device = (SOME $old:expr); args = $a:tt) => {
82+
compile_error!("duplicate field `device`")
83+
};
84+
(@munch [args = $val:expr $(, $rest_f:ident = $rest_v:expr)*]; kernel = $k:tt; workgroup_dim = $w:tt; thread_dim = $t:tt; dyn_cache = $d:tt; device = $device:tt; args = NONE) => {
85+
$crate::offload!(@munch [$($rest_f = $rest_v),*]; kernel = $k; workgroup_dim = $w; thread_dim = $t; dyn_cache = $d; device = $device; args = (SOME $val))
86+
};
87+
(@munch [args = $val:expr $(, $rest_f:ident = $rest_v:expr)*]; kernel = $k:tt; workgroup_dim = $w:tt; thread_dim = $t:tt; dyn_cache = $d:tt; device = $device:tt; args = (SOME $old:expr)) => {
7888
compile_error!("duplicate field `args`")
7989
};
8090

81-
(@munch [$invalid:ident = $val:expr $(, $rest_f:ident = $rest_v:expr)*]; kernel = $k:tt; workgroup_dim = $w:tt; thread_dim = $t:tt; dyn_cache = $d:tt; args = $a:tt) => {
91+
(@munch [$invalid:ident = $val:expr $(, $rest_f:ident = $rest_v:expr)*]; kernel = $k:tt; workgroup_dim = $w:tt; thread_dim = $t:tt; dyn_cache = $d:tt; device = $device:tt; args = $a:tt) => {
8292
compile_error!(concat!("unknown field `", stringify!($invalid), "`"))
8393
};
8494

85-
(@munch []; kernel = NONE; workgroup_dim = $w:tt; thread_dim = $t:tt; dyn_cache = $d:tt; args = $a:tt) => {
95+
(@munch []; kernel = NONE; workgroup_dim = $w:tt; thread_dim = $t:tt; dyn_cache = $d:tt; device = $device:tt; args = $a:tt) => {
8696
compile_error!("missing `kernel`")
8797
};
88-
(@munch []; kernel = $k:tt; workgroup_dim = $w:tt; thread_dim = $t:tt; dyn_cache = $d:tt; args = NONE) => {
98+
(@munch []; kernel = $k:tt; workgroup_dim = $w:tt; thread_dim = $t:tt; dyn_cache = $d:tt; device = $device:tt; args = NONE) => {
8999
compile_error!("missing `args`")
90100
};
91-
(@munch []; kernel = (SOME $kernel:expr); workgroup_dim = $w:tt; thread_dim = $t:tt; dyn_cache = $d:tt; args = (SOME $args:expr)) => {
101+
(@munch []; kernel = (SOME $kernel:expr); workgroup_dim = $w:tt; thread_dim = $t:tt; dyn_cache = $d:tt; device = $device:tt; args = (SOME $args:expr)) => {
92102
$crate::intrinsics::offload::<_, _, ()>(
93103
$kernel,
94104
$crate::offload!(@value $w),
95105
$crate::offload!(@value $t),
96106
$crate::offload!(@value $d),
107+
$crate::offload!(@device $device),
97108
$args,
98109
)
99110
};
100111

101112
(@value (SOME $val:expr)) => { $val };
102113
(@value ($val:expr)) => { $val };
114+
115+
// if `device` is omitted (`NONE), we use the OpenMP default device (`-1`)
116+
(@device NONE) => { -1 };
117+
(@device (SOME $val:expr)) => { {
118+
const { $crate::assert!($val >= 0, "offload device must be non-negative; omit `device` to use the default device") };
119+
let device: i32 = $val;
120+
$crate::assert!(
121+
device < $crate::intrinsics::offload_get_num_devices(),
122+
"offload device {} is not available",
123+
device,
124+
);
125+
device
126+
} };
103127
}

tests/codegen-llvm/gpu_offload/control_flow.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
// contains control flow.
77

88
#![feature(abi_gpu_kernel)]
9+
#![feature(gpu_offload)]
910
#![feature(rustc_attrs)]
10-
#![feature(core_intrinsics)]
1111
#![no_main]
1212

1313
// CHECK: @.offload_sizes.[[K:[^ ]*foo]] = private unnamed_addr constant
@@ -28,13 +28,12 @@ unsafe fn main() {
2828
let A = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0];
2929

3030
for i in 0..100 {
31-
core::intrinsics::offload::<_, _, ()>(
32-
foo,
33-
[256, 1, 1],
34-
[32, 1, 1],
35-
0,
36-
(A.as_ptr() as *const [f32; 6],),
37-
);
31+
core::offload::offload! {
32+
kernel = foo,
33+
workgroup_dim = [256, 1, 1],
34+
thread_dim = [32, 1, 1],
35+
args = (A.as_ptr() as *const [f32; 6],),
36+
}
3837
}
3938
}
4039

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//@ compile-flags: -Zoffload=Test -Zunstable-options -C opt-level=0 -Clto=fat
2+
//@ no-prefer-dynamic
3+
//@ needs-offload
4+
5+
// This test verifies that selecting an unavailable `device` in the `offload` macro panics.
6+
7+
#![feature(gpu_offload)]
8+
#![no_main]
9+
10+
#[unsafe(no_mangle)]
11+
fn main() {
12+
core::offload::offload! {
13+
kernel = kernel,
14+
device = 99,
15+
args = (),
16+
}
17+
}
18+
19+
#[unsafe(no_mangle)]
20+
fn kernel() {}
21+
22+
// CHECK-LABEL: define{{( dso_local)?}} void @main()
23+
// CHECK: store i32 99, ptr %device, align 4
24+
// CHECK-NEXT: %{{[0-9_]+}} = call i32 @omp_get_num_devices()
25+
// CHECK-NEXT: %{{[0-9_]+}} = load i32, ptr %device, align 4
26+
// CHECK-NEXT: %{{[0-9_]+}} = icmp slt i32 %{{[0-9_]+}}, %{{[0-9_]+}}
27+
// CHECK-NEXT: br i1 %{{[0-9_]+}}, label %bb{{[0-9]+}}, label %bb{{[0-9]+}}
28+
// CHECK: call void @{{.*}}panic_fmt
29+
// CHECK: unreachable
30+
// CHECK: call i32 @__tgt_target_kernel

0 commit comments

Comments
 (0)