aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Matz <matz@suse.de>2003-07-02 15:08:53 +0000
committerMichael Matz <matz@suse.de>2003-07-02 15:08:53 +0000
commit4eb1e6e493e7961bd287415be8132fb37561f088 (patch)
tree6b221efdb66cbacb3a1f957d2a57cf0ae0fa7558
parent5250df07048a40e5dd40c09df5893ab51f02f955 (diff)
http://gcc.gnu.org/ml/gcc-patches/2003-07/msg00206.html
* df.h (enum df_ref_flags, DF_REF_STRICTLY_PARTIAL_DEF): New. * ra-build.c (live_out_1): Set this flag on some refs. (select_regclass): Obey flag_caller_saves. * ra-rewrite.c (detect_web_parts_to_rebuild): Reset DF_REF_STRICTLY_PARTIAL_DEF. (create_flow_barriers_2): Rename from ... (create_flow_barriers): ... this. Reimplement. * ra.c (reg_alloc): Delete the fake clobbers inserted as flow barriers before returning. * toplev.c (parse_options_and_default_flags): Don't do register renaming with the new RA. git-svn-id: https://gcc.gnu.org/svn/gcc/branches/new-regalloc-branch@68840 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog.RA13
-rw-r--r--gcc/df.h3
-rw-r--r--gcc/ra-build.c12
-rw-r--r--gcc/ra-rewrite.c47
-rw-r--r--gcc/ra.c18
-rw-r--r--gcc/toplev.c10
6 files changed, 100 insertions, 3 deletions
diff --git a/gcc/ChangeLog.RA b/gcc/ChangeLog.RA
index 418457864e6..65a1aa2189b 100644
--- a/gcc/ChangeLog.RA
+++ b/gcc/ChangeLog.RA
@@ -1,4 +1,17 @@
2003-06-30 Michael Matz <matz@suse.de>
+ * df.h (enum df_ref_flags, DF_REF_STRICTLY_PARTIAL_DEF): New.
+ * ra-build.c (live_out_1): Set this flag on some refs.
+ (select_regclass): Obey flag_caller_saves.
+ * ra-rewrite.c (detect_web_parts_to_rebuild): Reset
+ DF_REF_STRICTLY_PARTIAL_DEF.
+ (create_flow_barriers_2): Rename from ...
+ (create_flow_barriers): ... this. Reimplement.
+ * ra.c (reg_alloc): Delete the fake clobbers inserted as
+ flow barriers before returning.
+ * toplev.c (parse_options_and_default_flags): Don't do register
+ renaming with the new RA.
+
+2003-06-30 Michael Matz <matz@suse.de>
* Makefile.in (cse.o): Depend on df.h.
* cse.c (insn_live_p): Trapping insns are not necessarily live.
* defaults.h (SPILL_REGS): Define.
diff --git a/gcc/df.h b/gcc/df.h
index 60c1c70d2ee..674b59c00bd 100644
--- a/gcc/df.h
+++ b/gcc/df.h
@@ -64,7 +64,8 @@ enum df_ref_flags
DF_REF_MEM_OK = 8,
DF_REF_ALREADY_SPILLED = 16,
DF_REF_COMPARE_RELATED = 32,
- DF_REF_EARLYCLOBBER = 64
+ DF_REF_EARLYCLOBBER = 64,
+ DF_REF_STRICTLY_PARTIAL_DEF = 128
};
/* Define a register reference structure. */
diff --git a/gcc/ra-build.c b/gcc/ra-build.c
index 04efc3bc238..eaecc03e786 100644
--- a/gcc/ra-build.c
+++ b/gcc/ra-build.c
@@ -804,6 +804,10 @@ live_out_1 (df, use, insn)
part and this DEF conflicting. */
{
unsigned HOST_WIDE_INT undef;
+ /*XXX:*/
+#ifdef WHEN_I_HAVE_FIXED_THIS_CASE
+ DF_REF_FLAGS (ref) |= DF_REF_STRICTLY_PARTIAL_DEF;
+#endif
undef = use->undefined;
while (undef)
bitmap_set_bit (undef_to_bitmap (wp, &undef),
@@ -837,6 +841,10 @@ live_out_1 (df, use, insn)
If they have no bits in common (lap == -1), they are
really independent. Therefore we there made a
conflict above. */
+ else
+ /* But we need to mark that this def was a strictly
+ partial definition. */
+ DF_REF_FLAGS (ref) |= DF_REF_STRICTLY_PARTIAL_DEF;
}
/* This is at least a partial overlap, so we need to union
the web parts. */
@@ -2733,6 +2741,7 @@ rematerializable_stack_arg_p (insn, src)
return 0;
}
+extern int flag_caller_saves;
extern int flag_non_call_exceptions;
/* Look at all webs, if they perhaps are rematerializable.
@@ -3008,7 +3017,8 @@ select_regclass ()
{
unsigned int num_refs = web->num_uses + web->num_defs;
unsigned int num_calls = web->num_calls;
- if (!CALLER_SAVE_PROFITABLE (num_refs, num_calls))
+ if (!flag_caller_saves
+ || !CALLER_SAVE_PROFITABLE (num_refs, num_calls))
AND_COMPL_HARD_REG_SET (web->usable_regs,
regs_invalidated_by_call);
}
diff --git a/gcc/ra-rewrite.c b/gcc/ra-rewrite.c
index 42546e77521..c25579a9af9 100644
--- a/gcc/ra-rewrite.c
+++ b/gcc/ra-rewrite.c
@@ -1756,7 +1756,8 @@ detect_web_parts_to_rebuild ()
/* For the spilled web itself we also need to clear it's
uplink, to be able to rebuild smaller webs. After all
- spilling has split the web. */
+ spilling has split the web. And also reset some flags
+ on the individual references, as they might have changed. */
for (i = 0; i < web->num_uses; i++)
{
unsigned int id = DF_REF_ID (web->uses[i]);
@@ -1778,6 +1779,7 @@ detect_web_parts_to_rebuild ()
web_parts[id].crosses_call = 0;
web_parts[id].crosses_bb = 0;
web_parts[id].crosses_memset = 0;
+ DF_REF_FLAGS (df->defs[id]) &= ~DF_REF_STRICTLY_PARTIAL_DEF;
}
/* Now look at all neighbors of this spilled web. */
@@ -2880,6 +2882,49 @@ void
create_flow_barriers ()
{
basic_block bb;
+ FOR_EACH_BB (bb)
+ {
+ rtx insn;
+ for (insn = bb->head; insn != bb->end; insn = NEXT_INSN (insn))
+ if (INSN_P (insn))
+ {
+ unsigned int d;
+ struct ra_insn_info info = insn_df[INSN_UID (insn)];
+ for (d = 0; d < info.num_defs; d++)
+ {
+ struct ref *ref = info.defs[d];
+ rtx rdef = *DF_REF_REAL_LOC (ref);
+ if (REG_P (rdef)
+ && REGNO (rdef) >= FIRST_PSEUDO_REGISTER
+ && (DF_REF_FLAGS (ref) & DF_REF_STRICTLY_PARTIAL_DEF) == 0
+ && GET_CODE (DF_REF_REG (ref)) == SUBREG)
+ {
+ struct web *web, *aweb;
+ unsigned int n;
+ web = find_web_for_subweb (def2web[DF_REF_ID (ref)]);
+ aweb = alias (web);
+ if (aweb->type != COLORED
+ && (aweb->type != PRECOLORED || web == aweb))
+ continue;
+
+ for (n = 0; n < info.num_uses; n++)
+ if (aweb == alias (find_web_for_subweb (use2web[DF_REF_ID
+ (info.uses[n])])))
+ break;
+ if (n != info.num_uses)
+ continue;
+
+ emit_insn_before (gen_rtx_CLOBBER (VOIDmode, rdef), insn);
+ }
+ }
+ }
+ }
+}
+
+static void
+create_flow_barriers_2 ()
+{
+ basic_block bb;
sbitmap live;
bitmap partly_defined = BITMAP_XMALLOC ();
live = sbitmap_alloc (num_webs);
diff --git a/gcc/ra.c b/gcc/ra.c
index a167d6b0003..39e84842c54 100644
--- a/gcc/ra.c
+++ b/gcc/ra.c
@@ -1240,6 +1240,24 @@ reg_alloc ()
setup_renumber (1);
sbitmap_free (insns_with_deaths);
+ /* And then delete the clobbers again, which were inserted just as
+ flow barriers. */
+ {
+ rtx insn, next;
+ for (insn = get_insns (); insn; insn = next)
+ {
+ next = NEXT_INSN (insn);
+ if (INSN_P (insn))
+ {
+ rtx pat = PATTERN (insn);
+ if (GET_CODE (pat) == CLOBBER
+ && REG_P (SET_DEST (pat))
+ && REGNO (SET_DEST (pat)) >= FIRST_PSEUDO_REGISTER)
+ delete_insn_and_edges (insn);
+ }
+ }
+ }
+
/* Build the insn chain before deleting some of the REG_DEAD notes.
It initializes the chain->live_throughout bitmap, and when we delete
some REG_DEAD we leave some pseudo in those bitmaps for insns, where
diff --git a/gcc/toplev.c b/gcc/toplev.c
index b68aeb8d5e2..86c9ad548dc 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -4972,6 +4972,16 @@ parse_options_and_default_flags (argc, argv)
flag_reorder_blocks = 0;
}
+ /* The lifeness information for uninitialized registers, of which only
+ subregs are defined/used is not completely correct (there are some
+ DEAD notes for pseudos, whose hardreg is _not_ dead there, as some
+ other uninitialized pseudo has the same hardreg, and is life at the
+ same time). This confuses register renaming and leads to aborts
+ in verify_local_live_at_start. */
+ if (flag_new_regalloc)
+ {
+ flag_rename_registers = 0;
+ }
/* Initialize whether `char' is signed. */
flag_signed_char = DEFAULT_SIGNED_CHAR;
#ifdef DEFAULT_SHORT_ENUMS