From 49bd11cdda80c3605e9bffd9cbd45115dd3b515e Mon Sep 17 00:00:00 2001 From: Laurence Tratt Date: Tue, 19 Nov 2024 16:33:49 +0000 Subject: [PATCH] Support calls which take and return floats/double. Co-authored-by: Edd Barrett --- tests/c/fp_in_out.c | 57 +++++++++++++++++++ .../compile/jitc_yk/codegen/x64/lsregalloc.rs | 20 +++---- 2 files changed, 64 insertions(+), 13 deletions(-) create mode 100644 tests/c/fp_in_out.c diff --git a/tests/c/fp_in_out.c b/tests/c/fp_in_out.c new file mode 100644 index 000000000..ab43e0502 --- /dev/null +++ b/tests/c/fp_in_out.c @@ -0,0 +1,57 @@ +// Run-time: +// env-var: YKD_SERIALISE_COMPILATION=1 +// env-var: YK_LOG=4 +// stderr: +// yk-jit-event: start-tracing +// 5.100000 +// 5.200000 +// yk-jit-event: stop-tracing +// 4.100000 +// 4.200000 +// yk-jit-event: enter-jit-code +// 3.100000 +// 3.200000 +// 2.100000 +// 2.200000 +// yk-jit-event: deoptimise + +// Check that passing floats to/from a function works correctly. + +#include +#include +#include +#include +#include +#include + +__attribute__((yk_outline)) +float f_f(float x) { + return x + 1.1; +} + +__attribute__((yk_outline)) +double f_d(double x) { + return x + 1.2; +} + +int main(int argc, char **argv) { + YkMT *mt = yk_mt_new(NULL); + yk_mt_hot_threshold_set(mt, 0); + YkLocation loc = yk_location_new(); + + int res = 9998; + int i = 4; + NOOPT_VAL(loc); + NOOPT_VAL(res); + NOOPT_VAL(i); + while (i > 0) { + yk_mt_control_point(mt, &loc); + fprintf(stderr, "%f\n", f_f((float) i)); + fprintf(stderr, "%f\n", f_d((double) i)); + i--; + } + NOOPT_VAL(res); + yk_location_drop(loc); + yk_mt_shutdown(mt); + return (EXIT_SUCCESS); +} diff --git a/ykrt/src/compile/jitc_yk/codegen/x64/lsregalloc.rs b/ykrt/src/compile/jitc_yk/codegen/x64/lsregalloc.rs index 529d5c6fd..91695d1ef 100644 --- a/ykrt/src/compile/jitc_yk/codegen/x64/lsregalloc.rs +++ b/ykrt/src/compile/jitc_yk/codegen/x64/lsregalloc.rs @@ -825,15 +825,13 @@ impl LSRegAlloc<'_> { match cnstr { RegConstraint::InputIntoReg(_, reg) | RegConstraint::InputIntoRegAndClobber(_, reg) + | RegConstraint::InputOutputIntoReg(_, reg) | RegConstraint::OutputFromReg(reg) | RegConstraint::Clobber(reg) => avoid.set(*reg), RegConstraint::Input(_) | RegConstraint::InputOutput(_) | RegConstraint::Output | RegConstraint::Temporary => {} - RegConstraint::InputOutputIntoReg(_, _) => { - panic!(); - } } } @@ -870,11 +868,11 @@ impl LSRegAlloc<'_> { }, RegConstraint::InputIntoReg(_, _) | RegConstraint::InputIntoRegAndClobber(_, _) + | RegConstraint::InputOutputIntoReg(_, _) | RegConstraint::Clobber(_) => { // OPT: do the same trick as Input/InputOutput } RegConstraint::Output | RegConstraint::OutputFromReg(_) => (), - RegConstraint::InputOutputIntoReg(_op, _reg) => unreachable!(), RegConstraint::Temporary => (), } } @@ -888,20 +886,19 @@ impl LSRegAlloc<'_> { RegConstraint::Input(op) | RegConstraint::InputIntoReg(op, _) | RegConstraint::InputIntoRegAndClobber(op, _) + | RegConstraint::InputOutputIntoReg(op, _) | RegConstraint::InputOutput(op) => { let reg = match x { RegConstraint::Input(_) | RegConstraint::InputOutput(_) => { self.assign_empty_fp_reg(asm, iidx, avoid) } RegConstraint::InputIntoReg(_, reg) - | RegConstraint::InputIntoRegAndClobber(_, reg) => { + | RegConstraint::InputIntoRegAndClobber(_, reg) + | RegConstraint::InputOutputIntoReg(_, reg) => { // OPT: Not everything needs spilling self.spill_fp_if_not_already(asm, *reg); *reg } - RegConstraint::InputOutputIntoReg(_, _) => { - unreachable!() - } RegConstraint::Output | RegConstraint::OutputFromReg(_) | RegConstraint::Temporary @@ -934,14 +931,12 @@ impl LSRegAlloc<'_> { self.fp_regset.unset(reg); RegState::Empty } - RegConstraint::InputOutput(_) => { + RegConstraint::InputOutput(_) | RegConstraint::InputOutputIntoReg(_, _) => { debug_assert!(!found_output); found_output = true; RegState::FromInst(iidx) } - RegConstraint::InputOutputIntoReg(_, _) - | RegConstraint::Output - | RegConstraint::OutputFromReg(_) => { + RegConstraint::Output | RegConstraint::OutputFromReg(_) => { unreachable!() } RegConstraint::Temporary => todo!(), @@ -971,7 +966,6 @@ impl LSRegAlloc<'_> { avoid.set(*reg); out[i] = Some(*reg); } - RegConstraint::InputOutputIntoReg(_, _) => unreachable!(), RegConstraint::Temporary => { let reg = self.assign_empty_fp_reg(asm, iidx, avoid); self.fp_regset.unset(reg);