arm: Warn if IRQ handler is not compiled with -mgeneral-regs-only [PR target/94743]
authorChristophe Lyon <christophe.lyon@linaro.org>
Tue, 30 Jun 2020 13:51:20 +0000 (13:51 +0000)
committerChristophe Lyon <christophe.lyon@linaro.org>
Tue, 30 Jun 2020 14:20:28 +0000 (14:20 +0000)
The interrupt attribute does not guarantee that the FP registers are
saved, which can result in problems difficult to debug.

Saving the FP registers and status registers can be a large penalty,
so it's probably not desirable to do that all the time.

If the handler calls other functions, we'd likely need to save all of
them, for lack of knowledge of which registers they actually clobber.

This is even more obscure for the end-user when the compiler inserts
calls to helper functions such as memcpy (some multilibs do use FP
registers to speed it up).

In the PR, we discussed adding routines in libgcc to save the FP
context and saving only locally-clobbered FP registers, but this seems
to be too much work for the purpose, given that in general such
handlers try to avoid this kind of penalty.
I suspect we would also want new attributes to instruct the compiler
that saving the FP context is not needed.

In the mean time, emit a warning to suggest re-compiling with
-mgeneral-regs-only. Note that this can lead to errors if the code
uses floating-point and -mfloat-abi=hard, eg:
argument of type 'double' not permitted with -mgeneral-regs-only

This can be troublesome for the user, but at least this would make
him aware of the latent issue.

The patch adds several testcases:

- pr94734-1-hard.c checks that a warning is emitted when using
  -mfloat-abi=hard. Function IRQ_HDLR_Test can make implicit calls to
  runtime floating-point routines (or direct use of FP instructions),
  IRQ_HDLR_Test2 doesn't. We emit a warning in both cases, though.

- pr94734-1-softfp.c: same as above wih -mfloat-abi=softfp.

- pr94734-1-soft.c checks that no warning is emitted when using
  -mfloat-abi=soft when the same code as above.

- pr94734-2.c checks that no warning is emitted when using
  -mgeneral-regs-only.

- pr94734-3.c checks that no warning is emitted when using
  -mgeneral-regs-only even using float-point data.

2020-06-30  Christophe Lyon  <christophe.lyon@linaro.org>

PR target/94743
gcc/
* config/arm/arm.c (arm_handle_isr_attribute): Warn if
-mgeneral-regs-only is not used.

gcc/testsuite/
* gcc.misc-tests/arm-isr.c: Add -mgeneral-regs-only.
* gcc.target/arm/empty_fiq_handler.c: Add -mgeneral-regs-only.
* gcc.target/arm/interrupt-1.c: Add -mgeneral-regs-only.
* gcc.target/arm/interrupt-2.c: Add -mgeneral-regs-only.
* gcc.target/arm/pr70830.c: Add -mgeneral-regs-only.
* gcc.target/arm/pr94743-1-hard.c: New test.
* gcc.target/arm/pr94743-1-soft.c: New test.
* gcc.target/arm/pr94743-1-softfp.c: New test.
* gcc.target/arm/pr94743-2.c: New test.
* gcc.target/arm/pr94743-3.c: New test.

gcc/config/arm/arm.c
gcc/testsuite/gcc.misc-tests/arm-isr.c
gcc/testsuite/gcc.target/arm/empty_fiq_handler.c
gcc/testsuite/gcc.target/arm/interrupt-1.c
gcc/testsuite/gcc.target/arm/interrupt-2.c
gcc/testsuite/gcc.target/arm/pr70830.c
gcc/testsuite/gcc.target/arm/pr94743-1-hard.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/pr94743-1-soft.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/pr94743-1-softfp.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/pr94743-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/pr94743-3.c [new file with mode: 0644]

index dac9a6fb5c41ce42cd7a278b417eab25239a043c..e15d28684352781eb5c5ab269506234cfe912eb4 100644 (file)
@@ -7257,6 +7257,11 @@ arm_handle_isr_attribute (tree *node, tree name, tree args, int flags,
                   name);
          *no_add_attrs = true;
        }
+      else if (TARGET_VFP_BASE)
+       {
+         warning (OPT_Wattributes, "FP registers might be clobbered despite %qE attribute: compile with %<-mgeneral-regs-only%>",
+                  name);
+       }
       /* FIXME: the argument if any is checked for type attributes;
         should it be checked for decl ones?  */
     }
index 737f9ffb643bcc89cdf0a4e9e62133e9c91f5add..9eff52c7914379414c57c458f0b38356b7a302bb 100644 (file)
@@ -1,3 +1,5 @@
+/* { dg-options "-mgeneral-regs-only" } */
+
 extern void abort ();
 extern void exit (int);
 
index 8313f2199122be153a737946e817a5e3bee60372..6911ffce1c872edc7d2af540afbde31921840382 100644 (file)
@@ -1,5 +1,6 @@
 /* { dg-do compile } */
 /* { dg-skip-if "" { ! arm_cortex_m } { "-mthumb" } } */
+/* { dg-options "-mgeneral-regs-only" } */
 
 /* Below code used to trigger an ICE due to missing constraints for
    sp = fp + cst pattern.  */
index 493763d7d4c99829c5a61b539f67a5ade65d05a9..de1ecc503c4f4cdf7addfffa353ae5c78677c237 100644 (file)
@@ -2,7 +2,7 @@
    __attribute__ ((interrupt)).  */
 /* { dg-do assemble } */
 /* { dg-require-effective-target arm_nothumb } */
-/* { dg-options "-O0 -marm -save-temps" } */
+/* { dg-options "-mgeneral-regs-only -O0 -marm -save-temps" } */
 
 /* This test is not valid when -mthumb.  */
 extern void bar (int);
index 5be1f1612ac1fc1e1486df1cad0b4782d5140246..c64b98b950202fcd3f6af6a2ca437d9844053861 100644 (file)
@@ -2,7 +2,7 @@
    __attribute__ ((interrupt)).  */
 /* { dg-do assemble } */
 /* { dg-require-effective-target arm_nothumb } */
-/* { dg-options "-O1 -marm -save-temps" } */
+/* { dg-options "-mgeneral-regs-only -O1 -marm -save-temps" } */
 
 /* This test is not valid when -mthumb.  */
 extern void bar (int);
index cd84c4283bd0ab107d0384f63f1dfda30fc54ed0..bca596c2d631d066fabeb26a876b22657820ba77 100644 (file)
@@ -1,7 +1,7 @@
 /* PR target/70830.  */
 /* { dg-do assemble } */
 /* { dg-require-effective-target arm_arm_ok } */
-/* { dg-options "-Os -marm -save-temps" } */
+/* { dg-options "-mgeneral-regs-only -Os -marm -save-temps" } */
 
 /* This test is not valid when -mthumb.  */
 
diff --git a/gcc/testsuite/gcc.target/arm/pr94743-1-hard.c b/gcc/testsuite/gcc.target/arm/pr94743-1-hard.c
new file mode 100644 (file)
index 0000000..928b79d
--- /dev/null
@@ -0,0 +1,29 @@
+/* PR target/94743 */
+/* { dg-do compile } */
+/* { dg-skip-if "do not override -mfloat-abi" { *-*-* } { "-mfloat-abi=*" } {"-mfloat-abi=hard" } } */
+/* { dg-require-effective-target arm_vfp_ok } */
+/* { dg-add-options arm_vfp } */
+/* Make sure with use -mfloat-abi=hard.  */
+/* { dg-additional-options "-mfloat-abi=hard" } */
+
+/* Check that we emit a warning when compiling an IRQ handler without
+   -mgeneral-regs-only.  */
+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 *-*-* } . } */
+  global_d.fpdata[3] += global_d.fpdata[3] * global_d1.fpdata[3];
+}
+
+/* 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-1-soft.c b/gcc/testsuite/gcc.target/arm/pr94743-1-soft.c
new file mode 100644 (file)
index 0000000..e06a16d
--- /dev/null
@@ -0,0 +1,27 @@
+/* PR target/94743 */
+/* { dg-do compile } */
+/* Thumb1 mode not supported for interrupt routines.  */
+/* { dg-require-effective-target arm32 } */
+/* { dg-skip-if "do not override -mfloat-abi" { *-*-* } { "-mfloat-abi=*" } {"-mfloat-abi=soft" } } */
+/* { dg-options "-mfloat-abi=soft" } */
+
+/* Check that we do not emit a warning when compiling an IRQ handler without
+   -mgeneral-regs-only with -mfloat-abi=soft.  */
+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)
+{
+  global_d.fpdata[3] += global_d.fpdata[3] * global_d1.fpdata[3];
+}
+
+/* This function does not need to clobber VFP registers.  */
+__attribute__ ((interrupt("IRQ"))) void IRQ_HDLR_Test2(void)
+{
+  global_d.fpdata[3] = 1.0;
+}
diff --git a/gcc/testsuite/gcc.target/arm/pr94743-1-softfp.c b/gcc/testsuite/gcc.target/arm/pr94743-1-softfp.c
new file mode 100644 (file)
index 0000000..6113eb6
--- /dev/null
@@ -0,0 +1,29 @@
+/* PR target/94743 */
+/* { dg-do compile } */
+/* { dg-skip-if "do not override -mfloat-abi" { *-*-* } { "-mfloat-abi=*" } {"-mfloat-abi=softfp" } } */
+/* { dg-require-effective-target arm_vfp_ok } */
+/* { dg-add-options arm_vfp } */
+/* Make sure with use -mfloat-abi=softfp.  */
+/* { dg-additional-options "-mfloat-abi=softfp" } */
+
+/* Check that we emit a warning when compiling an IRQ handler without
+   -mgeneral-regs-only.  */
+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 *-*-* } . } */
+  global_d.fpdata[3] += global_d.fpdata[3] * global_d1.fpdata[3];
+}
+
+/* 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-2.c b/gcc/testsuite/gcc.target/arm/pr94743-2.c
new file mode 100644 (file)
index 0000000..50a97de
--- /dev/null
@@ -0,0 +1,22 @@
+/* PR target/94743 */
+/* { dg-do compile } */
+/* Thumb1 mode not supported for interrupt routines.  */
+/* { dg-require-effective-target arm32 } */
+/* { dg-options "-mgeneral-regs-only" } */
+
+/* Check that we do not emit a warning when compiling an IRQ handler
+   with -mgeneral-regs-only.  */
+typedef struct {
+  /* Do not use floating-point types, which are not compatible with
+     -mgeneral-regs-only under -mfloat-abi=hard */
+  int fpdata[32];
+} dummy_t;
+
+dummy_t global_d;
+dummy_t global_d1;
+
+/* This function does not clobber VFP registers.  */
+__attribute__ ((interrupt("IRQ"))) void IRQ_HDLR_Test(void)
+{
+  global_d.fpdata[3] += global_d.fpdata[3] * global_d1.fpdata[3];
+}
diff --git a/gcc/testsuite/gcc.target/arm/pr94743-3.c b/gcc/testsuite/gcc.target/arm/pr94743-3.c
new file mode 100644 (file)
index 0000000..6b8ed2b
--- /dev/null
@@ -0,0 +1,23 @@
+/* PR target/94743 */
+/* { dg-do compile } */
+/* Thumb1 mode not supported for interrupt routines.  */
+/* { dg-require-effective-target arm32 } */
+/* { dg-skip-if "do not override -mfloat-abi" { *-*-* } { "-mfloat-abi=*" } {"-mfloat-abi=soft" } } */
+/* { dg-options "-mgeneral-regs-only -mfloat-abi=soft" } */
+
+/* Check that we do not emit a warning when compiling an IRQ handler
+   with -mgeneral-regs-only even when using floating-point data.  */
+typedef struct {
+  /* Since we use -mfloat=abi=soft, this will generate calls to
+     libgcc, but won't clobber VFP registers.  */
+  double fpdata[32];
+} dummy_t;
+
+dummy_t global_d;
+dummy_t global_d1;
+
+/* This function does not clobber VFP registers.  */
+__attribute__ ((interrupt("IRQ"))) void IRQ_HDLR_Test(void)
+{
+  global_d.fpdata[3] += global_d.fpdata[3] * global_d1.fpdata[3];
+}