Skip to content

Commit 918304b

Browse files
authored
Rollup merge of #124003 - WaffleLapkin:dellvmization, r=scottmcm,RalfJung,antoyo
Dellvmize some intrinsics (use `u32` instead of `Self` in some integer intrinsics) This implements rust-lang/compiler-team#693 minus what was implemented in #123226. Note: I decided to _not_ change `shl`/... builder methods, as it just doesn't seem worth it. r? ``@scottmcm``
2 parents cd90d5c + 468179c commit 918304b

File tree

19 files changed

+266
-51
lines changed

19 files changed

+266
-51
lines changed

compiler/rustc_codegen_cranelift/example/example.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ pub fn array_as_slice(arr: &[u8; 3]) -> &[u8] {
149149
arr
150150
}
151151

152-
pub unsafe fn use_ctlz_nonzero(a: u16) -> u16 {
152+
pub unsafe fn use_ctlz_nonzero(a: u16) -> u32 {
153153
intrinsics::ctlz_nonzero(a)
154154
}
155155

compiler/rustc_codegen_cranelift/example/mini_core.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,7 @@ pub mod intrinsics {
627627
pub fn min_align_of_val<T: ?::Sized>(val: *const T) -> usize;
628628
pub fn copy<T>(src: *const T, dst: *mut T, count: usize);
629629
pub fn transmute<T, U>(e: T) -> U;
630-
pub fn ctlz_nonzero<T>(x: T) -> T;
630+
pub fn ctlz_nonzero<T>(x: T) -> u32;
631631
#[rustc_safe_intrinsic]
632632
pub fn needs_drop<T: ?::Sized>() -> bool;
633633
#[rustc_safe_intrinsic]

compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use rustc_span::source_map::Spanned;
2626
use rustc_span::symbol::{sym, Symbol};
2727

2828
pub(crate) use self::llvm::codegen_llvm_intrinsic_call;
29+
use crate::cast::clif_intcast;
2930
use crate::prelude::*;
3031

3132
fn bug_on_incorrect_arg_count(intrinsic: impl std::fmt::Display) -> ! {
@@ -627,7 +628,8 @@ fn codegen_regular_intrinsic_call<'tcx>(
627628

628629
// FIXME trap on `ctlz_nonzero` with zero arg.
629630
let res = fx.bcx.ins().clz(val);
630-
let res = CValue::by_val(res, arg.layout());
631+
let res = clif_intcast(fx, res, types::I32, false);
632+
let res = CValue::by_val(res, ret.layout());
631633
ret.write_cvalue(fx, res);
632634
}
633635
sym::cttz | sym::cttz_nonzero => {
@@ -636,15 +638,17 @@ fn codegen_regular_intrinsic_call<'tcx>(
636638

637639
// FIXME trap on `cttz_nonzero` with zero arg.
638640
let res = fx.bcx.ins().ctz(val);
639-
let res = CValue::by_val(res, arg.layout());
641+
let res = clif_intcast(fx, res, types::I32, false);
642+
let res = CValue::by_val(res, ret.layout());
640643
ret.write_cvalue(fx, res);
641644
}
642645
sym::ctpop => {
643646
intrinsic_args!(fx, args => (arg); intrinsic);
644647
let val = arg.load_scalar(fx);
645648

646649
let res = fx.bcx.ins().popcnt(val);
647-
let res = CValue::by_val(res, arg.layout());
650+
let res = clif_intcast(fx, res, types::I32, false);
651+
let res = CValue::by_val(res, ret.layout());
648652
ret.write_cvalue(fx, res);
649653
}
650654
sym::bitreverse => {

compiler/rustc_codegen_gcc/example/example.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,10 @@ fn array_as_slice(arr: &[u8; 3]) -> &[u8] {
153153
arr
154154
}
155155

156-
unsafe fn use_ctlz_nonzero(a: u16) -> u16 {
157-
intrinsics::ctlz_nonzero(a)
158-
}
156+
// FIXME: fix the intrinsic implementation to work with the new ->u32 signature
157+
// unsafe fn use_ctlz_nonzero(a: u16) -> u32 {
158+
// intrinsics::ctlz_nonzero(a)
159+
// }
159160

160161
fn ptr_as_usize(ptr: *const u8) -> usize {
161162
ptr as usize

compiler/rustc_codegen_gcc/example/mini_core.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,7 @@ pub mod intrinsics {
593593
pub fn min_align_of_val<T: ?Sized>(val: *const T) -> usize;
594594
pub fn copy<T>(src: *const T, dst: *mut T, count: usize);
595595
pub fn transmute<T, U>(e: T) -> U;
596-
pub fn ctlz_nonzero<T>(x: T) -> T;
596+
pub fn ctlz_nonzero<T>(x: T) -> u32;
597597
#[rustc_safe_intrinsic]
598598
pub fn needs_drop<T: ?Sized>() -> bool;
599599
#[rustc_safe_intrinsic]

compiler/rustc_codegen_llvm/src/intrinsic.rs

+19-8
Original file line numberDiff line numberDiff line change
@@ -315,25 +315,32 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
315315
Some((width, signed)) => match name {
316316
sym::ctlz | sym::cttz => {
317317
let y = self.const_bool(false);
318-
self.call_intrinsic(
318+
let ret = self.call_intrinsic(
319319
&format!("llvm.{name}.i{width}"),
320320
&[args[0].immediate(), y],
321-
)
321+
);
322+
323+
self.intcast(ret, llret_ty, false)
322324
}
323325
sym::ctlz_nonzero => {
324326
let y = self.const_bool(true);
325327
let llvm_name = &format!("llvm.ctlz.i{width}");
326-
self.call_intrinsic(llvm_name, &[args[0].immediate(), y])
328+
let ret = self.call_intrinsic(llvm_name, &[args[0].immediate(), y]);
329+
self.intcast(ret, llret_ty, false)
327330
}
328331
sym::cttz_nonzero => {
329332
let y = self.const_bool(true);
330333
let llvm_name = &format!("llvm.cttz.i{width}");
331-
self.call_intrinsic(llvm_name, &[args[0].immediate(), y])
334+
let ret = self.call_intrinsic(llvm_name, &[args[0].immediate(), y]);
335+
self.intcast(ret, llret_ty, false)
336+
}
337+
sym::ctpop => {
338+
let ret = self.call_intrinsic(
339+
&format!("llvm.ctpop.i{width}"),
340+
&[args[0].immediate()],
341+
);
342+
self.intcast(ret, llret_ty, false)
332343
}
333-
sym::ctpop => self.call_intrinsic(
334-
&format!("llvm.ctpop.i{width}"),
335-
&[args[0].immediate()],
336-
),
337344
sym::bswap => {
338345
if width == 8 {
339346
args[0].immediate() // byte swap a u8/i8 is just a no-op
@@ -355,6 +362,10 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
355362
// rotate = funnel shift with first two args the same
356363
let llvm_name =
357364
&format!("llvm.fsh{}.i{}", if is_left { 'l' } else { 'r' }, width);
365+
366+
// llvm expects shift to be the same type as the values, but rust always uses `u32`
367+
let raw_shift = self.intcast(raw_shift, self.val_ty(val), false);
368+
358369
self.call_intrinsic(llvm_name, &[val, val, raw_shift])
359370
}
360371
sym::saturating_add | sym::saturating_sub => {

compiler/rustc_const_eval/src/interpret/intrinsics.rs

+21-10
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
173173
let ty = instance_args.type_at(0);
174174
let layout = self.layout_of(ty)?;
175175
let val = self.read_scalar(&args[0])?;
176-
let out_val = self.numeric_intrinsic(intrinsic_name, val, layout)?;
176+
177+
let out_val = self.numeric_intrinsic(intrinsic_name, val, layout, dest.layout)?;
177178
self.write_scalar(out_val, dest)?;
178179
}
179180
sym::saturating_add | sym::saturating_sub => {
@@ -200,21 +201,24 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
200201
sym::rotate_left | sym::rotate_right => {
201202
// rotate_left: (X << (S % BW)) | (X >> ((BW - S) % BW))
202203
// rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW))
203-
let layout = self.layout_of(instance_args.type_at(0))?;
204+
let layout_val = self.layout_of(instance_args.type_at(0))?;
204205
let val = self.read_scalar(&args[0])?;
205-
let val_bits = val.to_bits(layout.size)?;
206+
let val_bits = val.to_bits(layout_val.size)?;
207+
208+
let layout_raw_shift = self.layout_of(self.tcx.types.u32)?;
206209
let raw_shift = self.read_scalar(&args[1])?;
207-
let raw_shift_bits = raw_shift.to_bits(layout.size)?;
208-
let width_bits = u128::from(layout.size.bits());
210+
let raw_shift_bits = raw_shift.to_bits(layout_raw_shift.size)?;
211+
212+
let width_bits = u128::from(layout_val.size.bits());
209213
let shift_bits = raw_shift_bits % width_bits;
210214
let inv_shift_bits = (width_bits - shift_bits) % width_bits;
211215
let result_bits = if intrinsic_name == sym::rotate_left {
212216
(val_bits << shift_bits) | (val_bits >> inv_shift_bits)
213217
} else {
214218
(val_bits >> shift_bits) | (val_bits << inv_shift_bits)
215219
};
216-
let truncated_bits = self.truncate(result_bits, layout);
217-
let result = Scalar::from_uint(truncated_bits, layout.size);
220+
let truncated_bits = self.truncate(result_bits, layout_val);
221+
let result = Scalar::from_uint(truncated_bits, layout_val.size);
218222
self.write_scalar(result, dest)?;
219223
}
220224
sym::copy => {
@@ -472,6 +476,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
472476
name: Symbol,
473477
val: Scalar<M::Provenance>,
474478
layout: TyAndLayout<'tcx>,
479+
ret_layout: TyAndLayout<'tcx>,
475480
) -> InterpResult<'tcx, Scalar<M::Provenance>> {
476481
assert!(layout.ty.is_integral(), "invalid type for numeric intrinsic: {}", layout.ty);
477482
let bits = val.to_bits(layout.size)?;
@@ -483,11 +488,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
483488
}
484489
sym::ctlz | sym::ctlz_nonzero => u128::from(bits.leading_zeros()) - extra,
485490
sym::cttz | sym::cttz_nonzero => u128::from((bits << extra).trailing_zeros()) - extra,
486-
sym::bswap => (bits << extra).swap_bytes(),
487-
sym::bitreverse => (bits << extra).reverse_bits(),
491+
sym::bswap => {
492+
assert_eq!(layout, ret_layout);
493+
(bits << extra).swap_bytes()
494+
}
495+
sym::bitreverse => {
496+
assert_eq!(layout, ret_layout);
497+
(bits << extra).reverse_bits()
498+
}
488499
_ => bug!("not a numeric intrinsic: {}", name),
489500
};
490-
Ok(Scalar::from_uint(bits_out, layout.size))
501+
Ok(Scalar::from_uint(bits_out, ret_layout.size))
491502
}
492503

493504
pub fn exact_div(

compiler/rustc_hir_analysis/src/check/intrinsic.rs

+6-8
Original file line numberDiff line numberDiff line change
@@ -412,13 +412,11 @@ pub fn check_intrinsic_type(
412412
(1, 0, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], Ty::new_unit(tcx))
413413
}
414414

415-
sym::ctpop
416-
| sym::ctlz
417-
| sym::ctlz_nonzero
418-
| sym::cttz
419-
| sym::cttz_nonzero
420-
| sym::bswap
421-
| sym::bitreverse => (1, 0, vec![param(0)], param(0)),
415+
sym::ctpop | sym::ctlz | sym::ctlz_nonzero | sym::cttz | sym::cttz_nonzero => {
416+
(1, 0, vec![param(0)], tcx.types.u32)
417+
}
418+
419+
sym::bswap | sym::bitreverse => (1, 0, vec![param(0)], param(0)),
422420

423421
sym::three_way_compare => {
424422
(1, 0, vec![param(0), param(0)], tcx.ty_ordering_enum(Some(span)))
@@ -461,7 +459,7 @@ pub fn check_intrinsic_type(
461459
(1, 0, vec![param(0), param(0)], param(0))
462460
}
463461
sym::unchecked_shl | sym::unchecked_shr => (2, 0, vec![param(0), param(1)], param(0)),
464-
sym::rotate_left | sym::rotate_right => (1, 0, vec![param(0), param(0)], param(0)),
462+
sym::rotate_left | sym::rotate_right => (1, 0, vec![param(0), tcx.types.u32], param(0)),
465463
sym::unchecked_add | sym::unchecked_sub | sym::unchecked_mul => {
466464
(1, 0, vec![param(0), param(0)], param(0))
467465
}

library/core/src/intrinsics.rs

+47
Original file line numberDiff line numberDiff line change
@@ -1987,6 +1987,13 @@ extern "rust-intrinsic" {
19871987
/// The stabilized versions of this intrinsic are available on the integer
19881988
/// primitives via the `count_ones` method. For example,
19891989
/// [`u32::count_ones`]
1990+
#[cfg(not(bootstrap))]
1991+
#[rustc_const_stable(feature = "const_ctpop", since = "1.40.0")]
1992+
#[rustc_safe_intrinsic]
1993+
#[rustc_nounwind]
1994+
pub fn ctpop<T: Copy>(x: T) -> u32;
1995+
1996+
#[cfg(bootstrap)]
19901997
#[rustc_const_stable(feature = "const_ctpop", since = "1.40.0")]
19911998
#[rustc_safe_intrinsic]
19921999
#[rustc_nounwind]
@@ -2028,6 +2035,13 @@ extern "rust-intrinsic" {
20282035
/// let num_leading = ctlz(x);
20292036
/// assert_eq!(num_leading, 16);
20302037
/// ```
2038+
#[cfg(not(bootstrap))]
2039+
#[rustc_const_stable(feature = "const_ctlz", since = "1.40.0")]
2040+
#[rustc_safe_intrinsic]
2041+
#[rustc_nounwind]
2042+
pub fn ctlz<T: Copy>(x: T) -> u32;
2043+
2044+
#[cfg(bootstrap)]
20312045
#[rustc_const_stable(feature = "const_ctlz", since = "1.40.0")]
20322046
#[rustc_safe_intrinsic]
20332047
#[rustc_nounwind]
@@ -2050,6 +2064,12 @@ extern "rust-intrinsic" {
20502064
/// let num_leading = unsafe { ctlz_nonzero(x) };
20512065
/// assert_eq!(num_leading, 3);
20522066
/// ```
2067+
#[cfg(not(bootstrap))]
2068+
#[rustc_const_stable(feature = "constctlz", since = "1.50.0")]
2069+
#[rustc_nounwind]
2070+
pub fn ctlz_nonzero<T: Copy>(x: T) -> u32;
2071+
2072+
#[cfg(bootstrap)]
20532073
#[rustc_const_stable(feature = "constctlz", since = "1.50.0")]
20542074
#[rustc_nounwind]
20552075
pub fn ctlz_nonzero<T: Copy>(x: T) -> T;
@@ -2090,6 +2110,13 @@ extern "rust-intrinsic" {
20902110
/// let num_trailing = cttz(x);
20912111
/// assert_eq!(num_trailing, 16);
20922112
/// ```
2113+
#[cfg(not(bootstrap))]
2114+
#[rustc_const_stable(feature = "const_cttz", since = "1.40.0")]
2115+
#[rustc_safe_intrinsic]
2116+
#[rustc_nounwind]
2117+
pub fn cttz<T: Copy>(x: T) -> u32;
2118+
2119+
#[cfg(bootstrap)]
20932120
#[rustc_const_stable(feature = "const_cttz", since = "1.40.0")]
20942121
#[rustc_safe_intrinsic]
20952122
#[rustc_nounwind]
@@ -2112,6 +2139,12 @@ extern "rust-intrinsic" {
21122139
/// let num_trailing = unsafe { cttz_nonzero(x) };
21132140
/// assert_eq!(num_trailing, 3);
21142141
/// ```
2142+
#[cfg(not(bootstrap))]
2143+
#[rustc_const_stable(feature = "const_cttz_nonzero", since = "1.53.0")]
2144+
#[rustc_nounwind]
2145+
pub fn cttz_nonzero<T: Copy>(x: T) -> u32;
2146+
2147+
#[cfg(bootstrap)]
21152148
#[rustc_const_stable(feature = "const_cttz_nonzero", since = "1.53.0")]
21162149
#[rustc_nounwind]
21172150
pub fn cttz_nonzero<T: Copy>(x: T) -> T;
@@ -2288,6 +2321,13 @@ extern "rust-intrinsic" {
22882321
/// The stabilized versions of this intrinsic are available on the integer
22892322
/// primitives via the `rotate_left` method. For example,
22902323
/// [`u32::rotate_left`]
2324+
#[cfg(not(bootstrap))]
2325+
#[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
2326+
#[rustc_safe_intrinsic]
2327+
#[rustc_nounwind]
2328+
pub fn rotate_left<T: Copy>(x: T, shift: u32) -> T;
2329+
2330+
#[cfg(bootstrap)]
22912331
#[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
22922332
#[rustc_safe_intrinsic]
22932333
#[rustc_nounwind]
@@ -2303,6 +2343,13 @@ extern "rust-intrinsic" {
23032343
/// The stabilized versions of this intrinsic are available on the integer
23042344
/// primitives via the `rotate_right` method. For example,
23052345
/// [`u32::rotate_right`]
2346+
#[cfg(not(bootstrap))]
2347+
#[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
2348+
#[rustc_safe_intrinsic]
2349+
#[rustc_nounwind]
2350+
pub fn rotate_right<T: Copy>(x: T, shift: u32) -> T;
2351+
2352+
#[cfg(bootstrap)]
23062353
#[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
23072354
#[rustc_safe_intrinsic]
23082355
#[rustc_nounwind]

library/core/src/num/nonzero.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,12 @@ macro_rules! nonzero_integer {
527527
#[inline]
528528
pub const fn leading_zeros(self) -> u32 {
529529
// SAFETY: since `self` cannot be zero, it is safe to call `ctlz_nonzero`.
530-
unsafe { intrinsics::ctlz_nonzero(self.get() as $UnsignedPrimitive) as u32 }
530+
unsafe {
531+
#[cfg(not(bootstrap))]
532+
return intrinsics::ctlz_nonzero(self.get() as $UnsignedPrimitive);
533+
#[cfg(bootstrap)]
534+
return intrinsics::ctlz_nonzero(self.get() as $UnsignedPrimitive) as u32;
535+
}
531536
}
532537

533538
/// Returns the number of trailing zeros in the binary representation
@@ -551,7 +556,12 @@ macro_rules! nonzero_integer {
551556
#[inline]
552557
pub const fn trailing_zeros(self) -> u32 {
553558
// SAFETY: since `self` cannot be zero, it is safe to call `cttz_nonzero`.
554-
unsafe { intrinsics::cttz_nonzero(self.get() as $UnsignedPrimitive) as u32 }
559+
unsafe {
560+
#[cfg(not(bootstrap))]
561+
return intrinsics::cttz_nonzero(self.get() as $UnsignedPrimitive);
562+
#[cfg(bootstrap)]
563+
return intrinsics::cttz_nonzero(self.get() as $UnsignedPrimitive) as u32;
564+
}
555565
}
556566

557567
/// Returns the number of ones in the binary representation of `self`.

0 commit comments

Comments
 (0)