Skip to content

Commit 9cb2a63

Browse files
committed
Support fma
1 parent 14ac6f1 commit 9cb2a63

3 files changed

Lines changed: 23 additions & 27 deletions

File tree

src/intrinsic/llvm.rs

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::borrow::Cow;
22

3-
use gccjit::{CType, Context, Field, Function, FunctionPtrType, RValue, ToRValue, Type};
3+
use gccjit::{Context, Field, Function, FunctionPtrType, RValue, ToRValue, Type};
44
use rustc_codegen_ssa::traits::BuilderMethods;
55

66
use crate::builder::Builder;
@@ -806,13 +806,6 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(
806806
]
807807
.into();
808808
}
809-
"fma" => {
810-
let mut new_args = args.to_vec();
811-
new_args[0] = builder.context.new_cast(None, new_args[0], builder.double_type);
812-
new_args[1] = builder.context.new_cast(None, new_args[1], builder.double_type);
813-
new_args[2] = builder.context.new_cast(None, new_args[2], builder.double_type);
814-
args = new_args.into();
815-
}
816809
"__builtin_ia32_sqrtsh_mask_round"
817810
| "__builtin_ia32_vcvtss2sh_mask_round"
818811
| "__builtin_ia32_vcvtsd2sh_mask_round"
@@ -933,10 +926,6 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>(
933926
&[first_mask, second_mask],
934927
);
935928
}
936-
"fma" => {
937-
let f16_type = builder.context.new_c_type(CType::Float16);
938-
return_value = builder.context.new_cast(None, return_value, f16_type);
939-
}
940929
"__builtin_ia32_encodekey128_u32" => {
941930
// The builtin __builtin_ia32_encodekey128_u32 writes the result in its pointer argument while
942931
// llvm.x86.encodekey128 returns a value.

src/intrinsic/mod.rs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -150,10 +150,7 @@ fn generic_f16_builtin<'gcc, 'tcx>(
150150
_ => unreachable!(),
151151
};
152152

153-
let func = cx.context.get_builtin_function(builtin_name);
154-
let args: Vec<_> = args.iter().map(|arg| f16_to_f32(cx, arg.immediate())).collect();
155-
let result = cx.context.new_call(None, func, &args);
156-
float_to_f16(cx, result, cx.f16_abi_type)
153+
call_f32_builtin_for_f16(cx, builtin_name, args)
157154
}
158155

159156
fn f16_builtin<'gcc, 'tcx>(
@@ -179,6 +176,14 @@ fn f16_builtin<'gcc, 'tcx>(
179176
_ => unreachable!(),
180177
};
181178

179+
call_f32_builtin_for_f16(cx, builtin_name, args)
180+
}
181+
182+
fn call_f32_builtin_for_f16<'gcc, 'tcx>(
183+
cx: &CodegenCx<'gcc, 'tcx>,
184+
builtin_name: &str,
185+
args: &[OperandRef<'tcx, RValue<'gcc>>],
186+
) -> RValue<'gcc> {
182187
let func = cx.context.get_builtin_function(builtin_name);
183188
let args: Vec<_> = args.iter().map(|arg| f16_to_f32(cx, arg.immediate())).collect();
184189
let result = cx.context.new_call(None, func, &args);
@@ -617,24 +622,20 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
617622
args: &[OperandRef<'tcx, Self::Value>],
618623
is_cleanup: bool,
619624
) -> Self::Value {
625+
let sym = self.tcx.symbol_name(instance).name;
626+
if sym == "llvm.fma.f16" {
627+
return call_f32_builtin_for_f16(self.cx, "fmaf", args);
628+
}
629+
620630
let func = if let Some(&func) = self.intrinsic_instances.borrow().get(&instance) {
621631
func
622632
} else {
623-
let sym = self.tcx.symbol_name(instance).name;
624-
625633
let func = if let Some(func) = self.intrinsics.borrow().get(sym) {
626634
*func
627635
} else {
628636
self.linkage.set(FunctionType::Extern);
629637

630-
let func = match sym {
631-
"llvm.fma.f16" => {
632-
// fma is not a target builtin, but a normal builtin, so we handle it differently
633-
// here.
634-
self.context.get_builtin_function("fma")
635-
}
636-
_ => llvm::intrinsic(sym, self),
637-
};
638+
let func = llvm::intrinsic(sym, self);
638639

639640
self.intrinsics.borrow_mut().insert(sym.to_string(), func);
640641

tests/run/f16.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,18 @@
33
// Run-time:
44
// status: 0
55

6-
#![feature(core_intrinsics, f16, float_algebraic)]
6+
#![feature(core_intrinsics, f16, float_algebraic, link_llvm_intrinsics)]
77
#![allow(internal_features)]
88

99
use std::cmp::Ordering;
1010
use std::hint::black_box;
1111
use std::intrinsics::{fmaf16, powif16};
1212

13+
unsafe extern "C" {
14+
#[link_name = "llvm.fma.f16"]
15+
fn llvm_fma_f16(a: f16, b: f16, c: f16) -> f16;
16+
}
17+
1318
fn assert_f16_bits(value: f16, bits: u16) {
1419
assert_eq!(value.to_bits(), bits);
1520
}
@@ -41,6 +46,7 @@ fn main() {
4146
assert_f16_bits(two / one, 0x4000);
4247
assert_f16_bits(-three, 0xc200);
4348
assert_f16_bits(fmaf16(one, two, -three), 0xbc00);
49+
assert_f16_bits(unsafe { llvm_fma_f16(one, two, -three) }, 0xbc00);
4450
assert_f16_bits(powif16(two, 3), 0x4800);
4551

4652
assert_f16_bits(black_box(123.0f16).algebraic_add(black_box(456.0f16)), 0x6086);

0 commit comments

Comments
 (0)