update_equiv_regs fix
Jan Hubicka
hubicka@atrey.karlin.mff.cuni.cz
Sat Dec 25 08:08:00 GMT 1999
Hi
It seems to me that update_equiv_regs contain bug that might result in
incorrect code. It moves the insns with REG_EUIV note right before the user of
register. I believe that when insn is parallel clobbering register it may
actually clobber live register. I don't have testcase, but I believe that the
problem is quite clear. Thats why I've added ok_to_move_before_p function to
verify that insn don't contain any clobbers of non-scratchs and uses of
nonconstant stuff.
Pá prosinec 24 10:24:56 CET 1999 Jan Hubicka <hubicka@freesoft.cz>
* equiv.c (ok_to_move_before_p): New static function.
(update_equiv_regs): Use it.
*** equiv.c.noequiv2 Fri Dec 24 08:46:03 1999
--- equiv.c Fri Dec 24 10:12:27 1999
*************** static int equiv_mem_modified;
*** 56,65 ****
Called via note_stores. */
static void validate_equiv_mem_from_store PROTO((rtx, rtx, void *));
static int validate_equiv_mem PROTO((rtx, rtx, rtx));
static int contains_replace_regs PROTO((rtx));
static int memref_referenced_p PROTO((rtx, rtx));
static int memref_used_between_p PROTO((rtx, rtx, rtx));
static void no_equiv PROTO((rtx, rtx, void *));
static void
--- 53,63 ----
Called via note_stores. */
static void validate_equiv_mem_from_store PROTO((rtx, rtx, void *));
static int validate_equiv_mem PROTO((rtx, rtx, rtx));
static int contains_replace_regs PROTO((rtx));
static int memref_referenced_p PROTO((rtx, rtx));
static int memref_used_between_p PROTO((rtx, rtx, rtx));
static void no_equiv PROTO((rtx, rtx, void *));
+ static int ok_to_move_before_p PROTO((rtx, rtx));
static void
*************** function_invariant_p (x)
*** 284,289 ****
--- 313,347 ----
return 0;
}
+ /* Return 1 if it is OK to move single_set insn INSN before insn WHERE.
+ We have to ensure, that insn don't contain any clobbers to live registers
+ or any uses of registers. */
+ static int
+ ok_to_move_before_p (insn, where)
+ rtx insn;
+ rtx where ATTRIBUTE_UNUSED;
+ {
+ rtx pat = PATTERN (insn);
+ int i;
+ if (GET_CODE (pat) != PARALLEL)
+ return 1;
+ for (i = 0; i < XVECLEN (pat, 0); i++)
+ {
+ rtx x = XVECEXP (pat, 0, i);
+
+ /* We ought to verify that register didn't changed in the insn,
+ but it is probably not too important, since USES are rare. */
+ if (GET_CODE (x) == USE && !function_invariant_p (XEXP (x, 0)))
+ return 0;
+
+ /* If it turns out to be important, we may check that given hard register
+ is dead and accept such insns. */
+ if (GET_CODE (x) == CLOBBER && GET_CODE (XEXP (x, 0)) != SCRATCH)
+ return 0;
+ }
+ return 0;
+ }
+
/* Find registers that are equivalent to a single value throughout the
compilation (either because they can be referenced in memory or are set once
from a single constant). Lower their priority for a register.
*************** update_equiv_regs ()
*** 592,597 ****
--- 635,641 ----
before INSN. Update the flow information. */
else if (depth == 0
&& GET_CODE (equiv_insn) == INSN
+ && ok_to_move_before_p (equiv_insn, insn)
&& GET_CODE (insn) == INSN
&& REG_BASIC_BLOCK (regno) < 0)
{
More information about the Gcc-patches
mailing list