Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion crates/rustc_codegen_spirv/src/builder/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -240,6 +240,26 @@ 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 {
// Scalars pass through unchanged
OperandValue::Immediate(v) => v,
// Pack scalar pairs to a single SSA aggregate
OperandValue::Pair(..) => args[0].immediate_or_packed_pair(self),
// Lvalues get loaded
OperandValue::Ref(place) => self.load(llty, place.llval, place.align),
// ZSTs become 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.
Expand Down
60 changes: 60 additions & 0 deletions tests/compiletests/ui/lang/core/intrinsics/black_box.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// build-pass
// compile-flags: -C llvm-args=--disassemble-fn=black_box::disassemble
#![no_std]

use core::hint::black_box;
use spirv_std::spirv;

// Minimal kernel that writes the disassembly function result to a buffer
#[spirv(compute(threads(1)))]
pub fn main(#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] out: &mut [u32]) {
let r = disassemble();
for i in 0..r.len() {
out[i] = r[i];
}
}

#[inline(never)]
pub fn disassemble() -> [u32; 12] {
let x = 42i32;
// Immediate: integer scalar passes through unchanged
let y = black_box(x);

let a = 3.14f32;
// Immediate: float scalar passes through unchanged
let b = black_box(a);

let v = [1u32, 2, 3, 4];
// Ref: non-immediate aggregate is loaded from memory
let w = black_box(v);

// Immediate: constants are immediates
let result = black_box(10) + black_box(20);

let data = 100u32;
// Immediate (pointer): reference value is an immediate scalar pointer
let ref_data = black_box(&data);

// Pair: two-element tuple packs into a single SSA aggregate
let pair = (5u32, 6u32);
let pair_bb = black_box(pair);
let pair_sum = pair_bb.0 + pair_bb.1;

// ZeroSized: unit type becomes `undef` of the right type
let _z = black_box(());

[
y as u32,
f32::to_bits(b),
w[0],
w[1],
w[2],
w[3],
result,
*ref_data,
pair_sum,
0,
0,
0,
]
}
19 changes: 19 additions & 0 deletions tests/compiletests/ui/lang/core/intrinsics/black_box.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
warning: black_box intrinsic does not prevent optimization in Rust GPU

%1 = OpFunction %2 DontInline %3
%4 = OpLabel
OpLine %5 32 17
%6 = OpIAdd %7 %8 %9
OpLine %5 41 19
%10 = OpIAdd %7 %11 %12
OpLine %5 47 8
%13 = OpBitcast %7 %14
OpLine %15 1092 17
%16 = OpBitcast %7 %17
OpLine %5 46 4
%18 = OpCompositeConstruct %2 %13 %16 %19 %20 %21 %22 %6 %23 %10 %24 %24 %24
OpNoLine
OpReturnValue %18
OpFunctionEnd
warning: 1 warning emitted

16 changes: 16 additions & 0 deletions tests/difftests/tests/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions tests/difftests/tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ members = [
"lang/core/ops/trig_ops/trig_ops-wgsl",
"lang/core/ops/vector_swizzle/vector_swizzle-rust",
"lang/core/ops/vector_swizzle/vector_swizzle-wgsl",
"lang/core/intrinsics/black_box_noop/with-black-box",
"lang/core/intrinsics/black_box_noop/without-black-box",
]

[workspace.package]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "black_box-noop-with"
edition.workspace = true

[lints]
workspace = true

[lib]
crate-type = ["dylib"]

# GPU deps
[dependencies]
spirv-std.workspace = true

# CPU deps (for the test harness)
[target.'cfg(not(target_arch = "spirv"))'.dependencies]
difftest.workspace = true
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#![no_std]

use core::hint::black_box;
use spirv_std::spirv;

#[spirv(compute(threads(1)))]
pub fn main_cs(#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] out: &mut [u32]) {
let x = 42i32;
let y = black_box(x) as u32;

let a = 3.14f32;
let b = black_box(a).to_bits();

let v = [1u32, 2, 3, 4];
let w = black_box(v);

let result = black_box(10) + black_box(20);

let data = 100u32;
let ref_data = black_box(&data);

let pair = (5u32, 6u32);
let pair_bb = black_box(pair);
let pair_sum = pair_bb.0 + pair_bb.1;

let _ = black_box(());

let values = [
y, b, w[0], w[1], w[2], w[3], result, *ref_data, pair_sum, 0, 0, 0,
];
out[0] = values[0];
out[1] = values[1];
out[2] = values[2];
out[3] = values[3];
out[4] = values[4];
out[5] = values[5];
out[6] = values[6];
out[7] = values[7];
out[8] = values[8];
out[9] = values[9];
out[10] = values[10];
out[11] = values[11];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use difftest::config::{Config, TestMetadata};
use difftest::scaffold::compute::{RustComputeShader, WgpuComputeTest};

fn main() {
let config = Config::from_path(std::env::args().nth(1).unwrap()).unwrap();
let test = WgpuComputeTest::new(RustComputeShader::default(), [1, 1, 1], 12 * 4);
test.run_test(&config).unwrap();
config
.write_metadata(&TestMetadata::u32())
.expect("Failed to write metadata");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "black_box-noop-without"
edition.workspace = true

[lints]
workspace = true

[lib]
crate-type = ["dylib"]

# GPU deps
[dependencies]
spirv-std.workspace = true

# CPU deps (for the test harness)
[target.'cfg(not(target_arch = "spirv"))'.dependencies]
difftest.workspace = true

Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#![no_std]

use spirv_std::spirv;

#[spirv(compute(threads(1)))]
pub fn main_cs(#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] out: &mut [u32]) {
let x = 42i32;
let y = x as u32;

let a = 3.14f32;
let b = a.to_bits();

let v = [1u32, 2, 3, 4];
let w = v;

let result = 10 + 20;

let data = 100u32;
let ref_data = &data;

let pair = (5u32, 6u32);
let pair_sum = pair.0 + pair.1;

let values = [
y, b, w[0], w[1], w[2], w[3], result, *ref_data, pair_sum, 0, 0, 0,
];
out[0] = values[0];
out[1] = values[1];
out[2] = values[2];
out[3] = values[3];
out[4] = values[4];
out[5] = values[5];
out[6] = values[6];
out[7] = values[7];
out[8] = values[8];
out[9] = values[9];
out[10] = values[10];
out[11] = values[11];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use difftest::config::{Config, TestMetadata};
use difftest::scaffold::compute::{RustComputeShader, WgpuComputeTest};

fn main() {
let config = Config::from_path(std::env::args().nth(1).unwrap()).unwrap();
let test = WgpuComputeTest::new(RustComputeShader::default(), [1, 1, 1], 12 * 4);
test.run_test(&config).unwrap();
config
.write_metadata(&TestMetadata::u32())
.expect("Failed to write metadata");
}