This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[new-regalloc-branch] combine with precolored regs & rewrite_program
- To: gcc-patches at gcc dot gnu dot org
- Subject: [new-regalloc-branch] combine with precolored regs & rewrite_program
- From: Denis Chertykov <denisc at overta dot ru>
- Date: Tue, 31 Jul 2001 02:07:02 +0400
- Cc: Denis Chertykov <denisc at overta dot ru>, Michael Matz <matzmich at cs dot tu-berlin dot de>, Daniel Berlin <dan at cgsoftware dot com>
I will not apply this patch without approval.
Tue Jul 31 01:47:59 2001 Denis Chertykov <denisc@overta.ru>
* ra.c (combine): combine add_hardregs's of U and V.
(ok): Restriction for combining a web with a precolored web is
removed. Check a precolored web for usable_regs.
(rewrite_program): Since we always call `regclass' if
`changed' we can emit a new pseudos which will have a new reg
class preferences.
Index: ra.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/Attic/ra.c,v
retrieving revision 1.1.2.26
diff -c -3 -p -r1.1.2.26 ra.c
*** ra.c 2001/07/30 17:31:59 1.1.2.26
--- ra.c 2001/07/30 21:49:26
*************** ok (target, source)
*** 2798,2803 ****
--- 2798,2804 ----
struct web *target, *source;
{
struct conflict_link *wl;
+ int i;
/* Source is PRECOLORED. We test here, if it isn't one of the fixed
registers. In this case we disallow the coalescing.
*************** ok (target, source)
*** 2811,2821 ****
if (TEST_HARD_REG_BIT (never_use_colors, source->color))
return 0;
! /* XXX we can't right now combine a web with a hard-reg to a web
! with a multi-word pseudo, cause we get the conflicts wrong (we forget
! to add the other hard-regs to the conflicts, and only see the first). */
! if (source->add_hardregs != target->add_hardregs)
! return 0;
for (wl = target->conflict_list; wl; wl = wl->next)
{
--- 2812,2822 ----
if (TEST_HARD_REG_BIT (never_use_colors, source->color))
return 0;
! /* We can't coalesce target with the precolored registers which isn't in
! usable_regs. */
! for (i = target->add_hardregs; i >= 0; --i)
! if (!TEST_HARD_REG_BIT (usable_regs[target->regclass], source->color + i))
! return 0;
for (wl = target->conflict_list; wl; wl = wl->next)
{
*************** combine (u, v)
*** 2926,2955 ****
u->is_coalesced = 1;
v->is_coalesced = 1;
merge_moves (u, v);
! /* XXX combine add_hardregs's of U and V. */
! for (wl = v->conflict_list; wl; wl = wl->next)
{
! struct web *pweb = wl->t;
! if (pweb->type != SELECT && pweb->type != COALESCED)
! {
! if (wl->sub == NULL)
! record_conflict (u, pweb);
! else
{
! struct sub_conflict *sl;
! /* So, between V and PWEB there are sub_conflicts. We need
! to relocate those conflicts to be between U and PWEB.
! In the case only a part of V conflicted with (part of) PWEB
! we nevertheless make the new conflict between the whole U and
! the (part of) PWEB. Later we might try to find in U the
! correct subpart corresponding (by size and offset) to the
! part of V (sl->s) which was the source of the conflict. */
! for (sl = wl->sub; sl; sl = sl->next)
! record_conflict (u, sl->t);
}
! decrement_degree (pweb, 1 + v->add_hardregs);
! }
}
if (u->num_conflicts >= NUM_REGS (u) && u->type == FREEZE)
{
remove_list (u->dlink, &freeze_wl);
--- 2927,2990 ----
u->is_coalesced = 1;
v->is_coalesced = 1;
merge_moves (u, v);
! /* combine add_hardregs's of U and V. */
! if (u->type == PRECOLORED)
{
! int i;
! struct web *web;
!
! for (i = 0; i <= v->add_hardregs; ++i)
! {
! web = hardreg2web [i + u->color];
! for (wl = v->conflict_list; wl; wl = wl->next)
{
! struct web *pweb = wl->t;
! if (pweb->type != SELECT && pweb->type != COALESCED)
! {
! if (wl->sub == NULL)
! record_conflict (pweb, web);
! else
! {
! struct sub_conflict *sl;
! for (sl = wl->sub; sl; sl = sl->next)
! record_conflict (u, sl->t);
! }
! }
}
! }
!
! for (wl = v->conflict_list; wl; wl = wl->next)
! {
! struct web *pweb = wl->t;
! if (pweb->type != SELECT && pweb->type != COALESCED)
! decrement_degree (pweb, 1 + v->add_hardregs);
! }
}
+ else
+ for (wl = v->conflict_list; wl; wl = wl->next)
+ {
+ struct web *pweb = wl->t;
+ if (pweb->type != SELECT && pweb->type != COALESCED)
+ {
+ if (wl->sub == NULL)
+ record_conflict (u, pweb);
+ else
+ {
+ struct sub_conflict *sl;
+ /* So, between V and PWEB there are sub_conflicts. We need
+ to relocate those conflicts to be between U and PWEB.
+ In the case only a part of V conflicted with (part of) PWEB
+ we nevertheless make the new conflict between the whole U
+ and the (part of) PWEB. Later we might try to find in U the
+ correct subpart corresponding (by size and offset) to the
+ part of V (sl->s) which was the source of the conflict. */
+ for (sl = wl->sub; sl; sl = sl->next)
+ record_conflict (u, sl->t);
+ }
+ decrement_degree (pweb, 1 + v->add_hardregs);
+ }
+ }
+
if (u->num_conflicts >= NUM_REGS (u) && u->type == FREEZE)
{
remove_list (u->dlink, &freeze_wl);
*************** rewrite_program (void)
*** 3641,3648 ****
dest = gen_rtx_MEM (GET_MODE (source),
plus_constant (XEXP (dest, 0),
SUBREG_BYTE (source)));
}
! emit_insn (gen_move_insn (dest, source));
insns = get_insns ();
end_sequence ();
emit_insns_after (insns, insn);
--- 3676,3693 ----
dest = gen_rtx_MEM (GET_MODE (source),
plus_constant (XEXP (dest, 0),
SUBREG_BYTE (source)));
+ emit_insn (gen_move_insn (dest, source));
+ }
+ else
+ {
+ rtx reg = gen_reg_rtx (GET_MODE (source));
+ if (validate_change (insn, DF_REF_LOC (web->defs[j]),
+ reg, 0))
+ emit_insn (gen_move_insn (dest, reg));
+ else
+ emit_insn (gen_move_insn (dest, source));
}
!
insns = get_insns ();
end_sequence ();
emit_insns_after (insns, insn);
*************** rewrite_program (void)
*** 3703,3710 ****
source = gen_rtx_MEM (GET_MODE (target),
plus_constant (XEXP (source, 0),
SUBREG_BYTE (target)));
}
! emit_insn (gen_move_insn (target, source));
insns = get_insns ();
end_sequence ();
emit_insns_before (insns, insn);
--- 3748,3766 ----
source = gen_rtx_MEM (GET_MODE (target),
plus_constant (XEXP (source, 0),
SUBREG_BYTE (target)));
+ emit_insn (gen_move_insn (target, source));
+ }
+ else
+ {
+ rtx reg = gen_reg_rtx (GET_MODE (target));
+
+ if (validate_change (insn, DF_REF_LOC (web->uses[j]),
+ reg, 0))
+ emit_insn (gen_move_insn (reg ,source));
+ else
+ emit_insn (gen_move_insn (target, source));
}
!
insns = get_insns ();
end_sequence ();
emit_insns_before (insns, insn);