Rollup merge of #120562 - oli-obk:revert_stuff, r=cuviper
Revert unsound libcore changes fixes #120537 these were introduced in #119911
This commit is contained in:
commit
977945d285
@ -200,7 +200,6 @@
|
|||||||
//
|
//
|
||||||
// Language features:
|
// Language features:
|
||||||
// tidy-alphabetical-start
|
// tidy-alphabetical-start
|
||||||
#![cfg_attr(not(bootstrap), feature(is_val_statically_known))]
|
|
||||||
#![feature(abi_unadjusted)]
|
#![feature(abi_unadjusted)]
|
||||||
#![feature(adt_const_params)]
|
#![feature(adt_const_params)]
|
||||||
#![feature(allow_internal_unsafe)]
|
#![feature(allow_internal_unsafe)]
|
||||||
|
@ -1374,40 +1374,8 @@ macro_rules! int_impl {
|
|||||||
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
||||||
#[must_use = "this returns the result of the operation, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn checked_pow(self, mut exp: u32) -> Option<Self> {
|
pub const fn checked_pow(self, mut exp: u32) -> Option<Self> {
|
||||||
// SAFETY: This path has the same behavior as the other.
|
|
||||||
if unsafe { intrinsics::is_val_statically_known(self) }
|
|
||||||
&& self.unsigned_abs().is_power_of_two()
|
|
||||||
{
|
|
||||||
if self == 1 { // Avoid divide by zero
|
|
||||||
return Some(1);
|
|
||||||
}
|
|
||||||
if self == -1 { // Avoid divide by zero
|
|
||||||
return Some(if exp & 1 != 0 { -1 } else { 1 });
|
|
||||||
}
|
|
||||||
// SAFETY: We just checked this is a power of two. and above zero.
|
|
||||||
let power_used = unsafe { intrinsics::cttz_nonzero(self.wrapping_abs()) as u32 };
|
|
||||||
if exp > Self::BITS / power_used { return None; } // Division of constants is free
|
|
||||||
|
|
||||||
// SAFETY: exp <= Self::BITS / power_used
|
|
||||||
let res = unsafe { intrinsics::unchecked_shl(
|
|
||||||
1 as Self,
|
|
||||||
intrinsics::unchecked_mul(power_used, exp) as Self
|
|
||||||
)};
|
|
||||||
// LLVM doesn't always optimize out the checks
|
|
||||||
// at the ir level.
|
|
||||||
|
|
||||||
let sign = self.is_negative() && exp & 1 != 0;
|
|
||||||
if !sign && res == Self::MIN {
|
|
||||||
None
|
|
||||||
} else if sign {
|
|
||||||
Some(res.wrapping_neg())
|
|
||||||
} else {
|
|
||||||
Some(res)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if exp == 0 {
|
if exp == 0 {
|
||||||
return Some(1);
|
return Some(1);
|
||||||
}
|
}
|
||||||
@ -1427,7 +1395,6 @@ macro_rules! int_impl {
|
|||||||
// needless overflow.
|
// needless overflow.
|
||||||
acc.checked_mul(base)
|
acc.checked_mul(base)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Strict exponentiation. Computes `self.pow(exp)`, panicking if
|
/// Strict exponentiation. Computes `self.pow(exp)`, panicking if
|
||||||
/// overflow occurred.
|
/// overflow occurred.
|
||||||
@ -2091,38 +2058,8 @@ macro_rules! int_impl {
|
|||||||
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
||||||
#[must_use = "this returns the result of the operation, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn wrapping_pow(self, mut exp: u32) -> Self {
|
pub const fn wrapping_pow(self, mut exp: u32) -> Self {
|
||||||
// SAFETY: This path has the same behavior as the other.
|
|
||||||
if unsafe { intrinsics::is_val_statically_known(self) }
|
|
||||||
&& self.unsigned_abs().is_power_of_two()
|
|
||||||
{
|
|
||||||
if self == 1 { // Avoid divide by zero
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if self == -1 { // Avoid divide by zero
|
|
||||||
return if exp & 1 != 0 { -1 } else { 1 };
|
|
||||||
}
|
|
||||||
// SAFETY: We just checked this is a power of two. and above zero.
|
|
||||||
let power_used = unsafe { intrinsics::cttz_nonzero(self.wrapping_abs()) as u32 };
|
|
||||||
if exp > Self::BITS / power_used { return 0; } // Division of constants is free
|
|
||||||
|
|
||||||
// SAFETY: exp <= Self::BITS / power_used
|
|
||||||
let res = unsafe { intrinsics::unchecked_shl(
|
|
||||||
1 as Self,
|
|
||||||
intrinsics::unchecked_mul(power_used, exp) as Self
|
|
||||||
)};
|
|
||||||
// LLVM doesn't always optimize out the checks
|
|
||||||
// at the ir level.
|
|
||||||
|
|
||||||
let sign = self.is_negative() && exp & 1 != 0;
|
|
||||||
if sign {
|
|
||||||
res.wrapping_neg()
|
|
||||||
} else {
|
|
||||||
res
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if exp == 0 {
|
if exp == 0 {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -2143,7 +2080,6 @@ macro_rules! int_impl {
|
|||||||
// needless overflow.
|
// needless overflow.
|
||||||
acc.wrapping_mul(base)
|
acc.wrapping_mul(base)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Calculates `self` + `rhs`
|
/// Calculates `self` + `rhs`
|
||||||
///
|
///
|
||||||
@ -2625,39 +2561,8 @@ macro_rules! int_impl {
|
|||||||
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
||||||
#[must_use = "this returns the result of the operation, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
|
pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
|
||||||
// SAFETY: This path has the same behavior as the other.
|
|
||||||
if unsafe { intrinsics::is_val_statically_known(self) }
|
|
||||||
&& self.unsigned_abs().is_power_of_two()
|
|
||||||
{
|
|
||||||
if self == 1 { // Avoid divide by zero
|
|
||||||
return (1, false);
|
|
||||||
}
|
|
||||||
if self == -1 { // Avoid divide by zero
|
|
||||||
return (if exp & 1 != 0 { -1 } else { 1 }, false);
|
|
||||||
}
|
|
||||||
// SAFETY: We just checked this is a power of two. and above zero.
|
|
||||||
let power_used = unsafe { intrinsics::cttz_nonzero(self.wrapping_abs()) as u32 };
|
|
||||||
if exp > Self::BITS / power_used { return (0, true); } // Division of constants is free
|
|
||||||
|
|
||||||
// SAFETY: exp <= Self::BITS / power_used
|
|
||||||
let res = unsafe { intrinsics::unchecked_shl(
|
|
||||||
1 as Self,
|
|
||||||
intrinsics::unchecked_mul(power_used, exp) as Self
|
|
||||||
)};
|
|
||||||
// LLVM doesn't always optimize out the checks
|
|
||||||
// at the ir level.
|
|
||||||
|
|
||||||
let sign = self.is_negative() && exp & 1 != 0;
|
|
||||||
let overflow = res == Self::MIN;
|
|
||||||
if sign {
|
|
||||||
(res.wrapping_neg(), overflow)
|
|
||||||
} else {
|
|
||||||
(res, overflow)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if exp == 0 {
|
if exp == 0 {
|
||||||
return (1,false);
|
return (1,false);
|
||||||
}
|
}
|
||||||
@ -2687,7 +2592,6 @@ macro_rules! int_impl {
|
|||||||
r.1 |= overflown;
|
r.1 |= overflown;
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Raises self to the power of `exp`, using exponentiation by squaring.
|
/// Raises self to the power of `exp`, using exponentiation by squaring.
|
||||||
///
|
///
|
||||||
@ -2704,48 +2608,9 @@ macro_rules! int_impl {
|
|||||||
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
||||||
#[must_use = "this returns the result of the operation, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_inherit_overflow_checks]
|
#[rustc_inherit_overflow_checks]
|
||||||
#[track_caller] // Hides the hackish overflow check for powers of two.
|
|
||||||
pub const fn pow(self, mut exp: u32) -> Self {
|
pub const fn pow(self, mut exp: u32) -> Self {
|
||||||
// SAFETY: This path has the same behavior as the other.
|
|
||||||
if unsafe { intrinsics::is_val_statically_known(self) }
|
|
||||||
&& self.unsigned_abs().is_power_of_two()
|
|
||||||
{
|
|
||||||
if self == 1 { // Avoid divide by zero
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if self == -1 { // Avoid divide by zero
|
|
||||||
return if exp & 1 != 0 { -1 } else { 1 };
|
|
||||||
}
|
|
||||||
// SAFETY: We just checked this is a power of two. and above zero.
|
|
||||||
let power_used = unsafe { intrinsics::cttz_nonzero(self.wrapping_abs()) as u32 };
|
|
||||||
if exp > Self::BITS / power_used { // Division of constants is free
|
|
||||||
#[allow(arithmetic_overflow)]
|
|
||||||
return Self::MAX * Self::MAX * 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// SAFETY: exp <= Self::BITS / power_used
|
|
||||||
let res = unsafe { intrinsics::unchecked_shl(
|
|
||||||
1 as Self,
|
|
||||||
intrinsics::unchecked_mul(power_used, exp) as Self
|
|
||||||
)};
|
|
||||||
// LLVM doesn't always optimize out the checks
|
|
||||||
// at the ir level.
|
|
||||||
|
|
||||||
let sign = self.is_negative() && exp & 1 != 0;
|
|
||||||
#[allow(arithmetic_overflow)]
|
|
||||||
if !sign && res == Self::MIN {
|
|
||||||
// So it panics.
|
|
||||||
_ = Self::MAX * Self::MAX;
|
|
||||||
}
|
|
||||||
if sign {
|
|
||||||
res.wrapping_neg()
|
|
||||||
} else {
|
|
||||||
res
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if exp == 0 {
|
if exp == 0 {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -2766,7 +2631,6 @@ macro_rules! int_impl {
|
|||||||
// needless overflow.
|
// needless overflow.
|
||||||
acc * base
|
acc * base
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the square root of the number, rounded down.
|
/// Returns the square root of the number, rounded down.
|
||||||
///
|
///
|
||||||
|
@ -1364,28 +1364,8 @@ macro_rules! uint_impl {
|
|||||||
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
||||||
#[must_use = "this returns the result of the operation, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn checked_pow(self, mut exp: u32) -> Option<Self> {
|
pub const fn checked_pow(self, mut exp: u32) -> Option<Self> {
|
||||||
// SAFETY: This path has the same behavior as the other.
|
|
||||||
if unsafe { intrinsics::is_val_statically_known(self) }
|
|
||||||
&& self.is_power_of_two()
|
|
||||||
{
|
|
||||||
if self == 1 { // Avoid divide by zero
|
|
||||||
return Some(1);
|
|
||||||
}
|
|
||||||
// SAFETY: We just checked this is a power of two. and above zero.
|
|
||||||
let power_used = unsafe { intrinsics::cttz_nonzero(self) as u32 };
|
|
||||||
if exp > Self::BITS / power_used { return None; } // Division of constants is free
|
|
||||||
|
|
||||||
// SAFETY: exp <= Self::BITS / power_used
|
|
||||||
unsafe { Some(intrinsics::unchecked_shl(
|
|
||||||
1 as Self,
|
|
||||||
intrinsics::unchecked_mul(power_used, exp) as Self
|
|
||||||
)) }
|
|
||||||
// LLVM doesn't always optimize out the checks
|
|
||||||
// at the ir level.
|
|
||||||
} else {
|
|
||||||
if exp == 0 {
|
if exp == 0 {
|
||||||
return Some(1);
|
return Some(1);
|
||||||
}
|
}
|
||||||
@ -1407,7 +1387,6 @@ macro_rules! uint_impl {
|
|||||||
|
|
||||||
acc.checked_mul(base)
|
acc.checked_mul(base)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Strict exponentiation. Computes `self.pow(exp)`, panicking if
|
/// Strict exponentiation. Computes `self.pow(exp)`, panicking if
|
||||||
/// overflow occurred.
|
/// overflow occurred.
|
||||||
@ -1908,28 +1887,8 @@ macro_rules! uint_impl {
|
|||||||
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
||||||
#[must_use = "this returns the result of the operation, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn wrapping_pow(self, mut exp: u32) -> Self {
|
pub const fn wrapping_pow(self, mut exp: u32) -> Self {
|
||||||
// SAFETY: This path has the same behavior as the other.
|
|
||||||
if unsafe { intrinsics::is_val_statically_known(self) }
|
|
||||||
&& self.is_power_of_two()
|
|
||||||
{
|
|
||||||
if self == 1 { // Avoid divide by zero
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
// SAFETY: We just checked this is a power of two. and above zero.
|
|
||||||
let power_used = unsafe { intrinsics::cttz_nonzero(self) as u32 };
|
|
||||||
if exp > Self::BITS / power_used { return 0; } // Division of constants is free
|
|
||||||
|
|
||||||
// SAFETY: exp <= Self::BITS / power_used
|
|
||||||
unsafe { intrinsics::unchecked_shl(
|
|
||||||
1 as Self,
|
|
||||||
intrinsics::unchecked_mul(power_used, exp) as Self
|
|
||||||
)}
|
|
||||||
// LLVM doesn't always optimize out the checks
|
|
||||||
// at the ir level.
|
|
||||||
} else {
|
|
||||||
if exp == 0 {
|
if exp == 0 {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -1950,7 +1909,6 @@ macro_rules! uint_impl {
|
|||||||
// needless overflow.
|
// needless overflow.
|
||||||
acc.wrapping_mul(base)
|
acc.wrapping_mul(base)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Calculates `self` + `rhs`
|
/// Calculates `self` + `rhs`
|
||||||
///
|
///
|
||||||
@ -2383,28 +2341,8 @@ macro_rules! uint_impl {
|
|||||||
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
||||||
#[must_use = "this returns the result of the operation, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
|
pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) {
|
||||||
// SAFETY: This path has the same behavior as the other.
|
|
||||||
if unsafe { intrinsics::is_val_statically_known(self) }
|
|
||||||
&& self.is_power_of_two()
|
|
||||||
{
|
|
||||||
if self == 1 { // Avoid divide by zero
|
|
||||||
return (1, false);
|
|
||||||
}
|
|
||||||
// SAFETY: We just checked this is a power of two. and above zero.
|
|
||||||
let power_used = unsafe { intrinsics::cttz_nonzero(self) as u32 };
|
|
||||||
if exp > Self::BITS / power_used { return (0, true); } // Division of constants is free
|
|
||||||
|
|
||||||
// SAFETY: exp <= Self::BITS / power_used
|
|
||||||
unsafe { (intrinsics::unchecked_shl(
|
|
||||||
1 as Self,
|
|
||||||
intrinsics::unchecked_mul(power_used, exp) as Self
|
|
||||||
), false) }
|
|
||||||
// LLVM doesn't always optimize out the checks
|
|
||||||
// at the ir level.
|
|
||||||
} else {
|
|
||||||
if exp == 0{
|
if exp == 0{
|
||||||
return (1,false);
|
return (1,false);
|
||||||
}
|
}
|
||||||
@ -2435,7 +2373,6 @@ macro_rules! uint_impl {
|
|||||||
|
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Raises self to the power of `exp`, using exponentiation by squaring.
|
/// Raises self to the power of `exp`, using exponentiation by squaring.
|
||||||
///
|
///
|
||||||
@ -2450,44 +2387,9 @@ macro_rules! uint_impl {
|
|||||||
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
#[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")]
|
||||||
#[must_use = "this returns the result of the operation, \
|
#[must_use = "this returns the result of the operation, \
|
||||||
without modifying the original"]
|
without modifying the original"]
|
||||||
#[rustc_allow_const_fn_unstable(is_val_statically_known, const_int_unchecked_arith)]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_inherit_overflow_checks]
|
#[rustc_inherit_overflow_checks]
|
||||||
#[track_caller] // Hides the hackish overflow check for powers of two.
|
|
||||||
pub const fn pow(self, mut exp: u32) -> Self {
|
pub const fn pow(self, mut exp: u32) -> Self {
|
||||||
// LLVM now knows that `self` is a constant value, but not a
|
|
||||||
// constant in Rust. This allows us to compute the power used at
|
|
||||||
// compile-time.
|
|
||||||
//
|
|
||||||
// This will likely add a branch in debug builds, but this should
|
|
||||||
// be ok.
|
|
||||||
//
|
|
||||||
// This is a massive performance boost in release builds as you can
|
|
||||||
// get the power of a power of two and the exponent through a `shl`
|
|
||||||
// instruction, but we must add a couple more checks for parity with
|
|
||||||
// our own `pow`.
|
|
||||||
// SAFETY: This path has the same behavior as the other.
|
|
||||||
if unsafe { intrinsics::is_val_statically_known(self) }
|
|
||||||
&& self.is_power_of_two()
|
|
||||||
{
|
|
||||||
if self == 1 { // Avoid divide by zero
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
// SAFETY: We just checked this is a power of two. and above zero.
|
|
||||||
let power_used = unsafe { intrinsics::cttz_nonzero(self) as u32 };
|
|
||||||
if exp > Self::BITS / power_used { // Division of constants is free
|
|
||||||
#[allow(arithmetic_overflow)]
|
|
||||||
return Self::MAX * Self::MAX * 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// SAFETY: exp <= Self::BITS / power_used
|
|
||||||
unsafe { intrinsics::unchecked_shl(
|
|
||||||
1 as Self,
|
|
||||||
intrinsics::unchecked_mul(power_used, exp) as Self
|
|
||||||
)}
|
|
||||||
// LLVM doesn't always optimize out the checks
|
|
||||||
// at the ir level.
|
|
||||||
} else {
|
|
||||||
if exp == 0 {
|
if exp == 0 {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -2508,7 +2410,6 @@ macro_rules! uint_impl {
|
|||||||
// needless overflow.
|
// needless overflow.
|
||||||
acc * base
|
acc * base
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the square root of the number, rounded down.
|
/// Returns the square root of the number, rounded down.
|
||||||
///
|
///
|
||||||
|
@ -1,55 +0,0 @@
|
|||||||
// compile-flags: --crate-type=lib -Zmerge-functions=disabled -O -C overflow-checks=false
|
|
||||||
|
|
||||||
// CHECK-LABEL: @a(
|
|
||||||
#[no_mangle]
|
|
||||||
pub fn a(exp: u32) -> u64 {
|
|
||||||
// CHECK: %{{[^ ]+}} = icmp ugt i32 %exp, 64
|
|
||||||
// CHECK: %{{[^ ]+}} = zext{{( nneg)?}} i32 %exp to i64
|
|
||||||
// CHECK: %{{[^ ]+}} = shl nuw i64 {{[^ ]+}}, %{{[^ ]+}}
|
|
||||||
// CHECK: ret i64 %{{[^ ]+}}
|
|
||||||
2u64.pow(exp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CHECK-LABEL: @b(
|
|
||||||
#[no_mangle]
|
|
||||||
pub fn b(exp: u32) -> i64 {
|
|
||||||
// CHECK: %{{[^ ]+}} = icmp ugt i32 %exp, 64
|
|
||||||
// CHECK: %{{[^ ]+}} = zext{{( nneg)?}} i32 %exp to i64
|
|
||||||
// CHECK: %{{[^ ]+}} = shl nuw i64 {{[^ ]+}}, %{{[^ ]+}}
|
|
||||||
// CHECK: ret i64 %{{[^ ]+}}
|
|
||||||
2i64.pow(exp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CHECK-LABEL: @c(
|
|
||||||
#[no_mangle]
|
|
||||||
pub fn c(exp: u32) -> u32 {
|
|
||||||
// CHECK: %{{[^ ]+}} = icmp ugt i32 %exp, 16
|
|
||||||
// CHECK: %{{[^ ]+}} = shl nuw nsw i32 %exp, 1
|
|
||||||
// CHECK: %{{[^ ]+}} = shl nuw i32 1, %{{[^ ]+}}
|
|
||||||
// CHECK: %{{[^ ]+}} = select i1 %{{[^ ]+}}, i32 0, i32 %{{[^ ]+}}
|
|
||||||
// CHECK: ret i32 %{{[^ ]+}}
|
|
||||||
4u32.pow(exp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CHECK-LABEL: @d(
|
|
||||||
#[no_mangle]
|
|
||||||
pub fn d(exp: u32) -> u32 {
|
|
||||||
// CHECK: %{{[^ ]+}} = icmp ugt i32 %exp, 6
|
|
||||||
// CHECK: %{{[^ ]+}} = mul nuw nsw i32 %exp, 5
|
|
||||||
// CHECK: %{{[^ ]+}} = shl nuw nsw i32 1, %{{[^ ]+}}
|
|
||||||
// CHECK: %{{[^ ]+}} = select i1 {{[^ ]+}}, i32 0, i32 %{{[^ ]+}}
|
|
||||||
// CHECK: ret i32 %{{[^ ]+}}
|
|
||||||
32u32.pow(exp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CHECK-LABEL: @e(
|
|
||||||
#[no_mangle]
|
|
||||||
pub fn e(exp: u32) -> i32 {
|
|
||||||
// CHECK: %{{[^ ]+}} = icmp ugt i32 %exp, 6
|
|
||||||
// CHECK: %{{[^ ]+}} = mul nuw {{(nsw )?}}i32 %exp, 5
|
|
||||||
// CHECK: %{{[^ ]+}} = shl nuw {{(nsw )?}}i32 1, %{{[^ ]+}}
|
|
||||||
// CHECK: %{{[^ ]+}} = select i1 {{[^ ]+}}, i32 0, i32 %{{[^ ]+}}
|
|
||||||
// CHECK: ret i32 %{{[^ ]+}}
|
|
||||||
32i32.pow(exp)
|
|
||||||
}
|
|
||||||
// note: d and e are expected to yield the same IR
|
|
Loading…
x
Reference in New Issue
Block a user