| [committed] Fix target/17565: asms in delay slots |
| |
| * From: Richard Sandiford <rsandifo at redhat dot com> |
| * To: gcc-patches at gcc dot gnu dot org |
| * Date: Mon, 20 Sep 2004 07:55:58 +0100 |
| * Subject: [committed] Fix target/17565: asms in delay slots |
| |
| The MIPS port was allowing asms to be put into delay slots if the |
| compiler guesses they are only one instruction long. This is wrong |
| because of the possibility of it containing macros. |
| |
| The problem can be reproduced as an assembler warning |
| in the following testcase: |
| |
| int foo (int n) |
| { |
| register int k asm ("$16") = n; |
| if (k > 0) |
| { |
| bar (); |
| asm ("li %0,0x12345678" : "=r" (k)); |
| } |
| return k; |
| } |
| |
| because the multi-instruction asm statement goes into the delay |
| slot of the call to bar(). |
| |
| This is reduced from a much more serious linux problem. Linux is fond |
| of using empty asm statements, and since gcc estimates empty asms to be |
| one instruction long, they too might be put into delay slots. This |
| actually has the effect of putting the following instruction into the |
| delay slot instead. Since there's no assembler warning, the problem was |
| only detected as a run-time failure. |
| |
| The fix is simple: set the asm value of "can_delay" to "no". |
| Tested on mipsisa64-elf, applied to mainline. |
| |
| This problem goes back to at least 2.95, so it isn't technically a |
| regression. On the other hand, it's the kind of bug that could trigger |
| for different types of code in different releases, so I'm sure there's |
| a testcase that fails (say) in 3.4 and not in 2.95. Will probably ask |
| Mark for permission to backport to 3.4. |
| |
| Richard |
| |
| |
| PR target/17565 |
| * config/mips/mips.md (define_asm_attributes): Set can_delay to no. |
| |
| testsuite/ |
| * gcc.target/mips/asm-1.c: New test. |
| |
| Index: config/mips/mips.md |
| =================================================================== |
| RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.md,v |
| retrieving revision 1.306 |
| diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.306 mips.md |
| *** gcc/gcc/config/mips/mips.md 13 Sep 2004 19:32:05 -0000 1.306 |
| --- gcc/gcc/config/mips/mips.md 20 Sep 2004 06:52:31 -0000 |
| *************** (define_attr "may_clobber_hilo" "no,yes" |
| *** 266,272 **** |
| |
| ;; Describe a user's asm statement. |
| (define_asm_attributes |
| ! [(set_attr "type" "multi")]) |
| |
| ;; ......................... |
| ;; |
| --- 266,273 ---- |
| |
| ;; Describe a user's asm statement. |
| (define_asm_attributes |
| ! [(set_attr "type" "multi") |
| ! (set_attr "can_delay" "no")]) |
| |
| ;; ......................... |
| ;; |
| Index: testsuite/gcc.target/mips/asm-1.c |
| =================================================================== |
| RCS file: testsuite/gcc.target/mips/asm-1.c |
| diff -N testsuite/gcc.target/mips/asm-1.c |
| *** gcc/gcc/testsuite/gcc.target/mips/asm-1.c 1 Jan 1970 00:00:00 -0000 |
| --- gcc/gcc/testsuite/gcc.target/mips/asm-1.c 20 Sep 2004 06:52:31 -0000 |
| *************** |
| *** 0 **** |
| --- 1,14 ---- |
| + /* PR target/17565. GCC used to put the asm into the delay slot |
| + of the call. */ |
| + /* { dg-do assemble } */ |
| + /* { dg-options "-O" } */ |
| + int foo (int n) |
| + { |
| + register int k asm ("$16") = n; |
| + if (k > 0) |
| + { |
| + bar (); |
| + asm ("li %0,0x12345678" : "=r" (k)); |
| + } |
| + return k; |
| + } |
| |