Skip to content

Commit 593d7ca

Browse files
committed
Implement missing f16/f128 builtins
1 parent ce3dae9 commit 593d7ca

File tree

2 files changed

+64
-13
lines changed

2 files changed

+64
-13
lines changed

src/builder.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -765,7 +765,15 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
765765

766766
#[cfg(feature = "master")]
767767
match self.cx.type_kind(a_type) {
768-
TypeKind::Half | TypeKind::Float => {
768+
TypeKind::Half => {
769+
let fmodf = self.context.get_builtin_function("fmodf");
770+
let f32_type = self.type_f32();
771+
let a = self.context.new_cast(self.location, a, f32_type);
772+
let b = self.context.new_cast(self.location, b, f32_type);
773+
let result = self.context.new_call(self.location, fmodf, &[a, b]);
774+
return self.context.new_cast(self.location, result, a_type);
775+
}
776+
TypeKind::Float => {
769777
let fmodf = self.context.get_builtin_function("fmodf");
770778
return self.context.new_call(self.location, fmodf, &[a, b]);
771779
}

src/intrinsic/mod.rs

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,10 @@ fn get_simple_intrinsic<'gcc, 'tcx>(
4545
let gcc_name = match name {
4646
sym::sqrtf32 => "sqrtf",
4747
sym::sqrtf64 => "sqrt",
48+
sym::sqrtf128 => "sqrtl",
4849
sym::powif32 => "__builtin_powif",
4950
sym::powif64 => "__builtin_powi",
51+
sym::powif128 => "__builtin_powil",
5052
sym::sinf32 => "sinf",
5153
sym::sinf64 => "sin",
5254
sym::cosf32 => "cosf",
@@ -65,29 +67,37 @@ fn get_simple_intrinsic<'gcc, 'tcx>(
6567
sym::log2f64 => "log2",
6668
sym::fmaf32 => "fmaf",
6769
sym::fmaf64 => "fma",
70+
sym::fmaf128 => "fmal",
6871
// FIXME: calling `fma` from libc without FMA target feature uses expensive software emulation
6972
sym::fmuladdf32 => "fmaf", // TODO: use gcc intrinsic analogous to llvm.fmuladd.f32
7073
sym::fmuladdf64 => "fma", // TODO: use gcc intrinsic analogous to llvm.fmuladd.f64
7174
sym::fabsf32 => "fabsf",
7275
sym::fabsf64 => "fabs",
7376
sym::minnumf32 => "fminf",
7477
sym::minnumf64 => "fmin",
78+
sym::minnumf128 => "fminl",
7579
sym::maxnumf32 => "fmaxf",
7680
sym::maxnumf64 => "fmax",
81+
sym::maxnumf128 => "fmaxl",
7782
sym::copysignf32 => "copysignf",
7883
sym::copysignf64 => "copysign",
7984
sym::copysignf128 => "copysignl",
8085
sym::floorf32 => "floorf",
8186
sym::floorf64 => "floor",
87+
sym::floorf128 => "floorl",
8288
sym::ceilf32 => "ceilf",
8389
sym::ceilf64 => "ceil",
90+
sym::ceilf128 => "ceill",
8491
sym::truncf32 => "truncf",
8592
sym::truncf64 => "trunc",
93+
sym::truncf128 => "truncl",
8694
// We match the LLVM backend and lower this to `rint`.
8795
sym::round_ties_even_f32 => "rintf",
8896
sym::round_ties_even_f64 => "rint",
97+
sym::round_ties_even_f128 => "rintl",
8998
sym::roundf32 => "roundf",
9099
sym::roundf64 => "round",
100+
sym::roundf128 => "roundl",
91101
sym::abort => "abort",
92102
_ => return None,
93103
};
@@ -160,6 +170,40 @@ fn get_simple_function<'gcc, 'tcx>(
160170
))
161171
}
162172

173+
fn f16_builtin<'gcc, 'tcx>(
174+
cx: &CodegenCx<'gcc, 'tcx>,
175+
name: Symbol,
176+
args: &[OperandRef<'tcx, RValue<'gcc>>],
177+
) -> RValue<'gcc> {
178+
let f32_type = cx.type_f32();
179+
let builtin_name = match name {
180+
sym::ceilf16 => "__builtin_ceilf",
181+
sym::floorf16 => "__builtin_floorf",
182+
sym::fmaf16 => "fmaf",
183+
sym::maxnumf16 => "__builtin_fmaxf",
184+
sym::minnumf16 => "__builtin_fminf",
185+
sym::powf16 => "__builtin_powf",
186+
sym::powif16 => {
187+
let func = cx.context.get_builtin_function("__builtin_powif");
188+
let arg0 = cx.context.new_cast(None, args[0].immediate(), f32_type);
189+
let args = [arg0, args[1].immediate()];
190+
let result = cx.context.new_call(None, func, &args);
191+
return cx.context.new_cast(None, result, cx.type_f16());
192+
}
193+
sym::roundf16 => "__builtin_roundf",
194+
sym::round_ties_even_f16 => "__builtin_rintf",
195+
sym::sqrtf16 => "__builtin_sqrtf",
196+
sym::truncf16 => "__builtin_truncf",
197+
_ => unreachable!(),
198+
};
199+
200+
let func = cx.context.get_builtin_function(builtin_name);
201+
let args: Vec<_> =
202+
args.iter().map(|arg| cx.context.new_cast(None, arg.immediate(), f32_type)).collect();
203+
let result = cx.context.new_call(None, func, &args);
204+
cx.context.new_cast(None, result, cx.type_f16())
205+
}
206+
163207
impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
164208
fn codegen_intrinsic_call(
165209
&mut self,
@@ -211,18 +255,17 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
211255
&args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
212256
)
213257
}
214-
sym::fmaf16 => {
215-
// TODO(antoyo): use the correct builtin for f16.
216-
let func = self.cx.context.get_builtin_function("fmaf");
217-
let args: Vec<_> = args
218-
.iter()
219-
.map(|arg| {
220-
self.cx.context.new_cast(self.location, arg.immediate(), self.cx.type_f32())
221-
})
222-
.collect();
223-
let result = self.cx.context.new_call(self.location, func, &args);
224-
self.cx.context.new_cast(self.location, result, self.cx.type_f16())
225-
}
258+
sym::ceilf16
259+
| sym::floorf16
260+
| sym::fmaf16
261+
| sym::maxnumf16
262+
| sym::minnumf16
263+
| sym::powf16
264+
| sym::powif16
265+
| sym::roundf16
266+
| sym::round_ties_even_f16
267+
| sym::sqrtf16
268+
| sym::truncf16 => f16_builtin(self, name, args),
226269
sym::is_val_statically_known => {
227270
let a = args[0].immediate();
228271
let builtin = self.context.get_builtin_function("__builtin_constant_p");

0 commit comments

Comments
 (0)