diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cselib.c | 27 | ||||
-rw-r--r-- | gcc/cselib.h | 1 | ||||
-rw-r--r-- | gcc/postreload.c | 13 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/i386-asm-3.c | 34 |
5 files changed, 73 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5e2bbef..6f63d50 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,4 +1,13 @@ 2004-09-13 Richard Henderson <rth@redhat.com> + + PR inline-asm/6806 + * cselib.c (cselib_invalidate_rtx): Export. Remove unused args. + (cselib_invalidate_rtx_note_stores): New. + (cselib_record_sets, cselib_process_insn): Update to match. + * cselib.h (cselib_invalidate_rtx): Declare. + * postreload.c (reload_cse_simplify): Invalidate asm clobbers. + +2004-09-13 Richard Henderson <rth@redhat.com> PR tree-opt/10528 * tree-inline.c (copy_body_r): Recompute bits for ADDR_EXPR, diff --git a/gcc/cselib.c b/gcc/cselib.c index aa92248..e58f2541 100644 --- a/gcc/cselib.c +++ b/gcc/cselib.c @@ -61,7 +61,6 @@ static void add_mem_for_addr (cselib_val *, cselib_val *, rtx); static cselib_val *cselib_lookup_mem (rtx, int); static void cselib_invalidate_regno (unsigned int, enum machine_mode); static void cselib_invalidate_mem (rtx); -static void cselib_invalidate_rtx (rtx, rtx, void *); static void cselib_record_set (rtx, cselib_val *, cselib_val *); static void cselib_record_sets (rtx); @@ -1141,13 +1140,10 @@ cselib_invalidate_mem (rtx mem_rtx) *vp = &dummy_val; } -/* Invalidate DEST, which is being assigned to or clobbered. The second and - the third parameter exist so that this function can be passed to - note_stores; they are ignored. */ +/* Invalidate DEST, which is being assigned to or clobbered. */ -static void -cselib_invalidate_rtx (rtx dest, rtx ignore ATTRIBUTE_UNUSED, - void *data ATTRIBUTE_UNUSED) +void +cselib_invalidate_rtx (rtx dest) { while (GET_CODE (dest) == STRICT_LOW_PART || GET_CODE (dest) == SIGN_EXTRACT || GET_CODE (dest) == ZERO_EXTRACT || GET_CODE (dest) == SUBREG) @@ -1163,7 +1159,16 @@ cselib_invalidate_rtx (rtx dest, rtx ignore ATTRIBUTE_UNUSED, invalidate the stack pointer correctly. Note that invalidating the stack pointer is different from invalidating DEST. */ if (push_operand (dest, GET_MODE (dest))) - cselib_invalidate_rtx (stack_pointer_rtx, NULL_RTX, NULL); + cselib_invalidate_rtx (stack_pointer_rtx); +} + +/* A wrapper for cselib_invalidate_rtx to be called via note_stores. */ + +static void +cselib_invalidate_rtx_note_stores (rtx dest, rtx ignore ATTRIBUTE_UNUSED, + void *data ATTRIBUTE_UNUSED) +{ + cselib_invalidate_rtx (dest); } /* Record the result of a SET instruction. DEST is being set; the source @@ -1296,7 +1301,7 @@ cselib_record_sets (rtx insn) /* Invalidate all locations written by this insn. Note that the elts we looked up in the previous loop aren't affected, just some of their locations may go away. */ - note_stores (body, cselib_invalidate_rtx, NULL); + note_stores (body, cselib_invalidate_rtx_note_stores, NULL); /* If this is an asm, look for duplicate sets. This can happen when the user uses the same value as an output multiple times. This is valid @@ -1384,7 +1389,7 @@ cselib_process_insn (rtx insn) unlikely to help. */ for (x = REG_NOTES (insn); x; x = XEXP (x, 1)) if (REG_NOTE_KIND (x) == REG_INC) - cselib_invalidate_rtx (XEXP (x, 0), NULL_RTX, NULL); + cselib_invalidate_rtx (XEXP (x, 0)); #endif /* Look for any CLOBBERs in CALL_INSN_FUNCTION_USAGE, but only @@ -1392,7 +1397,7 @@ cselib_process_insn (rtx insn) if (CALL_P (insn)) for (x = CALL_INSN_FUNCTION_USAGE (insn); x; x = XEXP (x, 1)) if (GET_CODE (XEXP (x, 0)) == CLOBBER) - cselib_invalidate_rtx (XEXP (XEXP (x, 0), 0), NULL_RTX, NULL); + cselib_invalidate_rtx (XEXP (XEXP (x, 0), 0)); cselib_current_insn = 0; diff --git a/gcc/cselib.h b/gcc/cselib.h index b529060..1aff251 100644 --- a/gcc/cselib.h +++ b/gcc/cselib.h @@ -70,3 +70,4 @@ extern enum machine_mode cselib_reg_set_mode (rtx); extern int rtx_equal_for_cselib_p (rtx, rtx); extern int references_value_p (rtx, int); extern rtx cselib_subst_to_values (rtx); +extern void cselib_invalidate_rtx (rtx); diff --git a/gcc/postreload.c b/gcc/postreload.c index 20d4a4f..2ff95b1 100644 --- a/gcc/postreload.c +++ b/gcc/postreload.c @@ -118,6 +118,19 @@ reload_cse_simplify (rtx insn, rtx testreg) int count = 0; rtx value = NULL_RTX; + /* Registers mentioned in the clobber list for an asm cannot be reused + within the body of the asm. Invalidate those registers now so that + we don't try to substitute values for them. */ + if (asm_noperands (body) >= 0) + { + for (i = XVECLEN (body, 0) - 1; i >= 0; --i) + { + rtx part = XVECEXP (body, 0, i); + if (GET_CODE (part) == CLOBBER && REG_P (XEXP (part, 0))) + cselib_invalidate_rtx (XEXP (part, 0)); + } + } + /* If every action in a PARALLEL is a noop, we can delete the entire PARALLEL. */ for (i = XVECLEN (body, 0) - 1; i >= 0; --i) diff --git a/gcc/testsuite/gcc.dg/i386-asm-3.c b/gcc/testsuite/gcc.dg/i386-asm-3.c new file mode 100644 index 0000000..f60f7d6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/i386-asm-3.c @@ -0,0 +1,34 @@ +/* PR inline-asm/6806 */ +/* { dg-do run { target i?86-*-* } } */ +/* { dg-options "-O2" } */ + +extern void abort (void); + +volatile int out = 1; +volatile int a = 2; +volatile int b = 4; +volatile int c = 8; +volatile int d = 16; +volatile int e = 32; +volatile int f = 64; + +int +main () +{ + asm volatile ("xorl %%eax, %%eax \n\t" + "xorl %%esi, %%esi \n\t" + "addl %1, %0 \n\t" + "addl %2, %0 \n\t" + "addl %3, %0 \n\t" + "addl %4, %0 \n\t" + "addl %5, %0 \n\t" + "addl %6, %0" + : "+r" (out) + : "r" (a), "r" (b), "r" (c), "g" (d), "g" (e), "g" (f) + : "%eax", "%esi"); + + if (out != 127) + abort (); + + return 0; +} |