diff options
author | Michael Matz <matz@suse.de> | 2003-07-02 15:08:53 +0000 |
---|---|---|
committer | Michael Matz <matz@suse.de> | 2003-07-02 15:08:53 +0000 |
commit | 4eb1e6e493e7961bd287415be8132fb37561f088 (patch) | |
tree | 6b221efdb66cbacb3a1f957d2a57cf0ae0fa7558 | |
parent | 5250df07048a40e5dd40c09df5893ab51f02f955 (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.RA | 13 | ||||
-rw-r--r-- | gcc/df.h | 3 | ||||
-rw-r--r-- | gcc/ra-build.c | 12 | ||||
-rw-r--r-- | gcc/ra-rewrite.c | 47 | ||||
-rw-r--r-- | gcc/ra.c | 18 | ||||
-rw-r--r-- | gcc/toplev.c | 10 |
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. @@ -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); @@ -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 |