Patch to fix recent local-alloc IA-64 breakage
John Wehle
john@feith.com
Mon Oct 23 04:57:00 GMT 2000
This appears to fix the recent problem. A make bootstrap and make
check is in progress on an Alpha to sanity check the change. I
unfortunately don't have access to an IA-64 (I looked at the testcase
with gcc set up as a cross compiler).
ChangeLog:
Mon Oct 23 01:34:44 EDT 2000 John Wehle (john@feith.com)
* local-alloc.c (equiv_init_call_clobbered_p): New function.
(struct equivalence): Add call_clobbered field.
(update_equiv_regs): Set it.
(equiv_init_movable_p): An equivalence which uses a call clobbered
register can't be moved past any calls.
Enjoy!
-- John Wehle
------------------8<------------------------8<------------------------
*** gcc/local-alloc.c.ORIGINAL Fri Oct 20 00:47:25 2000
--- gcc/local-alloc.c Mon Oct 23 02:38:58 2000
*************** struct equivalence
*** 251,256 ****
--- 251,262 ----
rtx src;
+ /* Used to recognize equivalences which can't be moved
+ across a call. For example the PIC register on the
+ IA-64 is call clobbered even though it's invariant. */
+
+ char call_clobbered;
+
/* Loop depth is used to recognize equivalences which appear
to be present within the same loop (or in an inner loop). */
*************** static int recorded_label_ref;
*** 272,277 ****
--- 278,284 ----
static void alloc_qty PARAMS ((int, enum machine_mode, int, int));
static void validate_equiv_mem_from_store PARAMS ((rtx, rtx, void *));
static int validate_equiv_mem PARAMS ((rtx, rtx, rtx));
+ static int equiv_init_call_clobbered_p PARAMS ((rtx));
static int equiv_init_varies_p PARAMS ((rtx));
static int equiv_init_movable_p PARAMS ((rtx, int));
static int contains_replace_regs PARAMS ((rtx));
*************** validate_equiv_mem (start, reg, memref)
*** 514,519 ****
--- 521,573 ----
return 0;
}
+ /* Returns non-zero if a register X mentions is call clobbered
+ or has an equivalent initialization which is call clobbered. */
+
+ static int
+ equiv_init_call_clobbered_p (x)
+ rtx x;
+ {
+ register RTX_CODE code = GET_CODE (x);
+ register int i;
+ register const char *fmt;
+
+ switch (code)
+ {
+ case CONST:
+ case CONST_INT:
+ case CONST_DOUBLE:
+ case SYMBOL_REF:
+ case LABEL_REF:
+ return 0;
+
+ case REG:
+ return reg_equiv[REGNO (x)].call_clobbered
+ || (REGNO (x) < FIRST_PSEUDO_REGISTER
+ && call_used_regs[REGNO (x)]);
+
+ default:
+ break;
+ }
+
+ fmt = GET_RTX_FORMAT (code);
+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ if (fmt[i] == 'e')
+ {
+ if (equiv_init_call_clobbered_p (XEXP (x, i)))
+ return 1;
+ }
+ else if (fmt[i] == 'E')
+ {
+ int j;
+ for (j = 0; j < XVECLEN (x, i); j++)
+ if (equiv_init_call_clobbered_p (XVECEXP (x, i, j)))
+ return 1;
+ }
+
+ return 0;
+ }
+
/* Returns zero if X is known to be invariant. */
static int
*************** equiv_init_movable_p (x, regno)
*** 601,606 ****
--- 655,668 ----
return 0;
case REG:
+ /* The equivalence can't be moved across a call if it depends
+ on other equivalences which contain call clobbered registers
+ or if it contains call clobbered registers. */
+ if ((reg_equiv[REGNO (x)].call_clobbered
+ || (REGNO (x) < FIRST_PSEUDO_REGISTER && call_used_regs[REGNO (x)]))
+ && REG_N_CALLS_CROSSED (regno))
+ return 0;
+
return (reg_equiv[REGNO (x)].loop_depth >= reg_equiv[regno].loop_depth
&& reg_equiv[REGNO (x)].replace)
|| (REG_BASIC_BLOCK (REGNO (x)) < 0 && ! rtx_varies_p (x));
*************** update_equiv_regs ()
*** 998,1003 ****
--- 1060,1067 ----
reg_equiv[regno].replacement = XEXP (note, 0);
reg_equiv[regno].src = src;
+ reg_equiv[regno].call_clobbered
+ = equiv_init_call_clobbered_p (src);
reg_equiv[regno].loop_depth = loop_depth;
/* Don't mess with things live during setjmp. */
-------------------------------------------------------------------------
| Feith Systems | Voice: 1-215-646-8000 | Email: john@feith.com |
| John Wehle | Fax: 1-215-540-5495 | |
-------------------------------------------------------------------------
More information about the Gcc-patches
mailing list