Skip to content

Commit f4ff5f0

Browse files
authored
Unrolled build for #153834
Rollup merge of #153834 - N1ark:generic-float-intrinsics, r=tgross35,RalfJung Merge `fabsf16/32/64/128` into `fabs::<F>` Following [a small conversation on Zulip](https://rust-lang.zulipchat.com/#narrow/channel/131828-t-compiler/topic/Float.20intrinsics/with/521501401) (and because I'd be interested in starting to contribute on Rust), I thought I'd give a try at merging the float intrinsics :) This PR just merges `fabsf16`, `fabsf32`, `fabsf64`, `fabsf128`, as it felt like an easy first target. Notes: - I'm opening the PR for one intrinsic as it's probably easier if the shift is done one intrinsic at a time, but let me know if you'd rather I do several at a time to reduce the number of PRs. - Currently this PR increases LOCs, despite being an attempt at simplifying the intrinsics/compilers. I believe this increase is a one time thing as I had to define new functions and move some things around, and hopefully future PRs/commits will reduce overall LoCs - `fabsf32` and `fabsf64` are `#[rustc_intrinsic_const_stable_indirect]`, while `fabsf16` and `fabsf128` aren't; because `f32`/`f64` expect the function to be const, the generic version must be made indirectly stable too. We'd need to check with T-lang this change is ok; the only other intrinsics where there is such a mismatch is `minnum`, `maxnum` and `copysign`. - I haven't touched libm because I'm not familiar with how it works; any guidance would be welcome!
2 parents 3f3c6f4 + 11c673b commit f4ff5f0

20 files changed

Lines changed: 222 additions & 163 deletions

File tree

compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -346,10 +346,6 @@ fn codegen_float_intrinsic_call<'tcx>(
346346
sym::log10f32 => ("log10f", 1, fx.tcx.types.f32, types::F32),
347347
sym::log10f64 => ("log10", 1, fx.tcx.types.f64, types::F64),
348348
sym::log10f128 => ("log10f128", 1, fx.tcx.types.f128, types::F128),
349-
sym::fabsf16 => ("fabsf16", 1, fx.tcx.types.f16, types::F16),
350-
sym::fabsf32 => ("fabsf", 1, fx.tcx.types.f32, types::F32),
351-
sym::fabsf64 => ("fabs", 1, fx.tcx.types.f64, types::F64),
352-
sym::fabsf128 => ("fabsf128", 1, fx.tcx.types.f128, types::F128),
353349
sym::fmaf16 => ("fmaf16", 3, fx.tcx.types.f16, types::F16),
354350
sym::fmaf32 => ("fmaf", 3, fx.tcx.types.f32, types::F32),
355351
sym::fmaf64 => ("fma", 3, fx.tcx.types.f64, types::F64),
@@ -441,11 +437,7 @@ fn codegen_float_intrinsic_call<'tcx>(
441437
sym::copysignf32 | sym::copysignf64 => {
442438
CValue::by_val(fx.bcx.ins().fcopysign(args[0], args[1]), layout)
443439
}
444-
sym::fabsf16 => CValue::by_val(codegen_f16_f128::abs_f16(fx, args[0]), layout),
445-
sym::fabsf128 => CValue::by_val(codegen_f16_f128::abs_f128(fx, args[0]), layout),
446-
sym::fabsf32
447-
| sym::fabsf64
448-
| sym::floorf32
440+
sym::floorf32
449441
| sym::floorf64
450442
| sym::ceilf32
451443
| sym::ceilf64
@@ -456,7 +448,6 @@ fn codegen_float_intrinsic_call<'tcx>(
456448
| sym::sqrtf32
457449
| sym::sqrtf64 => {
458450
let val = match intrinsic {
459-
sym::fabsf32 | sym::fabsf64 => fx.bcx.ins().fabs(args[0]),
460451
sym::floorf32 | sym::floorf64 => fx.bcx.ins().floor(args[0]),
461452
sym::ceilf32 | sym::ceilf64 => fx.bcx.ins().ceil(args[0]),
462453
sym::truncf32 | sym::truncf64 => fx.bcx.ins().trunc(args[0]),
@@ -1179,6 +1170,28 @@ fn codegen_regular_intrinsic_call<'tcx>(
11791170
ret.write_cvalue(fx, old);
11801171
}
11811172

1173+
sym::fabs => {
1174+
intrinsic_args!(fx, args => (arg); intrinsic);
1175+
let layout = arg.layout();
1176+
let ty::Float(float_ty) = layout.ty.kind() else {
1177+
span_bug!(
1178+
source_info.span,
1179+
"expected float type for fabs intrinsic: {:?}",
1180+
layout.ty
1181+
);
1182+
};
1183+
let x = arg.load_scalar(fx);
1184+
let val = match float_ty {
1185+
FloatTy::F32 | FloatTy::F64 => fx.bcx.ins().fabs(x),
1186+
// FIXME(bytecodealliance/wasmtime#8312): Use `fabsf16` once Cranelift
1187+
// backend lowerings are implemented.
1188+
FloatTy::F16 => codegen_f16_f128::abs_f16(fx, x),
1189+
FloatTy::F128 => codegen_f16_f128::abs_f128(fx, x),
1190+
};
1191+
let val = CValue::by_val(val, layout);
1192+
ret.write_cvalue(fx, val);
1193+
}
1194+
11821195
sym::minimumf16 => {
11831196
intrinsic_args!(fx, args => (a, b); intrinsic);
11841197
let a = a.load_scalar(fx);

compiler/rustc_codegen_gcc/src/intrinsic/mod.rs

Lines changed: 60 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ use rustc_codegen_ssa::traits::{
2323
IntrinsicCallBuilderMethods, LayoutTypeCodegenMethods,
2424
};
2525
use rustc_data_structures::fx::FxHashSet;
26-
use rustc_middle::bug;
2726
#[cfg(feature = "master")]
2827
use rustc_middle::ty::layout::FnAbiOf;
2928
use rustc_middle::ty::layout::LayoutOf;
3029
use rustc_middle::ty::{self, Instance, Ty};
30+
use rustc_middle::{bug, span_bug};
3131
use rustc_span::{Span, Symbol, sym};
3232
use rustc_target::callconv::{ArgAbi, PassMode};
3333

@@ -70,8 +70,6 @@ fn get_simple_intrinsic<'gcc, 'tcx>(
7070
// FIXME: calling `fma` from libc without FMA target feature uses expensive software emulation
7171
sym::fmuladdf32 => "fmaf", // FIXME: use gcc intrinsic analogous to llvm.fmuladd.f32
7272
sym::fmuladdf64 => "fma", // FIXME: use gcc intrinsic analogous to llvm.fmuladd.f64
73-
sym::fabsf32 => "fabsf",
74-
sym::fabsf64 => "fabs",
7573
sym::minimumf32 => "fminimumf",
7674
sym::minimumf64 => "fminimum",
7775
sym::minimumf128 => {
@@ -194,58 +192,29 @@ fn get_simple_function<'gcc, 'tcx>(
194192
}
195193

196194
fn get_simple_function_f128<'gcc, 'tcx>(
195+
span: Span,
197196
cx: &CodegenCx<'gcc, 'tcx>,
198197
name: Symbol,
199-
) -> Option<Function<'gcc>> {
200-
if !cx.supports_f128_type {
201-
return None;
202-
}
203-
198+
) -> Function<'gcc> {
204199
let f128_type = cx.type_f128();
205200
let func_name = match name {
206201
sym::ceilf128 => "ceilf128",
207-
sym::fabsf128 => "fabsf128",
202+
sym::fabs => "fabsf128",
208203
sym::floorf128 => "floorf128",
209204
sym::truncf128 => "truncf128",
210205
sym::roundf128 => "roundf128",
211206
sym::round_ties_even_f128 => "roundevenf128",
212207
sym::sqrtf128 => "sqrtf128",
213-
_ => return None,
208+
_ => span_bug!(span, "used get_simple_function_f128 for non-unary f128 intrinsic"),
214209
};
215-
Some(cx.context.new_function(
210+
cx.context.new_function(
216211
None,
217212
FunctionType::Extern,
218213
f128_type,
219214
&[cx.context.new_parameter(None, f128_type, "a")],
220215
func_name,
221216
false,
222-
))
223-
}
224-
225-
fn get_simple_function_f128_2args<'gcc, 'tcx>(
226-
cx: &CodegenCx<'gcc, 'tcx>,
227-
name: Symbol,
228-
) -> Option<Function<'gcc>> {
229-
if !cx.supports_f128_type {
230-
return None;
231-
}
232-
233-
let f128_type = cx.type_f128();
234-
let func_name = match name {
235-
sym::copysignf128 => "copysignf128",
236-
_ => return None,
237-
};
238-
Some(cx.context.new_function(
239-
None,
240-
FunctionType::Extern,
241-
f128_type,
242-
&[
243-
cx.context.new_parameter(None, f128_type, "a"),
244-
cx.context.new_parameter(None, f128_type, "b"),
245-
],
246-
func_name,
247-
false,
248-
))
217+
)
249218
}
250219

251220
fn f16_builtin<'gcc, 'tcx>(
@@ -257,7 +226,7 @@ fn f16_builtin<'gcc, 'tcx>(
257226
let builtin_name = match name {
258227
sym::ceilf16 => "__builtin_ceilf",
259228
sym::copysignf16 => "__builtin_copysignf",
260-
sym::fabsf16 => "fabsf",
229+
sym::fabs => "fabsf",
261230
sym::floorf16 => "__builtin_floorf",
262231
sym::fmaf16 => "fmaf",
263232
sym::powf16 => "__builtin_powf",
@@ -297,11 +266,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
297266
let fn_args = instance.args;
298267

299268
let simple = get_simple_intrinsic(self, name);
300-
// FIXME(antoyo): Only call get_simple_function_f128 and get_simple_function_f128_2args when
301-
// it is the symbols for the supported f128 builtins.
302-
let simple_func = get_simple_function(self, name)
303-
.or_else(|| get_simple_function_f128(self, name))
304-
.or_else(|| get_simple_function_f128_2args(self, name));
269+
let simple_func = get_simple_function(self, name);
305270

306271
let value = match name {
307272
_ if simple.is_some() => {
@@ -322,7 +287,6 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
322287
}
323288
sym::ceilf16
324289
| sym::copysignf16
325-
| sym::fabsf16
326290
| sym::floorf16
327291
| sym::fmaf16
328292
| sym::powf16
@@ -331,6 +295,40 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
331295
| sym::round_ties_even_f16
332296
| sym::sqrtf16
333297
| sym::truncf16 => f16_builtin(self, name, args),
298+
sym::ceilf128
299+
| sym::floorf128
300+
| sym::truncf128
301+
| sym::roundf128
302+
| sym::round_ties_even_f128
303+
| sym::sqrtf128
304+
if self.cx.supports_f128_type =>
305+
{
306+
let func = get_simple_function_f128(span, self, name);
307+
self.cx.context.new_call(
308+
self.location,
309+
func,
310+
&args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
311+
)
312+
}
313+
sym::copysignf128 if self.cx.supports_f128_type => {
314+
let f128_type = self.cx.type_f128();
315+
let func = self.cx.context.new_function(
316+
None,
317+
FunctionType::Extern,
318+
f128_type,
319+
&[
320+
self.cx.context.new_parameter(None, f128_type, "a"),
321+
self.cx.context.new_parameter(None, f128_type, "b"),
322+
],
323+
"copysignf128",
324+
false,
325+
);
326+
self.cx.context.new_call(
327+
self.location,
328+
func,
329+
&args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
330+
)
331+
}
334332
sym::fmaf128 => {
335333
let f128_type = self.cx.type_f128();
336334
let func = self.cx.context.new_function(
@@ -488,6 +486,23 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
488486
}
489487
}
490488
}
489+
sym::fabs => 'fabs: {
490+
let ty = args[0].layout.ty;
491+
let ty::Float(float_ty) = *ty.kind() else {
492+
span_bug!(span, "expected float type for fabs intrinsic: {:?}", ty);
493+
};
494+
let func = match float_ty {
495+
ty::FloatTy::F16 => break 'fabs f16_builtin(self, name, args),
496+
ty::FloatTy::F32 => self.context.get_builtin_function("fabsf"),
497+
ty::FloatTy::F64 => self.context.get_builtin_function("fabs"),
498+
ty::FloatTy::F128 => get_simple_function_f128(span, self, name),
499+
};
500+
self.cx.context.new_call(
501+
self.location,
502+
func,
503+
&args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
504+
)
505+
}
491506

492507
sym::raw_eq => {
493508
use rustc_abi::BackendRepr::*;

compiler/rustc_codegen_gcc/src/intrinsic/simd.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -811,7 +811,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
811811
}};
812812
}
813813
let ty::Float(ref f) = *in_elem.kind() else {
814-
return_error!(InvalidMonomorphization::FloatingPointType { span, name, in_ty });
814+
return_error!(InvalidMonomorphization::BasicFloatType { span, name, ty: in_ty });
815815
};
816816
let elem_ty = bx.cx.type_float_from_ty(*f);
817817
let (elem_ty_str, elem_ty, cast_type) = match f.bit_width() {

compiler/rustc_codegen_llvm/src/intrinsic.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,6 @@ fn call_simple_intrinsic<'ll, 'tcx>(
107107
sym::fmuladdf64 => ("llvm.fmuladd", &[bx.type_f64()]),
108108
sym::fmuladdf128 => ("llvm.fmuladd", &[bx.type_f128()]),
109109

110-
sym::fabsf16 => ("llvm.fabs", &[bx.type_f16()]),
111-
sym::fabsf32 => ("llvm.fabs", &[bx.type_f32()]),
112-
sym::fabsf64 => ("llvm.fabs", &[bx.type_f64()]),
113-
sym::fabsf128 => ("llvm.fabs", &[bx.type_f128()]),
114-
115110
// FIXME: LLVM currently mis-compile those intrinsics, re-enable them
116111
// when llvm/llvm-project#{139380,139381,140445} are fixed.
117112
//sym::minimumf16 => ("llvm.minimum", &[bx.type_f16()]),
@@ -502,6 +497,20 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
502497
}
503498
}
504499

500+
sym::fabs => {
501+
let ty = args[0].layout.ty;
502+
let ty::Float(f) = ty.kind() else {
503+
span_bug!(span, "the `fabs` intrinsic requires a floating-point argument, got {:?}", ty);
504+
};
505+
let llty = self.type_float_from_ty(*f);
506+
let llvm_name = "llvm.fabs";
507+
self.call_intrinsic(
508+
llvm_name,
509+
&[llty],
510+
&args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
511+
)
512+
}
513+
505514
sym::raw_eq => {
506515
use BackendRepr::*;
507516
let tp_ty = fn_args.type_at(0);
@@ -1936,7 +1945,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
19361945
}
19371946

19381947
let ty::Float(f) = in_elem.kind() else {
1939-
return_error!(InvalidMonomorphization::FloatingPointType { span, name, in_ty });
1948+
return_error!(InvalidMonomorphization::BasicFloatType { span, name, ty: in_ty });
19401949
};
19411950
let elem_ty = bx.cx.type_float_from_ty(*f);
19421951

compiler/rustc_codegen_ssa/src/errors.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -733,14 +733,6 @@ pub enum InvalidMonomorphization<'tcx> {
733733
in_ty: Ty<'tcx>,
734734
},
735735

736-
#[diag("invalid monomorphization of `{$name}` intrinsic: `{$in_ty}` is not a floating-point type", code = E0511)]
737-
FloatingPointType {
738-
#[primary_span]
739-
span: Span,
740-
name: Symbol,
741-
in_ty: Ty<'tcx>,
742-
},
743-
744736
#[diag("invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}`", code = E0511)]
745737
UnrecognizedIntrinsic {
746738
#[primary_span]

compiler/rustc_const_eval/src/interpret/intrinsics.rs

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -575,10 +575,23 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
575575
sym::copysignf64 => self.float_copysign_intrinsic::<Double>(args, dest)?,
576576
sym::copysignf128 => self.float_copysign_intrinsic::<Quad>(args, dest)?,
577577

578-
sym::fabsf16 => self.float_abs_intrinsic::<Half>(args, dest)?,
579-
sym::fabsf32 => self.float_abs_intrinsic::<Single>(args, dest)?,
580-
sym::fabsf64 => self.float_abs_intrinsic::<Double>(args, dest)?,
581-
sym::fabsf128 => self.float_abs_intrinsic::<Quad>(args, dest)?,
578+
sym::fabs => {
579+
let arg = self.read_immediate(&args[0])?;
580+
let ty::Float(float_ty) = arg.layout.ty.kind() else {
581+
span_bug!(
582+
self.cur_span(),
583+
"non-float type for float intrinsic: {}",
584+
arg.layout.ty,
585+
);
586+
};
587+
let out_val = match float_ty {
588+
FloatTy::F16 => self.unop_float_intrinsic::<Half>(intrinsic_name, arg)?,
589+
FloatTy::F32 => self.unop_float_intrinsic::<Single>(intrinsic_name, arg)?,
590+
FloatTy::F64 => self.unop_float_intrinsic::<Double>(intrinsic_name, arg)?,
591+
FloatTy::F128 => self.unop_float_intrinsic::<Quad>(intrinsic_name, arg)?,
592+
};
593+
self.write_scalar(out_val, dest)?;
594+
}
582595

583596
sym::floorf16 => self.float_round_intrinsic::<Half>(
584597
args,
@@ -1020,6 +1033,22 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
10201033
interp_ok(Scalar::from_bool(lhs_bytes == rhs_bytes))
10211034
}
10221035

1036+
fn unop_float_intrinsic<F>(
1037+
&self,
1038+
name: Symbol,
1039+
arg: ImmTy<'tcx, M::Provenance>,
1040+
) -> InterpResult<'tcx, Scalar<M::Provenance>>
1041+
where
1042+
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
1043+
{
1044+
let x: F = arg.to_scalar().to_float()?;
1045+
match name {
1046+
// bitwise, no NaN adjustments
1047+
sym::fabs => interp_ok(x.abs().into()),
1048+
_ => bug!("not a unary float intrinsic: {}", name),
1049+
}
1050+
}
1051+
10231052
fn float_minmax<F>(
10241053
&self,
10251054
a: Scalar<M::Provenance>,
@@ -1078,20 +1107,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
10781107
interp_ok(())
10791108
}
10801109

1081-
fn float_abs_intrinsic<F>(
1082-
&mut self,
1083-
args: &[OpTy<'tcx, M::Provenance>],
1084-
dest: &PlaceTy<'tcx, M::Provenance>,
1085-
) -> InterpResult<'tcx, ()>
1086-
where
1087-
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
1088-
{
1089-
let x: F = self.read_scalar(&args[0])?.to_float()?;
1090-
// bitwise, no NaN adjustments
1091-
self.write_scalar(x.abs(), dest)?;
1092-
interp_ok(())
1093-
}
1094-
10951110
fn float_round<F>(
10961111
&mut self,
10971112
x: Scalar<M::Provenance>,

0 commit comments

Comments
 (0)