From 84247de53f28bc415889d9c0a1c0ad7248de632e Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Wed, 13 Aug 2025 21:13:45 -0700 Subject: [PATCH 1/3] Make `black_box` a no-op Part of https://github.com/Rust-GPU/rust-gpu/issues/312 --- .../src/builder/intrinsics.rs | 29 ++++++++++++++++++- .../ui/lang/core/intrinsics/black_box.rs | 29 +++++++++++++++++++ .../ui/lang/core/intrinsics/black_box.stderr | 4 +++ 3 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 tests/compiletests/ui/lang/core/intrinsics/black_box.rs create mode 100644 tests/compiletests/ui/lang/core/intrinsics/black_box.stderr diff --git a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs index deab2b087c..f94cd49d62 100644 --- a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs +++ b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs @@ -9,7 +9,7 @@ use crate::custom_insts::CustomInst; use crate::spirv_type::SpirvType; use rspirv::dr::Operand; use rspirv::spirv::GLOp; -use rustc_codegen_ssa::mir::operand::OperandRef; +use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::{BuilderMethods, IntrinsicCallBuilderMethods}; use rustc_middle::ty::layout::LayoutOf; @@ -240,6 +240,33 @@ impl<'a, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'tcx> { sym::ctpop => self.count_ones(args[0].immediate()), sym::bitreverse => self.bit_reverse(args[0].immediate()), + sym::black_box => { + // TODO(LegNeato): do something more sophisticated that prevents DCE + self.tcx + .dcx() + .warn("black_box intrinsic does not prevent optimization in Rust GPU"); + + let layout = self.layout_of(arg_tys[0]); + let llty = layout.spirv_type(self.span(), self); + + match args[0].val { + // Pass through scalars + OperandValue::Immediate(v) => v, + + // Preserve both elements by spilling + reloading + OperandValue::Pair(..) => { + let tmp = self.alloca(layout.size, layout.align.abi); + self.store(args[0].immediate(), tmp, layout.align.abi); + self.load(llty, tmp, layout.align.abi) + } + + // For lvalues, load + OperandValue::Ref(place) => self.load(llty, place.llval, place.align), + + // For ZSTs, return undef of the right type + OperandValue::ZeroSized => self.undef(llty), + } + } sym::bswap => { // https://github.com/KhronosGroup/SPIRV-LLVM/pull/221/files // TODO: Definitely add tests to make sure this impl is right. diff --git a/tests/compiletests/ui/lang/core/intrinsics/black_box.rs b/tests/compiletests/ui/lang/core/intrinsics/black_box.rs new file mode 100644 index 0000000000..85172a4309 --- /dev/null +++ b/tests/compiletests/ui/lang/core/intrinsics/black_box.rs @@ -0,0 +1,29 @@ +// Test black_box intrinsic +// build-pass + +#![allow(internal_features)] +#![feature(core_intrinsics)] +#![no_std] + +use core::hint::black_box; +use spirv_std::spirv; + +#[spirv(compute(threads(1)))] +pub fn main() { + // Test with various types + let x = 42i32; + let y = black_box(x); + + let a = 3.14f32; + let b = black_box(a); + + let v = [1, 2, 3, 4]; + let w = black_box(v); + + // Test in expressions + let result = black_box(10) + black_box(20); + + // Test with references + let data = 100u32; + let ref_data = black_box(&data); +} diff --git a/tests/compiletests/ui/lang/core/intrinsics/black_box.stderr b/tests/compiletests/ui/lang/core/intrinsics/black_box.stderr new file mode 100644 index 0000000000..6fbd99fcb0 --- /dev/null +++ b/tests/compiletests/ui/lang/core/intrinsics/black_box.stderr @@ -0,0 +1,4 @@ +warning: black_box intrinsic does not prevent optimization in Rust GPU + +warning: 1 warning emitted + From 8837ab4e493407827331807b5bed69e3a3029396 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Mon, 18 Aug 2025 13:23:33 +0200 Subject: [PATCH 2/3] black_box: disassemble compiletest --- .../ui/lang/core/intrinsics/black_box.rs | 21 ++++++++++++++++++- .../ui/lang/core/intrinsics/black_box.stderr | 13 ++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/tests/compiletests/ui/lang/core/intrinsics/black_box.rs b/tests/compiletests/ui/lang/core/intrinsics/black_box.rs index 85172a4309..389a30c278 100644 --- a/tests/compiletests/ui/lang/core/intrinsics/black_box.rs +++ b/tests/compiletests/ui/lang/core/intrinsics/black_box.rs @@ -1,5 +1,6 @@ // Test black_box intrinsic // build-pass +// compile-flags: -C llvm-args=--disassemble-fn=black_box::disassemble #![allow(internal_features)] #![feature(core_intrinsics)] @@ -9,7 +10,14 @@ use core::hint::black_box; use spirv_std::spirv; #[spirv(compute(threads(1)))] -pub fn main() { +pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] out: &mut [u32]) { + let result = disassemble(); + for i in 0..result.len() { + out[i] = result[i]; + } +} + +pub fn disassemble() -> [u32; 8] { // Test with various types let x = 42i32; let y = black_box(x); @@ -26,4 +34,15 @@ pub fn main() { // Test with references let data = 100u32; let ref_data = black_box(&data); + + [ + y as u32, + f32::to_bits(b), + w[0], + w[1], + w[2], + w[3], + result, + *ref_data, + ] } diff --git a/tests/compiletests/ui/lang/core/intrinsics/black_box.stderr b/tests/compiletests/ui/lang/core/intrinsics/black_box.stderr index 6fbd99fcb0..a61737d9c2 100644 --- a/tests/compiletests/ui/lang/core/intrinsics/black_box.stderr +++ b/tests/compiletests/ui/lang/core/intrinsics/black_box.stderr @@ -1,4 +1,17 @@ warning: black_box intrinsic does not prevent optimization in Rust GPU +%1 = OpFunction %2 None %3 +%4 = OpLabel +OpLine %5 34 17 +%6 = OpIAdd %7 %8 %9 +OpLine %5 40 5 +%10 = OpBitcast %7 %11 +OpLine %12 1092 17 +%13 = OpBitcast %7 %14 +OpLine %5 40 4 +%15 = OpCompositeConstruct %2 %10 %13 %16 %17 %18 %19 %6 %20 +OpNoLine +OpReturnValue %15 +OpFunctionEnd warning: 1 warning emitted From 2f45f6412a223465a94b636e3ee50e7d16ddffb9 Mon Sep 17 00:00:00 2001 From: firestar99 Date: Mon, 18 Aug 2025 13:24:46 +0200 Subject: [PATCH 3/3] black_box: test passing slice through black_box, ICE --- tests/compiletests/ui/lang/core/intrinsics/black_box.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/compiletests/ui/lang/core/intrinsics/black_box.rs b/tests/compiletests/ui/lang/core/intrinsics/black_box.rs index 389a30c278..f6afc814b8 100644 --- a/tests/compiletests/ui/lang/core/intrinsics/black_box.rs +++ b/tests/compiletests/ui/lang/core/intrinsics/black_box.rs @@ -17,7 +17,7 @@ pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] out: &mut } } -pub fn disassemble() -> [u32; 8] { +pub fn disassemble() -> [u32; 12] { // Test with various types let x = 42i32; let y = black_box(x); @@ -35,6 +35,8 @@ pub fn disassemble() -> [u32; 8] { let data = 100u32; let ref_data = black_box(&data); + let ref_slice = black_box(v.as_slice()); + [ y as u32, f32::to_bits(b), @@ -44,5 +46,9 @@ pub fn disassemble() -> [u32; 8] { w[3], result, *ref_data, + ref_slice[0], + ref_slice[1], + ref_slice[2], + ref_slice[3], ] }