Change intrinsic types to use u32 instead of T to match stable reexports

This commit is contained in:
Maybe Waffle 2024-04-16 01:51:21 +00:00
parent 63f70b3d10
commit ceead1bda6
6 changed files with 117 additions and 31 deletions

View File

@ -315,25 +315,32 @@ fn codegen_intrinsic_call(
Some((width, signed)) => match name {
sym::ctlz | sym::cttz => {
let y = self.const_bool(false);
self.call_intrinsic(
let ret = self.call_intrinsic(
&format!("llvm.{name}.i{width}"),
&[args[0].immediate(), y],
)
);
self.intcast(ret, llret_ty, false)
}
sym::ctlz_nonzero => {
let y = self.const_bool(true);
let llvm_name = &format!("llvm.ctlz.i{width}");
self.call_intrinsic(llvm_name, &[args[0].immediate(), y])
let ret = self.call_intrinsic(llvm_name, &[args[0].immediate(), y]);
self.intcast(ret, llret_ty, false)
}
sym::cttz_nonzero => {
let y = self.const_bool(true);
let llvm_name = &format!("llvm.cttz.i{width}");
self.call_intrinsic(llvm_name, &[args[0].immediate(), y])
let ret = self.call_intrinsic(llvm_name, &[args[0].immediate(), y]);
self.intcast(ret, llret_ty, false)
}
sym::ctpop => {
let ret = self.call_intrinsic(
&format!("llvm.ctpop.i{width}"),
&[args[0].immediate()],
);
self.intcast(ret, llret_ty, false)
}
sym::ctpop => self.call_intrinsic(
&format!("llvm.ctpop.i{width}"),
&[args[0].immediate()],
),
sym::bswap => {
if width == 8 {
args[0].immediate() // byte swap a u8/i8 is just a no-op
@ -355,6 +362,10 @@ fn codegen_intrinsic_call(
// rotate = funnel shift with first two args the same
let llvm_name =
&format!("llvm.fsh{}.i{}", if is_left { 'l' } else { 'r' }, width);
// llvm expects shift to be the same type as the values, but rust always uses `u32`
let raw_shift = self.intcast(raw_shift, self.val_ty(val), false);
self.call_intrinsic(llvm_name, &[val, val, raw_shift])
}
sym::saturating_add | sym::saturating_sub => {

View File

@ -173,7 +173,8 @@ pub fn emulate_intrinsic(
let ty = instance_args.type_at(0);
let layout = self.layout_of(ty)?;
let val = self.read_scalar(&args[0])?;
let out_val = self.numeric_intrinsic(intrinsic_name, val, layout)?;
let out_val = self.numeric_intrinsic(intrinsic_name, val, layout, dest.layout)?;
self.write_scalar(out_val, dest)?;
}
sym::saturating_add | sym::saturating_sub => {
@ -200,12 +201,15 @@ pub fn emulate_intrinsic(
sym::rotate_left | sym::rotate_right => {
// rotate_left: (X << (S % BW)) | (X >> ((BW - S) % BW))
// rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW))
let layout = self.layout_of(instance_args.type_at(0))?;
let layout_val = self.layout_of(instance_args.type_at(0))?;
let val = self.read_scalar(&args[0])?;
let val_bits = val.to_bits(layout.size)?;
let val_bits = val.to_bits(layout_val.size)?;
let layout_raw_shift = self.layout_of(self.tcx.types.u32)?;
let raw_shift = self.read_scalar(&args[1])?;
let raw_shift_bits = raw_shift.to_bits(layout.size)?;
let width_bits = u128::from(layout.size.bits());
let raw_shift_bits = raw_shift.to_bits(layout_raw_shift.size)?;
let width_bits = u128::from(layout_val.size.bits());
let shift_bits = raw_shift_bits % width_bits;
let inv_shift_bits = (width_bits - shift_bits) % width_bits;
let result_bits = if intrinsic_name == sym::rotate_left {
@ -213,8 +217,8 @@ pub fn emulate_intrinsic(
} else {
(val_bits >> shift_bits) | (val_bits << inv_shift_bits)
};
let truncated_bits = self.truncate(result_bits, layout);
let result = Scalar::from_uint(truncated_bits, layout.size);
let truncated_bits = self.truncate(result_bits, layout_val);
let result = Scalar::from_uint(truncated_bits, layout_val.size);
self.write_scalar(result, dest)?;
}
sym::copy => {
@ -472,6 +476,7 @@ pub fn numeric_intrinsic(
name: Symbol,
val: Scalar<M::Provenance>,
layout: TyAndLayout<'tcx>,
ret_layout: TyAndLayout<'tcx>,
) -> InterpResult<'tcx, Scalar<M::Provenance>> {
assert!(layout.ty.is_integral(), "invalid type for numeric intrinsic: {}", layout.ty);
let bits = val.to_bits(layout.size)?;
@ -487,7 +492,7 @@ pub fn numeric_intrinsic(
sym::bitreverse => (bits << extra).reverse_bits(),
_ => bug!("not a numeric intrinsic: {}", name),
};
Ok(Scalar::from_uint(bits_out, layout.size))
Ok(Scalar::from_uint(bits_out, ret_layout.size))
}
pub fn exact_div(

View File

@ -411,13 +411,11 @@ pub fn check_intrinsic_type(
(1, 0, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], Ty::new_unit(tcx))
}
sym::ctpop
| sym::ctlz
| sym::ctlz_nonzero
| sym::cttz
| sym::cttz_nonzero
| sym::bswap
| sym::bitreverse => (1, 0, vec![param(0)], param(0)),
sym::ctpop | sym::ctlz | sym::ctlz_nonzero | sym::cttz | sym::cttz_nonzero => {
(1, 0, vec![param(0)], tcx.types.u32)
}
sym::bswap | sym::bitreverse => (1, 0, vec![param(0)], param(0)),
sym::three_way_compare => {
(1, 0, vec![param(0), param(0)], tcx.ty_ordering_enum(Some(span)))
@ -460,7 +458,7 @@ pub fn check_intrinsic_type(
(1, 0, vec![param(0), param(0)], param(0))
}
sym::unchecked_shl | sym::unchecked_shr => (2, 0, vec![param(0), param(1)], param(0)),
sym::rotate_left | sym::rotate_right => (1, 0, vec![param(0), param(0)], param(0)),
sym::rotate_left | sym::rotate_right => (1, 0, vec![param(0), tcx.types.u32], param(0)),
sym::unchecked_add | sym::unchecked_sub | sym::unchecked_mul => {
(1, 0, vec![param(0), param(0)], param(0))
}

View File

@ -1987,6 +1987,13 @@ pub const fn unlikely(b: bool) -> bool {
/// The stabilized versions of this intrinsic are available on the integer
/// primitives via the `count_ones` method. For example,
/// [`u32::count_ones`]
#[cfg(not(bootstrap))]
#[rustc_const_stable(feature = "const_ctpop", since = "1.40.0")]
#[rustc_safe_intrinsic]
#[rustc_nounwind]
pub fn ctpop<T: Copy>(x: T) -> u32;
#[cfg(bootstrap)]
#[rustc_const_stable(feature = "const_ctpop", since = "1.40.0")]
#[rustc_safe_intrinsic]
#[rustc_nounwind]
@ -2028,6 +2035,13 @@ pub const fn unlikely(b: bool) -> bool {
/// let num_leading = ctlz(x);
/// assert_eq!(num_leading, 16);
/// ```
#[cfg(not(bootstrap))]
#[rustc_const_stable(feature = "const_ctlz", since = "1.40.0")]
#[rustc_safe_intrinsic]
#[rustc_nounwind]
pub fn ctlz<T: Copy>(x: T) -> u32;
#[cfg(bootstrap)]
#[rustc_const_stable(feature = "const_ctlz", since = "1.40.0")]
#[rustc_safe_intrinsic]
#[rustc_nounwind]
@ -2050,6 +2064,12 @@ pub const fn unlikely(b: bool) -> bool {
/// let num_leading = unsafe { ctlz_nonzero(x) };
/// assert_eq!(num_leading, 3);
/// ```
#[cfg(not(bootstrap))]
#[rustc_const_stable(feature = "constctlz", since = "1.50.0")]
#[rustc_nounwind]
pub fn ctlz_nonzero<T: Copy>(x: T) -> u32;
#[cfg(bootstrap)]
#[rustc_const_stable(feature = "constctlz", since = "1.50.0")]
#[rustc_nounwind]
pub fn ctlz_nonzero<T: Copy>(x: T) -> T;
@ -2090,6 +2110,13 @@ pub const fn unlikely(b: bool) -> bool {
/// let num_trailing = cttz(x);
/// assert_eq!(num_trailing, 16);
/// ```
#[cfg(not(bootstrap))]
#[rustc_const_stable(feature = "const_cttz", since = "1.40.0")]
#[rustc_safe_intrinsic]
#[rustc_nounwind]
pub fn cttz<T: Copy>(x: T) -> u32;
#[cfg(bootstrap)]
#[rustc_const_stable(feature = "const_cttz", since = "1.40.0")]
#[rustc_safe_intrinsic]
#[rustc_nounwind]
@ -2112,6 +2139,12 @@ pub const fn unlikely(b: bool) -> bool {
/// let num_trailing = unsafe { cttz_nonzero(x) };
/// assert_eq!(num_trailing, 3);
/// ```
#[cfg(not(bootstrap))]
#[rustc_const_stable(feature = "const_cttz_nonzero", since = "1.53.0")]
#[rustc_nounwind]
pub fn cttz_nonzero<T: Copy>(x: T) -> u32;
#[cfg(bootstrap)]
#[rustc_const_stable(feature = "const_cttz_nonzero", since = "1.53.0")]
#[rustc_nounwind]
pub fn cttz_nonzero<T: Copy>(x: T) -> T;
@ -2288,6 +2321,13 @@ pub const fn unlikely(b: bool) -> bool {
/// The stabilized versions of this intrinsic are available on the integer
/// primitives via the `rotate_left` method. For example,
/// [`u32::rotate_left`]
#[cfg(not(bootstrap))]
#[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
#[rustc_safe_intrinsic]
#[rustc_nounwind]
pub fn rotate_left<T: Copy>(x: T, shift: u32) -> T;
#[cfg(bootstrap)]
#[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
#[rustc_safe_intrinsic]
#[rustc_nounwind]
@ -2303,6 +2343,13 @@ pub const fn unlikely(b: bool) -> bool {
/// The stabilized versions of this intrinsic are available on the integer
/// primitives via the `rotate_right` method. For example,
/// [`u32::rotate_right`]
#[cfg(not(bootstrap))]
#[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
#[rustc_safe_intrinsic]
#[rustc_nounwind]
pub fn rotate_right<T: Copy>(x: T, shift: u32) -> T;
#[cfg(bootstrap)]
#[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
#[rustc_safe_intrinsic]
#[rustc_nounwind]

View File

@ -528,7 +528,12 @@ impl $Ty {
#[inline]
pub const fn leading_zeros(self) -> u32 {
// SAFETY: since `self` cannot be zero, it is safe to call `ctlz_nonzero`.
unsafe { intrinsics::ctlz_nonzero(self.get() as $UnsignedPrimitive) as u32 }
unsafe {
#[cfg(not(bootstrap))]
return intrinsics::ctlz_nonzero(self.get() as $UnsignedPrimitive);
#[cfg(bootstrap)]
return intrinsics::ctlz_nonzero(self.get() as $UnsignedPrimitive) as u32;
}
}
/// Returns the number of trailing zeros in the binary representation
@ -552,7 +557,12 @@ pub const fn leading_zeros(self) -> u32 {
#[inline]
pub const fn trailing_zeros(self) -> u32 {
// SAFETY: since `self` cannot be zero, it is safe to call `cttz_nonzero`.
unsafe { intrinsics::cttz_nonzero(self.get() as $UnsignedPrimitive) as u32 }
unsafe {
#[cfg(not(bootstrap))]
return intrinsics::cttz_nonzero(self.get() as $UnsignedPrimitive);
#[cfg(bootstrap)]
return intrinsics::cttz_nonzero(self.get() as $UnsignedPrimitive) as u32;
}
}
/// Returns the number of ones in the binary representation of `self`.

View File

@ -77,7 +77,10 @@ macro_rules! uint_impl {
without modifying the original"]
#[inline(always)]
pub const fn count_ones(self) -> u32 {
intrinsics::ctpop(self as $ActualT) as u32
#[cfg(not(bootstrap))]
return intrinsics::ctpop(self as $ActualT);
#[cfg(bootstrap)]
return intrinsics::ctpop(self as $ActualT) as u32;
}
/// Returns the number of zeros in the binary representation of `self`.
@ -119,7 +122,10 @@ pub const fn count_zeros(self) -> u32 {
without modifying the original"]
#[inline(always)]
pub const fn leading_zeros(self) -> u32 {
intrinsics::ctlz(self as $ActualT) as u32
#[cfg(not(bootstrap))]
return intrinsics::ctlz(self as $ActualT);
#[cfg(bootstrap)]
return intrinsics::ctlz(self as $ActualT) as u32;
}
/// Returns the number of trailing zeros in the binary representation
@ -140,7 +146,10 @@ pub const fn leading_zeros(self) -> u32 {
without modifying the original"]
#[inline(always)]
pub const fn trailing_zeros(self) -> u32 {
intrinsics::cttz(self) as u32
#[cfg(not(bootstrap))]
return intrinsics::cttz(self);
#[cfg(bootstrap)]
return intrinsics::cttz(self) as u32;
}
/// Returns the number of leading ones in the binary representation of `self`.
@ -205,7 +214,10 @@ pub const fn trailing_ones(self) -> u32 {
without modifying the original"]
#[inline(always)]
pub const fn rotate_left(self, n: u32) -> Self {
intrinsics::rotate_left(self, n as $SelfT)
#[cfg(not(bootstrap))]
return intrinsics::rotate_left(self, n);
#[cfg(bootstrap)]
return intrinsics::rotate_left(self, n as $SelfT);
}
/// Shifts the bits to the right by a specified amount, `n`,
@ -230,7 +242,10 @@ pub const fn rotate_left(self, n: u32) -> Self {
without modifying the original"]
#[inline(always)]
pub const fn rotate_right(self, n: u32) -> Self {
intrinsics::rotate_right(self, n as $SelfT)
#[cfg(not(bootstrap))]
return intrinsics::rotate_right(self, n);
#[cfg(bootstrap)]
return intrinsics::rotate_right(self, n as $SelfT);
}
/// Reverses the byte order of the integer.