Skip to content

Commit e7247df

Browse files
committed
Use intrinsics for {f16,f32,f64,f128}::{minimum,maximum} operations
1 parent 7e552b4 commit e7247df

File tree

12 files changed

+389
-76
lines changed

12 files changed

+389
-76
lines changed

compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,6 +1109,43 @@ fn codegen_regular_intrinsic_call<'tcx>(
11091109
ret.write_cvalue(fx, old);
11101110
}
11111111

1112+
sym::minimumf32 => {
1113+
intrinsic_args!(fx, args => (a, b); intrinsic);
1114+
let a = a.load_scalar(fx);
1115+
let b = b.load_scalar(fx);
1116+
1117+
let val = fx.bcx.ins().fmin(a, b);
1118+
let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f32));
1119+
ret.write_cvalue(fx, val);
1120+
}
1121+
sym::minimumf64 => {
1122+
intrinsic_args!(fx, args => (a, b); intrinsic);
1123+
let a = a.load_scalar(fx);
1124+
let b = b.load_scalar(fx);
1125+
1126+
let val = fx.bcx.ins().fmin(a, b);
1127+
let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f64));
1128+
ret.write_cvalue(fx, val);
1129+
}
1130+
sym::maximumf32 => {
1131+
intrinsic_args!(fx, args => (a, b); intrinsic);
1132+
let a = a.load_scalar(fx);
1133+
let b = b.load_scalar(fx);
1134+
1135+
let val = fx.bcx.ins().fmax(a, b);
1136+
let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f32));
1137+
ret.write_cvalue(fx, val);
1138+
}
1139+
sym::maximumf64 => {
1140+
intrinsic_args!(fx, args => (a, b); intrinsic);
1141+
let a = a.load_scalar(fx);
1142+
let b = b.load_scalar(fx);
1143+
1144+
let val = fx.bcx.ins().fmax(a, b);
1145+
let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f64));
1146+
ret.write_cvalue(fx, val);
1147+
}
1148+
11121149
sym::minnumf32 => {
11131150
intrinsic_args!(fx, args => (a, b); intrinsic);
11141151
let a = a.load_scalar(fx);

compiler/rustc_codegen_gcc/src/intrinsic/mod.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,44 @@ fn get_simple_intrinsic<'gcc, 'tcx>(
7474
sym::fabsf64 => "fabs",
7575
sym::minnumf32 => "fminf",
7676
sym::minnumf64 => "fmin",
77+
sym::minimumf32 => "fminimumf",
78+
sym::minimumf64 => "fminimum",
79+
sym::minimumf128 => {
80+
// GCC doesn't have the intrinsic we want so we use the compiler-builtins one
81+
// https://docs.rs/compiler_builtins/latest/compiler_builtins/math/full_availability/fn.fminimumf128.html
82+
let f128_type = cx.type_f128();
83+
return Some(cx.context.new_function(
84+
None,
85+
FunctionType::Extern,
86+
f128_type,
87+
&[
88+
cx.context.new_parameter(None, f128_type, "a"),
89+
cx.context.new_parameter(None, f128_type, "b"),
90+
],
91+
"fminimumf128",
92+
false,
93+
));
94+
}
7795
sym::maxnumf32 => "fmaxf",
7896
sym::maxnumf64 => "fmax",
97+
sym::maximumf32 => "fmaximumf",
98+
sym::maximumf64 => "fmaximum",
99+
sym::maximumf128 => {
100+
// GCC doesn't have the intrinsic we want so we use the compiler-builtins one
101+
// https://docs.rs/compiler_builtins/latest/compiler_builtins/math/full_availability/fn.fmaximumf128.html
102+
let f128_type = cx.type_f128();
103+
return Some(cx.context.new_function(
104+
None,
105+
FunctionType::Extern,
106+
f128_type,
107+
&[
108+
cx.context.new_parameter(None, f128_type, "a"),
109+
cx.context.new_parameter(None, f128_type, "b"),
110+
],
111+
"fmaximumf128",
112+
false,
113+
));
114+
}
79115
sym::copysignf32 => "copysignf",
80116
sym::copysignf64 => "copysign",
81117
sym::copysignf128 => "copysignl",

compiler/rustc_codegen_llvm/src/context.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,11 +1009,21 @@ impl<'ll> CodegenCx<'ll, '_> {
10091009
ifn!("llvm.minnum.f64", fn(t_f64, t_f64) -> t_f64);
10101010
ifn!("llvm.minnum.f128", fn(t_f128, t_f128) -> t_f128);
10111011

1012+
ifn!("llvm.minimum.f16", fn(t_f16, t_f16) -> t_f16);
1013+
ifn!("llvm.minimum.f32", fn(t_f32, t_f32) -> t_f32);
1014+
ifn!("llvm.minimum.f64", fn(t_f64, t_f64) -> t_f64);
1015+
ifn!("llvm.minimum.f128", fn(t_f128, t_f128) -> t_f128);
1016+
10121017
ifn!("llvm.maxnum.f16", fn(t_f16, t_f16) -> t_f16);
10131018
ifn!("llvm.maxnum.f32", fn(t_f32, t_f32) -> t_f32);
10141019
ifn!("llvm.maxnum.f64", fn(t_f64, t_f64) -> t_f64);
10151020
ifn!("llvm.maxnum.f128", fn(t_f128, t_f128) -> t_f128);
10161021

1022+
ifn!("llvm.maximum.f16", fn(t_f16, t_f16) -> t_f16);
1023+
ifn!("llvm.maximum.f32", fn(t_f32, t_f32) -> t_f32);
1024+
ifn!("llvm.maximum.f64", fn(t_f64, t_f64) -> t_f64);
1025+
ifn!("llvm.maximum.f128", fn(t_f128, t_f128) -> t_f128);
1026+
10171027
ifn!("llvm.floor.f16", fn(t_f16) -> t_f16);
10181028
ifn!("llvm.floor.f32", fn(t_f32) -> t_f32);
10191029
ifn!("llvm.floor.f64", fn(t_f64) -> t_f64);

compiler/rustc_codegen_llvm/src/intrinsic.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,21 @@ fn get_simple_intrinsic<'ll>(
103103
sym::minnumf64 => "llvm.minnum.f64",
104104
sym::minnumf128 => "llvm.minnum.f128",
105105

106+
sym::minimumf16 => "llvm.minimum.f16",
107+
sym::minimumf32 => "llvm.minimum.f32",
108+
sym::minimumf64 => "llvm.minimum.f64",
109+
sym::minimumf128 => "llvm.minimum.f128",
110+
106111
sym::maxnumf16 => "llvm.maxnum.f16",
107112
sym::maxnumf32 => "llvm.maxnum.f32",
108113
sym::maxnumf64 => "llvm.maxnum.f64",
109114
sym::maxnumf128 => "llvm.maxnum.f128",
110115

116+
sym::maximumf16 => "llvm.maximum.f16",
117+
sym::maximumf32 => "llvm.maximum.f32",
118+
sym::maximumf64 => "llvm.maximum.f64",
119+
sym::maximumf128 => "llvm.maximum.f128",
120+
111121
sym::copysignf16 => "llvm.copysign.f16",
112122
sym::copysignf32 => "llvm.copysign.f32",
113123
sym::copysignf64 => "llvm.copysign.f64",

compiler/rustc_const_eval/src/interpret/intrinsics.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,11 +493,21 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
493493
sym::minnumf64 => self.float_min_intrinsic::<Double>(args, dest)?,
494494
sym::minnumf128 => self.float_min_intrinsic::<Quad>(args, dest)?,
495495

496+
sym::minimumf16 => self.float_minimum_intrinsic::<Half>(args, dest)?,
497+
sym::minimumf32 => self.float_minimum_intrinsic::<Single>(args, dest)?,
498+
sym::minimumf64 => self.float_minimum_intrinsic::<Double>(args, dest)?,
499+
sym::minimumf128 => self.float_minimum_intrinsic::<Quad>(args, dest)?,
500+
496501
sym::maxnumf16 => self.float_max_intrinsic::<Half>(args, dest)?,
497502
sym::maxnumf32 => self.float_max_intrinsic::<Single>(args, dest)?,
498503
sym::maxnumf64 => self.float_max_intrinsic::<Double>(args, dest)?,
499504
sym::maxnumf128 => self.float_max_intrinsic::<Quad>(args, dest)?,
500505

506+
sym::maximumf16 => self.float_maximum_intrinsic::<Half>(args, dest)?,
507+
sym::maximumf32 => self.float_maximum_intrinsic::<Single>(args, dest)?,
508+
sym::maximumf64 => self.float_maximum_intrinsic::<Double>(args, dest)?,
509+
sym::maximumf128 => self.float_maximum_intrinsic::<Quad>(args, dest)?,
510+
501511
sym::copysignf16 => self.float_copysign_intrinsic::<Half>(args, dest)?,
502512
sym::copysignf32 => self.float_copysign_intrinsic::<Single>(args, dest)?,
503513
sym::copysignf64 => self.float_copysign_intrinsic::<Double>(args, dest)?,
@@ -830,6 +840,38 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
830840
interp_ok(())
831841
}
832842

843+
fn float_minimum_intrinsic<F>(
844+
&mut self,
845+
args: &[OpTy<'tcx, M::Provenance>],
846+
dest: &MPlaceTy<'tcx, M::Provenance>,
847+
) -> InterpResult<'tcx, ()>
848+
where
849+
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
850+
{
851+
let a: F = self.read_scalar(&args[0])?.to_float()?;
852+
let b: F = self.read_scalar(&args[1])?.to_float()?;
853+
let res = a.minimum(b);
854+
let res = self.adjust_nan(res, &[a, b]);
855+
self.write_scalar(res, dest)?;
856+
interp_ok(())
857+
}
858+
859+
fn float_maximum_intrinsic<F>(
860+
&mut self,
861+
args: &[OpTy<'tcx, M::Provenance>],
862+
dest: &MPlaceTy<'tcx, M::Provenance>,
863+
) -> InterpResult<'tcx, ()>
864+
where
865+
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
866+
{
867+
let a: F = self.read_scalar(&args[0])?.to_float()?;
868+
let b: F = self.read_scalar(&args[1])?.to_float()?;
869+
let res = a.maximum(b);
870+
let res = self.adjust_nan(res, &[a, b]);
871+
self.write_scalar(res, dest)?;
872+
interp_ok(())
873+
}
874+
833875
fn float_copysign_intrinsic<F>(
834876
&mut self,
835877
args: &[OpTy<'tcx, M::Provenance>],

compiler/rustc_hir_analysis/src/check/intrinsic.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,18 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi
103103
| sym::minnumf32
104104
| sym::minnumf64
105105
| sym::minnumf128
106+
| sym::minimumf16
107+
| sym::minimumf32
108+
| sym::minimumf64
109+
| sym::minimumf128
106110
| sym::maxnumf16
107111
| sym::maxnumf32
108112
| sym::maxnumf64
109113
| sym::maxnumf128
114+
| sym::maximumf16
115+
| sym::maximumf32
116+
| sym::maximumf64
117+
| sym::maximumf128
110118
| sym::rustc_peek
111119
| sym::type_name
112120
| sym::forget
@@ -374,11 +382,21 @@ pub(crate) fn check_intrinsic_type(
374382
sym::minnumf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
375383
sym::minnumf128 => (0, 0, vec![tcx.types.f128, tcx.types.f128], tcx.types.f128),
376384

385+
sym::minimumf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16),
386+
sym::minimumf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
387+
sym::minimumf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
388+
sym::minimumf128 => (0, 0, vec![tcx.types.f128, tcx.types.f128], tcx.types.f128),
389+
377390
sym::maxnumf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16),
378391
sym::maxnumf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
379392
sym::maxnumf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
380393
sym::maxnumf128 => (0, 0, vec![tcx.types.f128, tcx.types.f128], tcx.types.f128),
381394

395+
sym::maximumf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16),
396+
sym::maximumf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
397+
sym::maximumf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),
398+
sym::maximumf128 => (0, 0, vec![tcx.types.f128, tcx.types.f128], tcx.types.f128),
399+
382400
sym::copysignf16 => (0, 0, vec![tcx.types.f16, tcx.types.f16], tcx.types.f16),
383401
sym::copysignf32 => (0, 0, vec![tcx.types.f32, tcx.types.f32], tcx.types.f32),
384402
sym::copysignf64 => (0, 0, vec![tcx.types.f64, tcx.types.f64], tcx.types.f64),

compiler/rustc_span/src/symbol.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,6 +1301,10 @@ symbols! {
13011301
match_beginning_vert,
13021302
match_default_bindings,
13031303
matches_macro,
1304+
maximumf128,
1305+
maximumf16,
1306+
maximumf32,
1307+
maximumf64,
13041308
maxnumf128,
13051309
maxnumf16,
13061310
maxnumf32,
@@ -1335,6 +1339,10 @@ symbols! {
13351339
min_generic_const_args,
13361340
min_specialization,
13371341
min_type_alias_impl_trait,
1342+
minimumf128,
1343+
minimumf16,
1344+
minimumf32,
1345+
minimumf64,
13381346
minnumf128,
13391347
minnumf16,
13401348
minnumf32,

0 commit comments

Comments
 (0)