From 834868c176adbec0f84b71289c2fbae7500b3fce Mon Sep 17 00:00:00 2001 From: Christophe Lyon Date: Thu, 14 May 2020 11:14:59 +0000 Subject: [PATCH] arm: Save FP regs in interrupt handlers [PR target/94743] 2020-05-xx Christophe Lyon gcc/ * config/arm/arm.c (reg_needs_saving_p): Remove limit to core registers. gcc/testsuite/ * gcc.target/arm/pr94743-4.c: New test. * gcc.target/arm/pr94743-5.c: New test. --- gcc/config/arm/arm.c | 4 ++-- gcc/testsuite/gcc.target/arm/pr94743-4.c | 31 ++++++++++++++++++++++++++++ gcc/testsuite/gcc.target/arm/pr94743-5.c | 35 ++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.target/arm/pr94743-4.c create mode 100644 gcc/testsuite/gcc.target/arm/pr94743-5.c diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 0107f50..38413fb 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -4200,8 +4200,8 @@ static bool reg_needs_saving_p (unsigned reg) if (IS_INTERRUPT (func_type)) if (df_regs_ever_live_p (reg) - /* Save call-clobbered core registers. */ - || (! crtl->is_leaf && call_used_or_fixed_reg_p (reg) && reg < FIRST_VFP_REGNUM)) + /* Save call-clobbered registers. */ + || (! crtl->is_leaf && call_used_or_fixed_reg_p (reg))) return true; else return false; diff --git a/gcc/testsuite/gcc.target/arm/pr94743-4.c b/gcc/testsuite/gcc.target/arm/pr94743-4.c new file mode 100644 index 0000000..378981a --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr94743-4.c @@ -0,0 +1,31 @@ +/* PR target/94743 */ +/* { dg-do compile } */ +/* { dg-skip-if "do not override -mfloat-abi" { *-*-* } { "-mfloat-abi=*" } {"-mfloat-abi=hard" } } */ +/* { dg-options "-mfloat-abi=hard" } */ + +/* Check that we emit a warning when compiling an IRQ handler without + -mgeneral-regs-only. */ +/* Also check that we save and restore the VFP registers clobbered + locally. */ +typedef struct { + double fpdata[32]; +} dummy_t; + +dummy_t global_d; +dummy_t global_d1; + +/* This function may clobber VFP registers, but it is a leaf function: + we can analyze which registers to save. */ +__attribute__ ((interrupt("IRQ"))) void IRQ_HDLR_Test(void) +{ /* { dg-warning { FP registers might be clobbered despite 'interrupt' attribute: compile with -mgeneral-regs-only} "" { target *-*-* } . } */ + global_d.fpdata[3] += global_d.fpdata[3] * global_d1.fpdata[3]; +} +/* { dg-final { scan-assembler-times "vpush.64\t{d\\d+, d\\d+, d\\d+}" 1 } } */ +/* { dg-final { scan-assembler-times "vldm\tsp!, {d\\d+-d\\d+}" 1 } } */ + +/* This function does not need to clobber VFP registers. */ +/* Do we want to emit a (useless?) warning? */ +__attribute__ ((interrupt("IRQ"))) void IRQ_HDLR_Test2(void) +{ /* { dg-warning { FP registers might be clobbered despite 'interrupt' attribute: compile with -mgeneral-regs-only} "" { target *-*-* } . } */ + global_d.fpdata[3] = 1.0; +} diff --git a/gcc/testsuite/gcc.target/arm/pr94743-5.c b/gcc/testsuite/gcc.target/arm/pr94743-5.c new file mode 100644 index 0000000..55fb1dd --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr94743-5.c @@ -0,0 +1,35 @@ +/* PR target/94743 */ +/* { dg-do compile } */ +/* { dg-skip-if "do not override -mfloat-abi" { *-*-* } { "-mfloat-abi=*" } {"-mfloat-abi=hard" } } */ +/* Require Neon so that we push d16-d31. */ +/* { dg-require-effective-target arm_neon_ok } */ +/* { dg-add-options arm_neon } */ +/* { dg-additional-options "-mfloat-abi=hard" } */ + +/* Check that we emit a warning when compiling an IRQ handler without + -mgeneral-regs-only. */ +/* Also check that we save and restore the call-clobbered VFP registers. */ +typedef struct { + double fpdata[32]; +} dummy_t; + +dummy_t global_d; +dummy_t global_d1; + +/* This function may clobber VFP registers. */ +__attribute__ ((interrupt("IRQ"))) void IRQ_HDLR_Test(void) +{ /* { dg-warning { FP registers might be clobbered despite 'interrupt' attribute: compile with -mgeneral-regs-only} "" { target *-*-* } . } */ + /* Force implicit call to memcpy. */ + global_d = global_d1; + global_d.fpdata[3] += global_d.fpdata[3] * global_d1.fpdata[3]; +} +/* { dg-final { scan-assembler-times "vpush.64\t{d0, d1, d2, d3, d4, d5, d6, d7}" 1 } } */ +/* { dg-final { scan-assembler-times "vpush.64\t{d16, d17, d18, d19, d20, d21, d22, d23, d24, d25, d26, d27, d28, d29, d30, d31}" 1 } } */ +/* { dg-final { scan-assembler-times "vldm\tsp!, {d16-d31}" 1 } } */ +/* { dg-final { scan-assembler-times "vldm\tsp!, {d0-d7}" 1 } } */ + +/* This function does not need to clobber VFP registers. */ +__attribute__ ((interrupt("IRQ"))) void IRQ_HDLR_Test2(void) +{ /* { dg-warning { FP registers might be clobbered despite 'interrupt' attribute: compile with -mgeneral-regs-only} "" { target *-*-* } . } */ + global_d.fpdata[3] = 1.0; +} -- 2.7.4