summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog18
-rw-r--r--gcc/df.c36
-rw-r--r--gcc/df.h11
-rw-r--r--gcc/ra-build.c17
-rw-r--r--gcc/ra-colorize.c10
-rw-r--r--gcc/ra.c20
-rw-r--r--gcc/ra.h7
7 files changed, 79 insertions, 40 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4d90245bf0d..1debc6929a1 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,21 @@
+2003-03-07 Michael Matz <matz@suse.de>
+
+ * df.h (enum df_ref_flags.DF_REF_STRIPPED): New.
+ (DF_FOR_REGALLOC): New.
+ * df.c (df_ref_record): Set DF_REF_STRIPPED.
+ (read_modify_subreg_p): Simplify.
+ (df_def_record_1, df_uses_record): Set DF_REF_MODE_CHANGE more often.
+ Use DF_FOR_REGALLOC.
+ * ra.h (struct web): New member subreg_stripped.
+ (invalid_mode_change_regs): Declare.
+ * ra.c (invalid_mode_change_regs): New.
+ (init_ra): Initialize it.
+ * ra-build.c (init_one_web_common, remember_web_was_spilled): Use it.
+ Use CANNOT_CHANGE_MODE_CLASS as ifdef guard.
+ (reinit_one_web, parts_to_web_1): Deal with subreg_stripped.
+ * ra-colorize.c (colorize_one_web): Use invalid_mode_change_regs.
+ Use CANNOT_CHANGE_MODE_CLASS as ifdef guard.
+
2003-03-07 Richard Earnshaw <rearnsha@arm.com>
* arm.md (addsf3, adddf3, subsf3, subdf3, mulsf3, muldf3, negsf2)
diff --git a/gcc/df.c b/gcc/df.c
index c151249a197..740f2ccad1c 100644
--- a/gcc/df.c
+++ b/gcc/df.c
@@ -849,6 +849,7 @@ df_ref_record (df, reg, loc, insn, ref_type, ref_flags)
{
loc = &SUBREG_REG (reg);
reg = *loc;
+ ref_flags |= DF_REF_STRIPPED;
}
regno = REGNO (GET_CODE (reg) == SUBREG ? SUBREG_REG (reg) : reg);
@@ -893,13 +894,8 @@ read_modify_subreg_p (x)
return false;
isize = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
osize = GET_MODE_SIZE (GET_MODE (x));
- if (isize <= osize)
- return true;
- if (isize <= UNITS_PER_WORD)
- return false;
- if (osize > UNITS_PER_WORD)
- return false;
- return true;
+ /* Paradoxical subreg writes don't leave a trace of the old content. */
+ return (isize > osize && isize > UNITS_PER_WORD);
}
@@ -927,9 +923,7 @@ df_def_record_1 (df, x, bb, insn)
}
#ifdef CLASS_CANNOT_CHANGE_MODE
- if (GET_CODE (dst) == SUBREG
- && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (dst)),
- GET_MODE (dst)))
+ if (GET_CODE (dst) == SUBREG)
flags |= DF_REF_MODE_CHANGE;
#endif
@@ -938,7 +932,8 @@ df_def_record_1 (df, x, bb, insn)
while (GET_CODE (dst) == STRICT_LOW_PART
|| GET_CODE (dst) == ZERO_EXTRACT
|| GET_CODE (dst) == SIGN_EXTRACT
- || read_modify_subreg_p (dst))
+ || ((df->flags & DF_FOR_REGALLOC) == 0
+ && read_modify_subreg_p (dst)))
{
/* Strict low part always contains SUBREG, but we do not want to make
it appear outside, as whole register is always considered. */
@@ -948,9 +943,7 @@ df_def_record_1 (df, x, bb, insn)
dst = *loc;
}
#ifdef CLASS_CANNOT_CHANGE_MODE
- if (GET_CODE (dst) == SUBREG
- && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (dst)),
- GET_MODE (dst)))
+ if (GET_CODE (dst) == SUBREG)
flags |= DF_REF_MODE_CHANGE;
#endif
loc = &XEXP (dst, 0);
@@ -1050,9 +1043,7 @@ df_uses_record (df, loc, ref_type, bb, insn, flags)
return;
}
#ifdef CLASS_CANNOT_CHANGE_MODE
- if (CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (x),
- GET_MODE (SUBREG_REG (x))))
- flags |= DF_REF_MODE_CHANGE;
+ flags |= DF_REF_MODE_CHANGE;
#endif
/* ... Fall through ... */
@@ -1072,13 +1063,12 @@ df_uses_record (df, loc, ref_type, bb, insn, flags)
{
enum df_ref_flags use_flags;
case SUBREG:
- if (read_modify_subreg_p (dst))
+ if ((df->flags & DF_FOR_REGALLOC) == 0
+ && read_modify_subreg_p (dst))
{
use_flags = DF_REF_READ_WRITE;
#ifdef CLASS_CANNOT_CHANGE_MODE
- if (CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (dst),
- GET_MODE (SUBREG_REG (dst))))
- use_flags |= DF_REF_MODE_CHANGE;
+ use_flags |= DF_REF_MODE_CHANGE;
#endif
df_uses_record (df, &SUBREG_REG (dst), DF_REF_REG_USE, bb,
insn, use_flags);
@@ -1102,9 +1092,7 @@ df_uses_record (df, loc, ref_type, bb, insn, flags)
abort ();
use_flags = DF_REF_READ_WRITE;
#ifdef CLASS_CANNOT_CHANGE_MODE
- if (CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (dst),
- GET_MODE (SUBREG_REG (dst))))
- use_flags |= DF_REF_MODE_CHANGE;
+ use_flags |= DF_REF_MODE_CHANGE;
#endif
df_uses_record (df, &SUBREG_REG (dst), DF_REF_REG_USE, bb,
insn, use_flags);
diff --git a/gcc/df.h b/gcc/df.h
index d20d298cf7a..a294843c6cb 100644
--- a/gcc/df.h
+++ b/gcc/df.h
@@ -31,6 +31,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define DF_ALL 255
#define DF_HARD_REGS 1024 /* Mark hard registers. */
#define DF_EQUIV_NOTES 2048 /* Mark uses present in EQUIV/EQUAL notes. */
+#define DF_FOR_REGALLOC 4096 /* If called for the register allocator. */
enum df_ref_type {DF_REF_REG_DEF, DF_REF_REG_USE, DF_REF_REG_MEM_LOAD,
DF_REF_REG_MEM_STORE};
@@ -52,13 +53,17 @@ enum df_ref_flags
DF_REF_READ_WRITE = 1,
/* This flag is set on register references inside a subreg on
- machines which have CLASS_CANNOT_CHANGE_MODE and where the mode
- change of that subreg expression is invalid for this class.
+ machines which have CANNOT_CHANGE_MODE_CLASS.
Note, that this flag can also be set on df_refs representing
the REG itself (i.e., one might not see the subreg anyore).
Also note, that this flag is set also for hardreg refs, i.e.,
you must check yourself if it's a pseudo. */
- DF_REF_MODE_CHANGE = 2
+ DF_REF_MODE_CHANGE = 2,
+
+ /* This flag is set, if we stripped the subreg from the reference.
+ In this case we must make conservative guesses, at what the
+ outer mode was. */
+ DF_REF_STRIPPED = 4
};
diff --git a/gcc/ra-build.c b/gcc/ra-build.c
index 4448065de0d..37ca30c7994 100644
--- a/gcc/ra-build.c
+++ b/gcc/ra-build.c
@@ -1305,10 +1305,9 @@ init_one_web_common (web, reg)
AND_COMPL_HARD_REG_SET (web->usable_regs, never_use_colors);
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
web->num_freedom = hard_regs_count (web->usable_regs);
web->num_freedom -= web->add_hardregs;
@@ -1351,6 +1350,7 @@ reinit_one_web (web, reg)
web->artificial = 0;
web->live_over_abnormal = 0;
web->mode_changed = 0;
+ web->subreg_stripped = 0;
web->move_related = 0;
web->in_load = 0;
web->target_of_spilled_move = 0;
@@ -1912,6 +1912,9 @@ parts_to_webs_1 (df, copy_webs, all_refs)
if ((DF_REF_FLAGS (ref) & DF_REF_MODE_CHANGE) != 0
&& web->regno >= FIRST_PSEUDO_REGISTER)
web->mode_changed = 1;
+ if ((DF_REF_FLAGS (ref) & DF_REF_STRIPPED) != 0
+ && web->regno >= FIRST_PSEUDO_REGISTER)
+ web->subreg_stripped = 1;
if (i >= def_id
&& TEST_BIT (live_over_abnormal, ref_id))
web->live_over_abnormal = 1;
@@ -1961,6 +1964,9 @@ parts_to_webs_1 (df, copy_webs, all_refs)
if ((DF_REF_FLAGS (ref) & DF_REF_MODE_CHANGE) != 0
&& web->regno >= FIRST_PSEUDO_REGISTER)
web->mode_changed = 1;
+ if ((DF_REF_FLAGS (ref) & DF_REF_STRIPPED) != 0
+ && web->regno >= FIRST_PSEUDO_REGISTER)
+ web->subreg_stripped = 1;
/* Setup def2web, or use2web, and increment num_defs or num_uses. */
if (i < def_id)
@@ -2364,10 +2370,9 @@ remember_web_was_spilled (web)
reg_class_contents[(int) GENERAL_REGS]);
AND_COMPL_HARD_REG_SET (web->usable_regs, never_use_colors);
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
web->num_freedom = hard_regs_count (web->usable_regs);
if (!web->num_freedom)
diff --git a/gcc/ra-colorize.c b/gcc/ra-colorize.c
index 359dfd86126..6c514df1c4e 100644
--- a/gcc/ra-colorize.c
+++ b/gcc/ra-colorize.c
@@ -1370,10 +1370,9 @@ colorize_one_web (web, hard)
else
COPY_HARD_REG_SET (colors,
usable_regs[reg_preferred_class (web->regno)]);
-#ifdef CLASS_CANNOT_CHANGE_MODE
+#ifdef CANNOT_CHANGE_MODE_CLASS
if (web->mode_changed)
- AND_COMPL_HARD_REG_SET (colors, reg_class_contents[
- (int) CLASS_CANNOT_CHANGE_MODE]);
+ AND_COMPL_HARD_REG_SET (colors, invalid_mode_change_regs);
#endif
COPY_HARD_REG_SET (call_clobbered, colors);
AND_HARD_REG_SET (call_clobbered, call_used_reg_set);
@@ -1404,10 +1403,9 @@ colorize_one_web (web, hard)
else
IOR_HARD_REG_SET (colors, usable_regs
[reg_alternate_class (web->regno)]);
-#ifdef CLASS_CANNOT_CHANGE_MODE
+#ifdef CANNOT_CHANGE_MODE_CLASS
if (web->mode_changed)
- AND_COMPL_HARD_REG_SET (colors, reg_class_contents[
- (int) CLASS_CANNOT_CHANGE_MODE]);
+ AND_COMPL_HARD_REG_SET (colors, invalid_mode_change_regs);
#endif
COPY_HARD_REG_SET (call_clobbered, colors);
AND_HARD_REG_SET (call_clobbered, call_used_reg_set);
diff --git a/gcc/ra.c b/gcc/ra.c
index dfd4ef5b519..45f22ced3bb 100644
--- a/gcc/ra.c
+++ b/gcc/ra.c
@@ -148,6 +148,7 @@ HARD_REG_SET never_use_colors;
HARD_REG_SET usable_regs[N_REG_CLASSES];
unsigned int num_free_regs[N_REG_CLASSES];
HARD_REG_SET hardregs_for_mode[NUM_MACHINE_MODES];
+HARD_REG_SET invalid_mode_change_regs;
unsigned char byte2bitcount[256];
unsigned int debug_new_regalloc = -1;
@@ -555,6 +556,23 @@ init_ra ()
COPY_HARD_REG_SET (hardregs_for_mode[i], rs);
}
+ 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;
+ enum machine_mode to;
+ for (to = VOIDmode; to < MAX_MACHINE_MODE; ++to)
+ {
+ int r;
+ for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
+ if (REG_CANNOT_CHANGE_MODE_P (from, to, r))
+ SET_HARD_REG_BIT (invalid_mode_change_regs, r);
+ }
+ }
+#endif
+
for (an_unusable_color = 0; an_unusable_color < FIRST_PSEUDO_REGISTER;
an_unusable_color++)
if (TEST_HARD_REG_BIT (never_use_colors, an_unusable_color))
@@ -755,7 +773,7 @@ reg_alloc ()
chains per insn, and per regno. In later passes only update
that info from the new and modified insns. */
df_analyse (df, (ra_pass == 1) ? 0 : (bitmap) -1,
- DF_HARD_REGS | DF_RD_CHAIN | DF_RU_CHAIN);
+ DF_HARD_REGS | DF_RD_CHAIN | DF_RU_CHAIN | DF_FOR_REGALLOC);
if ((debug_new_regalloc & DUMP_DF) != 0)
{
diff --git a/gcc/ra.h b/gcc/ra.h
index 522b77a7586..f324d362ad3 100644
--- a/gcc/ra.h
+++ b/gcc/ra.h
@@ -168,6 +168,11 @@ struct web
was illegal for hardregs in CLASS_CANNOT_CHANGE_MODE. */
unsigned int mode_changed:1;
+ /* Nonzero if some references of this web, where in subreg context,
+ but the actual subreg is already stripped (i.e. we don't know the
+ outer mode of the actual reference). */
+ unsigned int subreg_stripped:1;
+
/* Nonzero, when this web stems from the last pass of the allocator,
and all info is still valid (i.e. it wasn't spilled). */
unsigned int old_web:1;
@@ -497,6 +502,8 @@ extern unsigned int num_free_regs[N_REG_CLASSES];
represent the possible resources which could be taken away be a value
in mode M. */
extern HARD_REG_SET hardregs_for_mode[NUM_MACHINE_MODES];
+/* The set of hardregs, for which _any_ mode change is invalid. */
+extern HARD_REG_SET invalid_mode_change_regs;
/* For 0 <= I <= 255, the number of bits set in I. Used to calculate
the number of set bits in a HARD_REG_SET. */
extern unsigned char byte2bitcount[256];