diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 8b112e695275a..780550fc4cc74 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -346,10 +346,6 @@ fn codegen_float_intrinsic_call<'tcx>( sym::log10f32 => ("log10f", 1, fx.tcx.types.f32, types::F32), sym::log10f64 => ("log10", 1, fx.tcx.types.f64, types::F64), sym::log10f128 => ("log10f128", 1, fx.tcx.types.f128, types::F128), - sym::fabsf16 => ("fabsf16", 1, fx.tcx.types.f16, types::F16), - sym::fabsf32 => ("fabsf", 1, fx.tcx.types.f32, types::F32), - sym::fabsf64 => ("fabs", 1, fx.tcx.types.f64, types::F64), - sym::fabsf128 => ("fabsf128", 1, fx.tcx.types.f128, types::F128), sym::fmaf16 => ("fmaf16", 3, fx.tcx.types.f16, types::F16), sym::fmaf32 => ("fmaf", 3, fx.tcx.types.f32, types::F32), sym::fmaf64 => ("fma", 3, fx.tcx.types.f64, types::F64), @@ -441,11 +437,7 @@ fn codegen_float_intrinsic_call<'tcx>( sym::copysignf32 | sym::copysignf64 => { CValue::by_val(fx.bcx.ins().fcopysign(args[0], args[1]), layout) } - sym::fabsf16 => CValue::by_val(codegen_f16_f128::abs_f16(fx, args[0]), layout), - sym::fabsf128 => CValue::by_val(codegen_f16_f128::abs_f128(fx, args[0]), layout), - sym::fabsf32 - | sym::fabsf64 - | sym::floorf32 + sym::floorf32 | sym::floorf64 | sym::ceilf32 | sym::ceilf64 @@ -456,7 +448,6 @@ fn codegen_float_intrinsic_call<'tcx>( | sym::sqrtf32 | sym::sqrtf64 => { let val = match intrinsic { - sym::fabsf32 | sym::fabsf64 => fx.bcx.ins().fabs(args[0]), sym::floorf32 | sym::floorf64 => fx.bcx.ins().floor(args[0]), sym::ceilf32 | sym::ceilf64 => fx.bcx.ins().ceil(args[0]), sym::truncf32 | sym::truncf64 => fx.bcx.ins().trunc(args[0]), @@ -1179,6 +1170,28 @@ fn codegen_regular_intrinsic_call<'tcx>( ret.write_cvalue(fx, old); } + sym::fabs => { + intrinsic_args!(fx, args => (arg); intrinsic); + let layout = arg.layout(); + let ty::Float(float_ty) = layout.ty.kind() else { + span_bug!( + source_info.span, + "expected float type for fabs intrinsic: {:?}", + layout.ty + ); + }; + let x = arg.load_scalar(fx); + let val = match float_ty { + FloatTy::F32 | FloatTy::F64 => fx.bcx.ins().fabs(x), + // FIXME(bytecodealliance/wasmtime#8312): Use `fabsf16` once Cranelift + // backend lowerings are implemented. + FloatTy::F16 => codegen_f16_f128::abs_f16(fx, x), + FloatTy::F128 => codegen_f16_f128::abs_f128(fx, x), + }; + let val = CValue::by_val(val, layout); + ret.write_cvalue(fx, val); + } + sym::minimumf16 => { intrinsic_args!(fx, args => (a, b); intrinsic); let a = a.load_scalar(fx); diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 3f1b33c73e638..83ac627d27c54 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -23,11 +23,11 @@ use rustc_codegen_ssa::traits::{ IntrinsicCallBuilderMethods, LayoutTypeCodegenMethods, }; use rustc_data_structures::fx::FxHashSet; -use rustc_middle::bug; #[cfg(feature = "master")] use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Instance, Ty}; +use rustc_middle::{bug, span_bug}; use rustc_span::{Span, Symbol, sym}; use rustc_target::callconv::{ArgAbi, PassMode}; @@ -70,8 +70,6 @@ fn get_simple_intrinsic<'gcc, 'tcx>( // FIXME: calling `fma` from libc without FMA target feature uses expensive software emulation sym::fmuladdf32 => "fmaf", // FIXME: use gcc intrinsic analogous to llvm.fmuladd.f32 sym::fmuladdf64 => "fma", // FIXME: use gcc intrinsic analogous to llvm.fmuladd.f64 - sym::fabsf32 => "fabsf", - sym::fabsf64 => "fabs", sym::minimumf32 => "fminimumf", sym::minimumf64 => "fminimum", sym::minimumf128 => { @@ -194,58 +192,29 @@ fn get_simple_function<'gcc, 'tcx>( } fn get_simple_function_f128<'gcc, 'tcx>( + span: Span, cx: &CodegenCx<'gcc, 'tcx>, name: Symbol, -) -> Option> { - if !cx.supports_f128_type { - return None; - } - +) -> Function<'gcc> { let f128_type = cx.type_f128(); let func_name = match name { sym::ceilf128 => "ceilf128", - sym::fabsf128 => "fabsf128", + sym::fabs => "fabsf128", sym::floorf128 => "floorf128", sym::truncf128 => "truncf128", sym::roundf128 => "roundf128", sym::round_ties_even_f128 => "roundevenf128", sym::sqrtf128 => "sqrtf128", - _ => return None, + _ => span_bug!(span, "used get_simple_function_f128 for non-unary f128 intrinsic"), }; - Some(cx.context.new_function( + cx.context.new_function( None, FunctionType::Extern, f128_type, &[cx.context.new_parameter(None, f128_type, "a")], func_name, false, - )) -} - -fn get_simple_function_f128_2args<'gcc, 'tcx>( - cx: &CodegenCx<'gcc, 'tcx>, - name: Symbol, -) -> Option> { - if !cx.supports_f128_type { - return None; - } - - let f128_type = cx.type_f128(); - let func_name = match name { - sym::copysignf128 => "copysignf128", - _ => return None, - }; - Some(cx.context.new_function( - None, - FunctionType::Extern, - f128_type, - &[ - cx.context.new_parameter(None, f128_type, "a"), - cx.context.new_parameter(None, f128_type, "b"), - ], - func_name, - false, - )) + ) } fn f16_builtin<'gcc, 'tcx>( @@ -257,7 +226,7 @@ fn f16_builtin<'gcc, 'tcx>( let builtin_name = match name { sym::ceilf16 => "__builtin_ceilf", sym::copysignf16 => "__builtin_copysignf", - sym::fabsf16 => "fabsf", + sym::fabs => "fabsf", sym::floorf16 => "__builtin_floorf", sym::fmaf16 => "fmaf", sym::powf16 => "__builtin_powf", @@ -297,11 +266,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc let fn_args = instance.args; let simple = get_simple_intrinsic(self, name); - // FIXME(antoyo): Only call get_simple_function_f128 and get_simple_function_f128_2args when - // it is the symbols for the supported f128 builtins. - let simple_func = get_simple_function(self, name) - .or_else(|| get_simple_function_f128(self, name)) - .or_else(|| get_simple_function_f128_2args(self, name)); + let simple_func = get_simple_function(self, name); let value = match name { _ if simple.is_some() => { @@ -322,7 +287,6 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc } sym::ceilf16 | sym::copysignf16 - | sym::fabsf16 | sym::floorf16 | sym::fmaf16 | sym::powf16 @@ -331,6 +295,40 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc | sym::round_ties_even_f16 | sym::sqrtf16 | sym::truncf16 => f16_builtin(self, name, args), + sym::ceilf128 + | sym::floorf128 + | sym::truncf128 + | sym::roundf128 + | sym::round_ties_even_f128 + | sym::sqrtf128 + if self.cx.supports_f128_type => + { + let func = get_simple_function_f128(span, self, name); + self.cx.context.new_call( + self.location, + func, + &args.iter().map(|arg| arg.immediate()).collect::>(), + ) + } + sym::copysignf128 if self.cx.supports_f128_type => { + let f128_type = self.cx.type_f128(); + let func = self.cx.context.new_function( + None, + FunctionType::Extern, + f128_type, + &[ + self.cx.context.new_parameter(None, f128_type, "a"), + self.cx.context.new_parameter(None, f128_type, "b"), + ], + "copysignf128", + false, + ); + self.cx.context.new_call( + self.location, + func, + &args.iter().map(|arg| arg.immediate()).collect::>(), + ) + } sym::fmaf128 => { let f128_type = self.cx.type_f128(); let func = self.cx.context.new_function( @@ -488,6 +486,23 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc } } } + sym::fabs => 'fabs: { + let ty = args[0].layout.ty; + let ty::Float(float_ty) = *ty.kind() else { + span_bug!(span, "expected float type for fabs intrinsic: {:?}", ty); + }; + let func = match float_ty { + ty::FloatTy::F16 => break 'fabs f16_builtin(self, name, args), + ty::FloatTy::F32 => self.context.get_builtin_function("fabsf"), + ty::FloatTy::F64 => self.context.get_builtin_function("fabs"), + ty::FloatTy::F128 => get_simple_function_f128(span, self, name), + }; + self.cx.context.new_call( + self.location, + func, + &args.iter().map(|arg| arg.immediate()).collect::>(), + ) + } sym::raw_eq => { use rustc_abi::BackendRepr::*; diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs index 1263b2285a8d0..1900572eee7d3 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs @@ -811,7 +811,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( }}; } let ty::Float(ref f) = *in_elem.kind() else { - return_error!(InvalidMonomorphization::FloatingPointType { span, name, in_ty }); + return_error!(InvalidMonomorphization::BasicFloatType { span, name, ty: in_ty }); }; let elem_ty = bx.cx.type_float_from_ty(*f); let (elem_ty_str, elem_ty, cast_type) = match f.bit_width() { diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index cc6ecee60b0e4..e965ef8668174 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -107,11 +107,6 @@ fn call_simple_intrinsic<'ll, 'tcx>( sym::fmuladdf64 => ("llvm.fmuladd", &[bx.type_f64()]), sym::fmuladdf128 => ("llvm.fmuladd", &[bx.type_f128()]), - sym::fabsf16 => ("llvm.fabs", &[bx.type_f16()]), - sym::fabsf32 => ("llvm.fabs", &[bx.type_f32()]), - sym::fabsf64 => ("llvm.fabs", &[bx.type_f64()]), - sym::fabsf128 => ("llvm.fabs", &[bx.type_f128()]), - // FIXME: LLVM currently mis-compile those intrinsics, re-enable them // when llvm/llvm-project#{139380,139381,140445} are fixed. //sym::minimumf16 => ("llvm.minimum", &[bx.type_f16()]), @@ -502,6 +497,20 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { } } + sym::fabs => { + let ty = args[0].layout.ty; + let ty::Float(f) = ty.kind() else { + span_bug!(span, "the `fabs` intrinsic requires a floating-point argument, got {:?}", ty); + }; + let llty = self.type_float_from_ty(*f); + let llvm_name = "llvm.fabs"; + self.call_intrinsic( + llvm_name, + &[llty], + &args.iter().map(|arg| arg.immediate()).collect::>(), + ) + } + sym::raw_eq => { use BackendRepr::*; let tp_ty = fn_args.type_at(0); @@ -1936,7 +1945,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( } let ty::Float(f) = in_elem.kind() else { - return_error!(InvalidMonomorphization::FloatingPointType { span, name, in_ty }); + return_error!(InvalidMonomorphization::BasicFloatType { span, name, ty: in_ty }); }; let elem_ty = bx.cx.type_float_from_ty(*f); diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 41337fc21a7b7..fad776d249e0e 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -739,14 +739,6 @@ pub enum InvalidMonomorphization<'tcx> { in_ty: Ty<'tcx>, }, - #[diag("invalid monomorphization of `{$name}` intrinsic: `{$in_ty}` is not a floating-point type", code = E0511)] - FloatingPointType { - #[primary_span] - span: Span, - name: Symbol, - in_ty: Ty<'tcx>, - }, - #[diag("invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}`", code = E0511)] UnrecognizedIntrinsic { #[primary_span] diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index d5f69d78ea6ae..17311188879c1 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -575,10 +575,23 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { sym::copysignf64 => self.float_copysign_intrinsic::(args, dest)?, sym::copysignf128 => self.float_copysign_intrinsic::(args, dest)?, - sym::fabsf16 => self.float_abs_intrinsic::(args, dest)?, - sym::fabsf32 => self.float_abs_intrinsic::(args, dest)?, - sym::fabsf64 => self.float_abs_intrinsic::(args, dest)?, - sym::fabsf128 => self.float_abs_intrinsic::(args, dest)?, + sym::fabs => { + let arg = self.read_immediate(&args[0])?; + let ty::Float(float_ty) = arg.layout.ty.kind() else { + span_bug!( + self.cur_span(), + "non-float type for float intrinsic: {}", + arg.layout.ty, + ); + }; + let out_val = match float_ty { + FloatTy::F16 => self.unop_float_intrinsic::(intrinsic_name, arg)?, + FloatTy::F32 => self.unop_float_intrinsic::(intrinsic_name, arg)?, + FloatTy::F64 => self.unop_float_intrinsic::(intrinsic_name, arg)?, + FloatTy::F128 => self.unop_float_intrinsic::(intrinsic_name, arg)?, + }; + self.write_scalar(out_val, dest)?; + } sym::floorf16 => self.float_round_intrinsic::( args, @@ -1020,6 +1033,22 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { interp_ok(Scalar::from_bool(lhs_bytes == rhs_bytes)) } + fn unop_float_intrinsic( + &self, + name: Symbol, + arg: ImmTy<'tcx, M::Provenance>, + ) -> InterpResult<'tcx, Scalar> + where + F: rustc_apfloat::Float + rustc_apfloat::FloatConvert + Into>, + { + let x: F = arg.to_scalar().to_float()?; + match name { + // bitwise, no NaN adjustments + sym::fabs => interp_ok(x.abs().into()), + _ => bug!("not a unary float intrinsic: {}", name), + } + } + fn float_minmax( &self, a: Scalar, @@ -1078,20 +1107,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { interp_ok(()) } - fn float_abs_intrinsic( - &mut self, - args: &[OpTy<'tcx, M::Provenance>], - dest: &PlaceTy<'tcx, M::Provenance>, - ) -> InterpResult<'tcx, ()> - where - F: rustc_apfloat::Float + rustc_apfloat::FloatConvert + Into>, - { - let x: F = self.read_scalar(&args[0])?.to_float()?; - // bitwise, no NaN adjustments - self.write_scalar(x.abs(), dest)?; - interp_ok(()) - } - fn float_round( &mut self, x: Scalar, diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 47420997a509a..e7cb6d2ba1645 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -111,10 +111,7 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi | sym::expf32 | sym::expf64 | sym::expf128 - | sym::fabsf16 - | sym::fabsf32 - | sym::fabsf64 - | sym::fabsf128 + | sym::fabs | sym::fadd_algebraic | sym::fdiv_algebraic | sym::field_offset @@ -463,10 +460,7 @@ pub(crate) fn check_intrinsic_type( (0, 0, vec![tcx.types.f128, tcx.types.f128, tcx.types.f128], tcx.types.f128) } - sym::fabsf16 => (0, 0, vec![tcx.types.f16], tcx.types.f16), - sym::fabsf32 => (0, 0, vec![tcx.types.f32], tcx.types.f32), - sym::fabsf64 => (0, 0, vec![tcx.types.f64], tcx.types.f64), - sym::fabsf128 => (0, 0, vec![tcx.types.f128], tcx.types.f128), + sym::fabs => (1, 0, vec![param(0)], param(0)), sym::minimum_number_nsz_f16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16), sym::minimum_number_nsz_f32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 26ced79b822ac..eb95d3a0d9059 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -914,10 +914,7 @@ symbols! { f64_nan, f128, f128_nan, - fabsf16, - fabsf32, - fabsf64, - fabsf128, + fabs, fadd_algebraic, fadd_fast, fake_variadic, diff --git a/library/core/src/intrinsics/bounds.rs b/library/core/src/intrinsics/bounds.rs index 353908598d40b..21705005ed0ae 100644 --- a/library/core/src/intrinsics/bounds.rs +++ b/library/core/src/intrinsics/bounds.rs @@ -39,3 +39,14 @@ impl ChangePointee for *mut T { impl ChangePointee for *const T { type Output = *const U; } + +/// Built-in float types (f16, f32, f64 and f128). +/// +/// # Safety +/// Must actually *be* such a type. +pub unsafe trait FloatPrimitive: Sized + Copy {} + +unsafe impl FloatPrimitive for f16 {} +unsafe impl FloatPrimitive for f32 {} +unsafe impl FloatPrimitive for f64 {} +unsafe impl FloatPrimitive for f128 {} diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 68e4f1c2aa787..a5c7cf76622d8 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -1573,7 +1573,7 @@ pub const fn roundf128(x: f128) -> f128; /// This intrinsic does not have a stable counterpart. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn fadd_fast(a: T, b: T) -> T; +pub unsafe fn fadd_fast(a: T, b: T) -> T; /// Float subtraction that allows optimizations based on algebraic rules. /// Requires that inputs and output of the operation are finite, causing UB otherwise. @@ -1581,7 +1581,7 @@ pub unsafe fn fadd_fast(a: T, b: T) -> T; /// This intrinsic does not have a stable counterpart. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn fsub_fast(a: T, b: T) -> T; +pub unsafe fn fsub_fast(a: T, b: T) -> T; /// Float multiplication that allows optimizations based on algebraic rules. /// Requires that inputs and output of the operation are finite, causing UB otherwise. @@ -1589,7 +1589,7 @@ pub unsafe fn fsub_fast(a: T, b: T) -> T; /// This intrinsic does not have a stable counterpart. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn fmul_fast(a: T, b: T) -> T; +pub unsafe fn fmul_fast(a: T, b: T) -> T; /// Float division that allows optimizations based on algebraic rules. /// Requires that inputs and output of the operation are finite, causing UB otherwise. @@ -1597,7 +1597,7 @@ pub unsafe fn fmul_fast(a: T, b: T) -> T; /// This intrinsic does not have a stable counterpart. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn fdiv_fast(a: T, b: T) -> T; +pub unsafe fn fdiv_fast(a: T, b: T) -> T; /// Float remainder that allows optimizations based on algebraic rules. /// Requires that inputs and output of the operation are finite, causing UB otherwise. @@ -1605,7 +1605,7 @@ pub unsafe fn fdiv_fast(a: T, b: T) -> T; /// This intrinsic does not have a stable counterpart. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn frem_fast(a: T, b: T) -> T; +pub unsafe fn frem_fast(a: T, b: T) -> T; /// Converts with LLVM’s fptoui/fptosi, which may return undef for values out of range /// () @@ -1613,42 +1613,43 @@ pub unsafe fn frem_fast(a: T, b: T) -> T; /// Stabilized as [`f32::to_int_unchecked`] and [`f64::to_int_unchecked`]. #[rustc_intrinsic] #[rustc_nounwind] -pub unsafe fn float_to_int_unchecked(value: Float) -> Int; +pub unsafe fn float_to_int_unchecked(value: Float) +-> Int; /// Float addition that allows optimizations based on algebraic rules. /// /// Stabilized as [`f16::algebraic_add`], [`f32::algebraic_add`], [`f64::algebraic_add`] and [`f128::algebraic_add`]. #[rustc_nounwind] #[rustc_intrinsic] -pub const fn fadd_algebraic(a: T, b: T) -> T; +pub const fn fadd_algebraic(a: T, b: T) -> T; /// Float subtraction that allows optimizations based on algebraic rules. /// /// Stabilized as [`f16::algebraic_sub`], [`f32::algebraic_sub`], [`f64::algebraic_sub`] and [`f128::algebraic_sub`]. #[rustc_nounwind] #[rustc_intrinsic] -pub const fn fsub_algebraic(a: T, b: T) -> T; +pub const fn fsub_algebraic(a: T, b: T) -> T; /// Float multiplication that allows optimizations based on algebraic rules. /// /// Stabilized as [`f16::algebraic_mul`], [`f32::algebraic_mul`], [`f64::algebraic_mul`] and [`f128::algebraic_mul`]. #[rustc_nounwind] #[rustc_intrinsic] -pub const fn fmul_algebraic(a: T, b: T) -> T; +pub const fn fmul_algebraic(a: T, b: T) -> T; /// Float division that allows optimizations based on algebraic rules. /// /// Stabilized as [`f16::algebraic_div`], [`f32::algebraic_div`], [`f64::algebraic_div`] and [`f128::algebraic_div`]. #[rustc_nounwind] #[rustc_intrinsic] -pub const fn fdiv_algebraic(a: T, b: T) -> T; +pub const fn fdiv_algebraic(a: T, b: T) -> T; /// Float remainder that allows optimizations based on algebraic rules. /// /// Stabilized as [`f16::algebraic_rem`], [`f32::algebraic_rem`], [`f64::algebraic_rem`] and [`f128::algebraic_rem`]. #[rustc_nounwind] #[rustc_intrinsic] -pub const fn frem_algebraic(a: T, b: T) -> T; +pub const fn frem_algebraic(a: T, b: T) -> T; /// Returns the number of bits set in an integer type `T` /// @@ -3385,39 +3386,14 @@ pub const fn maximumf128(x: f128, y: f128) -> f128 { } } -/// Returns the absolute value of an `f16`. +/// Returns the absolute value of a floating-point value. /// -/// The stabilized version of this intrinsic is -/// [`f16::abs`](../../std/primitive.f16.html#method.abs) -#[rustc_nounwind] -#[rustc_intrinsic] -pub const fn fabsf16(x: f16) -> f16; - -/// Returns the absolute value of an `f32`. -/// -/// The stabilized version of this intrinsic is -/// [`f32::abs`](../../std/primitive.f32.html#method.abs) +/// The stabilized versions of this intrinsic are available on the float +/// primitives via the `abs` method. For example, [`f32::abs`]. #[rustc_nounwind] #[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] -pub const fn fabsf32(x: f32) -> f32; - -/// Returns the absolute value of an `f64`. -/// -/// The stabilized version of this intrinsic is -/// [`f64::abs`](../../std/primitive.f64.html#method.abs) -#[rustc_nounwind] -#[rustc_intrinsic_const_stable_indirect] -#[rustc_intrinsic] -pub const fn fabsf64(x: f64) -> f64; - -/// Returns the absolute value of an `f128`. -/// -/// The stabilized version of this intrinsic is -/// [`f128::abs`](../../std/primitive.f128.html#method.abs) -#[rustc_nounwind] -#[rustc_intrinsic] -pub const fn fabsf128(x: f128) -> f128; +pub const fn fabs(x: T) -> T; /// Copies the sign from `y` to `x` for `f16` values. /// diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index 68c87b48de94d..d833653fdba65 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -1409,7 +1409,7 @@ impl f128 { #[rustc_const_unstable(feature = "f128", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub const fn abs(self) -> Self { - intrinsics::fabsf128(self) + intrinsics::fabs(self) } /// Returns a number that represents the sign of `self`. diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index 3412e49c49cd0..b0664abcdc739 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -1393,7 +1393,7 @@ impl f16 { #[rustc_const_unstable(feature = "f16", issue = "116909")] #[must_use = "method returns a new number and does not mutate the original value"] pub const fn abs(self) -> Self { - intrinsics::fabsf16(self) + intrinsics::fabs(self) } /// Returns a number that represents the sign of `self`. diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index e33cb098e4e8d..b85bd2b271588 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -1568,7 +1568,7 @@ impl f32 { #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] #[inline] pub const fn abs(self) -> f32 { - intrinsics::fabsf32(self) + intrinsics::fabs(self) } /// Returns a number that represents the sign of `self`. diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 872f567efafdc..3e7c1e792ace6 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -1566,7 +1566,7 @@ impl f64 { #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")] #[inline] pub const fn abs(self) -> f64 { - intrinsics::fabsf64(self) + intrinsics::fabs(self) } /// Returns a number that represents the sign of `self`. diff --git a/tests/ui/intrinsics/bad-intrinsic-monomorphization-bounds.rs b/tests/ui/intrinsics/bad-intrinsic-monomorphization-bounds.rs new file mode 100644 index 0000000000000..6a32cd97c50b7 --- /dev/null +++ b/tests/ui/intrinsics/bad-intrinsic-monomorphization-bounds.rs @@ -0,0 +1,18 @@ +//@ check-fail + +#![feature(repr_simd, intrinsics, core_intrinsics)] +#![allow(warnings)] +#![crate_type = "rlib"] + +// Bad monomorphizations could previously cause LLVM asserts even though the +// error was caught in the compiler. + +use std::intrinsics; + +#[derive(Copy, Clone)] +pub struct Foo(i64); + +pub unsafe fn test_fadd_fast(a: Foo, b: Foo) -> Foo { + intrinsics::fadd_fast(a, b) + //~^ ERROR the trait bound `Foo: intrinsics::bounds::FloatPrimitive` is not satisfied +} diff --git a/tests/ui/intrinsics/bad-intrinsic-monomorphization-bounds.stderr b/tests/ui/intrinsics/bad-intrinsic-monomorphization-bounds.stderr new file mode 100644 index 0000000000000..db2a222c8f2c4 --- /dev/null +++ b/tests/ui/intrinsics/bad-intrinsic-monomorphization-bounds.stderr @@ -0,0 +1,30 @@ +error[E0277]: the trait bound `Foo: intrinsics::bounds::FloatPrimitive` is not satisfied + --> $DIR/bad-intrinsic-monomorphization-bounds.rs:16:5 + | +LL | intrinsics::fadd_fast(a, b) + | ^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | +help: the nightly-only, unstable trait `intrinsics::bounds::FloatPrimitive` is not implemented for `Foo` + --> $DIR/bad-intrinsic-monomorphization-bounds.rs:13:1 + | +LL | pub struct Foo(i64); + | ^^^^^^^^^^^^^^ +help: the following other types implement trait `intrinsics::bounds::FloatPrimitive` + --> $SRC_DIR/core/src/intrinsics/bounds.rs:LL:COL + | + = note: `f16` + ::: $SRC_DIR/core/src/intrinsics/bounds.rs:LL:COL + | + = note: `f32` + ::: $SRC_DIR/core/src/intrinsics/bounds.rs:LL:COL + | + = note: `f64` + ::: $SRC_DIR/core/src/intrinsics/bounds.rs:LL:COL + | + = note: `f128` +note: required by a bound in `fadd_fast` + --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/intrinsics/bad-intrinsic-monomorphization.rs b/tests/ui/intrinsics/bad-intrinsic-monomorphization.rs index d68cbf26ef110..8849ed2a67add 100644 --- a/tests/ui/intrinsics/bad-intrinsic-monomorphization.rs +++ b/tests/ui/intrinsics/bad-intrinsic-monomorphization.rs @@ -17,11 +17,6 @@ pub fn test_cttz(v: Foo) -> u32 { //~^ ERROR `cttz` intrinsic: expected basic integer type, found `Foo` } -pub unsafe fn test_fadd_fast(a: Foo, b: Foo) -> Foo { - intrinsics::fadd_fast(a, b) - //~^ ERROR `fadd_fast` intrinsic: expected basic float type, found `Foo` -} - pub unsafe fn test_simd_add(a: Foo, b: Foo) -> Foo { intrinsics::simd::simd_add(a, b) //~^ ERROR `simd_add` intrinsic: expected SIMD input type, found non-SIMD `Foo` diff --git a/tests/ui/intrinsics/bad-intrinsic-monomorphization.stderr b/tests/ui/intrinsics/bad-intrinsic-monomorphization.stderr index 51ef71c9e2988..329bf214c03d7 100644 --- a/tests/ui/intrinsics/bad-intrinsic-monomorphization.stderr +++ b/tests/ui/intrinsics/bad-intrinsic-monomorphization.stderr @@ -1,21 +1,15 @@ error[E0511]: invalid monomorphization of `simd_add` intrinsic: expected SIMD input type, found non-SIMD `Foo` - --> $DIR/bad-intrinsic-monomorphization.rs:26:5 + --> $DIR/bad-intrinsic-monomorphization.rs:21:5 | LL | intrinsics::simd::simd_add(a, b) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0511]: invalid monomorphization of `fadd_fast` intrinsic: expected basic float type, found `Foo` - --> $DIR/bad-intrinsic-monomorphization.rs:21:5 - | -LL | intrinsics::fadd_fast(a, b) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error[E0511]: invalid monomorphization of `cttz` intrinsic: expected basic integer type, found `Foo` --> $DIR/bad-intrinsic-monomorphization.rs:16:5 | LL | intrinsics::cttz(v) | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0511`. diff --git a/tests/ui/resolve/filter-intrinsics.rs b/tests/ui/resolve/filter-intrinsics.rs index 8d6d22817dc5c..9998bec1ad4fe 100644 --- a/tests/ui/resolve/filter-intrinsics.rs +++ b/tests/ui/resolve/filter-intrinsics.rs @@ -3,8 +3,8 @@ fn main() { let _ = transmute::(); //~^ ERROR cannot find - // Should suggest `std::intrinsics::fabsf64`, + // Should suggest `std::intrinsics::fabs`, // since there is no non-intrinsic to suggest. - let _ = fabsf64(1.0); + let _ = fabs(1.0); //~^ ERROR cannot find } diff --git a/tests/ui/resolve/filter-intrinsics.stderr b/tests/ui/resolve/filter-intrinsics.stderr index 9c9e92f6d4f83..3870cfcb1080a 100644 --- a/tests/ui/resolve/filter-intrinsics.stderr +++ b/tests/ui/resolve/filter-intrinsics.stderr @@ -9,15 +9,15 @@ help: consider importing this function LL + use std::mem::transmute; | -error[E0425]: cannot find function `fabsf64` in this scope +error[E0425]: cannot find function `fabs` in this scope --> $DIR/filter-intrinsics.rs:8:13 | -LL | let _ = fabsf64(1.0); - | ^^^^^^^ not found in this scope +LL | let _ = fabs(1.0); + | ^^^^ not found in this scope | help: consider importing this function | -LL + use std::intrinsics::fabsf64; +LL + use std::intrinsics::fabs; | error: aborting due to 2 previous errors