From 5d4c1bdf4bc2d6f6e7e1d2a45d633b6f42f7ec31 Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Thu, 3 Jul 2025 13:23:57 +0200 Subject: [PATCH 01/12] const folding: better const folding for int and bool --- .../src/builder/builder_methods.rs | 457 ++++++++++++------ 1 file changed, 301 insertions(+), 156 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs index 1fb35929c5..ccbb21053d 100644 --- a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs +++ b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs @@ -33,76 +33,174 @@ use smallvec::SmallVec; use std::borrow::Cow; use std::cell::Cell; use std::iter::{self, empty}; -use std::ops::RangeInclusive; +use std::ops::{BitAnd, BitOr, BitXor, Not, RangeInclusive}; use tracing::{Level, instrument, span}; use tracing::{trace, warn}; +enum ConstValue { + Unsigned(u128), + Signed(i128), + Bool(bool), +} + +impl<'a, 'tcx> Builder<'a, 'tcx> { + fn try_get_const_value(&self, val: SpirvValue) -> Option { + if let Some(const_val) = self.builder.lookup_const(val) { + let x = match const_val { + SpirvConst::Scalar(x) => x, + _ => return None, + }; + match self.lookup_type(val.ty) { + SpirvType::Integer(bits, signed) => { + let size = Size::from_bits(bits); + Some(if signed { + ConstValue::Signed(size.sign_extend(x)) + } else { + ConstValue::Unsigned(size.truncate(x)) + }) + } + SpirvType::Bool => Some(ConstValue::Bool(x != 0)), + _ => None, + } + } else { + None + } + } +} + macro_rules! simple_op { ( - $func_name:ident, $inst_name:ident + $func_name:ident + $(, int: $inst_int:ident)? + $(, uint: $inst_uint:ident)? + $(, sint: $inst_sint:ident)? + $(, float: $inst_float:ident)? + $(, bool: $inst_bool:ident)? $(, fold_const { - $(int($fold_int_lhs:ident, $fold_int_rhs:ident) => $fold_int:expr)? + $(int($int_lhs:ident, $int_rhs:ident) => $fold_int:expr;)? + $(uint($uint_lhs:ident, $uint_rhs:ident) => $fold_uint:expr;)? + $(sint($sint_lhs:ident, $sint_rhs:ident) => $fold_sint:expr;)? + $(bool($bool_lhs:ident, $bool_rhs:ident) => $fold_bool:expr;)? })? ) => { fn $func_name(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { assert_ty_eq!(self, lhs.ty, rhs.ty); let result_type = lhs.ty; - $(if let Some(const_lhs) = self.builder.lookup_const(lhs) { - if let Some(const_rhs) = self.builder.lookup_const(rhs) { - match self.lookup_type(result_type) { - $(SpirvType::Integer(bits, signed) => { - let size = Size::from_bits(bits); - let as_u128 = |const_val| { - let x = match const_val { - SpirvConst::Scalar(x) => x, - _ => return None, - }; - Some(if signed { - size.sign_extend(x) as u128 - } else { - size.truncate(x) - }) - }; - if let Some($fold_int_lhs) = as_u128(const_lhs) { - if let Some($fold_int_rhs) = as_u128(const_rhs) { - return self.const_uint_big(result_type, $fold_int); - } - } - })? - _ => {} + $( + #[allow(unreachable_patterns, clippy::collapsible_match)] + if let Some(const_lhs) = self.try_get_const_value(lhs) + && let Some(const_rhs) = self.try_get_const_value(rhs) + { + #[allow(unreachable_patterns)] + match (const_lhs, const_rhs) { + $( + (ConstValue::Unsigned($int_lhs), ConstValue::Unsigned($int_rhs)) => return self.const_uint_big(result_type, $fold_int), + (ConstValue::Signed($int_lhs), ConstValue::Signed($int_rhs)) => return self.const_uint_big(result_type, $fold_int as u128), + )? + $((ConstValue::Unsigned($uint_lhs), ConstValue::Unsigned($uint_rhs)) => return self.const_uint_big(result_type, $fold_uint), )? + $((ConstValue::Signed($sint_lhs), ConstValue::Signed($sint_rhs)) => return self.const_uint_big(result_type, $fold_sint as u128), )? + $((ConstValue::Bool($bool_lhs), ConstValue::Bool($bool_rhs)) => return self.const_uint_big(result_type, ($fold_bool).into()), )? + _ => (), } } - })? - - self.emit() - .$inst_name(result_type, None, lhs.def(self), rhs.def(self)) - .unwrap() - .with_type(result_type) - } - }; -} - -// shl and shr allow different types as their operands -macro_rules! simple_op_unchecked_type { - ($func_name:ident, $inst_name:ident) => { - fn $func_name(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { - self.emit() - .$inst_name(lhs.ty, None, lhs.def(self), rhs.def(self)) - .unwrap() - .with_type(lhs.ty) + )? + + match self.lookup_type(result_type) { + $(SpirvType::Integer(_, _) => { + self.emit() + .$inst_int(result_type, None, lhs.def(self), rhs.def(self)) + })? + $(SpirvType::Integer(_, false) => { + self.emit() + .$inst_uint(result_type, None, lhs.def(self), rhs.def(self)) + })? + $(SpirvType::Integer(_, true) => { + self.emit() + .$inst_sint(result_type, None, lhs.def(self), rhs.def(self)) + })? + $(SpirvType::Float(_) => { + self.emit() + .$inst_float(result_type, None, lhs.def(self), rhs.def(self)) + })? + $(SpirvType::Bool => { + self.emit() + .$inst_bool(result_type, None, lhs.def(self), rhs.def(self)) + })? + o => self.fatal(format!( + concat!(stringify!($func_name), "() not implemented for type {}"), + o.debug(result_type, self) + )), + } + .unwrap() + .with_type(result_type) } }; } macro_rules! simple_uni_op { - ($func_name:ident, $inst_name:ident) => { + ( + $func_name:ident + $(, int: $inst_int:ident)? + $(, uint: $inst_uint:ident)? + $(, sint: $inst_sint:ident)? + $(, float: $inst_float:ident)? + $(, bool: $inst_bool:ident)? + $(, fold_const { + $(int($int_val:ident) => $fold_int:expr;)? + $(uint($uint_val:ident) => $fold_uint:expr;)? + $(sint($sint_val:ident) => $fold_sint:expr;)? + $(bool($bool_val:ident) => $fold_bool:expr;)? + })? + ) => { fn $func_name(&mut self, val: Self::Value) -> Self::Value { - self.emit() - .$inst_name(val.ty, None, val.def(self)) - .unwrap() - .with_type(val.ty) + let result_type = val.ty; + + $( + #[allow(unreachable_patterns, clippy::collapsible_match)] + if let Some(const_val) = self.try_get_const_value(val) { + match const_val { + $( + ConstValue::Unsigned($int_val) => return self.const_uint_big(result_type, $fold_int), + ConstValue::Signed($int_val) => return self.const_uint_big(result_type, $fold_int as u128), + )? + $(ConstValue::Unsigned($uint_val) => return self.const_uint_big(result_type, $fold_uint), )? + $(ConstValue::Signed($sint_val) => return self.const_uint_big(result_type, $fold_sint as u128), )? + $(ConstValue::Bool($bool_val) => return self.const_uint_big(result_type, ($fold_bool).into()), )? + _ => (), + } + } + )? + + match self.lookup_type(result_type) { + $(SpirvType::Integer(_, _) => { + self.emit() + .$inst_int(result_type, None, val.def(self)) + })? + $(SpirvType::Integer(_, false) => { + self.emit() + .$inst_uint(result_type, None, val.def(self)) + })? + $(SpirvType::Integer(_, true) => { + self.emit() + .$inst_sint(result_type, None, val.def(self)) + })? + $(SpirvType::Float(_) => { + self.emit() + .$inst_float(result_type, None, val.def(self)) + })? + $(SpirvType::Bool => { + self.emit() + .$inst_bool(result_type, None, val.def(self)) + })? + o => self.fatal(format!( + concat!(stringify!($func_name), "() not implemented for type {}"), + o.debug(result_type, self) + )), + } + .unwrap() + .with_type(result_type) } }; } @@ -1357,132 +1455,179 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { self.emit().unreachable().unwrap(); } + // use wrapping_op everywhere, rustc will error out for us if the expr overflows simple_op! { - add, i_add, + add, + int: i_add, fold_const { - int(a, b) => a.wrapping_add(b) + int(a, b) => a.wrapping_add(b); } } // FIXME(eddyb) try to annotate the SPIR-V for `fast` and `algebraic`. - simple_op! {fadd, f_add} - simple_op! {fadd_fast, f_add} // fast=normal - simple_op! {fadd_algebraic, f_add} // algebraic=normal - simple_op! {sub, i_sub} - simple_op! {fsub, f_sub} - simple_op! {fsub_fast, f_sub} // fast=normal - simple_op! {fsub_algebraic, f_sub} // algebraic=normal + simple_op! {fadd, float: f_add} + simple_op! {fadd_fast, float: f_add} // fast=normal + simple_op! {fadd_algebraic, float: f_add} // algebraic=normal + simple_op! { + sub, + int: i_sub, + fold_const { + int(a, b) => a.wrapping_sub(b); + } + } + simple_op! {fsub, float: f_sub} + simple_op! {fsub_fast, float: f_sub} // fast=normal + simple_op! {fsub_algebraic, float: f_sub} // algebraic=normal + simple_op! { + mul, + int: i_mul, + fold_const { + int(a, b) => a.wrapping_mul(b); + } + } + simple_op! {fmul, float: f_mul} + simple_op! {fmul_fast, float: f_mul} // fast=normal + simple_op! {fmul_algebraic, float: f_mul} // algebraic=normal simple_op! { - mul, i_mul, - // HACK(eddyb) `rustc_codegen_ssa` relies on `Builder` methods doing - // on-the-fly constant-folding, for e.g. intrinsics that copy memory. + udiv, + uint: u_div, fold_const { - int(a, b) => a.wrapping_mul(b) + uint(a, b) => a.wrapping_div(b); } } - simple_op! {fmul, f_mul} - simple_op! {fmul_fast, f_mul} // fast=normal - simple_op! {fmul_algebraic, f_mul} // algebraic=normal - simple_op! {udiv, u_div} // Note: exactudiv is UB when there's a remainder, so it's valid to implement as a normal div. // TODO: Can we take advantage of the UB and emit something else? - simple_op! {exactudiv, u_div} - simple_op! {sdiv, s_div} + simple_op! { + exactudiv, + uint: u_div, + fold_const { + uint(a, b) => a.wrapping_div(b); + } + } + simple_op! { + sdiv, + sint: s_div, + fold_const { + sint(a, b) => a.wrapping_div(b); + } + } // Same note and TODO as exactudiv - simple_op! {exactsdiv, s_div} - simple_op! {fdiv, f_div} - simple_op! {fdiv_fast, f_div} // fast=normal - simple_op! {fdiv_algebraic, f_div} // algebraic=normal - simple_op! {urem, u_mod} - simple_op! {srem, s_rem} - simple_op! {frem, f_rem} - simple_op! {frem_fast, f_rem} // fast=normal - simple_op! {frem_algebraic, f_rem} // algebraic=normal - simple_op_unchecked_type! {shl, shift_left_logical} - simple_op_unchecked_type! {lshr, shift_right_logical} - simple_op_unchecked_type! {ashr, shift_right_arithmetic} - simple_op! {unchecked_sadd, i_add} // already unchecked by default - simple_op! {unchecked_uadd, i_add} // already unchecked by default - simple_op! {unchecked_ssub, i_sub} // already unchecked by default - simple_op! {unchecked_usub, i_sub} // already unchecked by default - simple_op! {unchecked_smul, i_mul} // already unchecked by default - simple_op! {unchecked_umul, i_mul} // already unchecked by default - simple_uni_op! {neg, s_negate} - simple_uni_op! {fneg, f_negate} - - fn and(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { - assert_ty_eq!(self, lhs.ty, rhs.ty); - let ty = lhs.ty; - match self.lookup_type(ty) { - SpirvType::Integer(_, _) => { - self.emit() - .bitwise_and(ty, None, lhs.def(self), rhs.def(self)) - } - SpirvType::Bool => self - .emit() - .logical_and(ty, None, lhs.def(self), rhs.def(self)), - o => self.fatal(format!( - "and() not implemented for type {}", - o.debug(ty, self) - )), + simple_op! { + exactsdiv, + sint: s_div, + fold_const { + sint(a, b) => a.wrapping_div(b); } - .unwrap() - .with_type(ty) } - fn or(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { - assert_ty_eq!(self, lhs.ty, rhs.ty); - let ty = lhs.ty; - match self.lookup_type(ty) { - SpirvType::Integer(_, _) => { - self.emit() - .bitwise_or(ty, None, lhs.def(self), rhs.def(self)) - } - SpirvType::Bool => self - .emit() - .logical_or(ty, None, lhs.def(self), rhs.def(self)), - o => self.fatal(format!( - "or() not implemented for type {}", - o.debug(ty, self) - )), + simple_op! {fdiv, float: f_div} + simple_op! {fdiv_fast, float: f_div} // fast=normal + simple_op! {fdiv_algebraic, float: f_div} // algebraic=normal + simple_op! { + urem, + uint: u_mod, + fold_const { + uint(a, b) => a.wrapping_rem(b); } - .unwrap() - .with_type(ty) } - fn xor(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { - assert_ty_eq!(self, lhs.ty, rhs.ty); - let ty = lhs.ty; - match self.lookup_type(ty) { - SpirvType::Integer(_, _) => { - self.emit() - .bitwise_xor(ty, None, lhs.def(self), rhs.def(self)) - } - SpirvType::Bool => { - self.emit() - .logical_not_equal(ty, None, lhs.def(self), rhs.def(self)) - } - o => self.fatal(format!( - "xor() not implemented for type {}", - o.debug(ty, self) - )), + simple_op! { + srem, + sint: s_rem, + fold_const { + sint(a, b) => a.wrapping_rem(b); + } + } + simple_op! {frem, float: f_rem} + simple_op! {frem_fast, float: f_rem} // fast=normal + simple_op! {frem_algebraic, float: f_rem} // algebraic=normal + simple_shift_op! { + shl, + int: shift_left_logical + // fold_const { + // int(a, b) => a.wrapping_shl(b as u32); + // } + } + simple_shift_op! { + lshr, + int: shift_right_logical + // fold_const { + // int(a, b) => a.wrapping_shr(b as u32); + // } + } + simple_shift_op! { + ashr, + int: shift_right_arithmetic + // fold_const { + // int(a, b) => a.wrapping_shr(b as u32); + // } + } + simple_uni_op! { + neg, + sint: s_negate, + fold_const { + sint(a) => a.wrapping_neg(); } - .unwrap() - .with_type(ty) } - fn not(&mut self, val: Self::Value) -> Self::Value { - match self.lookup_type(val.ty) { - SpirvType::Integer(_, _) => self.emit().not(val.ty, None, val.def(self)), - SpirvType::Bool => { - let true_ = self.constant_bool(self.span(), true); - // intel-compute-runtime doesn't like OpLogicalNot - self.emit() - .logical_not_equal(val.ty, None, val.def(self), true_.def(self)) - } - o => self.fatal(format!( - "not() not implemented for type {}", - o.debug(val.ty, self) - )), + simple_uni_op! {fneg, float: f_negate} + + /// already unchecked by default + fn unchecked_sadd(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { + self.add(lhs, rhs) + } + /// already unchecked by default + fn unchecked_uadd(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { + self.add(lhs, rhs) + } + /// already unchecked by default + fn unchecked_ssub(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { + self.sub(lhs, rhs) + } + /// already unchecked by default + fn unchecked_usub(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { + self.sub(lhs, rhs) + } + /// already unchecked by default + fn unchecked_smul(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { + self.mul(lhs, rhs) + } + /// already unchecked by default + fn unchecked_umul(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { + self.mul(lhs, rhs) + } + + simple_op! { + and, + int: bitwise_and, + bool: logical_and, + fold_const { + int(a, b) => a.bitand(b); + bool(a, b) => a.bitand(b); + } + } + simple_op! { + or, + int: bitwise_or, + bool: logical_or, + fold_const { + int(a, b) => a.bitor(b); + bool(a, b) => a.bitor(b); + } + } + simple_op! { + xor, + int: bitwise_xor, + bool: logical_not_equal, + fold_const { + int(a, b) => a.bitxor(b); + bool(a, b) => a.bitxor(b); + } + } + simple_uni_op! { + not, + int: not, + bool: logical_not, + fold_const { + int(a) => a.not(); + bool(a) => a.not(); } - .unwrap() - .with_type(val.ty) } #[instrument(level = "trace", skip(self))] From a7005480cdd4c758c1d35b1827f97c3272f3da8d Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Fri, 11 Jul 2025 12:29:49 +0200 Subject: [PATCH 02/12] const folding: fix libm intrinsics using int `add()` instead of `fadd()` --- crates/rustc_codegen_spirv/src/builder/libm_intrinsics.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/builder/libm_intrinsics.rs b/crates/rustc_codegen_spirv/src/builder/libm_intrinsics.rs index 4b57dc17c6..eb302e87b2 100644 --- a/crates/rustc_codegen_spirv/src/builder/libm_intrinsics.rs +++ b/crates/rustc_codegen_spirv/src/builder/libm_intrinsics.rs @@ -246,20 +246,20 @@ impl Builder<'_, '_> { LibmIntrinsic::Custom(LibmCustomIntrinsic::Log1p) => { assert_eq!(args.len(), 1); let one = self.constant_float(args[0].ty, 1.0); - let add = self.add(args[0], one); + let add = self.fadd(args[0], one); self.gl_op(GLOp::Log, result_type, [add]) } LibmIntrinsic::Custom(LibmCustomIntrinsic::Exp10) => { assert_eq!(args.len(), 1); // exp10(x) == exp(x * log(10)); let log10 = self.constant_float(args[0].ty, 10.0f64.ln()); - let mul = self.mul(args[0], log10); + let mul = self.fmul(args[0], log10); self.gl_op(GLOp::Exp, result_type, [mul]) } LibmIntrinsic::Custom(LibmCustomIntrinsic::Expm1) => { let exp = self.gl_op(GLOp::Exp, args[0].ty, [args[0]]); let one = self.constant_float(exp.ty, 1.0); - self.sub(exp, one) + self.fsub(exp, one) } LibmIntrinsic::Custom(LibmCustomIntrinsic::Erf) => { self.undef_zombie(result_type, "Erf not supported yet") From d780bfea9d7cefd48134df0bf3df6655300fa28e Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Fri, 11 Jul 2025 12:32:57 +0200 Subject: [PATCH 03/12] const folding: shift operations --- .../src/builder/builder_methods.rs | 90 ++++++++++++++++--- 1 file changed, 78 insertions(+), 12 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs index ccbb21053d..bb43fe1065 100644 --- a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs +++ b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs @@ -139,6 +139,72 @@ macro_rules! simple_op { }; } +// shl and shr allow different types as their operands +macro_rules! simple_shift_op { + ( + $func_name:ident + $(, int: $inst_int:ident)? + $(, uint: $inst_uint:ident)? + $(, sint: $inst_sint:ident)? + $(, fold_const { + $(int($int_lhs:ident, $int_rhs:ident) => $fold_int:expr;)? + $(uint($uint_lhs:ident, $uint_rhs:ident) => $fold_uint:expr;)? + $(sint($sint_lhs:ident, $sint_rhs:ident) => $fold_sint:expr;)? + })? + ) => { + fn $func_name(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value { + let result_type = lhs.ty; + + $( + #[allow(unreachable_patterns, clippy::collapsible_match)] + if let Some(const_lhs) = self.try_get_const_value(lhs) + && let Some(const_rhs) = self.try_get_const_value(rhs) + { + #[allow(unreachable_patterns)] + match (const_lhs, const_rhs) { + $( + (ConstValue::Unsigned($int_lhs), ConstValue::Unsigned($int_rhs)) => return self.const_uint_big(result_type, $fold_int), + (ConstValue::Unsigned($int_lhs), ConstValue::Signed($int_rhs)) => return self.const_uint_big(result_type, $fold_int), + (ConstValue::Signed($int_lhs), ConstValue::Unsigned($int_rhs)) => return self.const_uint_big(result_type, $fold_int as u128), + (ConstValue::Signed($int_lhs), ConstValue::Signed($int_rhs)) => return self.const_uint_big(result_type, $fold_int as u128), + )? + $( + (ConstValue::Unsigned($uint_lhs), ConstValue::Unsigned($uint_rhs)) => return self.const_uint_big(result_type, $fold_uint), + (ConstValue::Unsigned($uint_lhs), ConstValue::Signed($uint_rhs)) => return self.const_uint_big(result_type, $fold_uint), + )? + $( + (ConstValue::Signed($sint_lhs), ConstValue::Unsigned($sint_rhs)) => return self.const_uint_big(result_type, $fold_sint as u128), + (ConstValue::Signed($sint_lhs), ConstValue::Signed($sint_rhs)) => return self.const_uint_big(result_type, $fold_sint as u128), + )? + _ => (), + } + } + )? + + match self.lookup_type(result_type) { + $(SpirvType::Integer(_, _) => { + self.emit() + .$inst_int(result_type, None, lhs.def(self), rhs.def(self)) + })? + $(SpirvType::Integer(_, false) => { + self.emit() + .$inst_uint(result_type, None, lhs.def(self), rhs.def(self)) + })? + $(SpirvType::Integer(_, true) => { + self.emit() + .$inst_sint(result_type, None, lhs.def(self), rhs.def(self)) + })? + o => self.fatal(format!( + concat!(stringify!($func_name), "() not implemented for type {}"), + o.debug(result_type, self) + )), + } + .unwrap() + .with_type(result_type) + } + }; +} + macro_rules! simple_uni_op { ( $func_name:ident @@ -1540,24 +1606,24 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { simple_op! {frem_algebraic, float: f_rem} // algebraic=normal simple_shift_op! { shl, - int: shift_left_logical - // fold_const { - // int(a, b) => a.wrapping_shl(b as u32); - // } + int: shift_left_logical, + fold_const { + int(a, b) => a.wrapping_shl(b as u32); + } } simple_shift_op! { lshr, - int: shift_right_logical - // fold_const { - // int(a, b) => a.wrapping_shr(b as u32); - // } + uint: shift_right_logical, + fold_const { + uint(a, b) => a.wrapping_shr(b as u32); + } } simple_shift_op! { ashr, - int: shift_right_arithmetic - // fold_const { - // int(a, b) => a.wrapping_shr(b as u32); - // } + sint: shift_right_arithmetic, + fold_const { + sint(a, b) => a.wrapping_shr(b as u32); + } } simple_uni_op! { neg, From c0058d13e606a13140b1aefde5c7d2e628e94a27 Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Fri, 4 Jul 2025 14:38:20 +0200 Subject: [PATCH 04/12] const folding: icmp for int and bool --- .../src/builder/builder_methods.rs | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs index bb43fe1065..c39020f786 100644 --- a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs +++ b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs @@ -2462,6 +2462,62 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { assert_ty_eq!(self, lhs.ty, rhs.ty); let b = SpirvType::Bool.def(self.span(), self); + + if let Some(const_lhs) = self.try_get_const_value(lhs) + && let Some(const_rhs) = self.try_get_const_value(rhs) + { + let const_result = match self.lookup_type(lhs.ty) { + SpirvType::Integer(_, _) => match (const_lhs, const_rhs, op) { + (ConstValue::Unsigned(lhs), ConstValue::Unsigned(rhs), IntEQ) => { + Some(lhs.eq(&rhs)) + } + (ConstValue::Signed(lhs), ConstValue::Signed(rhs), IntEQ) => Some(lhs.eq(&rhs)), + (ConstValue::Unsigned(lhs), ConstValue::Unsigned(rhs), IntNE) => { + Some(lhs.ne(&rhs)) + } + (ConstValue::Signed(lhs), ConstValue::Signed(rhs), IntNE) => Some(lhs.ne(&rhs)), + (ConstValue::Unsigned(lhs), ConstValue::Unsigned(rhs), IntUGT) => { + Some(lhs.gt(&rhs)) + } + (ConstValue::Unsigned(lhs), ConstValue::Unsigned(rhs), IntUGE) => { + Some(lhs.ge(&rhs)) + } + (ConstValue::Unsigned(lhs), ConstValue::Unsigned(rhs), IntULT) => { + Some(lhs.lt(&rhs)) + } + (ConstValue::Unsigned(lhs), ConstValue::Unsigned(rhs), IntULE) => { + Some(lhs.le(&rhs)) + } + (ConstValue::Signed(lhs), ConstValue::Signed(rhs), IntUGT) => { + Some(lhs.gt(&rhs)) + } + (ConstValue::Signed(lhs), ConstValue::Signed(rhs), IntUGE) => { + Some(lhs.ge(&rhs)) + } + (ConstValue::Signed(lhs), ConstValue::Signed(rhs), IntULT) => { + Some(lhs.lt(&rhs)) + } + (ConstValue::Signed(lhs), ConstValue::Signed(rhs), IntULE) => { + Some(lhs.le(&rhs)) + } + (_, _, _) => None, + }, + SpirvType::Bool => match (const_lhs, const_rhs, op) { + (ConstValue::Bool(lhs), ConstValue::Bool(rhs), IntEQ) => Some(lhs.eq(&rhs)), + (ConstValue::Bool(lhs), ConstValue::Bool(rhs), IntNE) => Some(lhs.ne(&rhs)), + (ConstValue::Bool(lhs), ConstValue::Bool(rhs), IntUGT) => Some(lhs.gt(&rhs)), + (ConstValue::Bool(lhs), ConstValue::Bool(rhs), IntUGE) => Some(lhs.ge(&rhs)), + (ConstValue::Bool(lhs), ConstValue::Bool(rhs), IntULT) => Some(lhs.lt(&rhs)), + (ConstValue::Bool(lhs), ConstValue::Bool(rhs), IntULE) => Some(lhs.le(&rhs)), + (_, _, _) => None, + }, + _ => None, + }; + if let Some(result) = const_result { + return self.const_bool(result); + } + } + match self.lookup_type(lhs.ty) { SpirvType::Integer(_, _) => match op { IntEQ => self.emit().i_equal(b, None, lhs.def(self), rhs.def(self)), From f9d25e231e8a9c30e6b919cd642edac3f46f1540 Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Fri, 4 Jul 2025 14:43:45 +0200 Subject: [PATCH 05/12] const folding: select --- crates/rustc_codegen_spirv/src/builder/builder_methods.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs index c39020f786..60a64e8b19 100644 --- a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs +++ b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs @@ -2910,6 +2910,12 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { ) -> Self::Value { assert_ty_eq!(self, then_val.ty, else_val.ty); let result_type = then_val.ty; + + if let Some(ConstValue::Bool(b)) = self.try_get_const_value(cond) { + // as we directly return the values, it'll preserve their constness as well + return if b { then_val } else { else_val }; + } + self.emit() .select( result_type, From 6e0f31cd46680c25de82d00868ca1d8bce9d84fe Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Fri, 4 Jul 2025 15:03:15 +0200 Subject: [PATCH 06/12] const folding: bless compiletest --- .../ui/dis/entry-pass-mode-cast-array.stderr | 18 ++++-------------- tests/compiletests/ui/dis/issue-731.stderr | 18 ++++-------------- 2 files changed, 8 insertions(+), 28 deletions(-) diff --git a/tests/compiletests/ui/dis/entry-pass-mode-cast-array.stderr b/tests/compiletests/ui/dis/entry-pass-mode-cast-array.stderr index 959aaa2ddc..5fd5cdd459 100644 --- a/tests/compiletests/ui/dis/entry-pass-mode-cast-array.stderr +++ b/tests/compiletests/ui/dis/entry-pass-mode-cast-array.stderr @@ -3,21 +3,11 @@ OpLine %5 13 12 %6 = OpLoad %7 %8 OpLine %5 14 4 -%9 = OpULessThan %10 %11 %12 -OpNoLine -OpSelectionMerge %13 None -OpBranchConditional %9 %14 %15 -%14 = OpLabel -OpBranch %13 -%15 = OpLabel -OpReturn -%13 = OpLabel -OpLine %5 14 4 -%16 = OpCompositeExtract %17 %6 0 -%18 = OpFAdd %17 %16 %19 -%20 = OpCompositeInsert %7 %18 %6 0 +%9 = OpCompositeExtract %10 %6 0 +%11 = OpFAdd %10 %9 %12 +%13 = OpCompositeInsert %7 %11 %6 0 OpLine %5 15 4 -OpStore %21 %20 +OpStore %14 %13 OpNoLine OpReturn OpFunctionEnd diff --git a/tests/compiletests/ui/dis/issue-731.stderr b/tests/compiletests/ui/dis/issue-731.stderr index 4972c4a50a..78fdc54539 100644 --- a/tests/compiletests/ui/dis/issue-731.stderr +++ b/tests/compiletests/ui/dis/issue-731.stderr @@ -3,21 +3,11 @@ OpLine %5 11 12 %6 = OpLoad %7 %8 OpLine %5 12 4 -%9 = OpULessThan %10 %11 %12 -OpNoLine -OpSelectionMerge %13 None -OpBranchConditional %9 %14 %15 -%14 = OpLabel -OpBranch %13 -%15 = OpLabel -OpReturn -%13 = OpLabel -OpLine %5 12 4 -%16 = OpCompositeExtract %17 %6 0 -%18 = OpFAdd %17 %16 %19 -%20 = OpCompositeInsert %7 %18 %6 0 +%9 = OpCompositeExtract %10 %6 0 +%11 = OpFAdd %10 %9 %12 +%13 = OpCompositeInsert %7 %11 %6 0 OpLine %5 13 4 -OpStore %21 %20 +OpStore %14 %13 OpNoLine OpReturn OpFunctionEnd From ee8b5dedb088fb35001a267bef4d04fdb84c96ae Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Fri, 11 Jul 2025 13:19:53 +0200 Subject: [PATCH 07/12] const folding: only const fold if const value is valid prevent const folding from hiding issues --- .../src/builder/builder_methods.rs | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs index 60a64e8b19..afdd35f9b5 100644 --- a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs +++ b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs @@ -54,13 +54,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { match self.lookup_type(val.ty) { SpirvType::Integer(bits, signed) => { let size = Size::from_bits(bits); - Some(if signed { - ConstValue::Signed(size.sign_extend(x)) + // ensure the u128 constant didn't overflow and const-folding isn't hiding issues + if x == size.truncate(x) { + Some(if signed { + ConstValue::Signed(size.sign_extend(x)) + } else { + ConstValue::Unsigned(size.truncate(x)) + }) } else { - ConstValue::Unsigned(size.truncate(x)) - }) + None + } + } + SpirvType::Bool => { + match x { + 0 => Some(ConstValue::Bool(false)), + 1 => Some(ConstValue::Bool(true)), + // ensure const-folding isn't hiding issues + _ => None, + } } - SpirvType::Bool => Some(ConstValue::Bool(x != 0)), _ => None, } } else { From 042c92f5576a27272b41cbdc8d842574d9397879 Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Mon, 14 Jul 2025 16:52:01 +0200 Subject: [PATCH 08/12] const folding: compiletest div by 0 causes ICE --- tests/compiletests/ui/lang/u32/const_fold_div.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tests/compiletests/ui/lang/u32/const_fold_div.rs diff --git a/tests/compiletests/ui/lang/u32/const_fold_div.rs b/tests/compiletests/ui/lang/u32/const_fold_div.rs new file mode 100644 index 0000000000..1ae97ef36c --- /dev/null +++ b/tests/compiletests/ui/lang/u32/const_fold_div.rs @@ -0,0 +1,10 @@ +// build-pass + +#![allow(unconditional_panic)] + +use spirv_std::spirv; + +#[spirv(fragment)] +pub fn const_fold_div(out: &mut u32) { + *out = 7u32 / 0; +} From b9712472f0a7c1727248f3cd3ad17c1f9069505c Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Mon, 14 Jul 2025 16:57:46 +0200 Subject: [PATCH 09/12] const folding: use checked operations and allow bailing --- .../src/builder/builder_methods.rs | 85 ++++++++++--------- 1 file changed, 46 insertions(+), 39 deletions(-) diff --git a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs index afdd35f9b5..a7513b8e33 100644 --- a/crates/rustc_codegen_spirv/src/builder/builder_methods.rs +++ b/crates/rustc_codegen_spirv/src/builder/builder_methods.rs @@ -105,16 +105,18 @@ macro_rules! simple_op { if let Some(const_lhs) = self.try_get_const_value(lhs) && let Some(const_rhs) = self.try_get_const_value(rhs) { - #[allow(unreachable_patterns)] - match (const_lhs, const_rhs) { + let result = (|| Some(match (const_lhs, const_rhs) { $( - (ConstValue::Unsigned($int_lhs), ConstValue::Unsigned($int_rhs)) => return self.const_uint_big(result_type, $fold_int), - (ConstValue::Signed($int_lhs), ConstValue::Signed($int_rhs)) => return self.const_uint_big(result_type, $fold_int as u128), + (ConstValue::Unsigned($int_lhs), ConstValue::Unsigned($int_rhs)) => $fold_int, + (ConstValue::Signed($int_lhs), ConstValue::Signed($int_rhs)) => $fold_int as u128, )? - $((ConstValue::Unsigned($uint_lhs), ConstValue::Unsigned($uint_rhs)) => return self.const_uint_big(result_type, $fold_uint), )? - $((ConstValue::Signed($sint_lhs), ConstValue::Signed($sint_rhs)) => return self.const_uint_big(result_type, $fold_sint as u128), )? - $((ConstValue::Bool($bool_lhs), ConstValue::Bool($bool_rhs)) => return self.const_uint_big(result_type, ($fold_bool).into()), )? - _ => (), + $((ConstValue::Unsigned($uint_lhs), ConstValue::Unsigned($uint_rhs)) => $fold_uint,)? + $((ConstValue::Signed($sint_lhs), ConstValue::Signed($sint_rhs)) => $fold_sint as u128, )? + $((ConstValue::Bool($bool_lhs), ConstValue::Bool($bool_rhs)) => ($fold_bool).into(), )? + _ => return None, + }))(); + if let Some(result) = result { + return self.const_uint_big(result_type, result); } } )? @@ -172,23 +174,25 @@ macro_rules! simple_shift_op { if let Some(const_lhs) = self.try_get_const_value(lhs) && let Some(const_rhs) = self.try_get_const_value(rhs) { - #[allow(unreachable_patterns)] - match (const_lhs, const_rhs) { + let result = (|| Some(match (const_lhs, const_rhs) { $( - (ConstValue::Unsigned($int_lhs), ConstValue::Unsigned($int_rhs)) => return self.const_uint_big(result_type, $fold_int), - (ConstValue::Unsigned($int_lhs), ConstValue::Signed($int_rhs)) => return self.const_uint_big(result_type, $fold_int), - (ConstValue::Signed($int_lhs), ConstValue::Unsigned($int_rhs)) => return self.const_uint_big(result_type, $fold_int as u128), - (ConstValue::Signed($int_lhs), ConstValue::Signed($int_rhs)) => return self.const_uint_big(result_type, $fold_int as u128), + (ConstValue::Unsigned($int_lhs), ConstValue::Unsigned($int_rhs)) => $fold_int, + (ConstValue::Unsigned($int_lhs), ConstValue::Signed($int_rhs)) => $fold_int, + (ConstValue::Signed($int_lhs), ConstValue::Unsigned($int_rhs)) => $fold_int as u128, + (ConstValue::Signed($int_lhs), ConstValue::Signed($int_rhs)) => $fold_int as u128, )? $( - (ConstValue::Unsigned($uint_lhs), ConstValue::Unsigned($uint_rhs)) => return self.const_uint_big(result_type, $fold_uint), - (ConstValue::Unsigned($uint_lhs), ConstValue::Signed($uint_rhs)) => return self.const_uint_big(result_type, $fold_uint), + (ConstValue::Unsigned($uint_lhs), ConstValue::Unsigned($uint_rhs)) => $fold_uint, + (ConstValue::Unsigned($uint_lhs), ConstValue::Signed($uint_rhs)) => $fold_uint, )? $( - (ConstValue::Signed($sint_lhs), ConstValue::Unsigned($sint_rhs)) => return self.const_uint_big(result_type, $fold_sint as u128), - (ConstValue::Signed($sint_lhs), ConstValue::Signed($sint_rhs)) => return self.const_uint_big(result_type, $fold_sint as u128), + (ConstValue::Signed($sint_lhs), ConstValue::Unsigned($sint_rhs)) => $fold_sint as u128, + (ConstValue::Signed($sint_lhs), ConstValue::Signed($sint_rhs)) => $fold_sint as u128, )? - _ => (), + _ => return None, + }))(); + if let Some(result) = result { + return self.const_uint_big(result_type, result); } } )? @@ -238,15 +242,18 @@ macro_rules! simple_uni_op { $( #[allow(unreachable_patterns, clippy::collapsible_match)] if let Some(const_val) = self.try_get_const_value(val) { - match const_val { + let result = (|| Some(match (const_val) { $( - ConstValue::Unsigned($int_val) => return self.const_uint_big(result_type, $fold_int), - ConstValue::Signed($int_val) => return self.const_uint_big(result_type, $fold_int as u128), + ConstValue::Unsigned($int_val) => $fold_int, + ConstValue::Signed($int_val) => $fold_int as u128, )? - $(ConstValue::Unsigned($uint_val) => return self.const_uint_big(result_type, $fold_uint), )? - $(ConstValue::Signed($sint_val) => return self.const_uint_big(result_type, $fold_sint as u128), )? - $(ConstValue::Bool($bool_val) => return self.const_uint_big(result_type, ($fold_bool).into()), )? - _ => (), + $(ConstValue::Unsigned($uint_val) => $fold_uint, )? + $(ConstValue::Signed($sint_val) => $fold_sint as u128, )? + $(ConstValue::Bool($bool_val) => ($fold_bool).into(), )? + _ => return None, + }))(); + if let Some(result) = result { + return self.const_uint_big(result_type, result); } } )? @@ -1538,7 +1545,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { add, int: i_add, fold_const { - int(a, b) => a.wrapping_add(b); + int(a, b) => a.checked_add(b)?; } } // FIXME(eddyb) try to annotate the SPIR-V for `fast` and `algebraic`. @@ -1549,7 +1556,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { sub, int: i_sub, fold_const { - int(a, b) => a.wrapping_sub(b); + int(a, b) => a.checked_sub(b)?; } } simple_op! {fsub, float: f_sub} @@ -1559,7 +1566,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { mul, int: i_mul, fold_const { - int(a, b) => a.wrapping_mul(b); + int(a, b) => a.checked_mul(b)?; } } simple_op! {fmul, float: f_mul} @@ -1569,7 +1576,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { udiv, uint: u_div, fold_const { - uint(a, b) => a.wrapping_div(b); + uint(a, b) => a.checked_div(b)?; } } // Note: exactudiv is UB when there's a remainder, so it's valid to implement as a normal div. @@ -1578,14 +1585,14 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { exactudiv, uint: u_div, fold_const { - uint(a, b) => a.wrapping_div(b); + uint(a, b) => a.checked_div(b)?; } } simple_op! { sdiv, sint: s_div, fold_const { - sint(a, b) => a.wrapping_div(b); + sint(a, b) => a.checked_div(b)?; } } // Same note and TODO as exactudiv @@ -1593,7 +1600,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { exactsdiv, sint: s_div, fold_const { - sint(a, b) => a.wrapping_div(b); + sint(a, b) => a.checked_div(b)?; } } simple_op! {fdiv, float: f_div} @@ -1603,14 +1610,14 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { urem, uint: u_mod, fold_const { - uint(a, b) => a.wrapping_rem(b); + uint(a, b) => a.checked_rem(b)?; } } simple_op! { srem, sint: s_rem, fold_const { - sint(a, b) => a.wrapping_rem(b); + sint(a, b) => a.checked_rem(b)?; } } simple_op! {frem, float: f_rem} @@ -1620,28 +1627,28 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> { shl, int: shift_left_logical, fold_const { - int(a, b) => a.wrapping_shl(b as u32); + int(a, b) => a.checked_shl(b as u32)?; } } simple_shift_op! { lshr, uint: shift_right_logical, fold_const { - uint(a, b) => a.wrapping_shr(b as u32); + uint(a, b) => a.checked_shr(b as u32)?; } } simple_shift_op! { ashr, sint: shift_right_arithmetic, fold_const { - sint(a, b) => a.wrapping_shr(b as u32); + sint(a, b) => a.checked_shr(b as u32)?; } } simple_uni_op! { neg, sint: s_negate, fold_const { - sint(a) => a.wrapping_neg(); + sint(a) => a.checked_neg()?; } } simple_uni_op! {fneg, float: f_negate} From 33b0c0995253fdfa1db9b3519fceffacf15973c9 Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Mon, 14 Jul 2025 15:31:30 +0200 Subject: [PATCH 10/12] const folding: difftest for bitshift --- tests/difftests/tests/Cargo.lock | 58 ++++++++++ tests/difftests/tests/Cargo.toml | 6 +- .../const_fold_int/const-fold-cpu/Cargo.toml | 16 +++ .../const-fold-cpu/src/cpu_driver.rs | 13 +++ .../const_fold_int/const-fold-cpu/src/lib.rs | 108 ++++++++++++++++++ .../const_fold_int/const-fold-cpu/src/main.rs | 5 + .../const-fold-cpu/src/shader.rs | 13 +++ .../const-fold-cpu/src/shader_driver.rs | 19 +++ .../const-fold-shader/Cargo.toml | 18 +++ .../const-fold-shader/src/lib.rs | 4 + .../const-fold-shader/src/main.rs | 5 + .../dynamic-values-cpu/Cargo.toml | 15 +++ .../dynamic-values-cpu/src/main.rs | 5 + .../dynamic-values-shader/Cargo.toml | 18 +++ .../dynamic-values-shader/src/lib.rs | 4 + .../dynamic-values-shader/src/main.rs | 5 + 16 files changed, 310 insertions(+), 2 deletions(-) create mode 100644 tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-cpu/Cargo.toml create mode 100644 tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-cpu/src/cpu_driver.rs create mode 100644 tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-cpu/src/lib.rs create mode 100644 tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-cpu/src/main.rs create mode 100644 tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-cpu/src/shader.rs create mode 100644 tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-cpu/src/shader_driver.rs create mode 100644 tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-shader/Cargo.toml create mode 100644 tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-shader/src/lib.rs create mode 100644 tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-shader/src/main.rs create mode 100644 tests/difftests/tests/lang/core/ops/const_fold_int/dynamic-values-cpu/Cargo.toml create mode 100644 tests/difftests/tests/lang/core/ops/const_fold_int/dynamic-values-cpu/src/main.rs create mode 100644 tests/difftests/tests/lang/core/ops/const_fold_int/dynamic-values-shader/Cargo.toml create mode 100644 tests/difftests/tests/lang/core/ops/const_fold_int/dynamic-values-shader/src/lib.rs create mode 100644 tests/difftests/tests/lang/core/ops/const_fold_int/dynamic-values-shader/src/main.rs diff --git a/tests/difftests/tests/Cargo.lock b/tests/difftests/tests/Cargo.lock index a8238f3fea..0e28df3c2c 100644 --- a/tests/difftests/tests/Cargo.lock +++ b/tests/difftests/tests/Cargo.lock @@ -210,6 +210,43 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "const_fold_int-const-fold-cpu" +version = "0.0.0" +dependencies = [ + "bytemuck", + "difftest", + "num_enum", + "spirv-std", +] + +[[package]] +name = "const_fold_int-const-fold-shader" +version = "0.0.0" +dependencies = [ + "bytemuck", + "const_fold_int-const-fold-cpu", + "difftest", +] + +[[package]] +name = "const_fold_int-dynamic-values-cpu" +version = "0.0.0" +dependencies = [ + "bytemuck", + "const_fold_int-const-fold-cpu", + "difftest", +] + +[[package]] +name = "const_fold_int-dynamic-values-shader" +version = "0.0.0" +dependencies = [ + "bytemuck", + "const_fold_int-const-fold-cpu", + "difftest", +] + [[package]] name = "control_flow-rust" version = "0.0.0" @@ -818,6 +855,27 @@ dependencies = [ "libm", ] +[[package]] +name = "num_enum" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "objc" version = "0.2.7" diff --git a/tests/difftests/tests/Cargo.toml b/tests/difftests/tests/Cargo.toml index 48449e6cc7..4510155c3d 100644 --- a/tests/difftests/tests/Cargo.toml +++ b/tests/difftests/tests/Cargo.toml @@ -27,6 +27,10 @@ members = [ "lang/core/ops/matrix_ops/matrix_ops-rust", "lang/core/ops/matrix_ops/matrix_ops-wgsl", "lang/core/ops/bitwise_ops/bitwise_ops-rust", + "lang/core/ops/const_fold_int/const-fold-cpu", + "lang/core/ops/const_fold_int/const-fold-shader", + "lang/core/ops/const_fold_int/dynamic-values-cpu", + "lang/core/ops/const_fold_int/dynamic-values-shader", "lang/core/ops/bitwise_ops/bitwise_ops-wgsl", "lang/core/ops/trig_ops/trig_ops-rust", "lang/core/ops/trig_ops/trig_ops-wgsl", @@ -46,8 +50,6 @@ unexpected_cfgs = { level = "allow", check-cfg = [ [workspace.dependencies] spirv-std = { path = "../../../crates/spirv-std", version = "=0.9.0" } -spirv-std-types = { path = "../../../crates/spirv-std/shared", version = "=0.9.0" } -spirv-std-macros = { path = "../../../crates/spirv-std/macros", version = "=0.9.0" } difftest = { path = "../../../tests/difftests/lib" } # External dependencies that need to be mentioned more than once. num-traits = { version = "0.2.15", default-features = false } diff --git a/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-cpu/Cargo.toml b/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-cpu/Cargo.toml new file mode 100644 index 0000000000..123379743b --- /dev/null +++ b/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-cpu/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "const_fold_int-const-fold-cpu" +edition.workspace = true + +[lints] +workspace = true + +# GPU deps +[dependencies] +spirv-std.workspace = true +num_enum = { version = "0.7.4", default-features = false } + +# CPU deps (for the test harness) +[target.'cfg(not(target_arch = "spirv"))'.dependencies] +difftest.workspace = true +bytemuck.workspace = true diff --git a/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-cpu/src/cpu_driver.rs b/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-cpu/src/cpu_driver.rs new file mode 100644 index 0000000000..0a4f91ff14 --- /dev/null +++ b/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-cpu/src/cpu_driver.rs @@ -0,0 +1,13 @@ +use crate::{INTERESTING_PATTERNS, Variants}; +use difftest::config::Config; + +pub fn run(variant: Variants) { + let config = Config::from_path(std::env::args().nth(1).unwrap()).unwrap(); + let result = variant + .eval(&INTERESTING_PATTERNS) + .into_iter() + .flatten() + .flatten() + .collect::>(); + config.write_result(&result).unwrap() +} diff --git a/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-cpu/src/lib.rs b/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-cpu/src/lib.rs new file mode 100644 index 0000000000..6f97f326eb --- /dev/null +++ b/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-cpu/src/lib.rs @@ -0,0 +1,108 @@ +#![cfg_attr(target_arch = "spirv", no_std)] +#![allow(arithmetic_overflow)] + +#[cfg(not(target_arch = "spirv"))] +pub mod cpu_driver; +pub mod shader; +#[cfg(not(target_arch = "spirv"))] +pub mod shader_driver; + +use num_enum::{IntoPrimitive, TryFromPrimitive}; + +macro_rules! op_u { + ($value:expr) => { + [ + ($value << 0) as u32, + ($value << 1) as u32, + ($value << 2) as u32, + ($value << 30) as u32, + ($value << 31) as u32, + ($value << 32) as u32, + ($value << 33) as u32, + ($value << 34) as u32, + ($value >> 0) as u32, + ($value >> 1) as u32, + ($value >> 2) as u32, + ($value >> 30) as u32, + ($value >> 31) as u32, + ($value >> 32) as u32, + ($value >> 33) as u32, + ($value >> 34) as u32, + ] + }; +} + +macro_rules! op_i { + ($value:expr) => { + op_u!($value as i32) + }; +} + +macro_rules! interesting_patterns { + ($op_name:ident) => { + [ + $op_name!(0u32), + $op_name!(1u32), + $op_name!(0xFFFFFFFFu32), + $op_name!(0xDEADBEEFu32), + $op_name!(0b10011001100110011001100110011001u32), + $op_name!(0b10000000000000000000000000000001u32), + $op_name!(0x12345678u32), + $op_name!(0x87654321u32), + ] + }; +} + +macro_rules! identity { + ($expr:expr) => { + $expr + }; +} + +pub const INTERESTING_PATTERNS: [u32; 8] = interesting_patterns!(identity); + +#[repr(u32)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)] +pub enum Variants { + /// const folding in rust-gpu + ConstFold, + // /// `const {}` expr for const eval within rustc + // ConstExpr, + /// dynamic values from `input_patterns` + DynamicValues, +} + +pub type EvalResult = [[[u32; 16]; 8]; 2]; + +impl Variants { + pub fn eval(&self, input_patterns: &[u32; 8]) -> EvalResult { + match self { + Variants::ConstFold => [interesting_patterns!(op_u), interesting_patterns!(op_i)], + // Variants::ConstExpr => { + // const { [interesting_patterns!(op_u), interesting_patterns!(op_i)] } + // } + Variants::DynamicValues => [ + [ + op_u!(input_patterns[0]), + op_u!(input_patterns[1]), + op_u!(input_patterns[2]), + op_u!(input_patterns[3]), + op_u!(input_patterns[4]), + op_u!(input_patterns[5]), + op_u!(input_patterns[6]), + op_u!(input_patterns[7]), + ], + [ + op_i!(input_patterns[0]), + op_i!(input_patterns[1]), + op_i!(input_patterns[2]), + op_i!(input_patterns[3]), + op_i!(input_patterns[4]), + op_i!(input_patterns[5]), + op_i!(input_patterns[6]), + op_i!(input_patterns[7]), + ], + ], + } + } +} diff --git a/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-cpu/src/main.rs b/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-cpu/src/main.rs new file mode 100644 index 0000000000..bd74e1a185 --- /dev/null +++ b/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-cpu/src/main.rs @@ -0,0 +1,5 @@ +use const_fold_int_const_fold_cpu::Variants; + +fn main() { + const_fold_int_const_fold_cpu::cpu_driver::run(Variants::ConstFold); +} diff --git a/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-cpu/src/shader.rs b/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-cpu/src/shader.rs new file mode 100644 index 0000000000..982039dcc4 --- /dev/null +++ b/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-cpu/src/shader.rs @@ -0,0 +1,13 @@ +use crate::{EvalResult, Variants}; +use spirv_std::spirv; + +#[spirv(compute(threads(1)))] +pub fn main_cs( + #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] variant: &u32, + #[spirv(storage_buffer, descriptor_set = 0, binding = 1)] input_patterns: &[u32; 8], + #[spirv(storage_buffer, descriptor_set = 0, binding = 2)] output: &mut EvalResult, +) { + if let Ok(variant) = Variants::try_from(*variant) { + *output = variant.eval(input_patterns); + } +} diff --git a/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-cpu/src/shader_driver.rs b/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-cpu/src/shader_driver.rs new file mode 100644 index 0000000000..2b848b0bba --- /dev/null +++ b/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-cpu/src/shader_driver.rs @@ -0,0 +1,19 @@ +use crate::{EvalResult, INTERESTING_PATTERNS, Variants}; +use difftest::config::Config; +use difftest::scaffold::compute::{BufferConfig, RustComputeShader, WgpuComputeTestMultiBuffer}; + +pub fn run(variant: Variants) { + let config = Config::from_path(std::env::args().nth(1).unwrap()).unwrap(); + + let test = WgpuComputeTestMultiBuffer::new( + RustComputeShader::default(), + [64, 1, 1], + Vec::from(&[ + BufferConfig::read_only(&[u32::from(variant)]), + BufferConfig::read_only(&INTERESTING_PATTERNS), + BufferConfig::writeback(size_of::()), + ]), + ); + + test.run_test(&config).unwrap(); +} diff --git a/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-shader/Cargo.toml b/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-shader/Cargo.toml new file mode 100644 index 0000000000..83d06ddc63 --- /dev/null +++ b/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-shader/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "const_fold_int-const-fold-shader" +edition.workspace = true + +[lints] +workspace = true + +[lib] +crate-type = ["dylib"] + +# GPU deps +[dependencies] +const_fold_int-const-fold-cpu = { path = "../const-fold-cpu" } + +# CPU deps (for the test harness) +[target.'cfg(not(target_arch = "spirv"))'.dependencies] +difftest.workspace = true +bytemuck.workspace = true diff --git a/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-shader/src/lib.rs b/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-shader/src/lib.rs new file mode 100644 index 0000000000..71a8becb3f --- /dev/null +++ b/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-shader/src/lib.rs @@ -0,0 +1,4 @@ +#![cfg_attr(target_arch = "spirv", no_std)] +#![allow(arithmetic_overflow)] + +pub use const_fold_int_const_fold_cpu::shader::main_cs; diff --git a/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-shader/src/main.rs b/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-shader/src/main.rs new file mode 100644 index 0000000000..692158eea4 --- /dev/null +++ b/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-shader/src/main.rs @@ -0,0 +1,5 @@ +use const_fold_int_const_fold_cpu::Variants; + +fn main() { + const_fold_int_const_fold_cpu::shader_driver::run(Variants::ConstFold); +} diff --git a/tests/difftests/tests/lang/core/ops/const_fold_int/dynamic-values-cpu/Cargo.toml b/tests/difftests/tests/lang/core/ops/const_fold_int/dynamic-values-cpu/Cargo.toml new file mode 100644 index 0000000000..e79029bfe9 --- /dev/null +++ b/tests/difftests/tests/lang/core/ops/const_fold_int/dynamic-values-cpu/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "const_fold_int-dynamic-values-cpu" +edition.workspace = true + +[lints] +workspace = true + +# GPU deps +[dependencies] +const_fold_int-const-fold-cpu = { path = "../const-fold-cpu" } + +# CPU deps (for the test harness) +[target.'cfg(not(target_arch = "spirv"))'.dependencies] +difftest.workspace = true +bytemuck.workspace = true diff --git a/tests/difftests/tests/lang/core/ops/const_fold_int/dynamic-values-cpu/src/main.rs b/tests/difftests/tests/lang/core/ops/const_fold_int/dynamic-values-cpu/src/main.rs new file mode 100644 index 0000000000..c58039359d --- /dev/null +++ b/tests/difftests/tests/lang/core/ops/const_fold_int/dynamic-values-cpu/src/main.rs @@ -0,0 +1,5 @@ +use const_fold_int_const_fold_cpu::Variants; + +fn main() { + const_fold_int_const_fold_cpu::cpu_driver::run(Variants::DynamicValues); +} diff --git a/tests/difftests/tests/lang/core/ops/const_fold_int/dynamic-values-shader/Cargo.toml b/tests/difftests/tests/lang/core/ops/const_fold_int/dynamic-values-shader/Cargo.toml new file mode 100644 index 0000000000..99b20e4891 --- /dev/null +++ b/tests/difftests/tests/lang/core/ops/const_fold_int/dynamic-values-shader/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "const_fold_int-dynamic-values-shader" +edition.workspace = true + +[lints] +workspace = true + +[lib] +crate-type = ["rlib", "dylib"] + +# GPU deps +[dependencies] +const_fold_int-const-fold-cpu = { path = "../const-fold-cpu" } + +# CPU deps (for the test harness) +[target.'cfg(not(target_arch = "spirv"))'.dependencies] +difftest.workspace = true +bytemuck.workspace = true diff --git a/tests/difftests/tests/lang/core/ops/const_fold_int/dynamic-values-shader/src/lib.rs b/tests/difftests/tests/lang/core/ops/const_fold_int/dynamic-values-shader/src/lib.rs new file mode 100644 index 0000000000..71a8becb3f --- /dev/null +++ b/tests/difftests/tests/lang/core/ops/const_fold_int/dynamic-values-shader/src/lib.rs @@ -0,0 +1,4 @@ +#![cfg_attr(target_arch = "spirv", no_std)] +#![allow(arithmetic_overflow)] + +pub use const_fold_int_const_fold_cpu::shader::main_cs; diff --git a/tests/difftests/tests/lang/core/ops/const_fold_int/dynamic-values-shader/src/main.rs b/tests/difftests/tests/lang/core/ops/const_fold_int/dynamic-values-shader/src/main.rs new file mode 100644 index 0000000000..b0492a76c9 --- /dev/null +++ b/tests/difftests/tests/lang/core/ops/const_fold_int/dynamic-values-shader/src/main.rs @@ -0,0 +1,5 @@ +use const_fold_int_const_fold_cpu::Variants; + +fn main() { + const_fold_int_const_fold_cpu::shader_driver::run(Variants::DynamicValues); +} From d8ec881f618d5c3d487d6d5cb2183a2c51d4a153 Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Mon, 14 Jul 2025 16:36:26 +0200 Subject: [PATCH 11/12] const folding: difftest with rustc const block --- tests/difftests/tests/Cargo.lock | 18 +++++++++++++++++ tests/difftests/tests/Cargo.toml | 2 ++ .../const_fold_int/const-expr-cpu/Cargo.toml | 15 ++++++++++++++ .../const_fold_int/const-expr-cpu/src/main.rs | 5 +++++ .../const-expr-shader/Cargo.toml | 18 +++++++++++++++++ .../const-expr-shader/src/lib.rs | 4 ++++ .../const-expr-shader/src/main.rs | 5 +++++ .../const_fold_int/const-fold-cpu/src/lib.rs | 20 ++++++------------- 8 files changed, 73 insertions(+), 14 deletions(-) create mode 100644 tests/difftests/tests/lang/core/ops/const_fold_int/const-expr-cpu/Cargo.toml create mode 100644 tests/difftests/tests/lang/core/ops/const_fold_int/const-expr-cpu/src/main.rs create mode 100644 tests/difftests/tests/lang/core/ops/const_fold_int/const-expr-shader/Cargo.toml create mode 100644 tests/difftests/tests/lang/core/ops/const_fold_int/const-expr-shader/src/lib.rs create mode 100644 tests/difftests/tests/lang/core/ops/const_fold_int/const-expr-shader/src/main.rs diff --git a/tests/difftests/tests/Cargo.lock b/tests/difftests/tests/Cargo.lock index 0e28df3c2c..272b612da2 100644 --- a/tests/difftests/tests/Cargo.lock +++ b/tests/difftests/tests/Cargo.lock @@ -210,6 +210,24 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "const_fold_int-const-expr-cpu" +version = "0.0.0" +dependencies = [ + "bytemuck", + "const_fold_int-const-fold-cpu", + "difftest", +] + +[[package]] +name = "const_fold_int-const-expr-shader" +version = "0.0.0" +dependencies = [ + "bytemuck", + "const_fold_int-const-fold-cpu", + "difftest", +] + [[package]] name = "const_fold_int-const-fold-cpu" version = "0.0.0" diff --git a/tests/difftests/tests/Cargo.toml b/tests/difftests/tests/Cargo.toml index 4510155c3d..f939ad87dd 100644 --- a/tests/difftests/tests/Cargo.toml +++ b/tests/difftests/tests/Cargo.toml @@ -27,6 +27,8 @@ members = [ "lang/core/ops/matrix_ops/matrix_ops-rust", "lang/core/ops/matrix_ops/matrix_ops-wgsl", "lang/core/ops/bitwise_ops/bitwise_ops-rust", + "lang/core/ops/const_fold_int/const-expr-cpu", + "lang/core/ops/const_fold_int/const-expr-shader", "lang/core/ops/const_fold_int/const-fold-cpu", "lang/core/ops/const_fold_int/const-fold-shader", "lang/core/ops/const_fold_int/dynamic-values-cpu", diff --git a/tests/difftests/tests/lang/core/ops/const_fold_int/const-expr-cpu/Cargo.toml b/tests/difftests/tests/lang/core/ops/const_fold_int/const-expr-cpu/Cargo.toml new file mode 100644 index 0000000000..185bf5d4cd --- /dev/null +++ b/tests/difftests/tests/lang/core/ops/const_fold_int/const-expr-cpu/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "const_fold_int-const-expr-cpu" +edition.workspace = true + +[lints] +workspace = true + +# GPU deps +[dependencies] +const_fold_int-const-fold-cpu = { path = "../const-fold-cpu" } + +# CPU deps (for the test harness) +[target.'cfg(not(target_arch = "spirv"))'.dependencies] +difftest.workspace = true +bytemuck.workspace = true diff --git a/tests/difftests/tests/lang/core/ops/const_fold_int/const-expr-cpu/src/main.rs b/tests/difftests/tests/lang/core/ops/const_fold_int/const-expr-cpu/src/main.rs new file mode 100644 index 0000000000..200dcccc7e --- /dev/null +++ b/tests/difftests/tests/lang/core/ops/const_fold_int/const-expr-cpu/src/main.rs @@ -0,0 +1,5 @@ +use const_fold_int_const_fold_cpu::Variants; + +fn main() { + const_fold_int_const_fold_cpu::cpu_driver::run(Variants::ConstExpr); +} diff --git a/tests/difftests/tests/lang/core/ops/const_fold_int/const-expr-shader/Cargo.toml b/tests/difftests/tests/lang/core/ops/const_fold_int/const-expr-shader/Cargo.toml new file mode 100644 index 0000000000..a2e86b99d3 --- /dev/null +++ b/tests/difftests/tests/lang/core/ops/const_fold_int/const-expr-shader/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "const_fold_int-const-expr-shader" +edition.workspace = true + +[lints] +workspace = true + +[lib] +crate-type = ["dylib"] + +# GPU deps +[dependencies] +const_fold_int-const-fold-cpu = { path = "../const-fold-cpu" } + +# CPU deps (for the test harness) +[target.'cfg(not(target_arch = "spirv"))'.dependencies] +difftest.workspace = true +bytemuck.workspace = true diff --git a/tests/difftests/tests/lang/core/ops/const_fold_int/const-expr-shader/src/lib.rs b/tests/difftests/tests/lang/core/ops/const_fold_int/const-expr-shader/src/lib.rs new file mode 100644 index 0000000000..71a8becb3f --- /dev/null +++ b/tests/difftests/tests/lang/core/ops/const_fold_int/const-expr-shader/src/lib.rs @@ -0,0 +1,4 @@ +#![cfg_attr(target_arch = "spirv", no_std)] +#![allow(arithmetic_overflow)] + +pub use const_fold_int_const_fold_cpu::shader::main_cs; diff --git a/tests/difftests/tests/lang/core/ops/const_fold_int/const-expr-shader/src/main.rs b/tests/difftests/tests/lang/core/ops/const_fold_int/const-expr-shader/src/main.rs new file mode 100644 index 0000000000..e514e48237 --- /dev/null +++ b/tests/difftests/tests/lang/core/ops/const_fold_int/const-expr-shader/src/main.rs @@ -0,0 +1,5 @@ +use const_fold_int_const_fold_cpu::Variants; + +fn main() { + const_fold_int_const_fold_cpu::shader_driver::run(Variants::ConstExpr); +} diff --git a/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-cpu/src/lib.rs b/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-cpu/src/lib.rs index 6f97f326eb..1c7e310c44 100644 --- a/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-cpu/src/lib.rs +++ b/tests/difftests/tests/lang/core/ops/const_fold_int/const-fold-cpu/src/lib.rs @@ -14,20 +14,12 @@ macro_rules! op_u { [ ($value << 0) as u32, ($value << 1) as u32, - ($value << 2) as u32, ($value << 30) as u32, ($value << 31) as u32, - ($value << 32) as u32, - ($value << 33) as u32, - ($value << 34) as u32, ($value >> 0) as u32, ($value >> 1) as u32, - ($value >> 2) as u32, ($value >> 30) as u32, ($value >> 31) as u32, - ($value >> 32) as u32, - ($value >> 33) as u32, - ($value >> 34) as u32, ] }; } @@ -66,21 +58,21 @@ pub const INTERESTING_PATTERNS: [u32; 8] = interesting_patterns!(identity); pub enum Variants { /// const folding in rust-gpu ConstFold, - // /// `const {}` expr for const eval within rustc - // ConstExpr, + /// `const {}` expr for const eval within rustc + ConstExpr, /// dynamic values from `input_patterns` DynamicValues, } -pub type EvalResult = [[[u32; 16]; 8]; 2]; +pub type EvalResult = [[[u32; 8]; 8]; 2]; impl Variants { pub fn eval(&self, input_patterns: &[u32; 8]) -> EvalResult { match self { Variants::ConstFold => [interesting_patterns!(op_u), interesting_patterns!(op_i)], - // Variants::ConstExpr => { - // const { [interesting_patterns!(op_u), interesting_patterns!(op_i)] } - // } + Variants::ConstExpr => { + const { [interesting_patterns!(op_u), interesting_patterns!(op_i)] } + } Variants::DynamicValues => [ [ op_u!(input_patterns[0]), From 6e1980b33af2404cae5425fbe60a5d932830cb91 Mon Sep 17 00:00:00 2001 From: Firestar99 Date: Wed, 16 Jul 2025 13:19:45 +0200 Subject: [PATCH 12/12] difftest: fixup windows dependency resolution, from PR #334 --- Cargo.toml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index aa689a7da0..f23f7f8625 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,14 +50,18 @@ spirv-tools = { version = "0.12", default-features = false } rustc_codegen_spirv = { path = "./crates/rustc_codegen_spirv", version = "=0.9.0", default-features = false } rustc_codegen_spirv-types = { path = "./crates/rustc_codegen_spirv-types", version = "=0.9.0" } rustc_codegen_spirv-target-specs = { path = "crates/rustc_codegen_spirv-target-specs", version = "=0.9.0" } -tracing = "0.1" -tracing-subscriber = { version = "0.3.3", features = ["env-filter", "json"] } + +# difftest libraries mirrored from difftest workspace +difftest = { path = "tests/difftests/lib" } # External dependencies that need to be mentioned more than once. +tracing = "0.1" +tracing-subscriber = { version = "0.3.3", features = ["env-filter", "json"] } num-traits = { version = "0.2.15", default-features = false } glam = { version = ">=0.22, <=0.30", default-features = false } # libm 0.2.12 is a breaking change with new intrinsics libm = { version = ">=0.2.5, <=0.2.11", default-features = false } +bytemuck = { version = "1.23", features = ["derive"] } # Enable incremental by default in release mode. [profile.release]