From 15f5a5bba511ced0e0085225923b6c838ca48327 Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Wed, 29 Jan 2025 16:21:20 +0100 Subject: [PATCH 01/15] leading_zeros: add support for leading_zeros and trailing_zeros, limited to u32/i32 --- .../src/builder/ext_inst.rs | 33 +------- .../src/builder/intrinsics.rs | 77 ++++++++++++------- crates/rustc_codegen_spirv/src/symbols.rs | 4 - tests/ui/lang/u32/trailing_leading_bits.rs | 37 +++++++++ 4 files changed, 89 insertions(+), 62 deletions(-) create mode 100644 tests/ui/lang/u32/trailing_leading_bits.rs diff --git a/crates/rustc_codegen_spirv/src/builder/ext_inst.rs b/crates/rustc_codegen_spirv/src/builder/ext_inst.rs index e0dec8cf2d..7c4997de76 100644 --- a/crates/rustc_codegen_spirv/src/builder/ext_inst.rs +++ b/crates/rustc_codegen_spirv/src/builder/ext_inst.rs @@ -1,8 +1,8 @@ use super::Builder; use crate::builder_spirv::{SpirvValue, SpirvValueExt}; use crate::custom_insts; +use rspirv::dr::Operand; use rspirv::spirv::{GLOp, Word}; -use rspirv::{dr::Operand, spirv::Capability}; const GLSL_STD_450: &str = "GLSL.std.450"; @@ -13,7 +13,6 @@ pub struct ExtInst { custom: Option, glsl: Option, - integer_functions_2_intel: bool, } impl ExtInst { @@ -38,32 +37,11 @@ impl ExtInst { id } } - - pub fn require_integer_functions_2_intel(&mut self, bx: &Builder<'_, '_>, to_zombie: Word) { - if !self.integer_functions_2_intel { - self.integer_functions_2_intel = true; - if !bx - .builder - .has_capability(Capability::IntegerFunctions2INTEL) - { - bx.zombie(to_zombie, "capability IntegerFunctions2INTEL is required"); - } - if !bx - .builder - .has_extension(bx.sym.spv_intel_shader_integer_functions2) - { - bx.zombie( - to_zombie, - "extension SPV_INTEL_shader_integer_functions2 is required", - ); - } - } - } } impl<'a, 'tcx> Builder<'a, 'tcx> { pub fn custom_inst( - &mut self, + &self, result_type: Word, inst: custom_insts::CustomInst, ) -> SpirvValue { @@ -80,12 +58,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { .with_type(result_type) } - pub fn gl_op( - &mut self, - op: GLOp, - result_type: Word, - args: impl AsRef<[SpirvValue]>, - ) -> SpirvValue { + pub fn gl_op(&self, op: GLOp, result_type: Word, args: impl AsRef<[SpirvValue]>) -> SpirvValue { let args = args.as_ref(); let glsl = self.ext_inst.borrow_mut().import_glsl(self); self.emit() diff --git a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs index 45757888e9..e0eab8341c 100644 --- a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs +++ b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs @@ -211,35 +211,12 @@ impl<'a, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'tcx> { self.rotate(val, shift, is_left) } - // TODO: Do we want to manually implement these instead of using intel instructions? - sym::ctlz | sym::ctlz_nonzero => { - let result = self - .emit() - .u_count_leading_zeros_intel( - args[0].immediate().ty, - None, - args[0].immediate().def(self), - ) - .unwrap(); - self.ext_inst - .borrow_mut() - .require_integer_functions_2_intel(self, result); - result.with_type(args[0].immediate().ty) - } - sym::cttz | sym::cttz_nonzero => { - let result = self - .emit() - .u_count_trailing_zeros_intel( - args[0].immediate().ty, - None, - args[0].immediate().def(self), - ) - .unwrap(); - self.ext_inst - .borrow_mut() - .require_integer_functions_2_intel(self, result); - result.with_type(args[0].immediate().ty) + sym::ctlz => self.count_leading_trailing_zeros(args[0].immediate(), false, false), + sym::ctlz_nonzero => { + self.count_leading_trailing_zeros(args[0].immediate(), false, true) } + sym::cttz => self.count_leading_trailing_zeros(args[0].immediate(), true, false), + sym::cttz_nonzero => self.count_leading_trailing_zeros(args[0].immediate(), true, true), sym::ctpop => self .emit() @@ -398,6 +375,50 @@ impl<'a, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'tcx> { } impl Builder<'_, '_> { + pub fn count_leading_trailing_zeros( + &self, + arg: SpirvValue, + trailing: bool, + non_zero: bool, + ) -> SpirvValue { + let ty = arg.ty; + match self.cx.lookup_type(ty) { + SpirvType::Integer(bits, _) => { + let int_0 = self.constant_int(ty, 0); + let int_bits = self.constant_int(ty, bits as u128).def(self); + let bool = SpirvType::Bool.def(self.span(), self); + + let gl_op = if trailing { + // rust is always unsigned + GLOp::FindILsb + } else { + GLOp::FindUMsb + }; + + let glsl = self.ext_inst.borrow_mut().import_glsl(self); + let find_xsb = self + .emit() + .ext_inst(ty, None, glsl, gl_op as u32, [Operand::IdRef( + arg.def(self), + )]) + .unwrap(); + if non_zero { + find_xsb + } else { + let is_0 = self + .emit() + .i_equal(bool, None, arg.def(self), int_0.def(self)) + .unwrap(); + self.emit() + .select(ty, None, is_0, int_bits, find_xsb) + .unwrap() + } + .with_type(ty) + } + _ => self.fatal("counting leading / trailing zeros on a non-integer type"), + } + } + pub fn abort_with_kind_and_message_debug_printf( &mut self, kind: &str, diff --git a/crates/rustc_codegen_spirv/src/symbols.rs b/crates/rustc_codegen_spirv/src/symbols.rs index dd1d2b397c..e3d4dc2232 100644 --- a/crates/rustc_codegen_spirv/src/symbols.rs +++ b/crates/rustc_codegen_spirv/src/symbols.rs @@ -21,7 +21,6 @@ pub struct Symbols { pub spirv: Symbol, pub libm: Symbol, pub entry_point_name: Symbol, - pub spv_intel_shader_integer_functions2: Symbol, pub spv_khr_vulkan_memory_model: Symbol, descriptor_set: Symbol, @@ -411,9 +410,6 @@ impl Symbols { spirv: Symbol::intern("spirv"), libm: Symbol::intern("libm"), entry_point_name: Symbol::intern("entry_point_name"), - spv_intel_shader_integer_functions2: Symbol::intern( - "SPV_INTEL_shader_integer_functions2", - ), spv_khr_vulkan_memory_model: Symbol::intern("SPV_KHR_vulkan_memory_model"), descriptor_set: Symbol::intern("descriptor_set"), diff --git a/tests/ui/lang/u32/trailing_leading_bits.rs b/tests/ui/lang/u32/trailing_leading_bits.rs new file mode 100644 index 0000000000..e726da5777 --- /dev/null +++ b/tests/ui/lang/u32/trailing_leading_bits.rs @@ -0,0 +1,37 @@ +// Test all trailing and leading zeros. No need to test ones, they just call the zero variant with !value + +// build-pass + +use spirv_std::spirv; + +#[spirv(fragment)] +pub fn leading_zeros_u32( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &u32, + out: &mut u32, +) { + *out = u32::leading_zeros(*buffer); +} + +#[spirv(fragment)] +pub fn trailing_zeros_u32( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &u32, + out: &mut u32, +) { + *out = u32::trailing_zeros(*buffer); +} + +#[spirv(fragment)] +pub fn leading_zeros_i32( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &i32, + out: &mut u32, +) { + *out = i32::leading_zeros(*buffer); +} + +#[spirv(fragment)] +pub fn trailing_zeros_i32( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &i32, + out: &mut u32, +) { + *out = i32::trailing_zeros(*buffer); +} From ce566fa8f0aa63e546129c20d9a68690c2d2a6a5 Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Mon, 10 Feb 2025 11:05:35 +0100 Subject: [PATCH 02/15] leading_zeros: add tests for non 32bit integers, failing --- tests/ui/lang/u32/leading_zeros.rs | 69 ++++++ tests/ui/lang/u32/leading_zeros.stderr | 251 +++++++++++++++++++++ tests/ui/lang/u32/trailing_leading_bits.rs | 37 --- tests/ui/lang/u32/trailing_zeros.rs | 69 ++++++ tests/ui/lang/u32/trailing_zeros.stderr | 251 +++++++++++++++++++++ 5 files changed, 640 insertions(+), 37 deletions(-) create mode 100644 tests/ui/lang/u32/leading_zeros.rs create mode 100644 tests/ui/lang/u32/leading_zeros.stderr delete mode 100644 tests/ui/lang/u32/trailing_leading_bits.rs create mode 100644 tests/ui/lang/u32/trailing_zeros.rs create mode 100644 tests/ui/lang/u32/trailing_zeros.stderr diff --git a/tests/ui/lang/u32/leading_zeros.rs b/tests/ui/lang/u32/leading_zeros.rs new file mode 100644 index 0000000000..d157dfe73f --- /dev/null +++ b/tests/ui/lang/u32/leading_zeros.rs @@ -0,0 +1,69 @@ +// Test all trailing and leading zeros. No need to test ones, they just call the zero variant with !value + +// build-pass + +use spirv_std::spirv; + +#[spirv(fragment)] +pub fn leading_zeros_u8( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &u8, + out: &mut u32, +) { + *out = u8::leading_zeros(*buffer); +} + +#[spirv(fragment)] +pub fn leading_zeros_u16( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &u16, + out: &mut u32, +) { + *out = u16::leading_zeros(*buffer); +} + +#[spirv(fragment)] +pub fn leading_zeros_u32( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &u32, + out: &mut u32, +) { + *out = u32::leading_zeros(*buffer); +} + +#[spirv(fragment)] +pub fn leading_zeros_u64( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &u64, + out: &mut u32, +) { + *out = u64::leading_zeros(*buffer); +} + +#[spirv(fragment)] +pub fn leading_zeros_i8( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &i8, + out: &mut u32, +) { + *out = i8::leading_zeros(*buffer); +} + +#[spirv(fragment)] +pub fn leading_zeros_i16( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &i16, + out: &mut u32, +) { + *out = i16::leading_zeros(*buffer); +} + +#[spirv(fragment)] +pub fn leading_zeros_i32( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &i32, + out: &mut u32, +) { + *out = i32::leading_zeros(*buffer); +} + +#[spirv(fragment)] +pub fn leading_zeros_i64( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &i64, + out: &mut u32, +) { + *out = i64::leading_zeros(*buffer); +} diff --git a/tests/ui/lang/u32/leading_zeros.stderr b/tests/ui/lang/u32/leading_zeros.stderr new file mode 100644 index 0000000000..da5df187c2 --- /dev/null +++ b/tests/ui/lang/u32/leading_zeros.stderr @@ -0,0 +1,251 @@ +error: cannot cast between pointer types + from `*u32` + to `*u8` + --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:535:5 + | +535 | / uint_impl! { +536 | | Self = u8, +537 | | ActualT = u8, +538 | | SignedT = i8, +... | +552 | | bound_condition = "", +553 | | } + | |_____^ + | +note: used from within `::leading_zeros` + --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:535:5 + | +535 | / uint_impl! { +536 | | Self = u8, +537 | | ActualT = u8, +538 | | SignedT = i8, +... | +552 | | bound_condition = "", +553 | | } + | |_____^ +note: called by `leading_zeros::leading_zeros_u8` + --> $DIR/leading_zeros.rs:12:12 + | +12 | *out = u8::leading_zeros(*buffer); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: called by `leading_zeros_u8` + --> $DIR/leading_zeros.rs:8:8 + | +8 | pub fn leading_zeros_u8( + | ^^^^^^^^^^^^^^^^ + +error: cannot cast between pointer types + from `*u32` + to `*u16` + --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1151:5 + | +1151 | / uint_impl! { +1152 | | Self = u16, +1153 | | ActualT = u16, +1154 | | SignedT = i16, +... | +1168 | | bound_condition = "", +1169 | | } + | |_____^ + | +note: used from within `::leading_zeros` + --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1151:5 + | +1151 | / uint_impl! { +1152 | | Self = u16, +1153 | | ActualT = u16, +1154 | | SignedT = i16, +... | +1168 | | bound_condition = "", +1169 | | } + | |_____^ +note: called by `leading_zeros::leading_zeros_u16` + --> $DIR/leading_zeros.rs:20:12 + | +20 | *out = u16::leading_zeros(*buffer); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: called by `leading_zeros_u16` + --> $DIR/leading_zeros.rs:16:8 + | +16 | pub fn leading_zeros_u16( + | ^^^^^^^^^^^^^^^^^ + +error: cannot cast between pointer types + from `*u32` + to `*u64` + --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1223:5 + | +1223 | / uint_impl! { +1224 | | Self = u64, +1225 | | ActualT = u64, +1226 | | SignedT = i64, +... | +1240 | | bound_condition = "", +1241 | | } + | |_____^ + | +note: used from within `::leading_zeros` + --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1223:5 + | +1223 | / uint_impl! { +1224 | | Self = u64, +1225 | | ActualT = u64, +1226 | | SignedT = i64, +... | +1240 | | bound_condition = "", +1241 | | } + | |_____^ +note: called by `leading_zeros::leading_zeros_u64` + --> $DIR/leading_zeros.rs:36:12 + | +36 | *out = u64::leading_zeros(*buffer); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: called by `leading_zeros_u64` + --> $DIR/leading_zeros.rs:32:8 + | +32 | pub fn leading_zeros_u64( + | ^^^^^^^^^^^^^^^^^ + +error: cannot cast between pointer types + from `*u32` + to `*u8` + --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:535:5 + | +535 | / uint_impl! { +536 | | Self = u8, +537 | | ActualT = u8, +538 | | SignedT = i8, +... | +552 | | bound_condition = "", +553 | | } + | |_____^ + | +note: used from within `::leading_zeros` + --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:535:5 + | +535 | / uint_impl! { +536 | | Self = u8, +537 | | ActualT = u8, +538 | | SignedT = i8, +... | +552 | | bound_condition = "", +553 | | } + | |_____^ +note: called by `::leading_zeros` + --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:335:5 + | +335 | / int_impl! { +336 | | Self = i8, +337 | | ActualT = i8, +338 | | UnsignedT = u8, +... | +353 | | bound_condition = "", +354 | | } + | |_____^ +note: called by `leading_zeros::leading_zeros_i8` + --> $DIR/leading_zeros.rs:44:12 + | +44 | *out = i8::leading_zeros(*buffer); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: called by `leading_zeros_i8` + --> $DIR/leading_zeros.rs:40:8 + | +40 | pub fn leading_zeros_i8( + | ^^^^^^^^^^^^^^^^ + +error: cannot cast between pointer types + from `*u32` + to `*u16` + --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1151:5 + | +1151 | / uint_impl! { +1152 | | Self = u16, +1153 | | ActualT = u16, +1154 | | SignedT = i16, +... | +1168 | | bound_condition = "", +1169 | | } + | |_____^ + | +note: used from within `::leading_zeros` + --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1151:5 + | +1151 | / uint_impl! { +1152 | | Self = u16, +1153 | | ActualT = u16, +1154 | | SignedT = i16, +... | +1168 | | bound_condition = "", +1169 | | } + | |_____^ +note: called by `::leading_zeros` + --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:359:5 + | +359 | / int_impl! { +360 | | Self = i16, +361 | | ActualT = i16, +362 | | UnsignedT = u16, +... | +377 | | bound_condition = "", +378 | | } + | |_____^ +note: called by `leading_zeros::leading_zeros_i16` + --> $DIR/leading_zeros.rs:52:12 + | +52 | *out = i16::leading_zeros(*buffer); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: called by `leading_zeros_i16` + --> $DIR/leading_zeros.rs:48:8 + | +48 | pub fn leading_zeros_i16( + | ^^^^^^^^^^^^^^^^^ + +error: cannot cast between pointer types + from `*u32` + to `*u64` + --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1223:5 + | +1223 | / uint_impl! { +1224 | | Self = u64, +1225 | | ActualT = u64, +1226 | | SignedT = i64, +... | +1240 | | bound_condition = "", +1241 | | } + | |_____^ + | +note: used from within `::leading_zeros` + --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1223:5 + | +1223 | / uint_impl! { +1224 | | Self = u64, +1225 | | ActualT = u64, +1226 | | SignedT = i64, +... | +1240 | | bound_condition = "", +1241 | | } + | |_____^ +note: called by `::leading_zeros` + --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:407:5 + | +407 | / int_impl! { +408 | | Self = i64, +409 | | ActualT = i64, +410 | | UnsignedT = u64, +... | +425 | | bound_condition = "", +426 | | } + | |_____^ +note: called by `leading_zeros::leading_zeros_i64` + --> $DIR/leading_zeros.rs:68:12 + | +68 | *out = i64::leading_zeros(*buffer); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: called by `leading_zeros_i64` + --> $DIR/leading_zeros.rs:64:8 + | +64 | pub fn leading_zeros_i64( + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/tests/ui/lang/u32/trailing_leading_bits.rs b/tests/ui/lang/u32/trailing_leading_bits.rs deleted file mode 100644 index e726da5777..0000000000 --- a/tests/ui/lang/u32/trailing_leading_bits.rs +++ /dev/null @@ -1,37 +0,0 @@ -// Test all trailing and leading zeros. No need to test ones, they just call the zero variant with !value - -// build-pass - -use spirv_std::spirv; - -#[spirv(fragment)] -pub fn leading_zeros_u32( - #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &u32, - out: &mut u32, -) { - *out = u32::leading_zeros(*buffer); -} - -#[spirv(fragment)] -pub fn trailing_zeros_u32( - #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &u32, - out: &mut u32, -) { - *out = u32::trailing_zeros(*buffer); -} - -#[spirv(fragment)] -pub fn leading_zeros_i32( - #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &i32, - out: &mut u32, -) { - *out = i32::leading_zeros(*buffer); -} - -#[spirv(fragment)] -pub fn trailing_zeros_i32( - #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &i32, - out: &mut u32, -) { - *out = i32::trailing_zeros(*buffer); -} diff --git a/tests/ui/lang/u32/trailing_zeros.rs b/tests/ui/lang/u32/trailing_zeros.rs new file mode 100644 index 0000000000..314d60d323 --- /dev/null +++ b/tests/ui/lang/u32/trailing_zeros.rs @@ -0,0 +1,69 @@ +// Test all trailing and leading zeros. No need to test ones, they just call the zero variant with !value + +// build-pass + +use spirv_std::spirv; + +#[spirv(fragment)] +pub fn trailing_zeros_u8( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &u8, + out: &mut u32, +) { + *out = u8::trailing_zeros(*buffer); +} + +#[spirv(fragment)] +pub fn trailing_zeros_u16( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &u16, + out: &mut u32, +) { + *out = u16::trailing_zeros(*buffer); +} + +#[spirv(fragment)] +pub fn trailing_zeros_u32( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &u32, + out: &mut u32, +) { + *out = u32::trailing_zeros(*buffer); +} + +#[spirv(fragment)] +pub fn trailing_zeros_u64( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &u64, + out: &mut u32, +) { + *out = u64::trailing_zeros(*buffer); +} + +#[spirv(fragment)] +pub fn trailing_zeros_i8( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &i8, + out: &mut u32, +) { + *out = i8::trailing_zeros(*buffer); +} + +#[spirv(fragment)] +pub fn trailing_zeros_i16( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &i16, + out: &mut u32, +) { + *out = i16::trailing_zeros(*buffer); +} + +#[spirv(fragment)] +pub fn trailing_zeros_i32( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &i32, + out: &mut u32, +) { + *out = i32::trailing_zeros(*buffer); +} + +#[spirv(fragment)] +pub fn trailing_zeros_i64( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &i64, + out: &mut u32, +) { + *out = i64::trailing_zeros(*buffer); +} diff --git a/tests/ui/lang/u32/trailing_zeros.stderr b/tests/ui/lang/u32/trailing_zeros.stderr new file mode 100644 index 0000000000..cfa1090bef --- /dev/null +++ b/tests/ui/lang/u32/trailing_zeros.stderr @@ -0,0 +1,251 @@ +error: cannot cast between pointer types + from `*u32` + to `*u8` + --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:535:5 + | +535 | / uint_impl! { +536 | | Self = u8, +537 | | ActualT = u8, +538 | | SignedT = i8, +... | +552 | | bound_condition = "", +553 | | } + | |_____^ + | +note: used from within `::trailing_zeros` + --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:535:5 + | +535 | / uint_impl! { +536 | | Self = u8, +537 | | ActualT = u8, +538 | | SignedT = i8, +... | +552 | | bound_condition = "", +553 | | } + | |_____^ +note: called by `trailing_zeros::trailing_zeros_u8` + --> $DIR/trailing_zeros.rs:12:12 + | +12 | *out = u8::trailing_zeros(*buffer); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: called by `trailing_zeros_u8` + --> $DIR/trailing_zeros.rs:8:8 + | +8 | pub fn trailing_zeros_u8( + | ^^^^^^^^^^^^^^^^^ + +error: cannot cast between pointer types + from `*u32` + to `*u16` + --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1151:5 + | +1151 | / uint_impl! { +1152 | | Self = u16, +1153 | | ActualT = u16, +1154 | | SignedT = i16, +... | +1168 | | bound_condition = "", +1169 | | } + | |_____^ + | +note: used from within `::trailing_zeros` + --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1151:5 + | +1151 | / uint_impl! { +1152 | | Self = u16, +1153 | | ActualT = u16, +1154 | | SignedT = i16, +... | +1168 | | bound_condition = "", +1169 | | } + | |_____^ +note: called by `trailing_zeros::trailing_zeros_u16` + --> $DIR/trailing_zeros.rs:20:12 + | +20 | *out = u16::trailing_zeros(*buffer); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: called by `trailing_zeros_u16` + --> $DIR/trailing_zeros.rs:16:8 + | +16 | pub fn trailing_zeros_u16( + | ^^^^^^^^^^^^^^^^^^ + +error: cannot cast between pointer types + from `*u32` + to `*u64` + --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1223:5 + | +1223 | / uint_impl! { +1224 | | Self = u64, +1225 | | ActualT = u64, +1226 | | SignedT = i64, +... | +1240 | | bound_condition = "", +1241 | | } + | |_____^ + | +note: used from within `::trailing_zeros` + --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1223:5 + | +1223 | / uint_impl! { +1224 | | Self = u64, +1225 | | ActualT = u64, +1226 | | SignedT = i64, +... | +1240 | | bound_condition = "", +1241 | | } + | |_____^ +note: called by `trailing_zeros::trailing_zeros_u64` + --> $DIR/trailing_zeros.rs:36:12 + | +36 | *out = u64::trailing_zeros(*buffer); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: called by `trailing_zeros_u64` + --> $DIR/trailing_zeros.rs:32:8 + | +32 | pub fn trailing_zeros_u64( + | ^^^^^^^^^^^^^^^^^^ + +error: cannot cast between pointer types + from `*u32` + to `*u8` + --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:535:5 + | +535 | / uint_impl! { +536 | | Self = u8, +537 | | ActualT = u8, +538 | | SignedT = i8, +... | +552 | | bound_condition = "", +553 | | } + | |_____^ + | +note: used from within `::trailing_zeros` + --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:535:5 + | +535 | / uint_impl! { +536 | | Self = u8, +537 | | ActualT = u8, +538 | | SignedT = i8, +... | +552 | | bound_condition = "", +553 | | } + | |_____^ +note: called by `::trailing_zeros` + --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:335:5 + | +335 | / int_impl! { +336 | | Self = i8, +337 | | ActualT = i8, +338 | | UnsignedT = u8, +... | +353 | | bound_condition = "", +354 | | } + | |_____^ +note: called by `trailing_zeros::trailing_zeros_i8` + --> $DIR/trailing_zeros.rs:44:12 + | +44 | *out = i8::trailing_zeros(*buffer); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: called by `trailing_zeros_i8` + --> $DIR/trailing_zeros.rs:40:8 + | +40 | pub fn trailing_zeros_i8( + | ^^^^^^^^^^^^^^^^^ + +error: cannot cast between pointer types + from `*u32` + to `*u16` + --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1151:5 + | +1151 | / uint_impl! { +1152 | | Self = u16, +1153 | | ActualT = u16, +1154 | | SignedT = i16, +... | +1168 | | bound_condition = "", +1169 | | } + | |_____^ + | +note: used from within `::trailing_zeros` + --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1151:5 + | +1151 | / uint_impl! { +1152 | | Self = u16, +1153 | | ActualT = u16, +1154 | | SignedT = i16, +... | +1168 | | bound_condition = "", +1169 | | } + | |_____^ +note: called by `::trailing_zeros` + --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:359:5 + | +359 | / int_impl! { +360 | | Self = i16, +361 | | ActualT = i16, +362 | | UnsignedT = u16, +... | +377 | | bound_condition = "", +378 | | } + | |_____^ +note: called by `trailing_zeros::trailing_zeros_i16` + --> $DIR/trailing_zeros.rs:52:12 + | +52 | *out = i16::trailing_zeros(*buffer); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: called by `trailing_zeros_i16` + --> $DIR/trailing_zeros.rs:48:8 + | +48 | pub fn trailing_zeros_i16( + | ^^^^^^^^^^^^^^^^^^ + +error: cannot cast between pointer types + from `*u32` + to `*u64` + --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1223:5 + | +1223 | / uint_impl! { +1224 | | Self = u64, +1225 | | ActualT = u64, +1226 | | SignedT = i64, +... | +1240 | | bound_condition = "", +1241 | | } + | |_____^ + | +note: used from within `::trailing_zeros` + --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1223:5 + | +1223 | / uint_impl! { +1224 | | Self = u64, +1225 | | ActualT = u64, +1226 | | SignedT = i64, +... | +1240 | | bound_condition = "", +1241 | | } + | |_____^ +note: called by `::trailing_zeros` + --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:407:5 + | +407 | / int_impl! { +408 | | Self = i64, +409 | | ActualT = i64, +410 | | UnsignedT = u64, +... | +425 | | bound_condition = "", +426 | | } + | |_____^ +note: called by `trailing_zeros::trailing_zeros_i64` + --> $DIR/trailing_zeros.rs:68:12 + | +68 | *out = i64::trailing_zeros(*buffer); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: called by `trailing_zeros_i64` + --> $DIR/trailing_zeros.rs:64:8 + | +64 | pub fn trailing_zeros_i64( + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + From 70507e96ce5318dccf5b02a30fb1e50da5d30b1b Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Mon, 10 Feb 2025 12:39:21 +0100 Subject: [PATCH 03/15] leading_zeros: support 8bit, 16bit and emulate 64bit --- .../src/builder/intrinsics.rs | 88 +++++- tests/ui/lang/u32/leading_zeros.stderr | 251 ------------------ tests/ui/lang/u32/trailing_zeros.stderr | 251 ------------------ 3 files changed, 75 insertions(+), 515 deletions(-) delete mode 100644 tests/ui/lang/u32/leading_zeros.stderr delete mode 100644 tests/ui/lang/u32/trailing_zeros.stderr diff --git a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs index e0eab8341c..f6c0dd40ca 100644 --- a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs +++ b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs @@ -383,10 +383,9 @@ impl Builder<'_, '_> { ) -> SpirvValue { let ty = arg.ty; match self.cx.lookup_type(ty) { - SpirvType::Integer(bits, _) => { - let int_0 = self.constant_int(ty, 0); - let int_bits = self.constant_int(ty, bits as u128).def(self); + SpirvType::Integer(bits, signed) => { let bool = SpirvType::Bool.def(self.span(), self); + let u32 = SpirvType::Integer(32, false).def(self.span(), self); let gl_op = if trailing { // rust is always unsigned @@ -396,24 +395,87 @@ impl Builder<'_, '_> { }; let glsl = self.ext_inst.borrow_mut().import_glsl(self); - let find_xsb = self - .emit() - .ext_inst(ty, None, glsl, gl_op as u32, [Operand::IdRef( - arg.def(self), - )]) - .unwrap(); + let find_xsb = |arg| { + self.emit() + .ext_inst(u32, None, glsl, gl_op as u32, [Operand::IdRef(arg)]) + .unwrap() + }; + + let converted = match bits { + 8 | 16 => { + if trailing { + let arg = self.emit().s_convert(u32, None, arg.def(self)).unwrap(); + find_xsb(arg) + } else { + let arg = arg.def(self); + let arg = if signed { + let unsigned = + SpirvType::Integer(bits, false).def(self.span(), self); + self.emit().bitcast(unsigned, None, arg).unwrap() + } else { + arg + }; + let arg = self.emit().u_convert(u32, None, arg).unwrap(); + let xsb = find_xsb(arg); + let subtrahend = self.constant_u32(self.span(), 32 - bits).def(self); + self.emit().i_sub(u32, None, xsb, subtrahend).unwrap() + } + } + 32 => find_xsb(arg.def(self)), + 64 => { + let u32_0 = self.constant_int(u32, 0).def(self); + let u32_32 = self.constant_u32(self.span(), 32).def(self); + + let arg = arg.def(self); + let lower = self.emit().s_convert(u32, None, arg).unwrap(); + let higher = self + .emit() + .shift_left_logical(ty, None, arg, u32_32) + .unwrap(); + let higher = self.emit().s_convert(u32, None, higher).unwrap(); + + let lower_bits = find_xsb(lower); + let higher_bits = find_xsb(higher); + + if trailing { + let use_lower = self.emit().i_equal(bool, None, higher, u32_0).unwrap(); + let lower_bits = + self.emit().i_add(u32, None, lower_bits, u32_32).unwrap(); + self.emit() + .select(u32, None, use_lower, lower_bits, higher_bits) + .unwrap() + } else { + let use_higher = self.emit().i_equal(bool, None, lower, u32_0).unwrap(); + let higher_bits = + self.emit().i_add(u32, None, higher_bits, u32_32).unwrap(); + self.emit() + .select(u32, None, use_higher, higher_bits, lower_bits) + .unwrap() + } + } + _ => { + let undef = self.undef(ty).def(self); + self.zombie(undef, &format!( + "counting leading / trailing zeros on unsupported {ty:?} bit integer type" + )); + undef + } + }; + if non_zero { - find_xsb + converted } else { + let int_0 = self.constant_int(ty, 0).def(self); + let int_bits = self.constant_int(u32, bits as u128).def(self); let is_0 = self .emit() - .i_equal(bool, None, arg.def(self), int_0.def(self)) + .i_equal(bool, None, arg.def(self), int_0) .unwrap(); self.emit() - .select(ty, None, is_0, int_bits, find_xsb) + .select(u32, None, is_0, int_bits, converted) .unwrap() } - .with_type(ty) + .with_type(u32) } _ => self.fatal("counting leading / trailing zeros on a non-integer type"), } diff --git a/tests/ui/lang/u32/leading_zeros.stderr b/tests/ui/lang/u32/leading_zeros.stderr deleted file mode 100644 index da5df187c2..0000000000 --- a/tests/ui/lang/u32/leading_zeros.stderr +++ /dev/null @@ -1,251 +0,0 @@ -error: cannot cast between pointer types - from `*u32` - to `*u8` - --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:535:5 - | -535 | / uint_impl! { -536 | | Self = u8, -537 | | ActualT = u8, -538 | | SignedT = i8, -... | -552 | | bound_condition = "", -553 | | } - | |_____^ - | -note: used from within `::leading_zeros` - --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:535:5 - | -535 | / uint_impl! { -536 | | Self = u8, -537 | | ActualT = u8, -538 | | SignedT = i8, -... | -552 | | bound_condition = "", -553 | | } - | |_____^ -note: called by `leading_zeros::leading_zeros_u8` - --> $DIR/leading_zeros.rs:12:12 - | -12 | *out = u8::leading_zeros(*buffer); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: called by `leading_zeros_u8` - --> $DIR/leading_zeros.rs:8:8 - | -8 | pub fn leading_zeros_u8( - | ^^^^^^^^^^^^^^^^ - -error: cannot cast between pointer types - from `*u32` - to `*u16` - --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1151:5 - | -1151 | / uint_impl! { -1152 | | Self = u16, -1153 | | ActualT = u16, -1154 | | SignedT = i16, -... | -1168 | | bound_condition = "", -1169 | | } - | |_____^ - | -note: used from within `::leading_zeros` - --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1151:5 - | -1151 | / uint_impl! { -1152 | | Self = u16, -1153 | | ActualT = u16, -1154 | | SignedT = i16, -... | -1168 | | bound_condition = "", -1169 | | } - | |_____^ -note: called by `leading_zeros::leading_zeros_u16` - --> $DIR/leading_zeros.rs:20:12 - | -20 | *out = u16::leading_zeros(*buffer); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: called by `leading_zeros_u16` - --> $DIR/leading_zeros.rs:16:8 - | -16 | pub fn leading_zeros_u16( - | ^^^^^^^^^^^^^^^^^ - -error: cannot cast between pointer types - from `*u32` - to `*u64` - --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1223:5 - | -1223 | / uint_impl! { -1224 | | Self = u64, -1225 | | ActualT = u64, -1226 | | SignedT = i64, -... | -1240 | | bound_condition = "", -1241 | | } - | |_____^ - | -note: used from within `::leading_zeros` - --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1223:5 - | -1223 | / uint_impl! { -1224 | | Self = u64, -1225 | | ActualT = u64, -1226 | | SignedT = i64, -... | -1240 | | bound_condition = "", -1241 | | } - | |_____^ -note: called by `leading_zeros::leading_zeros_u64` - --> $DIR/leading_zeros.rs:36:12 - | -36 | *out = u64::leading_zeros(*buffer); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: called by `leading_zeros_u64` - --> $DIR/leading_zeros.rs:32:8 - | -32 | pub fn leading_zeros_u64( - | ^^^^^^^^^^^^^^^^^ - -error: cannot cast between pointer types - from `*u32` - to `*u8` - --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:535:5 - | -535 | / uint_impl! { -536 | | Self = u8, -537 | | ActualT = u8, -538 | | SignedT = i8, -... | -552 | | bound_condition = "", -553 | | } - | |_____^ - | -note: used from within `::leading_zeros` - --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:535:5 - | -535 | / uint_impl! { -536 | | Self = u8, -537 | | ActualT = u8, -538 | | SignedT = i8, -... | -552 | | bound_condition = "", -553 | | } - | |_____^ -note: called by `::leading_zeros` - --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:335:5 - | -335 | / int_impl! { -336 | | Self = i8, -337 | | ActualT = i8, -338 | | UnsignedT = u8, -... | -353 | | bound_condition = "", -354 | | } - | |_____^ -note: called by `leading_zeros::leading_zeros_i8` - --> $DIR/leading_zeros.rs:44:12 - | -44 | *out = i8::leading_zeros(*buffer); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: called by `leading_zeros_i8` - --> $DIR/leading_zeros.rs:40:8 - | -40 | pub fn leading_zeros_i8( - | ^^^^^^^^^^^^^^^^ - -error: cannot cast between pointer types - from `*u32` - to `*u16` - --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1151:5 - | -1151 | / uint_impl! { -1152 | | Self = u16, -1153 | | ActualT = u16, -1154 | | SignedT = i16, -... | -1168 | | bound_condition = "", -1169 | | } - | |_____^ - | -note: used from within `::leading_zeros` - --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1151:5 - | -1151 | / uint_impl! { -1152 | | Self = u16, -1153 | | ActualT = u16, -1154 | | SignedT = i16, -... | -1168 | | bound_condition = "", -1169 | | } - | |_____^ -note: called by `::leading_zeros` - --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:359:5 - | -359 | / int_impl! { -360 | | Self = i16, -361 | | ActualT = i16, -362 | | UnsignedT = u16, -... | -377 | | bound_condition = "", -378 | | } - | |_____^ -note: called by `leading_zeros::leading_zeros_i16` - --> $DIR/leading_zeros.rs:52:12 - | -52 | *out = i16::leading_zeros(*buffer); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: called by `leading_zeros_i16` - --> $DIR/leading_zeros.rs:48:8 - | -48 | pub fn leading_zeros_i16( - | ^^^^^^^^^^^^^^^^^ - -error: cannot cast between pointer types - from `*u32` - to `*u64` - --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1223:5 - | -1223 | / uint_impl! { -1224 | | Self = u64, -1225 | | ActualT = u64, -1226 | | SignedT = i64, -... | -1240 | | bound_condition = "", -1241 | | } - | |_____^ - | -note: used from within `::leading_zeros` - --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1223:5 - | -1223 | / uint_impl! { -1224 | | Self = u64, -1225 | | ActualT = u64, -1226 | | SignedT = i64, -... | -1240 | | bound_condition = "", -1241 | | } - | |_____^ -note: called by `::leading_zeros` - --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:407:5 - | -407 | / int_impl! { -408 | | Self = i64, -409 | | ActualT = i64, -410 | | UnsignedT = u64, -... | -425 | | bound_condition = "", -426 | | } - | |_____^ -note: called by `leading_zeros::leading_zeros_i64` - --> $DIR/leading_zeros.rs:68:12 - | -68 | *out = i64::leading_zeros(*buffer); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: called by `leading_zeros_i64` - --> $DIR/leading_zeros.rs:64:8 - | -64 | pub fn leading_zeros_i64( - | ^^^^^^^^^^^^^^^^^ - -error: aborting due to 6 previous errors - diff --git a/tests/ui/lang/u32/trailing_zeros.stderr b/tests/ui/lang/u32/trailing_zeros.stderr deleted file mode 100644 index cfa1090bef..0000000000 --- a/tests/ui/lang/u32/trailing_zeros.stderr +++ /dev/null @@ -1,251 +0,0 @@ -error: cannot cast between pointer types - from `*u32` - to `*u8` - --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:535:5 - | -535 | / uint_impl! { -536 | | Self = u8, -537 | | ActualT = u8, -538 | | SignedT = i8, -... | -552 | | bound_condition = "", -553 | | } - | |_____^ - | -note: used from within `::trailing_zeros` - --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:535:5 - | -535 | / uint_impl! { -536 | | Self = u8, -537 | | ActualT = u8, -538 | | SignedT = i8, -... | -552 | | bound_condition = "", -553 | | } - | |_____^ -note: called by `trailing_zeros::trailing_zeros_u8` - --> $DIR/trailing_zeros.rs:12:12 - | -12 | *out = u8::trailing_zeros(*buffer); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: called by `trailing_zeros_u8` - --> $DIR/trailing_zeros.rs:8:8 - | -8 | pub fn trailing_zeros_u8( - | ^^^^^^^^^^^^^^^^^ - -error: cannot cast between pointer types - from `*u32` - to `*u16` - --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1151:5 - | -1151 | / uint_impl! { -1152 | | Self = u16, -1153 | | ActualT = u16, -1154 | | SignedT = i16, -... | -1168 | | bound_condition = "", -1169 | | } - | |_____^ - | -note: used from within `::trailing_zeros` - --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1151:5 - | -1151 | / uint_impl! { -1152 | | Self = u16, -1153 | | ActualT = u16, -1154 | | SignedT = i16, -... | -1168 | | bound_condition = "", -1169 | | } - | |_____^ -note: called by `trailing_zeros::trailing_zeros_u16` - --> $DIR/trailing_zeros.rs:20:12 - | -20 | *out = u16::trailing_zeros(*buffer); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: called by `trailing_zeros_u16` - --> $DIR/trailing_zeros.rs:16:8 - | -16 | pub fn trailing_zeros_u16( - | ^^^^^^^^^^^^^^^^^^ - -error: cannot cast between pointer types - from `*u32` - to `*u64` - --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1223:5 - | -1223 | / uint_impl! { -1224 | | Self = u64, -1225 | | ActualT = u64, -1226 | | SignedT = i64, -... | -1240 | | bound_condition = "", -1241 | | } - | |_____^ - | -note: used from within `::trailing_zeros` - --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1223:5 - | -1223 | / uint_impl! { -1224 | | Self = u64, -1225 | | ActualT = u64, -1226 | | SignedT = i64, -... | -1240 | | bound_condition = "", -1241 | | } - | |_____^ -note: called by `trailing_zeros::trailing_zeros_u64` - --> $DIR/trailing_zeros.rs:36:12 - | -36 | *out = u64::trailing_zeros(*buffer); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: called by `trailing_zeros_u64` - --> $DIR/trailing_zeros.rs:32:8 - | -32 | pub fn trailing_zeros_u64( - | ^^^^^^^^^^^^^^^^^^ - -error: cannot cast between pointer types - from `*u32` - to `*u8` - --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:535:5 - | -535 | / uint_impl! { -536 | | Self = u8, -537 | | ActualT = u8, -538 | | SignedT = i8, -... | -552 | | bound_condition = "", -553 | | } - | |_____^ - | -note: used from within `::trailing_zeros` - --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:535:5 - | -535 | / uint_impl! { -536 | | Self = u8, -537 | | ActualT = u8, -538 | | SignedT = i8, -... | -552 | | bound_condition = "", -553 | | } - | |_____^ -note: called by `::trailing_zeros` - --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:335:5 - | -335 | / int_impl! { -336 | | Self = i8, -337 | | ActualT = i8, -338 | | UnsignedT = u8, -... | -353 | | bound_condition = "", -354 | | } - | |_____^ -note: called by `trailing_zeros::trailing_zeros_i8` - --> $DIR/trailing_zeros.rs:44:12 - | -44 | *out = i8::trailing_zeros(*buffer); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: called by `trailing_zeros_i8` - --> $DIR/trailing_zeros.rs:40:8 - | -40 | pub fn trailing_zeros_i8( - | ^^^^^^^^^^^^^^^^^ - -error: cannot cast between pointer types - from `*u32` - to `*u16` - --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1151:5 - | -1151 | / uint_impl! { -1152 | | Self = u16, -1153 | | ActualT = u16, -1154 | | SignedT = i16, -... | -1168 | | bound_condition = "", -1169 | | } - | |_____^ - | -note: used from within `::trailing_zeros` - --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1151:5 - | -1151 | / uint_impl! { -1152 | | Self = u16, -1153 | | ActualT = u16, -1154 | | SignedT = i16, -... | -1168 | | bound_condition = "", -1169 | | } - | |_____^ -note: called by `::trailing_zeros` - --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:359:5 - | -359 | / int_impl! { -360 | | Self = i16, -361 | | ActualT = i16, -362 | | UnsignedT = u16, -... | -377 | | bound_condition = "", -378 | | } - | |_____^ -note: called by `trailing_zeros::trailing_zeros_i16` - --> $DIR/trailing_zeros.rs:52:12 - | -52 | *out = i16::trailing_zeros(*buffer); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: called by `trailing_zeros_i16` - --> $DIR/trailing_zeros.rs:48:8 - | -48 | pub fn trailing_zeros_i16( - | ^^^^^^^^^^^^^^^^^^ - -error: cannot cast between pointer types - from `*u32` - to `*u64` - --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1223:5 - | -1223 | / uint_impl! { -1224 | | Self = u64, -1225 | | ActualT = u64, -1226 | | SignedT = i64, -... | -1240 | | bound_condition = "", -1241 | | } - | |_____^ - | -note: used from within `::trailing_zeros` - --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:1223:5 - | -1223 | / uint_impl! { -1224 | | Self = u64, -1225 | | ActualT = u64, -1226 | | SignedT = i64, -... | -1240 | | bound_condition = "", -1241 | | } - | |_____^ -note: called by `::trailing_zeros` - --> /home/firestar99/.rustup/toolchains/nightly-2024-11-22-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/num/mod.rs:407:5 - | -407 | / int_impl! { -408 | | Self = i64, -409 | | ActualT = i64, -410 | | UnsignedT = u64, -... | -425 | | bound_condition = "", -426 | | } - | |_____^ -note: called by `trailing_zeros::trailing_zeros_i64` - --> $DIR/trailing_zeros.rs:68:12 - | -68 | *out = i64::trailing_zeros(*buffer); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: called by `trailing_zeros_i64` - --> $DIR/trailing_zeros.rs:64:8 - | -64 | pub fn trailing_zeros_i64( - | ^^^^^^^^^^^^^^^^^^ - -error: aborting due to 6 previous errors - From 31ce03faa3a396bcd3c929334f94d497f68f8021 Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Mon, 10 Feb 2025 15:14:40 +0100 Subject: [PATCH 04/15] leading_zeros: fix unused warning for `enabled_extensions` --- .../rustc_codegen_spirv/src/builder_spirv.rs | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/builder_spirv.rs b/crates/rustc_codegen_spirv/src/builder_spirv.rs index 3c91b48872..4c87f0584d 100644 --- a/crates/rustc_codegen_spirv/src/builder_spirv.rs +++ b/crates/rustc_codegen_spirv/src/builder_spirv.rs @@ -425,7 +425,6 @@ pub struct BuilderSpirv<'tcx> { debug_file_cache: RefCell>>, enabled_capabilities: FxHashSet, - enabled_extensions: FxHashSet, } impl<'tcx> BuilderSpirv<'tcx> { @@ -443,7 +442,6 @@ impl<'tcx> BuilderSpirv<'tcx> { builder.module_mut().header.as_mut().unwrap().generator = 0x001B_0000; let mut enabled_capabilities = FxHashSet::default(); - let mut enabled_extensions = FxHashSet::default(); fn add_cap( builder: &mut Builder, @@ -455,11 +453,10 @@ impl<'tcx> BuilderSpirv<'tcx> { builder.capability(cap); enabled_capabilities.insert(cap); } - fn add_ext(builder: &mut Builder, enabled_extensions: &mut FxHashSet, ext: Symbol) { + fn add_ext(builder: &mut Builder, ext: Symbol) { // This should be the only callsite of Builder::extension (aside from tests), to make // sure the hashset stays in sync. builder.extension(ext.as_str()); - enabled_extensions.insert(ext); } for feature in features { @@ -468,7 +465,7 @@ impl<'tcx> BuilderSpirv<'tcx> { add_cap(&mut builder, &mut enabled_capabilities, cap); } TargetFeature::Extension(ext) => { - add_ext(&mut builder, &mut enabled_extensions, ext); + add_ext(&mut builder, ext); } } } @@ -476,11 +473,7 @@ impl<'tcx> BuilderSpirv<'tcx> { add_cap(&mut builder, &mut enabled_capabilities, Capability::Shader); if memory_model == MemoryModel::Vulkan { if version < (1, 5) { - add_ext( - &mut builder, - &mut enabled_extensions, - sym.spv_khr_vulkan_memory_model, - ); + add_ext(&mut builder, sym.spv_khr_vulkan_memory_model); } add_cap( &mut builder, @@ -502,7 +495,6 @@ impl<'tcx> BuilderSpirv<'tcx> { id_to_const: Default::default(), debug_file_cache: Default::default(), enabled_capabilities, - enabled_extensions, } } @@ -541,10 +533,6 @@ impl<'tcx> BuilderSpirv<'tcx> { self.enabled_capabilities.contains(&capability) } - pub fn has_extension(&self, extension: Symbol) -> bool { - self.enabled_extensions.contains(&extension) - } - pub fn select_function_by_id(&self, id: Word) -> BuilderCursor { let mut builder = self.builder.borrow_mut(); for (index, func) in builder.module_ref().functions.iter().enumerate() { From 7d3452c06a972b64a226e22d08273140acd8e9b0 Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Mon, 10 Feb 2025 14:38:52 +0100 Subject: [PATCH 05/15] count_ones: add failing tests for count_ones and bit_reverse --- tests/ui/lang/u32/bit_reverse.rs | 69 ++++++++++++++++++++++++++++++++ tests/ui/lang/u32/count_ones.rs | 69 ++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 tests/ui/lang/u32/bit_reverse.rs create mode 100644 tests/ui/lang/u32/count_ones.rs diff --git a/tests/ui/lang/u32/bit_reverse.rs b/tests/ui/lang/u32/bit_reverse.rs new file mode 100644 index 0000000000..41bfa8aac1 --- /dev/null +++ b/tests/ui/lang/u32/bit_reverse.rs @@ -0,0 +1,69 @@ +// Test all trailing and leading zeros. No need to test ones, they just call the zero variant with !value + +// build-pass + +use spirv_std::spirv; + +#[spirv(fragment)] +pub fn count_zeros_u8( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &u8, + out: &mut u8, +) { + *out = u8::reverse_bits(*buffer); +} + +#[spirv(fragment)] +pub fn count_zeros_u16( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &u16, + out: &mut u16, +) { + *out = u16::reverse_bits(*buffer); +} + +#[spirv(fragment)] +pub fn count_zeros_u32( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &u32, + out: &mut u32, +) { + *out = u32::reverse_bits(*buffer); +} + +#[spirv(fragment)] +pub fn count_zeros_u64( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &u64, + out: &mut u64, +) { + *out = u64::reverse_bits(*buffer); +} + +#[spirv(fragment)] +pub fn count_zeros_i8( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &i8, + out: &mut i8, +) { + *out = i8::reverse_bits(*buffer); +} + +#[spirv(fragment)] +pub fn count_zeros_i16( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &i16, + out: &mut i16, +) { + *out = i16::reverse_bits(*buffer); +} + +#[spirv(fragment)] +pub fn count_zeros_i32( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &i32, + out: &mut i32, +) { + *out = i32::reverse_bits(*buffer); +} + +#[spirv(fragment)] +pub fn count_zeros_i64( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &i64, + out: &mut i64, +) { + *out = i64::reverse_bits(*buffer); +} diff --git a/tests/ui/lang/u32/count_ones.rs b/tests/ui/lang/u32/count_ones.rs new file mode 100644 index 0000000000..11058eea4c --- /dev/null +++ b/tests/ui/lang/u32/count_ones.rs @@ -0,0 +1,69 @@ +// Test all trailing and leading zeros. No need to test ones, they just call the zero variant with !value + +// build-pass + +use spirv_std::spirv; + +#[spirv(fragment)] +pub fn count_ones_u8( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &u8, + out: &mut u32, +) { + *out = u8::count_ones(*buffer); +} + +#[spirv(fragment)] +pub fn count_ones_u16( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &u16, + out: &mut u32, +) { + *out = u16::count_ones(*buffer); +} + +#[spirv(fragment)] +pub fn count_ones_u32( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &u32, + out: &mut u32, +) { + *out = u32::count_ones(*buffer); +} + +#[spirv(fragment)] +pub fn count_ones_u64( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &u64, + out: &mut u32, +) { + *out = u64::count_ones(*buffer); +} + +#[spirv(fragment)] +pub fn count_ones_i8( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &i8, + out: &mut u32, +) { + *out = i8::count_ones(*buffer); +} + +#[spirv(fragment)] +pub fn count_ones_i16( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &i16, + out: &mut u32, +) { + *out = i16::count_ones(*buffer); +} + +#[spirv(fragment)] +pub fn count_ones_i32( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &i32, + out: &mut u32, +) { + *out = i32::count_ones(*buffer); +} + +#[spirv(fragment)] +pub fn count_ones_i64( + #[spirv(descriptor_set = 0, binding = 0, storage_buffer)] buffer: &i64, + out: &mut u32, +) { + *out = i64::count_ones(*buffer); +} From 5083b9e0df025dd710783b93b0c43480a6af34fd Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Mon, 10 Feb 2025 14:39:09 +0100 Subject: [PATCH 06/15] count_ones: fix pointer cast errors --- crates/rustc_codegen_spirv/src/builder/intrinsics.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs index f6c0dd40ca..c1eac867f3 100644 --- a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs +++ b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs @@ -218,11 +218,13 @@ impl<'a, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'tcx> { sym::cttz => self.count_leading_trailing_zeros(args[0].immediate(), true, false), sym::cttz_nonzero => self.count_leading_trailing_zeros(args[0].immediate(), true, true), - sym::ctpop => self - .emit() - .bit_count(args[0].immediate().ty, None, args[0].immediate().def(self)) - .unwrap() - .with_type(args[0].immediate().ty), + sym::ctpop => { + let u32 = SpirvType::Integer(32, false).def(self.span(), self); + self.emit() + .bit_count(u32, None, args[0].immediate().def(self)) + .unwrap() + .with_type(u32) + } sym::bitreverse => self .emit() .bit_reverse(args[0].immediate().ty, None, args[0].immediate().def(self)) From 4c046f73eda11f052477c7100c632baf0b9f60ae Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Mon, 10 Feb 2025 14:52:48 +0100 Subject: [PATCH 07/15] count_ones: fix count_ones, must be u32-only in vulkan --- .../src/builder/intrinsics.rs | 56 ++++++++++++++++--- 1 file changed, 49 insertions(+), 7 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs index c1eac867f3..aff86c76bb 100644 --- a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs +++ b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs @@ -218,13 +218,7 @@ impl<'a, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'tcx> { sym::cttz => self.count_leading_trailing_zeros(args[0].immediate(), true, false), sym::cttz_nonzero => self.count_leading_trailing_zeros(args[0].immediate(), true, true), - sym::ctpop => { - let u32 = SpirvType::Integer(32, false).def(self.span(), self); - self.emit() - .bit_count(u32, None, args[0].immediate().def(self)) - .unwrap() - .with_type(u32) - } + sym::ctpop => self.count_ones(args[0].immediate()), sym::bitreverse => self .emit() .bit_reverse(args[0].immediate().ty, None, args[0].immediate().def(self)) @@ -377,6 +371,54 @@ impl<'a, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'tcx> { } impl Builder<'_, '_> { + pub fn count_ones(&self, arg: SpirvValue) -> SpirvValue { + let ty = arg.ty; + match self.cx.lookup_type(ty) { + SpirvType::Integer(bits, signed) => { + let u32 = SpirvType::Integer(32, false).def(self.span(), self); + + match bits { + 8 | 16 => { + let arg = arg.def(self); + let arg = if signed { + let unsigned = + SpirvType::Integer(bits, false).def(self.span(), self); + self.emit().bitcast(unsigned, None, arg).unwrap() + } else { + arg + }; + let arg = self.emit().u_convert(u32, None, arg).unwrap(); + self.emit().bit_count(u32, None, arg).unwrap() + } + 32 => self.emit().bit_count(u32, None, arg.def(self)).unwrap(), + 64 => { + let u32_32 = self.constant_u32(self.span(), 32).def(self); + let arg = arg.def(self); + let lower = self.emit().s_convert(u32, None, arg).unwrap(); + let higher = self + .emit() + .shift_left_logical(ty, None, arg, u32_32) + .unwrap(); + let higher = self.emit().s_convert(u32, None, higher).unwrap(); + + let lower_bits = self.emit().bit_count(u32, None, lower).unwrap(); + let higher_bits = self.emit().bit_count(u32, None, higher).unwrap(); + self.emit().i_add(u32, None, lower_bits, higher_bits).unwrap() + } + _ => { + let undef = self.undef(ty).def(self); + self.zombie(undef, &format!( + "counting leading / trailing zeros on unsupported {ty:?} bit integer type" + )); + undef + } + } + .with_type(u32) + } + _ => self.fatal("count_ones on a non-integer type"), + } + } + pub fn count_leading_trailing_zeros( &self, arg: SpirvValue, From 6733b1ad5e542598212f6a5b7be370272015b0e5 Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Mon, 10 Feb 2025 15:10:39 +0100 Subject: [PATCH 08/15] count_ones: fix bit_reverse, must be u32-only in vulkan --- .../src/builder/intrinsics.rs | 78 +++++++++++++++++-- 1 file changed, 73 insertions(+), 5 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs index aff86c76bb..e1e35b0eb4 100644 --- a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs +++ b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs @@ -219,11 +219,7 @@ impl<'a, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'tcx> { sym::cttz_nonzero => self.count_leading_trailing_zeros(args[0].immediate(), true, true), sym::ctpop => self.count_ones(args[0].immediate()), - sym::bitreverse => self - .emit() - .bit_reverse(args[0].immediate().ty, None, args[0].immediate().def(self)) - .unwrap() - .with_type(args[0].immediate().ty), + sym::bitreverse => self.bit_reverse(args[0].immediate()), sym::bswap => { // https://github.com/KhronosGroup/SPIRV-LLVM/pull/221/files // TODO: Definitely add tests to make sure this impl is right. @@ -418,6 +414,78 @@ impl Builder<'_, '_> { _ => self.fatal("count_ones on a non-integer type"), } } + pub fn bit_reverse(&self, arg: SpirvValue) -> SpirvValue { + let ty = arg.ty; + match self.cx.lookup_type(ty) { + SpirvType::Integer(bits, signed) => { + let u32 = SpirvType::Integer(32, false).def(self.span(), self); + let uint = SpirvType::Integer(bits, false).def(self.span(), self); + + match (bits, signed) { + (8 | 16, signed) => { + let arg = arg.def(self); + let arg = if signed { + self.emit().bitcast(uint, None, arg).unwrap() + } else { + arg + }; + let arg = self.emit().u_convert(u32, None, arg).unwrap(); + + let reverse = self.emit().bit_reverse(u32, None, arg).unwrap(); + let shift = self.constant_u32(self.span(), 32 - bits).def(self); + let reverse = self.emit().shift_right_logical(u32, None, reverse, shift).unwrap(); + let reverse = self.emit().u_convert(uint, None, reverse).unwrap(); + if signed { + self.emit().bitcast(ty, None, reverse).unwrap() + } else { + reverse + } + } + (32, false) => self.emit().bit_reverse(u32, None, arg.def(self)).unwrap(), + (32, true) => { + let arg = self.emit().bitcast(u32, None, arg.def(self)).unwrap(); + let reverse = self.emit().bit_reverse(u32, None, arg).unwrap(); + self.emit().bitcast(ty, None, reverse).unwrap() + }, + (64, signed) => { + let u32_32 = self.constant_u32(self.span(), 32).def(self); + let arg = arg.def(self); + let lower = self.emit().s_convert(u32, None, arg).unwrap(); + let higher = self + .emit() + .shift_left_logical(ty, None, arg, u32_32) + .unwrap(); + let higher = self.emit().s_convert(u32, None, higher).unwrap(); + + // note that higher and lower have swapped + let higher_bits = self.emit().bit_reverse(u32, None, lower).unwrap(); + let lower_bits = self.emit().bit_reverse(u32, None, higher).unwrap(); + + let higher_bits = self.emit().u_convert(uint, None, higher_bits).unwrap(); + let shift = self.constant_u32(self.span(), 32).def(self); + let higher_bits = self.emit().shift_right_logical(uint, None, higher_bits, shift).unwrap(); + let lower_bits = self.emit().u_convert(uint, None, lower_bits).unwrap(); + + let result = self.emit().bitwise_or(ty, None, lower_bits, higher_bits).unwrap(); + if signed { + self.emit().bitcast(ty, None, result).unwrap() + } else { + result + } + } + _ => { + let undef = self.undef(ty).def(self); + self.zombie(undef, &format!( + "counting leading / trailing zeros on unsupported {ty:?} bit integer type" + )); + undef + } + } + .with_type(ty) + } + _ => self.fatal("count_ones on a non-integer type"), + } + } pub fn count_leading_trailing_zeros( &self, From ef1d3ffc1e46b754c8cf2452e4956ab8e163ee99 Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Thu, 13 Mar 2025 18:26:26 +0100 Subject: [PATCH 09/15] count_ones: fix u64 bitshifts in all new functions --- crates/rustc_codegen_spirv/src/builder/intrinsics.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs index e1e35b0eb4..1389de1738 100644 --- a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs +++ b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs @@ -393,7 +393,7 @@ impl Builder<'_, '_> { let lower = self.emit().s_convert(u32, None, arg).unwrap(); let higher = self .emit() - .shift_left_logical(ty, None, arg, u32_32) + .shift_right_logical(ty, None, arg, u32_32) .unwrap(); let higher = self.emit().s_convert(u32, None, higher).unwrap(); @@ -414,6 +414,7 @@ impl Builder<'_, '_> { _ => self.fatal("count_ones on a non-integer type"), } } + pub fn bit_reverse(&self, arg: SpirvValue) -> SpirvValue { let ty = arg.ty; match self.cx.lookup_type(ty) { @@ -453,7 +454,7 @@ impl Builder<'_, '_> { let lower = self.emit().s_convert(u32, None, arg).unwrap(); let higher = self .emit() - .shift_left_logical(ty, None, arg, u32_32) + .shift_right_logical(ty, None, arg, u32_32) .unwrap(); let higher = self.emit().s_convert(u32, None, higher).unwrap(); @@ -463,7 +464,7 @@ impl Builder<'_, '_> { let higher_bits = self.emit().u_convert(uint, None, higher_bits).unwrap(); let shift = self.constant_u32(self.span(), 32).def(self); - let higher_bits = self.emit().shift_right_logical(uint, None, higher_bits, shift).unwrap(); + let higher_bits = self.emit().shift_left_logical(uint, None, higher_bits, shift).unwrap(); let lower_bits = self.emit().u_convert(uint, None, lower_bits).unwrap(); let result = self.emit().bitwise_or(ty, None, lower_bits, higher_bits).unwrap(); @@ -542,7 +543,7 @@ impl Builder<'_, '_> { let lower = self.emit().s_convert(u32, None, arg).unwrap(); let higher = self .emit() - .shift_left_logical(ty, None, arg, u32_32) + .shift_right_logical(ty, None, arg, u32_32) .unwrap(); let higher = self.emit().s_convert(u32, None, higher).unwrap(); From ac49f2fc846f3cab2e901e2a1ea1e5761d5f9c2b Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Thu, 13 Mar 2025 18:26:59 +0100 Subject: [PATCH 10/15] count_ones: fix mismatched error messages to methods containing them --- crates/rustc_codegen_spirv/src/builder/intrinsics.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs index 1389de1738..58b8d9057c 100644 --- a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs +++ b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs @@ -404,14 +404,14 @@ impl Builder<'_, '_> { _ => { let undef = self.undef(ty).def(self); self.zombie(undef, &format!( - "counting leading / trailing zeros on unsupported {ty:?} bit integer type" + "count_ones() on unsupported {ty:?} bit integer type" )); undef } } .with_type(u32) } - _ => self.fatal("count_ones on a non-integer type"), + _ => self.fatal("count_ones() on a non-integer type"), } } @@ -477,14 +477,14 @@ impl Builder<'_, '_> { _ => { let undef = self.undef(ty).def(self); self.zombie(undef, &format!( - "counting leading / trailing zeros on unsupported {ty:?} bit integer type" + "bit_reverse() on unsupported {ty:?} bit integer type" )); undef } } .with_type(ty) } - _ => self.fatal("count_ones on a non-integer type"), + _ => self.fatal("bit_reverse() on a non-integer type"), } } @@ -569,7 +569,7 @@ impl Builder<'_, '_> { _ => { let undef = self.undef(ty).def(self); self.zombie(undef, &format!( - "counting leading / trailing zeros on unsupported {ty:?} bit integer type" + "count_leading_trailing_zeros() on unsupported {ty:?} bit integer type" )); undef } @@ -590,7 +590,7 @@ impl Builder<'_, '_> { } .with_type(u32) } - _ => self.fatal("counting leading / trailing zeros on a non-integer type"), + _ => self.fatal("count_leading_trailing_zeros() on a non-integer type"), } } From 144952758aca3a2599ce6f801370878065815253 Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Thu, 13 Mar 2025 18:30:43 +0100 Subject: [PATCH 11/15] count_ones: cargo fmt --- .../src/builder/intrinsics.rs | 42 ++++++++++++------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs index 58b8d9057c..16fbbd65cd 100644 --- a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs +++ b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs @@ -377,8 +377,7 @@ impl Builder<'_, '_> { 8 | 16 => { let arg = arg.def(self); let arg = if signed { - let unsigned = - SpirvType::Integer(bits, false).def(self.span(), self); + let unsigned = SpirvType::Integer(bits, false).def(self.span(), self); self.emit().bitcast(unsigned, None, arg).unwrap() } else { arg @@ -399,17 +398,20 @@ impl Builder<'_, '_> { let lower_bits = self.emit().bit_count(u32, None, lower).unwrap(); let higher_bits = self.emit().bit_count(u32, None, higher).unwrap(); - self.emit().i_add(u32, None, lower_bits, higher_bits).unwrap() + self.emit() + .i_add(u32, None, lower_bits, higher_bits) + .unwrap() } _ => { let undef = self.undef(ty).def(self); - self.zombie(undef, &format!( - "count_ones() on unsupported {ty:?} bit integer type" - )); + self.zombie( + undef, + &format!("count_ones() on unsupported {ty:?} bit integer type"), + ); undef } } - .with_type(u32) + .with_type(u32) } _ => self.fatal("count_ones() on a non-integer type"), } @@ -434,7 +436,10 @@ impl Builder<'_, '_> { let reverse = self.emit().bit_reverse(u32, None, arg).unwrap(); let shift = self.constant_u32(self.span(), 32 - bits).def(self); - let reverse = self.emit().shift_right_logical(u32, None, reverse, shift).unwrap(); + let reverse = self + .emit() + .shift_right_logical(u32, None, reverse, shift) + .unwrap(); let reverse = self.emit().u_convert(uint, None, reverse).unwrap(); if signed { self.emit().bitcast(ty, None, reverse).unwrap() @@ -447,7 +452,7 @@ impl Builder<'_, '_> { let arg = self.emit().bitcast(u32, None, arg.def(self)).unwrap(); let reverse = self.emit().bit_reverse(u32, None, arg).unwrap(); self.emit().bitcast(ty, None, reverse).unwrap() - }, + } (64, signed) => { let u32_32 = self.constant_u32(self.span(), 32).def(self); let arg = arg.def(self); @@ -464,10 +469,16 @@ impl Builder<'_, '_> { let higher_bits = self.emit().u_convert(uint, None, higher_bits).unwrap(); let shift = self.constant_u32(self.span(), 32).def(self); - let higher_bits = self.emit().shift_left_logical(uint, None, higher_bits, shift).unwrap(); + let higher_bits = self + .emit() + .shift_left_logical(uint, None, higher_bits, shift) + .unwrap(); let lower_bits = self.emit().u_convert(uint, None, lower_bits).unwrap(); - let result = self.emit().bitwise_or(ty, None, lower_bits, higher_bits).unwrap(); + let result = self + .emit() + .bitwise_or(ty, None, lower_bits, higher_bits) + .unwrap(); if signed { self.emit().bitcast(ty, None, result).unwrap() } else { @@ -476,13 +487,14 @@ impl Builder<'_, '_> { } _ => { let undef = self.undef(ty).def(self); - self.zombie(undef, &format!( - "bit_reverse() on unsupported {ty:?} bit integer type" - )); + self.zombie( + undef, + &format!("bit_reverse() on unsupported {ty:?} bit integer type"), + ); undef } } - .with_type(ty) + .with_type(ty) } _ => self.fatal("bit_reverse() on a non-integer type"), } From 57c7d9d0782baf7e693587c7c63c11e88bef9962 Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Fri, 21 Mar 2025 16:35:27 +0100 Subject: [PATCH 12/15] leading_zeros: fix leading zeros for u32 --- .../src/builder/intrinsics.rs | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs index 16fbbd65cd..3ac761a97b 100644 --- a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs +++ b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs @@ -512,18 +512,27 @@ impl Builder<'_, '_> { let bool = SpirvType::Bool.def(self.span(), self); let u32 = SpirvType::Integer(32, false).def(self.span(), self); - let gl_op = if trailing { - // rust is always unsigned - GLOp::FindILsb - } else { - GLOp::FindUMsb - }; - let glsl = self.ext_inst.borrow_mut().import_glsl(self); let find_xsb = |arg| { - self.emit() - .ext_inst(u32, None, glsl, gl_op as u32, [Operand::IdRef(arg)]) - .unwrap() + if trailing { + self.emit() + .ext_inst(u32, None, glsl, GLOp::FindILsb as u32, [Operand::IdRef( + arg, + )]) + .unwrap() + } else { + // rust is always unsigned, so FindUMsb + let bla = self + .emit() + .ext_inst(u32, None, glsl, GLOp::FindUMsb as u32, [Operand::IdRef( + arg, + )]) + .unwrap(); + // the glsl op returns the Msb bit, not the amount of leading zeros of this u32 + // leading zeros = 31 - Msb bit + let u32_31 = self.constant_u32(self.span(), 31).def(self); + self.emit().i_sub(u32, None, u32_31, bla).unwrap() + } }; let converted = match bits { From ee1904b335ea74dc14aa8d765f69b10ff6b6d5ac Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Fri, 21 Mar 2025 22:03:30 +0100 Subject: [PATCH 13/15] leading_zeros: remove sign conversions, always unsigned, except for leading_zeros --- .../src/builder/intrinsics.rs | 85 +++++++++---------- 1 file changed, 38 insertions(+), 47 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs index 3ac761a97b..ac77f7c068 100644 --- a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs +++ b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs @@ -370,18 +370,12 @@ impl Builder<'_, '_> { pub fn count_ones(&self, arg: SpirvValue) -> SpirvValue { let ty = arg.ty; match self.cx.lookup_type(ty) { - SpirvType::Integer(bits, signed) => { + SpirvType::Integer(bits, false) => { let u32 = SpirvType::Integer(32, false).def(self.span(), self); match bits { 8 | 16 => { let arg = arg.def(self); - let arg = if signed { - let unsigned = SpirvType::Integer(bits, false).def(self.span(), self); - self.emit().bitcast(unsigned, None, arg).unwrap() - } else { - arg - }; let arg = self.emit().u_convert(u32, None, arg).unwrap(); self.emit().bit_count(u32, None, arg).unwrap() } @@ -413,25 +407,23 @@ impl Builder<'_, '_> { } .with_type(u32) } - _ => self.fatal("count_ones() on a non-integer type"), + _ => self.fatal(format!( + "count_ones() expected an unsigned integer type, got {:?}", + self.cx.lookup_type(ty) + )), } } pub fn bit_reverse(&self, arg: SpirvValue) -> SpirvValue { let ty = arg.ty; match self.cx.lookup_type(ty) { - SpirvType::Integer(bits, signed) => { + SpirvType::Integer(bits, false) => { let u32 = SpirvType::Integer(32, false).def(self.span(), self); let uint = SpirvType::Integer(bits, false).def(self.span(), self); - match (bits, signed) { - (8 | 16, signed) => { + match bits { + 8 | 16 => { let arg = arg.def(self); - let arg = if signed { - self.emit().bitcast(uint, None, arg).unwrap() - } else { - arg - }; let arg = self.emit().u_convert(u32, None, arg).unwrap(); let reverse = self.emit().bit_reverse(u32, None, arg).unwrap(); @@ -440,20 +432,10 @@ impl Builder<'_, '_> { .emit() .shift_right_logical(u32, None, reverse, shift) .unwrap(); - let reverse = self.emit().u_convert(uint, None, reverse).unwrap(); - if signed { - self.emit().bitcast(ty, None, reverse).unwrap() - } else { - reverse - } - } - (32, false) => self.emit().bit_reverse(u32, None, arg.def(self)).unwrap(), - (32, true) => { - let arg = self.emit().bitcast(u32, None, arg.def(self)).unwrap(); - let reverse = self.emit().bit_reverse(u32, None, arg).unwrap(); - self.emit().bitcast(ty, None, reverse).unwrap() + self.emit().u_convert(uint, None, reverse).unwrap() } - (64, signed) => { + 32 => self.emit().bit_reverse(u32, None, arg.def(self)).unwrap(), + 64 => { let u32_32 = self.constant_u32(self.span(), 32).def(self); let arg = arg.def(self); let lower = self.emit().s_convert(u32, None, arg).unwrap(); @@ -475,15 +457,9 @@ impl Builder<'_, '_> { .unwrap(); let lower_bits = self.emit().u_convert(uint, None, lower_bits).unwrap(); - let result = self - .emit() + self.emit() .bitwise_or(ty, None, lower_bits, higher_bits) - .unwrap(); - if signed { - self.emit().bitcast(ty, None, result).unwrap() - } else { - result - } + .unwrap() } _ => { let undef = self.undef(ty).def(self); @@ -496,7 +472,10 @@ impl Builder<'_, '_> { } .with_type(ty) } - _ => self.fatal("bit_reverse() on a non-integer type"), + _ => self.fatal(format!( + "bit_reverse() expected an unsigned integer type, got {:?}", + self.cx.lookup_type(ty) + )), } } @@ -508,7 +487,7 @@ impl Builder<'_, '_> { ) -> SpirvValue { let ty = arg.ty; match self.cx.lookup_type(ty) { - SpirvType::Integer(bits, signed) => { + SpirvType::Integer(bits, false) => { let bool = SpirvType::Bool.def(self.span(), self); let u32 = SpirvType::Integer(32, false).def(self.span(), self); @@ -542,13 +521,6 @@ impl Builder<'_, '_> { find_xsb(arg) } else { let arg = arg.def(self); - let arg = if signed { - let unsigned = - SpirvType::Integer(bits, false).def(self.span(), self); - self.emit().bitcast(unsigned, None, arg).unwrap() - } else { - arg - }; let arg = self.emit().u_convert(u32, None, arg).unwrap(); let xsb = find_xsb(arg); let subtrahend = self.constant_u32(self.span(), 32 - bits).def(self); @@ -611,7 +583,26 @@ impl Builder<'_, '_> { } .with_type(u32) } - _ => self.fatal("count_leading_trailing_zeros() on a non-integer type"), + SpirvType::Integer(bits, true) => { + // rustc wants `[i8,i16,i32,i64]::leading_zeros()` with `non_zero: true` for some reason. I do not know + // how these are reachable, marking them as zombies makes none of our compiletests fail. + let unsigned = SpirvType::Integer(bits, false).def(self.span(), self); + let arg = self + .emit() + .bitcast(unsigned, None, arg.def(self)) + .unwrap() + .with_type(unsigned); + let result = self.count_leading_trailing_zeros(arg, trailing, non_zero); + self.emit() + .bitcast(ty, None, result.def(self)) + .unwrap() + .with_type(ty) + } + e => { + self.fatal(format!( + "count_leading_trailing_zeros(trailing: {trailing}, non_zero: {non_zero}) expected an integer type, got {e:?}", + )); + } } } From ad3ace99f44fa0c8f31927457391e8ad9e6e4b7d Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Fri, 21 Mar 2025 22:04:16 +0100 Subject: [PATCH 14/15] leading_zeros: make all conversions unsigned --- .../rustc_codegen_spirv/src/builder/intrinsics.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs index ac77f7c068..71034e7697 100644 --- a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs +++ b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs @@ -383,12 +383,12 @@ impl Builder<'_, '_> { 64 => { let u32_32 = self.constant_u32(self.span(), 32).def(self); let arg = arg.def(self); - let lower = self.emit().s_convert(u32, None, arg).unwrap(); + let lower = self.emit().u_convert(u32, None, arg).unwrap(); let higher = self .emit() .shift_right_logical(ty, None, arg, u32_32) .unwrap(); - let higher = self.emit().s_convert(u32, None, higher).unwrap(); + let higher = self.emit().u_convert(u32, None, higher).unwrap(); let lower_bits = self.emit().bit_count(u32, None, lower).unwrap(); let higher_bits = self.emit().bit_count(u32, None, higher).unwrap(); @@ -438,12 +438,12 @@ impl Builder<'_, '_> { 64 => { let u32_32 = self.constant_u32(self.span(), 32).def(self); let arg = arg.def(self); - let lower = self.emit().s_convert(u32, None, arg).unwrap(); + let lower = self.emit().u_convert(u32, None, arg).unwrap(); let higher = self .emit() .shift_right_logical(ty, None, arg, u32_32) .unwrap(); - let higher = self.emit().s_convert(u32, None, higher).unwrap(); + let higher = self.emit().u_convert(u32, None, higher).unwrap(); // note that higher and lower have swapped let higher_bits = self.emit().bit_reverse(u32, None, lower).unwrap(); @@ -517,7 +517,7 @@ impl Builder<'_, '_> { let converted = match bits { 8 | 16 => { if trailing { - let arg = self.emit().s_convert(u32, None, arg.def(self)).unwrap(); + let arg = self.emit().u_convert(u32, None, arg.def(self)).unwrap(); find_xsb(arg) } else { let arg = arg.def(self); @@ -533,12 +533,12 @@ impl Builder<'_, '_> { let u32_32 = self.constant_u32(self.span(), 32).def(self); let arg = arg.def(self); - let lower = self.emit().s_convert(u32, None, arg).unwrap(); + let lower = self.emit().u_convert(u32, None, arg).unwrap(); let higher = self .emit() .shift_right_logical(ty, None, arg, u32_32) .unwrap(); - let higher = self.emit().s_convert(u32, None, higher).unwrap(); + let higher = self.emit().u_convert(u32, None, higher).unwrap(); let lower_bits = find_xsb(lower); let higher_bits = find_xsb(higher); From 00f41df6720e713910e06e52d37fe9ea2200d5fb Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Fri, 21 Mar 2025 22:11:18 +0100 Subject: [PATCH 15/15] leading_zeros: code cleanup --- crates/rustc_codegen_spirv/src/builder/intrinsics.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs index 71034e7697..9fbbf4106e 100644 --- a/crates/rustc_codegen_spirv/src/builder/intrinsics.rs +++ b/crates/rustc_codegen_spirv/src/builder/intrinsics.rs @@ -450,10 +450,9 @@ impl Builder<'_, '_> { let lower_bits = self.emit().bit_reverse(u32, None, higher).unwrap(); let higher_bits = self.emit().u_convert(uint, None, higher_bits).unwrap(); - let shift = self.constant_u32(self.span(), 32).def(self); let higher_bits = self .emit() - .shift_left_logical(uint, None, higher_bits, shift) + .shift_left_logical(uint, None, higher_bits, u32_32) .unwrap(); let lower_bits = self.emit().u_convert(uint, None, lower_bits).unwrap(); @@ -501,7 +500,7 @@ impl Builder<'_, '_> { .unwrap() } else { // rust is always unsigned, so FindUMsb - let bla = self + let msb_bit = self .emit() .ext_inst(u32, None, glsl, GLOp::FindUMsb as u32, [Operand::IdRef( arg, @@ -510,7 +509,7 @@ impl Builder<'_, '_> { // the glsl op returns the Msb bit, not the amount of leading zeros of this u32 // leading zeros = 31 - Msb bit let u32_31 = self.constant_u32(self.span(), 31).def(self); - self.emit().i_sub(u32, None, u32_31, bla).unwrap() + self.emit().i_sub(u32, None, u32_31, msb_bit).unwrap() } };