123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- [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;
- + }
|