[new-ra] Bootstrap on amd64 and pentiumpro
Michael Matz
matz@suse.de
Mon Apr 5 09:29:00 GMT 2004
Hi,
the branch as is doesn't bootstrap on amd64 and i386 (if configured as
pentiumpro). The main issue is the non-handling of
CANNOT_CHANGE_MODE_CLASS machines, which somewhen got lost. Hmpf.
There was also a problem that somewhen it deleted insns which have
sideeffects.
And a third one regarding the acceptance of certain instruction constraint
wise. Denis: I now remember (because I rediscovered the bug ;-)) why we
can't ignore the character after '*'. We must accept as reload would
(which ignores '*'). The actual problem is move patterns. For amd64 the
SSE moves are implemented by hiding the 'Y' constraint after '*', so it
doesn't get accidentially taken up by regclass to influence register
choices.
But if we ignore them also in pre-reload we have no way anymore to move
something in or out of SSE registers (because at least the mov insns must
work).
And a last thing is, that pre-reload sometimes has to create a subreg of
pseudo as scratch operand, so we have to accept this during newra.
Anyway the branch now bootstraps on amd64 and i386.
Ciao,
Michael.
--
* df.c (df_def_record_1, df_uses_record): Set DF_REF_MODE_CHANGE.
* pre-reload.c (scan_alternative): Don't ignore characters after '*'.
(scan_alternative): Use pre_operands_match_p, handle other
direction too.
* ra-build.c (select_regclass): Use ALL_REGS for nonreferenced webs.
Move never_use_colors intersection down. Handle
CANNOT_CHANGE_MODE_CLASS machines.
(calc_pref_class): Use invalid_mode_change_regs instead predicate.
* ra-rewrite.c (assign_stack_slots_1): Don't delete complicated
insns.
(web_class_spill_ref): Handle the case of multiple uses and defs
in one insns. Handle defs and uses by the same code.
* ra.c (init_ra): Calculate invalid_mode_change_regs at all
and correctly.
* recog.c (scratch_operand): During register allocation accept
? .ra-build.c.swp
Index: df.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/df.c,v
retrieving revision 1.1.2.26
diff -u -p -r1.1.2.26 df.c
--- df.c 6 Nov 2003 17:07:02 -0000 1.1.2.26
+++ df.c 5 Apr 2004 08:28:54 -0000
@@ -928,6 +928,9 @@ df_def_record_1 (struct df *df, rtx x, b
return;
}
+ if (GET_CODE (dst) == SUBREG)
+ flags |= DF_REF_MODE_CHANGE;
+
/* Maybe, we should flag the use of STRICT_LOW_PART somehow. It might
be handy for the reg allocator. */
while (GET_CODE (dst) == STRICT_LOW_PART
@@ -943,6 +946,8 @@ df_def_record_1 (struct df *df, rtx x, b
loc = &XEXP (dst, 0);
dst = *loc;
}
+ if (GET_CODE (dst) == SUBREG)
+ flags |= DF_REF_MODE_CHANGE;
loc = &XEXP (dst, 0);
dst = *loc;
flags |= DF_REF_READ_WRITE;
@@ -1033,6 +1038,7 @@ df_uses_record (struct df *df, rtx *loc,
df_uses_record (df, loc, ref_type, bb, insn, flags);
return;
}
+ flags |= DF_REF_MODE_CHANGE;
/* ... Fall through ... */
case REG:
@@ -1053,7 +1059,7 @@ df_uses_record (struct df *df, rtx *loc,
if ((df->flags & DF_FOR_REGALLOC) == 0
&& read_modify_subreg_p (dst))
{
- use_flags = DF_REF_READ_WRITE;
+ use_flags = DF_REF_READ_WRITE | DF_REF_MODE_CHANGE;
df_uses_record (df, &SUBREG_REG (dst), DF_REF_REG_USE, bb,
insn, use_flags);
break;
@@ -1074,7 +1080,7 @@ df_uses_record (struct df *df, rtx *loc,
dst = XEXP (dst, 0);
if (GET_CODE (dst) != SUBREG)
abort ();
- use_flags = DF_REF_READ_WRITE;
+ use_flags = DF_REF_READ_WRITE | DF_REF_MODE_CHANGE;
df_uses_record (df, &SUBREG_REG (dst), DF_REF_REG_USE, bb,
insn, use_flags);
break;
Index: pre-reload.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/pre-reload.c,v
retrieving revision 1.1.2.23
diff -u -p -r1.1.2.23 pre-reload.c
--- pre-reload.c 5 Mar 2004 06:05:30 -0000 1.1.2.23
+++ pre-reload.c 5 Apr 2004 08:28:54 -0000
@@ -2366,9 +2366,10 @@ scan_alternative (this_alt, constraints,
c = '\0';
break;
- case '=': case '+':
+ case '=': case '+': case '*':
break;
+#if 0
case '*':
/* Ignore next constraint because it's reloading.
It's not a regclass. */
@@ -2377,6 +2378,7 @@ scan_alternative (this_alt, constraints,
if (c && c != ',')
len = CONSTRAINT_LEN (c, p);
break;
+#endif
case '%':
/* The last operand should not be marked commutative. */
@@ -2802,8 +2804,13 @@ scan_alternative (this_alt, constraints,
/* Don't coutn an input operand that is constrained to match
the early clobber operand. */
&& ! (this_alt[j].matches == i
- && rtx_equal_p (recog_data.operand[i],
- recog_data.operand[j]))
+ && pre_operands_match_p (recog_data.operand[i],
+ recog_data.operand[j]))
+ /* Similarly if the output operand is constrained to match
+ the input operand. This can only happen for clobbers. */
+ && ! (this_alt[i].matches == j
+ && pre_operands_match_p (recog_data.operand[i],
+ recog_data.operand[j]))
/* Is it altered by storing the earlyclobber operand? */
&& !pre_reload_immune_p (recog_data.operand[j],
recog_data.operand[i],
Index: ra-build.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ra-build.c,v
retrieving revision 1.1.2.27
diff -u -p -r1.1.2.27 ra-build.c
--- ra-build.c 5 Mar 2004 06:05:30 -0000 1.1.2.27
+++ ra-build.c 5 Apr 2004 08:28:54 -0000
@@ -3092,12 +3092,6 @@ select_regclass ()
[reg_alternate_class (web->regno)]);
}
}
- /* add_hardregs is wrong in multi-length classes, e.g.
- using a DFmode pseudo on x86 can result in class FLOAT_INT_REGS,
- where, if it finally is allocated to GENERAL_REGS it needs two,
- if allocated to FLOAT_REGS only one hardreg. XXX */
- AND_COMPL_HARD_REG_SET (web->usable_regs, never_use_colors);
-
/* Don't limit usable regs for uninitialized webs too much.
This could make us spill them (when usable_regs becomes empty
if we also remove caller saved regs),
@@ -3110,6 +3104,15 @@ select_regclass ()
if (!web->num_defs)
IOR_HARD_REG_SET (web->usable_regs,
reg_class_contents[(int) GENERAL_REGS]);
+
+ /* XXX A non referenced web sometimes happens when we were able to
+ remove all references by rematerialization. We shouldn't even
+ try to color them or look at them at all, but for now we simply
+ make sure they can be colored to something. */
+ if (web->num_defs == 0 && web->num_uses == 0)
+ IOR_HARD_REG_SET (web->usable_regs,
+ reg_class_contents[(int) ALL_REGS]);
+
if (web->crosses_call)
{
unsigned int num_refs = web->num_uses + web->num_defs;
@@ -3137,12 +3140,13 @@ select_regclass ()
prune_hardregs_for_mode (&web->usable_regs,
PSEUDO_REGNO_MODE (web->regno));
-#ifdef CLASS_CANNOT_CHANGE_MODE
+#ifdef CANNOT_CHANGE_MODE_CLASS
if (web->mode_changed)
- AND_COMPL_HARD_REG_SET (web->usable_regs, reg_class_contents
- [(int) CLASS_CANNOT_CHANGE_MODE]);
+ AND_COMPL_HARD_REG_SET (web->usable_regs, invalid_mode_change_regs);
#endif
+ AND_COMPL_HARD_REG_SET (web->usable_regs, never_use_colors);
+
if ((web->spill_temp == 1 || web->spill_temp == 2)
&& ! web->changed
&& ! flag_ra_pre_reload)
@@ -3171,6 +3175,10 @@ found:
}
}
+ /* add_hardregs is wrong in multi-length classes, e.g.
+ using a DFmode pseudo on x86 can result in class FLOAT_INT_REGS,
+ where, if it finally is allocated to GENERAL_REGS it needs two,
+ if allocated to FLOAT_REGS only one hardreg. XXX */
web->add_hardregs
= CLASS_MAX_NREGS (web->regclass,
web->parent_web
@@ -4004,8 +4012,8 @@ calc_pref_class (struct costs *p, struct
#endif
#ifdef CANNOT_CHANGE_MODE_CLASS
|| (web->mode_changed
- && invalid_mode_change_p (web->regno, (enum reg_class) class,
- mode))
+ && hard_regs_intersect_p (&invalid_mode_change_regs,
+ ®_class_contents[class]))
#endif
)
;
Index: ra-rewrite.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ra-rewrite.c,v
retrieving revision 1.1.2.27
diff -u -p -r1.1.2.27 ra-rewrite.c
--- ra-rewrite.c 13 Nov 2003 19:02:01 -0000 1.1.2.27
+++ ra-rewrite.c 5 Apr 2004 08:28:54 -0000
@@ -2674,9 +2674,18 @@ assign_stack_slots_1 ()
unsigned int i;
rtx dead = DF_REF_INSN (web->defs[0]);
struct ra_insn_info *info = &insn_df[INSN_UID (dead)];
+ rtx set;
- if (info->num_defs != 1 || GET_CODE (dead) != INSN
- || can_throw_internal (dead))
+ /* This web only has one definition and the insn also only one
+ def. But we really have to test if the only set in that insn
+ indeed sets a reg, because otherwise it could be a clobber and
+ the real set does change memory. We can't delete such insns. */
+ if (info->num_defs != 1
+ || !(set = single_set (dead))
+ || !REG_P (SET_DEST (set))
+ || volatile_refs_p (SET_SRC (set))
+ || can_throw_internal (dead)
+ || (flag_non_call_exceptions && may_trap_p (dead)))
continue;
for (i = 0; i < info->num_uses; ++i)
{
@@ -4063,120 +4072,106 @@ web_class_spill_ref (web, ref)
{
rtx insns;
rtx insn = DF_REF_INSN (ref);
-
- if (DF_REF_REG_USE_P (ref))
- {
- int num_refs;
- int i, j;
- rtx source, target;
- struct ref **refs;
- rtx def_dst = NULL;
- rtx def_src = NULL;
- rtx reg = gen_reg_rtx (PSEUDO_REGNO_MODE (web->regno));
- basic_block bb = BLOCK_FOR_INSN (insn);
-
- for (i = 0, refs = web->uses, num_refs = web->num_uses;
- i < 2;
- refs = web->defs, num_refs = web->num_defs, i++)
- for (j = 0; j < num_refs; j++)
- {
- if (DF_REF_INSN (refs[j]) != insn)
- continue;
-
- target = DF_REF_REG (refs[j]);
- source = reg;
-
- if (GET_CODE (target) == SUBREG)
- source = simplify_gen_subreg (GET_MODE (target), source,
- GET_MODE (source),
- SUBREG_BYTE (target));
- ra_validate_change (insn, DF_REF_LOC (refs[j]), source, 1);
- if (i == 1) /* This is a def. */
- {
- if (def_src)
- abort ();
- def_src = source;
- def_dst = DF_REF_REG (refs[j]);
- }
- }
- if (!ra_apply_change_group ())
- abort ();
-
- df_insn_modify (df, bb, insn);
- bitmap_set_bit (ra_modified_insns, INSN_UID (insn));
-
- start_sequence ();
- ra_emit_move_insn (reg, web->orig_x);
- insns = get_insns ();
- end_sequence ();
- if (insns)
- {
- rtx pi;
- rtx aux_insn = PREV_INSN (insn);
- emit_insn_before (insns, insn);
- if (bb->head == insn)
- bb->head = NEXT_INSN (aux_insn);
- for (pi = PREV_INSN (insn); pi != aux_insn;
- pi = PREV_INSN (pi))
+ int num_refs;
+ int i, j;
+ struct ref **refs;
+ rtx *new_defs, *new_uses;
+ int ind_defs = 0, ind_uses = 0;
+ rtx reg = gen_reg_rtx (PSEUDO_REGNO_MODE (web->regno));
+ basic_block bb = BLOCK_FOR_INSN (insn);
+
+ new_defs = alloca (2 * (web->num_defs + web->num_uses)
+ * sizeof (new_defs[0]));
+ new_uses = alloca (2 * (web->num_defs + web->num_uses)
+ * sizeof (new_uses[0]));
+ for (i = 0, refs = web->uses, num_refs = web->num_uses;
+ i < 2;
+ refs = web->defs, num_refs = web->num_defs, i++)
+ for (j = 0; j < num_refs; j++)
+ if (DF_REF_INSN (refs[j]) == insn)
+ {
+ rtx target = DF_REF_REG (refs[j]);
+ rtx source = reg;
+
+ if (GET_CODE (target) == SUBREG)
+ source = simplify_gen_subreg (GET_MODE (target), source,
+ GET_MODE (source),
+ SUBREG_BYTE (target));
+ ra_validate_change (insn, DF_REF_LOC (refs[j]), source, 1);
+ if (i == 0)
+ /* A use. */
{
- set_block_for_insn (pi, bb);
- df_insn_modify (df, bb, pi);
- bitmap_set_bit (ra_modified_insns, INSN_UID (pi));
+ /* Full REGs come first. */
+ if (GET_CODE (target) == REG)
+ new_uses[0] = source, new_uses[1] = target, ind_uses = 1;
+ else if (ind_uses == 0 || GET_CODE (new_uses[0]) == SUBREG)
+ /* Otherwise if we are a SUBREG add us only if there's
+ not already a full REG in the first position. */
+ {
+ new_uses[2 * ind_uses] = copy_rtx (source);
+ new_uses[2 * ind_uses + 1] = copy_rtx (target);
+ ind_uses++;
+ }
}
- }
-
- if (def_src)
- {
- start_sequence ();
- ra_emit_move_insn (def_dst, copy_rtx (def_src));
- insns = get_insns ();
- end_sequence ();
- if (insns)
+ else
+ /* A def. */
{
- rtx ni;
- rtx aux_insn = NEXT_INSN (insn);
- emit_insn_after (insns, insn);
- if (bb->end == insn)
- bb->end = PREV_INSN (aux_insn);
- for (ni = insns; ni != aux_insn; ni = NEXT_INSN (ni))
+ if (GET_CODE (target) == REG)
+ new_defs[0] = source, new_defs[1] = target, ind_defs = 1;
+ else if (ind_defs == 0 || GET_CODE (new_defs[0]) == SUBREG)
+ /* Otherwise if we are a SUBREG add us only if there's
+ not already a full REG in the first position. */
{
- set_block_for_insn (ni, bb);
- df_insn_modify (df, bb, ni);
- bitmap_set_bit (ra_modified_insns, INSN_UID (ni));
+ new_defs[2 * ind_defs] = copy_rtx (source);
+ new_defs[2 * ind_defs + 1] = copy_rtx (target);
+ ind_defs++;
}
}
}
+ if (!ra_apply_change_group ())
+ abort ();
+
+ df_insn_modify (df, bb, insn);
+ bitmap_set_bit (ra_modified_insns, INSN_UID (insn));
+
+ start_sequence ();
+ for (i = 0; i < ind_uses; i++)
+ ra_emit_move_insn (new_uses[2 * i], new_uses[2 * i + 1]);
+ insns = get_insns ();
+ end_sequence ();
+ if (insns)
+ {
+ rtx pi;
+ rtx aux_insn = PREV_INSN (insn);
+ emit_insn_before (insns, insn);
+ if (bb->head == insn)
+ bb->head = NEXT_INSN (aux_insn);
+ for (pi = PREV_INSN (insn); pi != aux_insn;
+ pi = PREV_INSN (pi))
+ {
+ set_block_for_insn (pi, bb);
+ df_insn_modify (df, bb, pi);
+ bitmap_set_bit (ra_modified_insns, INSN_UID (pi));
+ }
}
- else if (DF_REF_REG_DEF_P (ref))
+
+ start_sequence ();
+ for (i = 0; i < ind_defs; i++)
+ ra_emit_move_insn (new_defs[2 * i + 1], new_defs[2 * i]);
+ insns = get_insns ();
+ end_sequence ();
+ if (insns)
{
+ rtx ni;
rtx aux_insn = NEXT_INSN (insn);
- rtx reg = gen_reg_rtx (GET_MODE (DF_REF_REG (ref)));
- basic_block bb = BLOCK_FOR_INSN (insn);
-
- if (ra_validate_change (insn, DF_REF_LOC (ref), reg, 0))
+ emit_insn_after (insns, insn);
+ if (bb->end == insn)
+ bb->end = PREV_INSN (aux_insn);
+ for (ni = insns; ni != aux_insn; ni = NEXT_INSN (ni))
{
- df_insn_modify (df, bb, insn);
- bitmap_set_bit (ra_modified_insns, INSN_UID (insn));
- }
- else
- abort ();
-
- start_sequence ();
- ra_emit_move_insn (DF_REF_REG (ref), reg);
- insns = get_insns ();
- end_sequence ();
- if (insns)
- {
- rtx ni;
- emit_insn_after (insns, insn);
- if (bb->end == insn)
- bb->end = PREV_INSN (aux_insn);
- for (ni = insns; ni != aux_insn; ni = NEXT_INSN (ni))
- {
- set_block_for_insn (ni, bb);
- df_insn_modify (df, bb, ni);
- bitmap_set_bit (ra_modified_insns, INSN_UID (ni));
- }
+ set_block_for_insn (ni, bb);
+ df_insn_modify (df, bb, ni);
+ bitmap_set_bit (ra_modified_insns, INSN_UID (ni));
}
}
}
Index: ra.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ra.c,v
retrieving revision 1.1.2.77
diff -u -p -r1.1.2.77 ra.c
--- ra.c 5 Mar 2004 06:05:30 -0000 1.1.2.77
+++ ra.c 5 Apr 2004 08:28:54 -0000
@@ -233,7 +233,7 @@ hard_regs_count (HARD_REG_SET rs)
/* Basically like emit_move_insn (i.e. validifies constants and such),
but also handle MODE_CC moves (but then the operands must already
- be basically valid. */
+ be basically valid). */
rtx
ra_emit_move_insn (rtx x, rtx y)
@@ -634,7 +634,6 @@ init_ra (void)
CLEAR_HARD_REG_SET (invalid_mode_change_regs);
#ifdef CANNOT_CHANGE_MODE_CLASS
- if (0)
for (i = 0; i < NUM_MACHINE_MODES; i++)
{
enum machine_mode from = (enum machine_mode) i;
@@ -643,7 +642,7 @@ init_ra (void)
{
int r;
for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
- if (REG_CANNOT_CHANGE_MODE_P (from, to, r))
+ if (REG_CANNOT_CHANGE_MODE_P (r, from, to))
SET_HARD_REG_BIT (invalid_mode_change_regs, r);
}
}
Index: recog.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/recog.c,v
retrieving revision 1.87.2.10
diff -u -p -r1.87.2.10 recog.c
--- recog.c 10 Oct 2003 14:19:02 -0000 1.87.2.10
+++ recog.c 5 Apr 2004 08:28:54 -0000
@@ -1092,7 +1092,8 @@ scratch_operand (rtx op, enum machine_mo
return (GET_CODE (op) == SCRATCH
|| (GET_CODE (op) == REG
&& (REGNO (op) < FIRST_PSEUDO_REGISTER || while_newra
- || (newra_in_progress && !SPILL_SLOT_P (REGNO (op))))));
+ || (newra_in_progress && !SPILL_SLOT_P (REGNO (op)))))
+ || (while_newra && GET_CODE (op) == SUBREG));
}
/* Return 1 if OP is a valid immediate operand for mode MODE.
More information about the Gcc-patches
mailing list