This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[new-regalloc] Bootstrap dammit
- From: Michael Matz <matz at suse dot de>
- To: <gcc-patches at gcc dot gnu dot org>
- Date: Fri, 21 Feb 2003 01:43:52 +0100 (CET)
- Subject: [new-regalloc] Bootstrap dammit
Hi,
the below patch makes the branch bootstrap again most languages (Ada not
tested). Now I've finally a better base for ensuring that the merge of my
other things don't introduce too much breakage.
Ciao,
Michael.
--
* df.h (DF_REF_ALREADY_SPILLED, DF_REF_COMPARE_RELATED,
DF_REF_EARLYCLOBBER): New.
* df.c (df_ref_search_cached): Ignore some flags for equality.
(read_modify_subreg_p): Return false.
(df_uses_record): Mark compare related refs.
* ra-build.c (copy_insn_p): If there are stack pseudos, it's no
copy insn.
(detect_remat_webs): Don't rematerialize trapping expressions.
(class_ok_for_mode): New.
(web_class): Use it.
* ra-colorize.c (proper_hard_reg_subset_p): New.
(colorize_one_web): Use it.
* ra-rewrite.c (delete_useless_defs): Don't delete throwing insns.
(assign_stack_slots_1): Ditto.
Index: df.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/df.c,v
retrieving revision 1.1.2.19
diff -u -p -r1.1.2.19 df.c
--- df.c 20 Nov 2002 22:43:10 -0000 1.1.2.19
+++ df.c 21 Feb 2003 00:10:55 -0000
@@ -799,7 +799,9 @@ df_ref_search_cached (df, reg, loc, insn
&& DF_REF_LOC (this_ref) == loc
&& DF_REF_INSN (this_ref) == insn
&& DF_REF_TYPE (this_ref) == ref_type
- && (DF_REF_FLAGS (this_ref) & ~DF_REF_DELETED) == ref_flags)
+ && (DF_REF_FLAGS (this_ref)
+ & (DF_REF_READ_WRITE | DF_REF_MODE_CHANGE
+ | DF_REF_COMPARE_RELATED)) == ref_flags)
{
DF_REF_FLAGS (this_ref) &= ~DF_REF_DELETED;
return this_ref;
@@ -939,23 +941,29 @@ df_ref_record (df, reg, loc, insn, ref_t
}
}
-/* Writes to paradoxical subregs, or subregs which are too narrow
- are read-modify-write. */
+/* Writes to subregs which are too narrow are read-modify-write. */
static inline bool
read_modify_subreg_p (x)
rtx x;
{
unsigned int isize, osize;
+ /* Hmm, with exact subreg tracking _no_ writes to subregs are
+ read-mod-write in any way. Inside a STRICT_LOW_PART they are,
+ but not otherwise. Narrow subregs at least clobber the whole word
+ they belong to, wider subregs a whole number of words.
+ Paradoxical subreg writes don't leave a trace of the old content. */
+ return false;
if (GET_CODE (x) != SUBREG)
return false;
isize = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
osize = GET_MODE_SIZE (GET_MODE (x));
+ /* Paradoxical subreg writes don't leave a trace of the old content. */
if (isize <= osize)
- return true;
- if (isize <= UNITS_PER_WORD)
return false;
- if (osize >= UNITS_PER_WORD)
+ if (osize >= GET_MODE_SIZE (SImode))
+ return false;
+ if (isize <= UNITS_PER_WORD)
return false;
return true;
}
@@ -1225,6 +1233,10 @@ df_uses_record (df, loc, ref_type, bb, i
/* ... Fall through to handle uses ... */
default:
+ /* Mark registers used in comparisons, because we might want to adjust
+ their spill cost in the graph coloring register allocator. */
+ if (GET_RTX_CLASS (code) == '<')
+ flags |= DF_REF_COMPARE_RELATED;
break;
}
Index: df.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/df.h,v
retrieving revision 1.1.2.11
diff -u -p -r1.1.2.11 df.h
--- df.h 20 Nov 2002 22:43:09 -0000 1.1.2.11
+++ df.h 21 Feb 2003 00:10:55 -0000
@@ -61,7 +61,10 @@ enum df_ref_flags
I.e. you must check yourself if it's a pseudo. */
DF_REF_MODE_CHANGE = 2,
DF_REF_DELETED = 4,
- DF_REF_MEM_OK = 8
+ DF_REF_MEM_OK = 8,
+ DF_REF_ALREADY_SPILLED = 16,
+ DF_REF_COMPARE_RELATED = 32,
+ DF_REF_EARLYCLOBBER = 64
};
/* Define a register reference structure. */
Index: ra-build.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ra-build.c,v
retrieving revision 1.1.2.9
diff -u -p -r1.1.2.9 ra-build.c
--- ra-build.c 1 Feb 2003 17:27:08 -0000 1.1.2.9
+++ ra-build.c 21 Feb 2003 00:10:55 -0000
@@ -279,8 +279,8 @@ copy_insn_p (insn, source, target)
/* Copies between hardregs are useless for us, as not coalesable anyway. */
if ((s_regno < FIRST_PSEUDO_REGISTER
&& d_regno < FIRST_PSEUDO_REGISTER)
- /*|| SPILL_SLOT_P (s_regno)
- || SPILL_SLOT_P (d_regno)*/)
+ || SPILL_SLOT_P (s_regno)
+ || SPILL_SLOT_P (d_regno))
return 0;
if (source)
@@ -2599,6 +2599,8 @@ rematerializable_stack_arg_p (insn, src)
return 0;
}
+extern int flag_non_call_exceptions;
+
/* Look at all webs, if they perhaps are rematerializable.
They are, if all their defs are simple sets to the same value,
and that value is simple enough, and want_to_remat() holds for it. */
@@ -2657,6 +2659,8 @@ detect_remat_webs ()
&& bitmap_bit_p (emitted_by_spill, INSN_UID (insn))
&& memref_is_stack_slot (src))
|| rematerializable_stack_arg_p (insn, src))
+ /* Don't even try to rematerialize trapping things. */
+ && !(flag_non_call_exceptions && may_trap_p (src))
/* And we must be able to construct an insn without
side-effects to actually load that value into a reg. */
&& want_to_remat (src))
@@ -3683,6 +3687,23 @@ conflicts_early_clobbered ()
}
}
+static int class_ok_for_mode PARAMS ((enum reg_class, enum machine_mode));
+
+/* Returns true if at least one of the hardregs in CLASS is OK
+ for MODE. */
+static int
+class_ok_for_mode (class, mode)
+ enum reg_class class;
+ enum machine_mode mode;
+{
+ int i;
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (TEST_HARD_REG_BIT (reg_class_contents[(int) class], i)
+ && HARD_REGNO_MODE_OK (i, mode))
+ return 1;
+ return 0;
+}
+
/* Select a reg_class for the WEB. Split the WEB if single reg_class
can't be selected. */
static void
@@ -3752,6 +3773,9 @@ web_class (web)
}
else
{
+ /* XXX Ugly hack to suppress repeated spilling tries for such webs. */
+ if (!class_ok_for_mode (class, PSEUDO_REGNO_MODE (web->regno)))
+ class = GENERAL_REGS;
web->regclass = class;
COPY_HARD_REG_SET (web->usable_regs, usable_regs[class]);
}
Index: ra-colorize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ra-colorize.c,v
retrieving revision 1.1.2.8
diff -u -p -r1.1.2.8 ra-colorize.c
--- ra-colorize.c 1 Feb 2003 17:27:08 -0000 1.1.2.8
+++ ra-colorize.c 21 Feb 2003 00:10:55 -0000
@@ -72,6 +72,7 @@ static int get_biased_reg PARAMS ((HARD_
HARD_REG_SET, enum machine_mode));
static char * hardregset_to_string PARAMS ((HARD_REG_SET));
static void calculate_dont_begin PARAMS ((struct web *, HARD_REG_SET *));
+static int proper_hard_reg_subset_p PARAMS ((HARD_REG_SET, HARD_REG_SET));
static void colorize_one_web PARAMS ((struct web *, int));
static void assign_colors PARAMS ((void));
static void try_recolor_web PARAMS ((struct web *));
@@ -1293,6 +1294,22 @@ calculate_dont_begin (web, result)
COPY_HARD_REG_SET (*result, dont_begin);
}
+/* Returns nonzero if S1 is a proper subset of S2. */
+
+static int
+proper_hard_reg_subset_p (s1, s2)
+ HARD_REG_SET s1, s2;
+{
+ HARD_REG_SET s;
+ COPY_HARD_REG_SET (s, s2);
+ AND_COMPL_HARD_REG_SET (s, s1);
+ /* If s == s2 - s1 is empty s1 is not a proper subset of s2. */
+ GO_IF_HARD_REG_SUBSET (s, reg_class_contents[(int) NO_REGS], lose);
+ return 1;
+lose:
+ return 0;
+}
+
/* Try to assign a color to WEB. If HARD if nonzero, we try many
tricks to get it one color, including respilling already colored
neighbors.
@@ -1619,7 +1636,12 @@ colorize_one_web (web, hard)
/* If in the last iteration no insns were emitted for this
web we also try to spill neighbors which are spill
temps (and not only type 2 spill temps). */
- if (web->changed && !aw->changed && aw->spill_temp)
+ if (web->changed && aw->spill_temp
+ && (!aw->changed
+ /* Similar if the other (spill-temp) web has more
+ usable regs than us. */
+ || proper_hard_reg_subset_p (web->usable_regs,
+ aw->usable_regs)))
set_cand (8, aw);
if (aw->spill_temp && aw->span_deaths /* && !aw->changed */
&& !web->span_deaths
Index: ra-rewrite.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ra-rewrite.c,v
retrieving revision 1.1.2.8
diff -u -p -r1.1.2.8 ra-rewrite.c
--- ra-rewrite.c 1 Feb 2003 17:27:08 -0000 1.1.2.8
+++ ra-rewrite.c 21 Feb 2003 00:10:55 -0000
@@ -1983,7 +1983,8 @@ delete_useless_defs ()
rtx insn = DF_REF_INSN (df->defs[i]);
rtx set = single_set (insn);
struct web *web = find_web_for_subweb (def2web[i]);
- if (set && web->type == SPILLED && web->stack_slot == NULL)
+ if (set && web->type == SPILLED && web->stack_slot == NULL
+ && !can_throw_internal (insn))
{
deleted_def_insns++;
deleted_def_cost += BLOCK_FOR_INSN (insn)->frequency + 1;
@@ -2459,7 +2460,8 @@ assign_stack_slots_1 ()
rtx dead = DF_REF_INSN (web->defs[0]);
struct ra_insn_info *info = &insn_df[INSN_UID (dead)];
- if (info->num_defs != 1 || GET_CODE (dead) != INSN)
+ if (info->num_defs != 1 || GET_CODE (dead) != INSN
+ || can_throw_internal (dead))
continue;
for (i = 0; i < info->num_uses; ++i)
{