This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR 20972


The register allocator is, in rare instances, sharing a register between
the base address of a store instruction and the value to be stored,
when the base address is uninitialized.

For example:

	char val=5, *ptr;
     *ptr = val;

Might become:

	move     #5, r5
	store	r5, [r5]

This itself is not an issue, since val's life ends where ptr's life
begins, and so they can share a register.

However, in the case of PR 20972, what we see is more like:

*ptr++ = val;

Which generates:

store r5, [r5]++

In this case, the post-increment addressing has the potential
of corrupting the source value.

gcc's scheduler is allowing 'ptr' and 'val' to share a register
because it treats a post-increment instruction as a 'set' operation,
which means it does not conflict with the inputs.  However, since
post-increment addressing calculates the resulting value from the
initial value, it is more accurately considered a 'clobber'
operation.  The attached patch causes the allocator to consider a
post-increment as a clobber, calculating its conflicts before
any inputs are killed.

Attached is also a test case that demonstrates the same failure for
an arm-none-elf target, which is on the primary platform list.

Since I am unable to build the mainline right now for arm-*-elf,
tested with 20050405 mainline source for arm-unknown-elf and
i686-pc-cygwin with no regressions.  I'd be glad to hold off and
retest after the ultimate patch for 20126 is committed, if that
would be preferred.

If approved, can someone please commit?

Thanks -

Josh
~~~~
Josh Conner
Apple Computer

2005-04-11 Josh Conner <jconner@apple.com>

		* global.c (global_conflicts): Treat an auto-increment
			instruction as a clobber of the base register
			instead of a set.


Index: gcc/global.c =================================================================== RCS file: /cvsroot/gcc/gcc/gcc/global.c,v retrieving revision 1.123 diff -c -3 -p -r1.123 global.c *** gcc/global.c 17 Feb 2005 22:41:32 -0000 1.123 --- gcc/global.c 12 Apr 2005 16:42:49 -0000 *************** global_conflicts (void) *** 810,815 **** --- 810,823 ----

note_stores (PATTERN (insn), mark_reg_clobber, NULL);

+ #ifdef AUTO_INC_DEC
+             /* Auto-increment instructions clobber the base
+                register.  */
+             for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
+               if (REG_NOTE_KIND (link) == REG_INC)
+                 mark_reg_store (XEXP (link, 0), NULL_RTX, NULL);
+ #endif
+
              /* Mark any registers dead after INSN as dead now.  */

              for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
*************** global_conflicts (void)
*** 823,834 ****

note_stores (PATTERN (insn), mark_reg_store, NULL);

- #ifdef AUTO_INC_DEC
- for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
- if (REG_NOTE_KIND (link) == REG_INC)
- mark_reg_store (XEXP (link, 0), NULL_RTX, NULL);
- #endif
-
/* If INSN has multiple outputs, then any reg that dies here
and is used inside of an output
must conflict with the other outputs.
--- 831,836 ----


Attachment: 20050411-1.c
Description: Text document




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]