Rollup merge of #123226 - scottmcm:u32-shifts, r=WaffleLapkin

De-LLVM the unchecked shifts [MCP#693]

This is just one part of the MCP (https://github.com/rust-lang/compiler-team/issues/693), but it's the one that IMHO removes the most noise from the standard library code.

Seems net simpler this way, since MIR already supported heterogeneous shifts anyway, and thus it's not more work for backends than before.

r? WaffleLapkin
This commit is contained in:
Matthias Krüger 2024-04-02 21:22:01 +02:00 committed by GitHub
commit 1b0e46f8a0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
32 changed files with 408 additions and 576 deletions

View File

@ -5,7 +5,7 @@ use crate::back::write::{
compute_per_cgu_lto_type, start_async_codegen, submit_codegened_module_to_llvm, compute_per_cgu_lto_type, start_async_codegen, submit_codegened_module_to_llvm,
submit_post_lto_module_to_llvm, submit_pre_lto_module_to_llvm, ComputedLtoType, OngoingCodegen, submit_post_lto_module_to_llvm, submit_pre_lto_module_to_llvm, ComputedLtoType, OngoingCodegen,
}; };
use crate::common::{IntPredicate, RealPredicate, TypeKind}; use crate::common::{self, IntPredicate, RealPredicate, TypeKind};
use crate::errors; use crate::errors;
use crate::meth; use crate::meth;
use crate::mir; use crate::mir;
@ -33,7 +33,7 @@ use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem};
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
use rustc_session::config::{self, CrateType, EntryFnType, OutputType}; use rustc_session::config::{self, CrateType, EntryFnType, OptLevel, OutputType};
use rustc_session::Session; use rustc_session::Session;
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
use rustc_span::Symbol; use rustc_span::Symbol;
@ -300,14 +300,35 @@ pub fn coerce_unsized_into<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
} }
} }
pub fn cast_shift_expr_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( /// Returns `rhs` sufficiently masked, truncated, and/or extended so that
/// it can be used to shift `lhs`.
///
/// Shifts in MIR are all allowed to have mismatched LHS & RHS types.
/// The shift methods in `BuilderMethods`, however, are fully homogeneous
/// (both parameters and the return type are all the same type).
///
/// If `is_unchecked` is false, this masks the RHS to ensure it stays in-bounds,
/// as the `BuilderMethods` shifts are UB for out-of-bounds shift amounts.
/// For 32- and 64-bit types, this matches the semantics
/// of Java. (See related discussion on #1877 and #10183.)
///
/// If `is_unchecked` is true, this does no masking, and adds sufficient `assume`
/// calls or operation flags to preserve as much freedom to optimize as possible.
pub fn build_shift_expr_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
bx: &mut Bx, bx: &mut Bx,
lhs: Bx::Value, lhs: Bx::Value,
rhs: Bx::Value, mut rhs: Bx::Value,
is_unchecked: bool,
) -> Bx::Value { ) -> Bx::Value {
// Shifts may have any size int on the rhs // Shifts may have any size int on the rhs
let mut rhs_llty = bx.cx().val_ty(rhs); let mut rhs_llty = bx.cx().val_ty(rhs);
let mut lhs_llty = bx.cx().val_ty(lhs); let mut lhs_llty = bx.cx().val_ty(lhs);
let mask = common::shift_mask_val(bx, lhs_llty, rhs_llty, false);
if !is_unchecked {
rhs = bx.and(rhs, mask);
}
if bx.cx().type_kind(rhs_llty) == TypeKind::Vector { if bx.cx().type_kind(rhs_llty) == TypeKind::Vector {
rhs_llty = bx.cx().element_type(rhs_llty) rhs_llty = bx.cx().element_type(rhs_llty)
} }
@ -317,6 +338,12 @@ pub fn cast_shift_expr_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
let rhs_sz = bx.cx().int_width(rhs_llty); let rhs_sz = bx.cx().int_width(rhs_llty);
let lhs_sz = bx.cx().int_width(lhs_llty); let lhs_sz = bx.cx().int_width(lhs_llty);
if lhs_sz < rhs_sz { if lhs_sz < rhs_sz {
if is_unchecked && bx.sess().opts.optimize != OptLevel::No {
// FIXME: Use `trunc nuw` once that's available
let inrange = bx.icmp(IntPredicate::IntULE, rhs, mask);
bx.assume(inrange);
}
bx.trunc(rhs, lhs_llty) bx.trunc(rhs, lhs_llty)
} else if lhs_sz > rhs_sz { } else if lhs_sz > rhs_sz {
// We zero-extend even if the RHS is signed. So e.g. `(x: i32) << -1i8` will zero-extend the // We zero-extend even if the RHS is signed. So e.g. `(x: i32) << -1i8` will zero-extend the

View File

@ -3,10 +3,9 @@
use rustc_hir::LangItem; use rustc_hir::LangItem;
use rustc_middle::mir; use rustc_middle::mir;
use rustc_middle::ty::Instance; use rustc_middle::ty::Instance;
use rustc_middle::ty::{self, layout::TyAndLayout, Ty, TyCtxt}; use rustc_middle::ty::{self, layout::TyAndLayout, TyCtxt};
use rustc_span::Span; use rustc_span::Span;
use crate::base;
use crate::traits::*; use crate::traits::*;
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
@ -128,44 +127,6 @@ pub fn build_langcall<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
(bx.fn_abi_of_instance(instance, ty::List::empty()), bx.get_fn_addr(instance), instance) (bx.fn_abi_of_instance(instance, ty::List::empty()), bx.get_fn_addr(instance), instance)
} }
// To avoid UB from LLVM, these two functions mask RHS with an
// appropriate mask unconditionally (i.e., the fallback behavior for
// all shifts). For 32- and 64-bit types, this matches the semantics
// of Java. (See related discussion on #1877 and #10183.)
pub fn build_masked_lshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
bx: &mut Bx,
lhs: Bx::Value,
rhs: Bx::Value,
) -> Bx::Value {
let rhs = base::cast_shift_expr_rhs(bx, lhs, rhs);
// #1877, #10183: Ensure that input is always valid
let rhs = shift_mask_rhs(bx, rhs);
bx.shl(lhs, rhs)
}
pub fn build_masked_rshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
bx: &mut Bx,
lhs_t: Ty<'tcx>,
lhs: Bx::Value,
rhs: Bx::Value,
) -> Bx::Value {
let rhs = base::cast_shift_expr_rhs(bx, lhs, rhs);
// #1877, #10183: Ensure that input is always valid
let rhs = shift_mask_rhs(bx, rhs);
let is_signed = lhs_t.is_signed();
if is_signed { bx.ashr(lhs, rhs) } else { bx.lshr(lhs, rhs) }
}
fn shift_mask_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
bx: &mut Bx,
rhs: Bx::Value,
) -> Bx::Value {
let rhs_llty = bx.val_ty(rhs);
let shift_val = shift_mask_val(bx, rhs_llty, rhs_llty, false);
bx.and(rhs, shift_val)
}
pub fn shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( pub fn shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
bx: &mut Bx, bx: &mut Bx,
llty: Bx::Type, llty: Bx::Type,

View File

@ -3,7 +3,7 @@ use super::place::PlaceRef;
use super::{FunctionCx, LocalRef}; use super::{FunctionCx, LocalRef};
use crate::base; use crate::base;
use crate::common::{self, IntPredicate}; use crate::common::IntPredicate;
use crate::traits::*; use crate::traits::*;
use crate::MemFlags; use crate::MemFlags;
@ -860,14 +860,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
bx.inbounds_gep(llty, lhs, &[rhs]) bx.inbounds_gep(llty, lhs, &[rhs])
} }
} }
mir::BinOp::Shl => common::build_masked_lshift(bx, lhs, rhs), mir::BinOp::Shl | mir::BinOp::ShlUnchecked => {
mir::BinOp::ShlUnchecked => { let rhs = base::build_shift_expr_rhs(bx, lhs, rhs, op == mir::BinOp::ShlUnchecked);
let rhs = base::cast_shift_expr_rhs(bx, lhs, rhs);
bx.shl(lhs, rhs) bx.shl(lhs, rhs)
} }
mir::BinOp::Shr => common::build_masked_rshift(bx, input_ty, lhs, rhs), mir::BinOp::Shr | mir::BinOp::ShrUnchecked => {
mir::BinOp::ShrUnchecked => { let rhs = base::build_shift_expr_rhs(bx, lhs, rhs, op == mir::BinOp::ShrUnchecked);
let rhs = base::cast_shift_expr_rhs(bx, lhs, rhs);
if is_signed { bx.ashr(lhs, rhs) } else { bx.lshr(lhs, rhs) } if is_signed { bx.ashr(lhs, rhs) } else { bx.lshr(lhs, rhs) }
} }
mir::BinOp::Ne mir::BinOp::Ne

View File

@ -454,9 +454,8 @@ pub fn check_intrinsic_type(
sym::unchecked_div | sym::unchecked_rem | sym::exact_div => { sym::unchecked_div | sym::unchecked_rem | sym::exact_div => {
(1, 0, vec![param(0), param(0)], param(0)) (1, 0, vec![param(0), param(0)], param(0))
} }
sym::unchecked_shl | sym::unchecked_shr | sym::rotate_left | sym::rotate_right => { sym::unchecked_shl | sym::unchecked_shr => (2, 0, vec![param(0), param(1)], param(0)),
(1, 0, vec![param(0), param(0)], param(0)) sym::rotate_left | sym::rotate_right => (1, 0, vec![param(0), param(0)], param(0)),
}
sym::unchecked_add | sym::unchecked_sub | sym::unchecked_mul => { sym::unchecked_add | sym::unchecked_sub | sym::unchecked_mul => {
(1, 0, vec![param(0), param(0)], param(0)) (1, 0, vec![param(0), param(0)], param(0))
} }

View File

@ -2224,18 +2224,20 @@ extern "rust-intrinsic" {
/// Safe wrappers for this intrinsic are available on the integer /// Safe wrappers for this intrinsic are available on the integer
/// primitives via the `checked_shl` method. For example, /// primitives via the `checked_shl` method. For example,
/// [`u32::checked_shl`] /// [`u32::checked_shl`]
#[cfg(not(bootstrap))]
#[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")] #[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")]
#[rustc_nounwind] #[rustc_nounwind]
pub fn unchecked_shl<T: Copy>(x: T, y: T) -> T; pub fn unchecked_shl<T: Copy, U: Copy>(x: T, y: U) -> T;
/// Performs an unchecked right shift, resulting in undefined behavior when /// Performs an unchecked right shift, resulting in undefined behavior when
/// `y < 0` or `y >= N`, where N is the width of T in bits. /// `y < 0` or `y >= N`, where N is the width of T in bits.
/// ///
/// Safe wrappers for this intrinsic are available on the integer /// Safe wrappers for this intrinsic are available on the integer
/// primitives via the `checked_shr` method. For example, /// primitives via the `checked_shr` method. For example,
/// [`u32::checked_shr`] /// [`u32::checked_shr`]
#[cfg(not(bootstrap))]
#[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")] #[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")]
#[rustc_nounwind] #[rustc_nounwind]
pub fn unchecked_shr<T: Copy>(x: T, y: T) -> T; pub fn unchecked_shr<T: Copy, U: Copy>(x: T, y: U) -> T;
/// Returns the result of an unchecked addition, resulting in /// Returns the result of an unchecked addition, resulting in
/// undefined behavior when `x + y > T::MAX` or `x + y < T::MIN`. /// undefined behavior when `x + y > T::MAX` or `x + y < T::MIN`.

View File

@ -1227,10 +1227,18 @@ macro_rules! int_impl {
#[inline(always)] #[inline(always)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self { pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self {
// SAFETY: the caller must uphold the safety contract for #[cfg(bootstrap)]
// `unchecked_shl`. {
// Any legal shift amount is losslessly representable in the self type. // For bootstrapping, just use built-in primitive shift.
unsafe { intrinsics::unchecked_shl(self, conv_rhs_for_unchecked_shift!($SelfT, rhs)) } // panicking is a legal manifestation of UB
self << rhs
}
#[cfg(not(bootstrap))]
{
// SAFETY: the caller must uphold the safety contract for
// `unchecked_shl`.
unsafe { intrinsics::unchecked_shl(self, rhs) }
}
} }
/// Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is /// Checked shift right. Computes `self >> rhs`, returning `None` if `rhs` is
@ -1310,10 +1318,18 @@ macro_rules! int_impl {
#[inline(always)] #[inline(always)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self { pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self {
// SAFETY: the caller must uphold the safety contract for #[cfg(bootstrap)]
// `unchecked_shr`. {
// Any legal shift amount is losslessly representable in the self type. // For bootstrapping, just use built-in primitive shift.
unsafe { intrinsics::unchecked_shr(self, conv_rhs_for_unchecked_shift!($SelfT, rhs)) } // panicking is a legal manifestation of UB
self >> rhs
}
#[cfg(not(bootstrap))]
{
// SAFETY: the caller must uphold the safety contract for
// `unchecked_shr`.
unsafe { intrinsics::unchecked_shr(self, rhs) }
}
} }
/// Checked absolute value. Computes `self.abs()`, returning `None` if /// Checked absolute value. Computes `self.abs()`, returning `None` if

View File

@ -285,17 +285,6 @@ macro_rules! widening_impl {
}; };
} }
macro_rules! conv_rhs_for_unchecked_shift {
($SelfT:ty, $x:expr) => {{
// If the `as` cast will truncate, ensure we still tell the backend
// that the pre-truncation value was also small.
if <$SelfT>::BITS < 32 {
intrinsics::assume($x <= (<$SelfT>::MAX as u32));
}
$x as $SelfT
}};
}
impl i8 { impl i8 {
int_impl! { int_impl! {
Self = i8, Self = i8,

View File

@ -1286,10 +1286,18 @@ macro_rules! uint_impl {
#[inline(always)] #[inline(always)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self { pub const unsafe fn unchecked_shl(self, rhs: u32) -> Self {
// SAFETY: the caller must uphold the safety contract for #[cfg(bootstrap)]
// `unchecked_shl`. {
// Any legal shift amount is losslessly representable in the self type. // For bootstrapping, just use built-in primitive shift.
unsafe { intrinsics::unchecked_shl(self, conv_rhs_for_unchecked_shift!($SelfT, rhs)) } // panicking is a legal manifestation of UB
self << rhs
}
#[cfg(not(bootstrap))]
{
// SAFETY: the caller must uphold the safety contract for
// `unchecked_shl`.
unsafe { intrinsics::unchecked_shl(self, rhs) }
}
} }
/// Checked shift right. Computes `self >> rhs`, returning `None` /// Checked shift right. Computes `self >> rhs`, returning `None`
@ -1369,10 +1377,18 @@ macro_rules! uint_impl {
#[inline(always)] #[inline(always)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self { pub const unsafe fn unchecked_shr(self, rhs: u32) -> Self {
// SAFETY: the caller must uphold the safety contract for #[cfg(bootstrap)]
// `unchecked_shr`. {
// Any legal shift amount is losslessly representable in the self type. // For bootstrapping, just use built-in primitive shift.
unsafe { intrinsics::unchecked_shr(self, conv_rhs_for_unchecked_shift!($SelfT, rhs)) } // panicking is a legal manifestation of UB
self >> rhs
}
#[cfg(not(bootstrap))]
{
// SAFETY: the caller must uphold the safety contract for
// `unchecked_shr`.
unsafe { intrinsics::unchecked_shr(self, rhs) }
}
} }
/// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if /// Checked exponentiation. Computes `self.pow(exp)`, returning `None` if

View File

@ -1781,9 +1781,19 @@ pub(crate) const unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usiz
// FIXME(#75598): Direct use of these intrinsics improves codegen significantly at opt-level <= // FIXME(#75598): Direct use of these intrinsics improves codegen significantly at opt-level <=
// 1, where the method versions of these operations are not inlined. // 1, where the method versions of these operations are not inlined.
use intrinsics::{ use intrinsics::{
assume, cttz_nonzero, exact_div, mul_with_overflow, unchecked_rem, unchecked_shl, assume, cttz_nonzero, exact_div, mul_with_overflow, unchecked_rem, unchecked_sub,
unchecked_shr, unchecked_sub, wrapping_add, wrapping_mul, wrapping_sub, wrapping_add, wrapping_mul, wrapping_sub,
}; };
#[cfg(bootstrap)]
const unsafe fn unchecked_shl(value: usize, shift: usize) -> usize {
value << shift
}
#[cfg(bootstrap)]
const unsafe fn unchecked_shr(value: usize, shift: usize) -> usize {
value >> shift
}
#[cfg(not(bootstrap))]
use intrinsics::{unchecked_shl, unchecked_shr};
/// Calculate multiplicative modular inverse of `x` modulo `m`. /// Calculate multiplicative modular inverse of `x` modulo `m`.
/// ///

View File

@ -2,6 +2,7 @@
#![crate_type = "lib"] #![crate_type = "lib"]
#![feature(unchecked_shifts)] #![feature(unchecked_shifts)]
#![feature(core_intrinsics)]
// CHECK-LABEL: @unchecked_shl_unsigned_same // CHECK-LABEL: @unchecked_shl_unsigned_same
#[no_mangle] #[no_mangle]
@ -19,7 +20,7 @@ pub unsafe fn unchecked_shl_unsigned_smaller(a: u16, b: u32) -> u16 {
// This uses -DAG to avoid failing on irrelevant reorderings, // This uses -DAG to avoid failing on irrelevant reorderings,
// like emitting the truncation earlier. // like emitting the truncation earlier.
// CHECK-DAG: %[[INRANGE:.+]] = icmp ult i32 %b, 65536 // CHECK-DAG: %[[INRANGE:.+]] = icmp ult i32 %b, 16
// CHECK-DAG: tail call void @llvm.assume(i1 %[[INRANGE]]) // CHECK-DAG: tail call void @llvm.assume(i1 %[[INRANGE]])
// CHECK-DAG: %[[TRUNC:.+]] = trunc i32 %b to i16 // CHECK-DAG: %[[TRUNC:.+]] = trunc i32 %b to i16
// CHECK-DAG: shl i16 %a, %[[TRUNC]] // CHECK-DAG: shl i16 %a, %[[TRUNC]]
@ -51,7 +52,7 @@ pub unsafe fn unchecked_shr_signed_smaller(a: i16, b: u32) -> i16 {
// This uses -DAG to avoid failing on irrelevant reorderings, // This uses -DAG to avoid failing on irrelevant reorderings,
// like emitting the truncation earlier. // like emitting the truncation earlier.
// CHECK-DAG: %[[INRANGE:.+]] = icmp ult i32 %b, 32768 // CHECK-DAG: %[[INRANGE:.+]] = icmp ult i32 %b, 16
// CHECK-DAG: tail call void @llvm.assume(i1 %[[INRANGE]]) // CHECK-DAG: tail call void @llvm.assume(i1 %[[INRANGE]])
// CHECK-DAG: %[[TRUNC:.+]] = trunc i32 %b to i16 // CHECK-DAG: %[[TRUNC:.+]] = trunc i32 %b to i16
// CHECK-DAG: ashr i16 %a, %[[TRUNC]] // CHECK-DAG: ashr i16 %a, %[[TRUNC]]
@ -66,3 +67,47 @@ pub unsafe fn unchecked_shr_signed_bigger(a: i64, b: u32) -> i64 {
// CHECK: ashr i64 %a, %[[EXT]] // CHECK: ashr i64 %a, %[[EXT]]
a.unchecked_shr(b) a.unchecked_shr(b)
} }
// CHECK-LABEL: @unchecked_shr_u128_i8
#[no_mangle]
pub unsafe fn unchecked_shr_u128_i8(a: u128, b: i8) -> u128 {
// CHECK-NOT: assume
// CHECK: %[[EXT:.+]] = zext{{( nneg)?}} i8 %b to i128
// CHECK: lshr i128 %a, %[[EXT]]
std::intrinsics::unchecked_shr(a, b)
}
// CHECK-LABEL: @unchecked_shl_i128_u8
#[no_mangle]
pub unsafe fn unchecked_shl_i128_u8(a: i128, b: u8) -> i128 {
// CHECK-NOT: assume
// CHECK: %[[EXT:.+]] = zext{{( nneg)?}} i8 %b to i128
// CHECK: shl i128 %a, %[[EXT]]
std::intrinsics::unchecked_shl(a, b)
}
// CHECK-LABEL: @unchecked_shl_u8_i128
#[no_mangle]
pub unsafe fn unchecked_shl_u8_i128(a: u8, b: i128) -> u8 {
// This uses -DAG to avoid failing on irrelevant reorderings,
// like emitting the truncation earlier.
// CHECK-DAG: %[[INRANGE:.+]] = icmp ult i128 %b, 8
// CHECK-DAG: tail call void @llvm.assume(i1 %[[INRANGE]])
// CHECK-DAG: %[[TRUNC:.+]] = trunc i128 %b to i8
// CHECK-DAG: shl i8 %a, %[[TRUNC]]
std::intrinsics::unchecked_shl(a, b)
}
// CHECK-LABEL: @unchecked_shr_i8_u128
#[no_mangle]
pub unsafe fn unchecked_shr_i8_u128(a: i8, b: u128) -> i8 {
// This uses -DAG to avoid failing on irrelevant reorderings,
// like emitting the truncation earlier.
// CHECK-DAG: %[[INRANGE:.+]] = icmp ult i128 %b, 8
// CHECK-DAG: tail call void @llvm.assume(i1 %[[INRANGE]])
// CHECK-DAG: %[[TRUNC:.+]] = trunc i128 %b to i8
// CHECK-DAG: ashr i8 %a, %[[TRUNC]]
std::intrinsics::unchecked_shr(a, b)
}

View File

@ -4,6 +4,9 @@
//@ compile-flags: -Zmir-opt-level=2 -Zinline-mir //@ compile-flags: -Zmir-opt-level=2 -Zinline-mir
// These used to be more interesting when the library had to fix the RHS type.
// After MCP#693, though, that's the backend's problem, not something in MIR.
// EMIT_MIR unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff // EMIT_MIR unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff
// EMIT_MIR unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir // EMIT_MIR unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir
pub unsafe fn unchecked_shl_unsigned_smaller(a: u16, b: u32) -> u16 { pub unsafe fn unchecked_shl_unsigned_smaller(a: u16, b: u32) -> u16 {
@ -12,22 +15,6 @@ pub unsafe fn unchecked_shl_unsigned_smaller(a: u16, b: u32) -> u16 {
a.unchecked_shl(b) a.unchecked_shl(b)
} }
// EMIT_MIR unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff
// EMIT_MIR unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir
pub unsafe fn unchecked_shr_signed_smaller(a: i16, b: u32) -> i16 {
// CHECK-LABEL: fn unchecked_shr_signed_smaller(
// CHECK: (inlined core::num::<impl i16>::unchecked_shr)
a.unchecked_shr(b)
}
// EMIT_MIR unchecked_shifts.unchecked_shl_unsigned_bigger.Inline.diff
// EMIT_MIR unchecked_shifts.unchecked_shl_unsigned_bigger.PreCodegen.after.mir
pub unsafe fn unchecked_shl_unsigned_bigger(a: u64, b: u32) -> u64 {
// CHECK-LABEL: fn unchecked_shl_unsigned_bigger(
// CHECK: (inlined core::num::<impl u64>::unchecked_shl)
a.unchecked_shl(b)
}
// EMIT_MIR unchecked_shifts.unchecked_shr_signed_bigger.Inline.diff // EMIT_MIR unchecked_shifts.unchecked_shr_signed_bigger.Inline.diff
// EMIT_MIR unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.mir // EMIT_MIR unchecked_shifts.unchecked_shr_signed_bigger.PreCodegen.after.mir
pub unsafe fn unchecked_shr_signed_bigger(a: i64, b: u32) -> i64 { pub unsafe fn unchecked_shr_signed_bigger(a: i64, b: u32) -> i64 {

View File

@ -1,36 +0,0 @@
- // MIR for `unchecked_shl_unsigned_bigger` before Inline
+ // MIR for `unchecked_shl_unsigned_bigger` after Inline
fn unchecked_shl_unsigned_bigger(_1: u64, _2: u32) -> u64 {
debug a => _1;
debug b => _2;
let mut _0: u64;
let mut _3: u64;
let mut _4: u32;
+ scope 1 (inlined core::num::<impl u64>::unchecked_shl) {
+ debug self => _3;
+ debug rhs => _4;
+ let mut _5: u64;
+ scope 2 {
+ }
+ }
bb0: {
StorageLive(_3);
_3 = _1;
StorageLive(_4);
_4 = _2;
- _0 = core::num::<impl u64>::unchecked_shl(move _3, move _4) -> [return: bb1, unwind unreachable];
- }
-
- bb1: {
+ StorageLive(_5);
+ _5 = _4 as u64 (IntToInt);
+ _0 = ShlUnchecked(_3, move _5);
+ StorageDead(_5);
StorageDead(_4);
StorageDead(_3);
return;
}
}

View File

@ -1,36 +0,0 @@
- // MIR for `unchecked_shl_unsigned_bigger` before Inline
+ // MIR for `unchecked_shl_unsigned_bigger` after Inline
fn unchecked_shl_unsigned_bigger(_1: u64, _2: u32) -> u64 {
debug a => _1;
debug b => _2;
let mut _0: u64;
let mut _3: u64;
let mut _4: u32;
+ scope 1 (inlined core::num::<impl u64>::unchecked_shl) {
+ debug self => _3;
+ debug rhs => _4;
+ let mut _5: u64;
+ scope 2 {
+ }
+ }
bb0: {
StorageLive(_3);
_3 = _1;
StorageLive(_4);
_4 = _2;
- _0 = core::num::<impl u64>::unchecked_shl(move _3, move _4) -> [return: bb1, unwind continue];
- }
-
- bb1: {
+ StorageLive(_5);
+ _5 = _4 as u64 (IntToInt);
+ _0 = ShlUnchecked(_3, move _5);
+ StorageDead(_5);
StorageDead(_4);
StorageDead(_3);
return;
}
}

View File

@ -1,22 +0,0 @@
// MIR for `unchecked_shl_unsigned_bigger` after PreCodegen
fn unchecked_shl_unsigned_bigger(_1: u64, _2: u32) -> u64 {
debug a => _1;
debug b => _2;
let mut _0: u64;
scope 1 (inlined core::num::<impl u64>::unchecked_shl) {
debug self => _1;
debug rhs => _2;
let mut _3: u64;
scope 2 {
}
}
bb0: {
StorageLive(_3);
_3 = _2 as u64 (IntToInt);
_0 = ShlUnchecked(_1, move _3);
StorageDead(_3);
return;
}
}

View File

@ -1,22 +0,0 @@
// MIR for `unchecked_shl_unsigned_bigger` after PreCodegen
fn unchecked_shl_unsigned_bigger(_1: u64, _2: u32) -> u64 {
debug a => _1;
debug b => _2;
let mut _0: u64;
scope 1 (inlined core::num::<impl u64>::unchecked_shl) {
debug self => _1;
debug rhs => _2;
let mut _3: u64;
scope 2 {
}
}
bb0: {
StorageLive(_3);
_3 = _2 as u64 (IntToInt);
_0 = ShlUnchecked(_1, move _3);
StorageDead(_3);
return;
}
}

View File

@ -10,8 +10,6 @@
+ scope 1 (inlined core::num::<impl u16>::unchecked_shl) { + scope 1 (inlined core::num::<impl u16>::unchecked_shl) {
+ debug self => _3; + debug self => _3;
+ debug rhs => _4; + debug rhs => _4;
+ let mut _5: u16;
+ let mut _6: bool;
+ scope 2 { + scope 2 {
+ } + }
+ } + }
@ -25,14 +23,7 @@
- } - }
- -
- bb1: { - bb1: {
+ StorageLive(_5); + _0 = ShlUnchecked(_3, _4);
+ StorageLive(_6);
+ _6 = Le(_4, const 65535_u32);
+ assume(move _6);
+ StorageDead(_6);
+ _5 = _4 as u16 (IntToInt);
+ _0 = ShlUnchecked(_3, move _5);
+ StorageDead(_5);
StorageDead(_4); StorageDead(_4);
StorageDead(_3); StorageDead(_3);
return; return;

View File

@ -10,8 +10,6 @@
+ scope 1 (inlined core::num::<impl u16>::unchecked_shl) { + scope 1 (inlined core::num::<impl u16>::unchecked_shl) {
+ debug self => _3; + debug self => _3;
+ debug rhs => _4; + debug rhs => _4;
+ let mut _5: u16;
+ let mut _6: bool;
+ scope 2 { + scope 2 {
+ } + }
+ } + }
@ -25,14 +23,7 @@
- } - }
- -
- bb1: { - bb1: {
+ StorageLive(_5); + _0 = ShlUnchecked(_3, _4);
+ StorageLive(_6);
+ _6 = Le(_4, const 65535_u32);
+ assume(move _6);
+ StorageDead(_6);
+ _5 = _4 as u16 (IntToInt);
+ _0 = ShlUnchecked(_3, move _5);
+ StorageDead(_5);
StorageDead(_4); StorageDead(_4);
StorageDead(_3); StorageDead(_3);
return; return;

View File

@ -7,21 +7,12 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 {
scope 1 (inlined core::num::<impl u16>::unchecked_shl) { scope 1 (inlined core::num::<impl u16>::unchecked_shl) {
debug self => _1; debug self => _1;
debug rhs => _2; debug rhs => _2;
let mut _3: bool;
let mut _4: u16;
scope 2 { scope 2 {
} }
} }
bb0: { bb0: {
StorageLive(_4); _0 = ShlUnchecked(_1, _2);
StorageLive(_3);
_3 = Le(_2, const 65535_u32);
assume(move _3);
StorageDead(_3);
_4 = _2 as u16 (IntToInt);
_0 = ShlUnchecked(_1, move _4);
StorageDead(_4);
return; return;
} }
} }

View File

@ -7,21 +7,12 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 {
scope 1 (inlined core::num::<impl u16>::unchecked_shl) { scope 1 (inlined core::num::<impl u16>::unchecked_shl) {
debug self => _1; debug self => _1;
debug rhs => _2; debug rhs => _2;
let mut _3: bool;
let mut _4: u16;
scope 2 { scope 2 {
} }
} }
bb0: { bb0: {
StorageLive(_4); _0 = ShlUnchecked(_1, _2);
StorageLive(_3);
_3 = Le(_2, const 65535_u32);
assume(move _3);
StorageDead(_3);
_4 = _2 as u16 (IntToInt);
_0 = ShlUnchecked(_1, move _4);
StorageDead(_4);
return; return;
} }
} }

View File

@ -10,7 +10,6 @@
+ scope 1 (inlined core::num::<impl i64>::unchecked_shr) { + scope 1 (inlined core::num::<impl i64>::unchecked_shr) {
+ debug self => _3; + debug self => _3;
+ debug rhs => _4; + debug rhs => _4;
+ let mut _5: i64;
+ scope 2 { + scope 2 {
+ } + }
+ } + }
@ -24,10 +23,7 @@
- } - }
- -
- bb1: { - bb1: {
+ StorageLive(_5); + _0 = ShrUnchecked(_3, _4);
+ _5 = _4 as i64 (IntToInt);
+ _0 = ShrUnchecked(_3, move _5);
+ StorageDead(_5);
StorageDead(_4); StorageDead(_4);
StorageDead(_3); StorageDead(_3);
return; return;

View File

@ -10,7 +10,6 @@
+ scope 1 (inlined core::num::<impl i64>::unchecked_shr) { + scope 1 (inlined core::num::<impl i64>::unchecked_shr) {
+ debug self => _3; + debug self => _3;
+ debug rhs => _4; + debug rhs => _4;
+ let mut _5: i64;
+ scope 2 { + scope 2 {
+ } + }
+ } + }
@ -24,10 +23,7 @@
- } - }
- -
- bb1: { - bb1: {
+ StorageLive(_5); + _0 = ShrUnchecked(_3, _4);
+ _5 = _4 as i64 (IntToInt);
+ _0 = ShrUnchecked(_3, move _5);
+ StorageDead(_5);
StorageDead(_4); StorageDead(_4);
StorageDead(_3); StorageDead(_3);
return; return;

View File

@ -7,16 +7,12 @@ fn unchecked_shr_signed_bigger(_1: i64, _2: u32) -> i64 {
scope 1 (inlined core::num::<impl i64>::unchecked_shr) { scope 1 (inlined core::num::<impl i64>::unchecked_shr) {
debug self => _1; debug self => _1;
debug rhs => _2; debug rhs => _2;
let mut _3: i64;
scope 2 { scope 2 {
} }
} }
bb0: { bb0: {
StorageLive(_3); _0 = ShrUnchecked(_1, _2);
_3 = _2 as i64 (IntToInt);
_0 = ShrUnchecked(_1, move _3);
StorageDead(_3);
return; return;
} }
} }

View File

@ -7,16 +7,12 @@ fn unchecked_shr_signed_bigger(_1: i64, _2: u32) -> i64 {
scope 1 (inlined core::num::<impl i64>::unchecked_shr) { scope 1 (inlined core::num::<impl i64>::unchecked_shr) {
debug self => _1; debug self => _1;
debug rhs => _2; debug rhs => _2;
let mut _3: i64;
scope 2 { scope 2 {
} }
} }
bb0: { bb0: {
StorageLive(_3); _0 = ShrUnchecked(_1, _2);
_3 = _2 as i64 (IntToInt);
_0 = ShrUnchecked(_1, move _3);
StorageDead(_3);
return; return;
} }
} }

View File

@ -1,41 +0,0 @@
- // MIR for `unchecked_shr_signed_smaller` before Inline
+ // MIR for `unchecked_shr_signed_smaller` after Inline
fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 {
debug a => _1;
debug b => _2;
let mut _0: i16;
let mut _3: i16;
let mut _4: u32;
+ scope 1 (inlined core::num::<impl i16>::unchecked_shr) {
+ debug self => _3;
+ debug rhs => _4;
+ let mut _5: i16;
+ let mut _6: bool;
+ scope 2 {
+ }
+ }
bb0: {
StorageLive(_3);
_3 = _1;
StorageLive(_4);
_4 = _2;
- _0 = core::num::<impl i16>::unchecked_shr(move _3, move _4) -> [return: bb1, unwind unreachable];
- }
-
- bb1: {
+ StorageLive(_5);
+ StorageLive(_6);
+ _6 = Le(_4, const 32767_u32);
+ assume(move _6);
+ StorageDead(_6);
+ _5 = _4 as i16 (IntToInt);
+ _0 = ShrUnchecked(_3, move _5);
+ StorageDead(_5);
StorageDead(_4);
StorageDead(_3);
return;
}
}

View File

@ -1,41 +0,0 @@
- // MIR for `unchecked_shr_signed_smaller` before Inline
+ // MIR for `unchecked_shr_signed_smaller` after Inline
fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 {
debug a => _1;
debug b => _2;
let mut _0: i16;
let mut _3: i16;
let mut _4: u32;
+ scope 1 (inlined core::num::<impl i16>::unchecked_shr) {
+ debug self => _3;
+ debug rhs => _4;
+ let mut _5: i16;
+ let mut _6: bool;
+ scope 2 {
+ }
+ }
bb0: {
StorageLive(_3);
_3 = _1;
StorageLive(_4);
_4 = _2;
- _0 = core::num::<impl i16>::unchecked_shr(move _3, move _4) -> [return: bb1, unwind continue];
- }
-
- bb1: {
+ StorageLive(_5);
+ StorageLive(_6);
+ _6 = Le(_4, const 32767_u32);
+ assume(move _6);
+ StorageDead(_6);
+ _5 = _4 as i16 (IntToInt);
+ _0 = ShrUnchecked(_3, move _5);
+ StorageDead(_5);
StorageDead(_4);
StorageDead(_3);
return;
}
}

View File

@ -1,27 +0,0 @@
// MIR for `unchecked_shr_signed_smaller` after PreCodegen
fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 {
debug a => _1;
debug b => _2;
let mut _0: i16;
scope 1 (inlined core::num::<impl i16>::unchecked_shr) {
debug self => _1;
debug rhs => _2;
let mut _3: bool;
let mut _4: i16;
scope 2 {
}
}
bb0: {
StorageLive(_4);
StorageLive(_3);
_3 = Le(_2, const 32767_u32);
assume(move _3);
StorageDead(_3);
_4 = _2 as i16 (IntToInt);
_0 = ShrUnchecked(_1, move _4);
StorageDead(_4);
return;
}
}

View File

@ -1,27 +0,0 @@
// MIR for `unchecked_shr_signed_smaller` after PreCodegen
fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 {
debug a => _1;
debug b => _2;
let mut _0: i16;
scope 1 (inlined core::num::<impl i16>::unchecked_shr) {
debug self => _1;
debug rhs => _2;
let mut _3: bool;
let mut _4: i16;
scope 2 {
}
}
bb0: {
StorageLive(_4);
StorageLive(_3);
_3 = Le(_2, const 32767_u32);
assume(move _3);
StorageDead(_3);
_4 = _2 as i16 (IntToInt);
_0 = ShrUnchecked(_1, move _4);
StorageDead(_4);
return;
}
}

View File

@ -16,7 +16,7 @@ pub fn wrapping(a: i32, b: i32) {
} }
// EMIT_MIR lower_intrinsics.unchecked.LowerIntrinsics.diff // EMIT_MIR lower_intrinsics.unchecked.LowerIntrinsics.diff
pub unsafe fn unchecked(a: i32, b: i32) { pub unsafe fn unchecked(a: i32, b: i32, c: u32) {
// CHECK-LABEL: fn unchecked( // CHECK-LABEL: fn unchecked(
// CHECK: {{_.*}} = AddUnchecked( // CHECK: {{_.*}} = AddUnchecked(
// CHECK: {{_.*}} = SubUnchecked( // CHECK: {{_.*}} = SubUnchecked(
@ -25,6 +25,8 @@ pub unsafe fn unchecked(a: i32, b: i32) {
// CHECK: {{_.*}} = Rem( // CHECK: {{_.*}} = Rem(
// CHECK: {{_.*}} = ShlUnchecked( // CHECK: {{_.*}} = ShlUnchecked(
// CHECK: {{_.*}} = ShrUnchecked( // CHECK: {{_.*}} = ShrUnchecked(
// CHECK: {{_.*}} = ShlUnchecked(
// CHECK: {{_.*}} = ShrUnchecked(
let _a = core::intrinsics::unchecked_add(a, b); let _a = core::intrinsics::unchecked_add(a, b);
let _b = core::intrinsics::unchecked_sub(a, b); let _b = core::intrinsics::unchecked_sub(a, b);
let _c = core::intrinsics::unchecked_mul(a, b); let _c = core::intrinsics::unchecked_mul(a, b);
@ -32,6 +34,8 @@ pub unsafe fn unchecked(a: i32, b: i32) {
let _y = core::intrinsics::unchecked_rem(a, b); let _y = core::intrinsics::unchecked_rem(a, b);
let _i = core::intrinsics::unchecked_shl(a, b); let _i = core::intrinsics::unchecked_shl(a, b);
let _j = core::intrinsics::unchecked_shr(a, b); let _j = core::intrinsics::unchecked_shr(a, b);
let _k = core::intrinsics::unchecked_shl(a, c);
let _l = core::intrinsics::unchecked_shr(a, c);
} }
// EMIT_MIR lower_intrinsics.size_of.LowerIntrinsics.diff // EMIT_MIR lower_intrinsics.size_of.LowerIntrinsics.diff

View File

@ -1,45 +1,58 @@
- // MIR for `unchecked` before LowerIntrinsics - // MIR for `unchecked` before LowerIntrinsics
+ // MIR for `unchecked` after LowerIntrinsics + // MIR for `unchecked` after LowerIntrinsics
fn unchecked(_1: i32, _2: i32) -> () { fn unchecked(_1: i32, _2: i32, _3: u32) -> () {
debug a => _1; debug a => _1;
debug b => _2; debug b => _2;
debug c => _3;
let mut _0: (); let mut _0: ();
let _3: i32; let _4: i32;
let mut _4: i32;
let mut _5: i32; let mut _5: i32;
let mut _7: i32; let mut _6: i32;
let mut _8: i32; let mut _8: i32;
let mut _10: i32; let mut _9: i32;
let mut _11: i32; let mut _11: i32;
let mut _13: i32; let mut _12: i32;
let mut _14: i32; let mut _14: i32;
let mut _16: i32; let mut _15: i32;
let mut _17: i32; let mut _17: i32;
let mut _19: i32; let mut _18: i32;
let mut _20: i32; let mut _20: i32;
let mut _22: i32; let mut _21: i32;
let mut _23: i32; let mut _23: i32;
let mut _24: i32;
let mut _26: i32;
let mut _27: u32;
let mut _29: i32;
let mut _30: u32;
scope 1 { scope 1 {
debug _a => _3; debug _a => _4;
let _6: i32; let _7: i32;
scope 2 { scope 2 {
debug _b => _6; debug _b => _7;
let _9: i32; let _10: i32;
scope 3 { scope 3 {
debug _c => _9; debug _c => _10;
let _12: i32; let _13: i32;
scope 4 { scope 4 {
debug _x => _12; debug _x => _13;
let _15: i32; let _16: i32;
scope 5 { scope 5 {
debug _y => _15; debug _y => _16;
let _18: i32; let _19: i32;
scope 6 { scope 6 {
debug _i => _18; debug _i => _19;
let _21: i32; let _22: i32;
scope 7 { scope 7 {
debug _j => _21; debug _j => _22;
let _25: i32;
scope 8 {
debug _k => _25;
let _28: i32;
scope 9 {
debug _l => _28;
}
}
} }
} }
} }
@ -49,105 +62,133 @@
} }
bb0: { bb0: {
StorageLive(_3);
StorageLive(_4); StorageLive(_4);
_4 = _1;
StorageLive(_5); StorageLive(_5);
_5 = _2; _5 = _1;
- _3 = unchecked_add::<i32>(move _4, move _5) -> [return: bb1, unwind unreachable]; StorageLive(_6);
+ _3 = AddUnchecked(move _4, move _5); _6 = _2;
- _4 = unchecked_add::<i32>(move _5, move _6) -> [return: bb1, unwind unreachable];
+ _4 = AddUnchecked(move _5, move _6);
+ goto -> bb1; + goto -> bb1;
} }
bb1: { bb1: {
StorageDead(_6);
StorageDead(_5); StorageDead(_5);
StorageDead(_4);
StorageLive(_6);
StorageLive(_7); StorageLive(_7);
_7 = _1;
StorageLive(_8); StorageLive(_8);
_8 = _2; _8 = _1;
- _6 = unchecked_sub::<i32>(move _7, move _8) -> [return: bb2, unwind unreachable]; StorageLive(_9);
+ _6 = SubUnchecked(move _7, move _8); _9 = _2;
- _7 = unchecked_sub::<i32>(move _8, move _9) -> [return: bb2, unwind unreachable];
+ _7 = SubUnchecked(move _8, move _9);
+ goto -> bb2; + goto -> bb2;
} }
bb2: { bb2: {
StorageDead(_9);
StorageDead(_8); StorageDead(_8);
StorageDead(_7);
StorageLive(_9);
StorageLive(_10); StorageLive(_10);
_10 = _1;
StorageLive(_11); StorageLive(_11);
_11 = _2; _11 = _1;
- _9 = unchecked_mul::<i32>(move _10, move _11) -> [return: bb3, unwind unreachable]; StorageLive(_12);
+ _9 = MulUnchecked(move _10, move _11); _12 = _2;
- _10 = unchecked_mul::<i32>(move _11, move _12) -> [return: bb3, unwind unreachable];
+ _10 = MulUnchecked(move _11, move _12);
+ goto -> bb3; + goto -> bb3;
} }
bb3: { bb3: {
StorageDead(_12);
StorageDead(_11); StorageDead(_11);
StorageDead(_10);
StorageLive(_12);
StorageLive(_13); StorageLive(_13);
_13 = _1;
StorageLive(_14); StorageLive(_14);
_14 = _2; _14 = _1;
- _12 = unchecked_div::<i32>(move _13, move _14) -> [return: bb4, unwind unreachable]; StorageLive(_15);
+ _12 = Div(move _13, move _14); _15 = _2;
- _13 = unchecked_div::<i32>(move _14, move _15) -> [return: bb4, unwind unreachable];
+ _13 = Div(move _14, move _15);
+ goto -> bb4; + goto -> bb4;
} }
bb4: { bb4: {
StorageDead(_15);
StorageDead(_14); StorageDead(_14);
StorageDead(_13);
StorageLive(_15);
StorageLive(_16); StorageLive(_16);
_16 = _1;
StorageLive(_17); StorageLive(_17);
_17 = _2; _17 = _1;
- _15 = unchecked_rem::<i32>(move _16, move _17) -> [return: bb5, unwind unreachable]; StorageLive(_18);
+ _15 = Rem(move _16, move _17); _18 = _2;
- _16 = unchecked_rem::<i32>(move _17, move _18) -> [return: bb5, unwind unreachable];
+ _16 = Rem(move _17, move _18);
+ goto -> bb5; + goto -> bb5;
} }
bb5: { bb5: {
StorageDead(_18);
StorageDead(_17); StorageDead(_17);
StorageDead(_16);
StorageLive(_18);
StorageLive(_19); StorageLive(_19);
_19 = _1;
StorageLive(_20); StorageLive(_20);
_20 = _2; _20 = _1;
- _18 = unchecked_shl::<i32>(move _19, move _20) -> [return: bb6, unwind unreachable]; StorageLive(_21);
+ _18 = ShlUnchecked(move _19, move _20); _21 = _2;
- _19 = unchecked_shl::<i32, i32>(move _20, move _21) -> [return: bb6, unwind unreachable];
+ _19 = ShlUnchecked(move _20, move _21);
+ goto -> bb6; + goto -> bb6;
} }
bb6: { bb6: {
StorageDead(_21);
StorageDead(_20); StorageDead(_20);
StorageDead(_19);
StorageLive(_21);
StorageLive(_22); StorageLive(_22);
_22 = _1;
StorageLive(_23); StorageLive(_23);
_23 = _2; _23 = _1;
- _21 = unchecked_shr::<i32>(move _22, move _23) -> [return: bb7, unwind unreachable]; StorageLive(_24);
+ _21 = ShrUnchecked(move _22, move _23); _24 = _2;
- _22 = unchecked_shr::<i32, i32>(move _23, move _24) -> [return: bb7, unwind unreachable];
+ _22 = ShrUnchecked(move _23, move _24);
+ goto -> bb7; + goto -> bb7;
} }
bb7: { bb7: {
StorageDead(_24);
StorageDead(_23); StorageDead(_23);
StorageDead(_22); StorageLive(_25);
StorageLive(_26);
_26 = _1;
StorageLive(_27);
_27 = _3;
- _25 = unchecked_shl::<i32, u32>(move _26, move _27) -> [return: bb8, unwind unreachable];
+ _25 = ShlUnchecked(move _26, move _27);
+ goto -> bb8;
}
bb8: {
StorageDead(_27);
StorageDead(_26);
StorageLive(_28);
StorageLive(_29);
_29 = _1;
StorageLive(_30);
_30 = _3;
- _28 = unchecked_shr::<i32, u32>(move _29, move _30) -> [return: bb9, unwind unreachable];
+ _28 = ShrUnchecked(move _29, move _30);
+ goto -> bb9;
}
bb9: {
StorageDead(_30);
StorageDead(_29);
_0 = const (); _0 = const ();
StorageDead(_21); StorageDead(_28);
StorageDead(_18); StorageDead(_25);
StorageDead(_15); StorageDead(_22);
StorageDead(_12); StorageDead(_19);
StorageDead(_9); StorageDead(_16);
StorageDead(_6); StorageDead(_13);
StorageDead(_3); StorageDead(_10);
StorageDead(_7);
StorageDead(_4);
return; return;
} }
} }

View File

@ -1,45 +1,58 @@
- // MIR for `unchecked` before LowerIntrinsics - // MIR for `unchecked` before LowerIntrinsics
+ // MIR for `unchecked` after LowerIntrinsics + // MIR for `unchecked` after LowerIntrinsics
fn unchecked(_1: i32, _2: i32) -> () { fn unchecked(_1: i32, _2: i32, _3: u32) -> () {
debug a => _1; debug a => _1;
debug b => _2; debug b => _2;
debug c => _3;
let mut _0: (); let mut _0: ();
let _3: i32; let _4: i32;
let mut _4: i32;
let mut _5: i32; let mut _5: i32;
let mut _7: i32; let mut _6: i32;
let mut _8: i32; let mut _8: i32;
let mut _10: i32; let mut _9: i32;
let mut _11: i32; let mut _11: i32;
let mut _13: i32; let mut _12: i32;
let mut _14: i32; let mut _14: i32;
let mut _16: i32; let mut _15: i32;
let mut _17: i32; let mut _17: i32;
let mut _19: i32; let mut _18: i32;
let mut _20: i32; let mut _20: i32;
let mut _22: i32; let mut _21: i32;
let mut _23: i32; let mut _23: i32;
let mut _24: i32;
let mut _26: i32;
let mut _27: u32;
let mut _29: i32;
let mut _30: u32;
scope 1 { scope 1 {
debug _a => _3; debug _a => _4;
let _6: i32; let _7: i32;
scope 2 { scope 2 {
debug _b => _6; debug _b => _7;
let _9: i32; let _10: i32;
scope 3 { scope 3 {
debug _c => _9; debug _c => _10;
let _12: i32; let _13: i32;
scope 4 { scope 4 {
debug _x => _12; debug _x => _13;
let _15: i32; let _16: i32;
scope 5 { scope 5 {
debug _y => _15; debug _y => _16;
let _18: i32; let _19: i32;
scope 6 { scope 6 {
debug _i => _18; debug _i => _19;
let _21: i32; let _22: i32;
scope 7 { scope 7 {
debug _j => _21; debug _j => _22;
let _25: i32;
scope 8 {
debug _k => _25;
let _28: i32;
scope 9 {
debug _l => _28;
}
}
} }
} }
} }
@ -49,105 +62,133 @@
} }
bb0: { bb0: {
StorageLive(_3);
StorageLive(_4); StorageLive(_4);
_4 = _1;
StorageLive(_5); StorageLive(_5);
_5 = _2; _5 = _1;
- _3 = unchecked_add::<i32>(move _4, move _5) -> [return: bb1, unwind unreachable]; StorageLive(_6);
+ _3 = AddUnchecked(move _4, move _5); _6 = _2;
- _4 = unchecked_add::<i32>(move _5, move _6) -> [return: bb1, unwind unreachable];
+ _4 = AddUnchecked(move _5, move _6);
+ goto -> bb1; + goto -> bb1;
} }
bb1: { bb1: {
StorageDead(_6);
StorageDead(_5); StorageDead(_5);
StorageDead(_4);
StorageLive(_6);
StorageLive(_7); StorageLive(_7);
_7 = _1;
StorageLive(_8); StorageLive(_8);
_8 = _2; _8 = _1;
- _6 = unchecked_sub::<i32>(move _7, move _8) -> [return: bb2, unwind unreachable]; StorageLive(_9);
+ _6 = SubUnchecked(move _7, move _8); _9 = _2;
- _7 = unchecked_sub::<i32>(move _8, move _9) -> [return: bb2, unwind unreachable];
+ _7 = SubUnchecked(move _8, move _9);
+ goto -> bb2; + goto -> bb2;
} }
bb2: { bb2: {
StorageDead(_9);
StorageDead(_8); StorageDead(_8);
StorageDead(_7);
StorageLive(_9);
StorageLive(_10); StorageLive(_10);
_10 = _1;
StorageLive(_11); StorageLive(_11);
_11 = _2; _11 = _1;
- _9 = unchecked_mul::<i32>(move _10, move _11) -> [return: bb3, unwind unreachable]; StorageLive(_12);
+ _9 = MulUnchecked(move _10, move _11); _12 = _2;
- _10 = unchecked_mul::<i32>(move _11, move _12) -> [return: bb3, unwind unreachable];
+ _10 = MulUnchecked(move _11, move _12);
+ goto -> bb3; + goto -> bb3;
} }
bb3: { bb3: {
StorageDead(_12);
StorageDead(_11); StorageDead(_11);
StorageDead(_10);
StorageLive(_12);
StorageLive(_13); StorageLive(_13);
_13 = _1;
StorageLive(_14); StorageLive(_14);
_14 = _2; _14 = _1;
- _12 = unchecked_div::<i32>(move _13, move _14) -> [return: bb4, unwind unreachable]; StorageLive(_15);
+ _12 = Div(move _13, move _14); _15 = _2;
- _13 = unchecked_div::<i32>(move _14, move _15) -> [return: bb4, unwind unreachable];
+ _13 = Div(move _14, move _15);
+ goto -> bb4; + goto -> bb4;
} }
bb4: { bb4: {
StorageDead(_15);
StorageDead(_14); StorageDead(_14);
StorageDead(_13);
StorageLive(_15);
StorageLive(_16); StorageLive(_16);
_16 = _1;
StorageLive(_17); StorageLive(_17);
_17 = _2; _17 = _1;
- _15 = unchecked_rem::<i32>(move _16, move _17) -> [return: bb5, unwind unreachable]; StorageLive(_18);
+ _15 = Rem(move _16, move _17); _18 = _2;
- _16 = unchecked_rem::<i32>(move _17, move _18) -> [return: bb5, unwind unreachable];
+ _16 = Rem(move _17, move _18);
+ goto -> bb5; + goto -> bb5;
} }
bb5: { bb5: {
StorageDead(_18);
StorageDead(_17); StorageDead(_17);
StorageDead(_16);
StorageLive(_18);
StorageLive(_19); StorageLive(_19);
_19 = _1;
StorageLive(_20); StorageLive(_20);
_20 = _2; _20 = _1;
- _18 = unchecked_shl::<i32>(move _19, move _20) -> [return: bb6, unwind unreachable]; StorageLive(_21);
+ _18 = ShlUnchecked(move _19, move _20); _21 = _2;
- _19 = unchecked_shl::<i32, i32>(move _20, move _21) -> [return: bb6, unwind unreachable];
+ _19 = ShlUnchecked(move _20, move _21);
+ goto -> bb6; + goto -> bb6;
} }
bb6: { bb6: {
StorageDead(_21);
StorageDead(_20); StorageDead(_20);
StorageDead(_19);
StorageLive(_21);
StorageLive(_22); StorageLive(_22);
_22 = _1;
StorageLive(_23); StorageLive(_23);
_23 = _2; _23 = _1;
- _21 = unchecked_shr::<i32>(move _22, move _23) -> [return: bb7, unwind unreachable]; StorageLive(_24);
+ _21 = ShrUnchecked(move _22, move _23); _24 = _2;
- _22 = unchecked_shr::<i32, i32>(move _23, move _24) -> [return: bb7, unwind unreachable];
+ _22 = ShrUnchecked(move _23, move _24);
+ goto -> bb7; + goto -> bb7;
} }
bb7: { bb7: {
StorageDead(_24);
StorageDead(_23); StorageDead(_23);
StorageDead(_22); StorageLive(_25);
StorageLive(_26);
_26 = _1;
StorageLive(_27);
_27 = _3;
- _25 = unchecked_shl::<i32, u32>(move _26, move _27) -> [return: bb8, unwind unreachable];
+ _25 = ShlUnchecked(move _26, move _27);
+ goto -> bb8;
}
bb8: {
StorageDead(_27);
StorageDead(_26);
StorageLive(_28);
StorageLive(_29);
_29 = _1;
StorageLive(_30);
_30 = _3;
- _28 = unchecked_shr::<i32, u32>(move _29, move _30) -> [return: bb9, unwind unreachable];
+ _28 = ShrUnchecked(move _29, move _30);
+ goto -> bb9;
}
bb9: {
StorageDead(_30);
StorageDead(_29);
_0 = const (); _0 = const ();
StorageDead(_21); StorageDead(_28);
StorageDead(_18); StorageDead(_25);
StorageDead(_15); StorageDead(_22);
StorageDead(_12); StorageDead(_19);
StorageDead(_9); StorageDead(_16);
StorageDead(_6); StorageDead(_13);
StorageDead(_3); StorageDead(_10);
StorageDead(_7);
StorageDead(_4);
return; return;
} }
} }

View File

@ -27,7 +27,7 @@ const SHL_U128: u128 = unsafe { intrinsics::unchecked_shl(5_u128, 128) };
const SHL_I8: i8 = unsafe { intrinsics::unchecked_shl(5_i8, 8) }; const SHL_I8: i8 = unsafe { intrinsics::unchecked_shl(5_i8, 8) };
//~^ ERROR evaluation of constant value failed //~^ ERROR evaluation of constant value failed
const SHL_I16: i16 = unsafe { intrinsics::unchecked_shl(5_16, 16) }; const SHL_I16: i16 = unsafe { intrinsics::unchecked_shl(5_i16, 16) };
//~^ ERROR evaluation of constant value failed //~^ ERROR evaluation of constant value failed
const SHL_I32: i32 = unsafe { intrinsics::unchecked_shl(5_i32, 32) }; const SHL_I32: i32 = unsafe { intrinsics::unchecked_shl(5_i32, 32) };
//~^ ERROR evaluation of constant value failed //~^ ERROR evaluation of constant value failed
@ -40,7 +40,7 @@ const SHL_I128: i128 = unsafe { intrinsics::unchecked_shl(5_i128, 128) };
const SHL_I8_NEG: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -1) }; const SHL_I8_NEG: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -1) };
//~^ ERROR evaluation of constant value failed //~^ ERROR evaluation of constant value failed
const SHL_I16_NEG: i16 = unsafe { intrinsics::unchecked_shl(5_16, -1) }; const SHL_I16_NEG: i16 = unsafe { intrinsics::unchecked_shl(5_i16, -1) };
//~^ ERROR evaluation of constant value failed //~^ ERROR evaluation of constant value failed
const SHL_I32_NEG: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -1) }; const SHL_I32_NEG: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -1) };
//~^ ERROR evaluation of constant value failed //~^ ERROR evaluation of constant value failed
@ -54,7 +54,7 @@ const SHL_I128_NEG: i128 = unsafe { intrinsics::unchecked_shl(5_i128, -1) };
const SHL_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -6) }; const SHL_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -6) };
//~^ ERROR evaluation of constant value failed //~^ ERROR evaluation of constant value failed
const SHL_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shl(5_16, -13) }; const SHL_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shl(5_i16, -13) };
//~^ ERROR evaluation of constant value failed //~^ ERROR evaluation of constant value failed
const SHL_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -25) }; const SHL_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shl(5_i32, -25) };
//~^ ERROR evaluation of constant value failed //~^ ERROR evaluation of constant value failed
@ -82,7 +82,7 @@ const SHR_U128: u128 = unsafe { intrinsics::unchecked_shr(5_u128, 128) };
const SHR_I8: i8 = unsafe { intrinsics::unchecked_shr(5_i8, 8) }; const SHR_I8: i8 = unsafe { intrinsics::unchecked_shr(5_i8, 8) };
//~^ ERROR evaluation of constant value failed //~^ ERROR evaluation of constant value failed
const SHR_I16: i16 = unsafe { intrinsics::unchecked_shr(5_16, 16) }; const SHR_I16: i16 = unsafe { intrinsics::unchecked_shr(5_i16, 16) };
//~^ ERROR evaluation of constant value failed //~^ ERROR evaluation of constant value failed
const SHR_I32: i32 = unsafe { intrinsics::unchecked_shr(5_i32, 32) }; const SHR_I32: i32 = unsafe { intrinsics::unchecked_shr(5_i32, 32) };
//~^ ERROR evaluation of constant value failed //~^ ERROR evaluation of constant value failed
@ -95,7 +95,7 @@ const SHR_I128: i128 = unsafe { intrinsics::unchecked_shr(5_i128, 128) };
const SHR_I8_NEG: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -1) }; const SHR_I8_NEG: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -1) };
//~^ ERROR evaluation of constant value failed //~^ ERROR evaluation of constant value failed
const SHR_I16_NEG: i16 = unsafe { intrinsics::unchecked_shr(5_16, -1) }; const SHR_I16_NEG: i16 = unsafe { intrinsics::unchecked_shr(5_i16, -1) };
//~^ ERROR evaluation of constant value failed //~^ ERROR evaluation of constant value failed
const SHR_I32_NEG: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -1) }; const SHR_I32_NEG: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -1) };
//~^ ERROR evaluation of constant value failed //~^ ERROR evaluation of constant value failed
@ -109,7 +109,7 @@ const SHR_I128_NEG: i128 = unsafe { intrinsics::unchecked_shr(5_i128, -1) };
const SHR_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -6) }; const SHR_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -6) };
//~^ ERROR evaluation of constant value failed //~^ ERROR evaluation of constant value failed
const SHR_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shr(5_16, -13) }; const SHR_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shr(5_i16, -13) };
//~^ ERROR evaluation of constant value failed //~^ ERROR evaluation of constant value failed
const SHR_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -25) }; const SHR_I32_NEG_RANDOM: i32 = unsafe { intrinsics::unchecked_shr(5_i32, -25) };
//~^ ERROR evaluation of constant value failed //~^ ERROR evaluation of constant value failed

View File

@ -37,8 +37,8 @@ LL | const SHL_I8: i8 = unsafe { intrinsics::unchecked_shl(5_i8, 8) };
error[E0080]: evaluation of constant value failed error[E0080]: evaluation of constant value failed
--> $DIR/const-int-unchecked.rs:30:31 --> $DIR/const-int-unchecked.rs:30:31
| |
LL | const SHL_I16: i16 = unsafe { intrinsics::unchecked_shl(5_16, 16) }; LL | const SHL_I16: i16 = unsafe { intrinsics::unchecked_shl(5_i16, 16) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 16 in `unchecked_shl` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 16 in `unchecked_shl`
error[E0080]: evaluation of constant value failed error[E0080]: evaluation of constant value failed
--> $DIR/const-int-unchecked.rs:32:31 --> $DIR/const-int-unchecked.rs:32:31
@ -67,8 +67,8 @@ LL | const SHL_I8_NEG: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -1) };
error[E0080]: evaluation of constant value failed error[E0080]: evaluation of constant value failed
--> $DIR/const-int-unchecked.rs:43:35 --> $DIR/const-int-unchecked.rs:43:35
| |
LL | const SHL_I16_NEG: i16 = unsafe { intrinsics::unchecked_shl(5_16, -1) }; LL | const SHL_I16_NEG: i16 = unsafe { intrinsics::unchecked_shl(5_i16, -1) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -1 in `unchecked_shl` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -1 in `unchecked_shl`
error[E0080]: evaluation of constant value failed error[E0080]: evaluation of constant value failed
--> $DIR/const-int-unchecked.rs:45:35 --> $DIR/const-int-unchecked.rs:45:35
@ -97,8 +97,8 @@ LL | const SHL_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shl(5_i8, -6)
error[E0080]: evaluation of constant value failed error[E0080]: evaluation of constant value failed
--> $DIR/const-int-unchecked.rs:57:42 --> $DIR/const-int-unchecked.rs:57:42
| |
LL | const SHL_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shl(5_16, -13) }; LL | const SHL_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shl(5_i16, -13) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -13 in `unchecked_shl` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -13 in `unchecked_shl`
error[E0080]: evaluation of constant value failed error[E0080]: evaluation of constant value failed
--> $DIR/const-int-unchecked.rs:59:42 --> $DIR/const-int-unchecked.rs:59:42
@ -157,8 +157,8 @@ LL | const SHR_I8: i8 = unsafe { intrinsics::unchecked_shr(5_i8, 8) };
error[E0080]: evaluation of constant value failed error[E0080]: evaluation of constant value failed
--> $DIR/const-int-unchecked.rs:85:31 --> $DIR/const-int-unchecked.rs:85:31
| |
LL | const SHR_I16: i16 = unsafe { intrinsics::unchecked_shr(5_16, 16) }; LL | const SHR_I16: i16 = unsafe { intrinsics::unchecked_shr(5_i16, 16) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 16 in `unchecked_shr` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by 16 in `unchecked_shr`
error[E0080]: evaluation of constant value failed error[E0080]: evaluation of constant value failed
--> $DIR/const-int-unchecked.rs:87:31 --> $DIR/const-int-unchecked.rs:87:31
@ -187,8 +187,8 @@ LL | const SHR_I8_NEG: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -1) };
error[E0080]: evaluation of constant value failed error[E0080]: evaluation of constant value failed
--> $DIR/const-int-unchecked.rs:98:35 --> $DIR/const-int-unchecked.rs:98:35
| |
LL | const SHR_I16_NEG: i16 = unsafe { intrinsics::unchecked_shr(5_16, -1) }; LL | const SHR_I16_NEG: i16 = unsafe { intrinsics::unchecked_shr(5_i16, -1) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -1 in `unchecked_shr` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -1 in `unchecked_shr`
error[E0080]: evaluation of constant value failed error[E0080]: evaluation of constant value failed
--> $DIR/const-int-unchecked.rs:100:35 --> $DIR/const-int-unchecked.rs:100:35
@ -217,8 +217,8 @@ LL | const SHR_I8_NEG_RANDOM: i8 = unsafe { intrinsics::unchecked_shr(5_i8, -6)
error[E0080]: evaluation of constant value failed error[E0080]: evaluation of constant value failed
--> $DIR/const-int-unchecked.rs:112:42 --> $DIR/const-int-unchecked.rs:112:42
| |
LL | const SHR_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shr(5_16, -13) }; LL | const SHR_I16_NEG_RANDOM: i16 = unsafe { intrinsics::unchecked_shr(5_i16, -13) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -13 in `unchecked_shr` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing shift by -13 in `unchecked_shr`
error[E0080]: evaluation of constant value failed error[E0080]: evaluation of constant value failed
--> $DIR/const-int-unchecked.rs:114:42 --> $DIR/const-int-unchecked.rs:114:42