diff options
author | dberlin <dberlin@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-06-11 18:02:15 +0000 |
---|---|---|
committer | dberlin <dberlin@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-06-11 18:02:15 +0000 |
commit | 3072d30e7983a3ca5ad030f1f98a5c39bcc2c07b (patch) | |
tree | fdb9e9f8a0700a2713dc690fed1a2cf20dae8392 /gcc/config/ia64/ia64.c | |
parent | 8ceb1bfd33bc40bf0cbe1fab8903c2c31efd10ee (diff) | |
download | gcc-3072d30e7983a3ca5ad030f1f98a5c39bcc2c07b.tar.gz |
Merge dataflow branch into mainline
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@125624 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/ia64/ia64.c')
-rw-r--r-- | gcc/config/ia64/ia64.c | 436 |
1 files changed, 261 insertions, 175 deletions
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index 5e1328b3bfb..24af522fac3 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -53,8 +53,10 @@ Boston, MA 02110-1301, USA. */ #include "cfglayout.h" #include "tree-gimple.h" #include "intl.h" +#include "df.h" #include "debug.h" #include "params.h" +#include "dbgcnt.h" #include "tm-constrs.h" /* This is used for communication between ASM_OUTPUT_LABEL and @@ -122,6 +124,18 @@ unsigned int ia64_section_threshold; TRUE if we do insn bundling instead of insn scheduling. */ int bundling_p = 0; +enum ia64_frame_regs +{ + reg_fp, + reg_save_b0, + reg_save_pr, + reg_save_ar_pfs, + reg_save_ar_unat, + reg_save_ar_lc, + reg_save_gp, + number_of_ia64_frame_regs +}; + /* Structure to be filled in by ia64_compute_frame_size with register save masks and offsets for the current function. */ @@ -136,13 +150,7 @@ struct ia64_frame_info unsigned int gr_used_mask; /* mask of registers in use as gr spill registers or long-term scratches. */ int n_spilled; /* number of spilled registers. */ - int reg_fp; /* register for fp. */ - int reg_save_b0; /* save register for b0. */ - int reg_save_pr; /* save register for prs. */ - int reg_save_ar_pfs; /* save register for ar.pfs. */ - int reg_save_ar_unat; /* save register for ar.unat. */ - int reg_save_ar_lc; /* save register for ar.lc. */ - int reg_save_gp; /* save register for gp. */ + int r[number_of_ia64_frame_regs]; /* Frame related registers. */ int n_input_regs; /* number of input registers used. */ int n_local_regs; /* number of local registers used. */ int n_output_regs; /* number of output registers used. */ @@ -154,6 +162,8 @@ struct ia64_frame_info /* Current frame information calculated by ia64_compute_frame_size. */ static struct ia64_frame_info current_frame_info; +/* The actual registers that are emitted. */ +static int emitted_frame_related_regs[number_of_ia64_frame_regs]; static int ia64_first_cycle_multipass_dfa_lookahead (void); static void ia64_dependencies_evaluation_hook (rtx, rtx); @@ -173,7 +183,7 @@ static int ia64_spec_check_p (rtx); static int ia64_spec_check_src_p (rtx); static rtx gen_tls_get_addr (void); static rtx gen_thread_pointer (void); -static int find_gr_spill (int); +static int find_gr_spill (enum ia64_frame_regs, int); static int next_scratch_gr_reg (void); static void mark_reg_gr_used_mask (rtx, void *); static void ia64_compute_frame_size (HOST_WIDE_INT); @@ -1872,13 +1882,42 @@ ia64_expand_call (rtx retval, rtx addr, rtx nextarg ATTRIBUTE_UNUSED, use_reg (&CALL_INSN_FUNCTION_USAGE (insn), b0); } +static void +reg_emitted (enum ia64_frame_regs r) +{ + if (emitted_frame_related_regs[r] == 0) + emitted_frame_related_regs[r] = current_frame_info.r[r]; + else + gcc_assert (emitted_frame_related_regs[r] == current_frame_info.r[r]); +} + +static int +get_reg (enum ia64_frame_regs r) +{ + reg_emitted (r); + return current_frame_info.r[r]; +} + +static bool +is_emitted (int regno) +{ + enum ia64_frame_regs r; + + for (r = reg_fp; r < number_of_ia64_frame_regs; r++) + if (emitted_frame_related_regs[r] == regno) + return true; + return false; +} + void ia64_reload_gp (void) { rtx tmp; - if (current_frame_info.reg_save_gp) - tmp = gen_rtx_REG (DImode, current_frame_info.reg_save_gp); + if (current_frame_info.r[reg_save_gp]) + { + tmp = gen_rtx_REG (DImode, get_reg (reg_save_gp)); + } else { HOST_WIDE_INT offset; @@ -2158,20 +2197,33 @@ ia64_globalize_decl_name (FILE * stream, tree decl) TRY_LOCALS is true if we should attempt to locate a local regnum. */ static int -find_gr_spill (int try_locals) +find_gr_spill (enum ia64_frame_regs r, int try_locals) { int regno; + if (emitted_frame_related_regs[r] != 0) + { + regno = emitted_frame_related_regs[r]; + if (regno >= LOC_REG (0) && regno < LOC_REG (80 - frame_pointer_needed)) + current_frame_info.n_local_regs = regno - LOC_REG (0) + 1; + else if (current_function_is_leaf + && regno >= GR_REG (1) && regno <= GR_REG (31)) + current_frame_info.gr_used_mask |= 1 << regno; + + return regno; + } + /* If this is a leaf function, first try an otherwise unused call-clobbered register. */ if (current_function_is_leaf) { for (regno = GR_REG (1); regno <= GR_REG (31); regno++) - if (! regs_ever_live[regno] + if (! df_regs_ever_live_p (regno) && call_used_regs[regno] && ! fixed_regs[regno] && ! global_regs[regno] - && ((current_frame_info.gr_used_mask >> regno) & 1) == 0) + && ((current_frame_info.gr_used_mask >> regno) & 1) == 0 + && ! is_emitted (regno)) { current_frame_info.gr_used_mask |= 1 << regno; return regno; @@ -2243,6 +2295,7 @@ mark_reg_gr_used_mask (rtx reg, void *data ATTRIBUTE_UNUSED) } } + /* Returns the number of bytes offset between the frame pointer and the stack pointer for the current function. SIZE is the number of bytes of space needed for local variables. */ @@ -2284,7 +2337,7 @@ ia64_compute_frame_size (HOST_WIDE_INT size) since we'll be adjusting that down later. */ regno = LOC_REG (78) + ! frame_pointer_needed; for (; regno >= LOC_REG (0); regno--) - if (regs_ever_live[regno]) + if (df_regs_ever_live_p (regno) && !is_emitted (regno)) break; current_frame_info.n_local_regs = regno - LOC_REG (0) + 1; @@ -2299,13 +2352,13 @@ ia64_compute_frame_size (HOST_WIDE_INT size) else { for (regno = IN_REG (7); regno >= IN_REG (0); regno--) - if (regs_ever_live[regno]) + if (df_regs_ever_live_p (regno)) break; current_frame_info.n_input_regs = regno - IN_REG (0) + 1; } for (regno = OUT_REG (7); regno >= OUT_REG (0); regno--) - if (regs_ever_live[regno]) + if (df_regs_ever_live_p (regno)) break; i = regno - OUT_REG (0) + 1; @@ -2327,7 +2380,7 @@ ia64_compute_frame_size (HOST_WIDE_INT size) which will always wind up on the stack. */ for (regno = FR_REG (2); regno <= FR_REG (127); regno++) - if (regs_ever_live[regno] && ! call_used_regs[regno]) + if (df_regs_ever_live_p (regno) && ! call_used_regs[regno]) { SET_HARD_REG_BIT (mask, regno); spill_size += 16; @@ -2336,7 +2389,7 @@ ia64_compute_frame_size (HOST_WIDE_INT size) } for (regno = GR_REG (1); regno <= GR_REG (31); regno++) - if (regs_ever_live[regno] && ! call_used_regs[regno]) + if (df_regs_ever_live_p (regno) && ! call_used_regs[regno]) { SET_HARD_REG_BIT (mask, regno); spill_size += 8; @@ -2345,7 +2398,7 @@ ia64_compute_frame_size (HOST_WIDE_INT size) } for (regno = BR_REG (1); regno <= BR_REG (7); regno++) - if (regs_ever_live[regno] && ! call_used_regs[regno]) + if (df_regs_ever_live_p (regno) && ! call_used_regs[regno]) { SET_HARD_REG_BIT (mask, regno); spill_size += 8; @@ -2357,15 +2410,15 @@ ia64_compute_frame_size (HOST_WIDE_INT size) if (frame_pointer_needed) { - current_frame_info.reg_fp = find_gr_spill (1); + current_frame_info.r[reg_fp] = find_gr_spill (reg_fp, 1); /* If we did not get a register, then we take LOC79. This is guaranteed to be free, even if regs_ever_live is already set, because this is HARD_FRAME_POINTER_REGNUM. This requires incrementing n_local_regs, as we don't count loc79 above. */ - if (current_frame_info.reg_fp == 0) + if (current_frame_info.r[reg_fp] == 0) { - current_frame_info.reg_fp = LOC_REG (79); - current_frame_info.n_local_regs++; + current_frame_info.r[reg_fp] = LOC_REG (79); + current_frame_info.n_local_regs = LOC_REG (79) - LOC_REG (0) + 1; } } @@ -2376,8 +2429,8 @@ ia64_compute_frame_size (HOST_WIDE_INT size) able to unwind the stack. */ SET_HARD_REG_BIT (mask, BR_REG (0)); - current_frame_info.reg_save_b0 = find_gr_spill (1); - if (current_frame_info.reg_save_b0 == 0) + current_frame_info.r[reg_save_b0] = find_gr_spill (reg_save_b0, 1); + if (current_frame_info.r[reg_save_b0] == 0) { extra_spill_size += 8; n_spilled += 1; @@ -2385,8 +2438,8 @@ ia64_compute_frame_size (HOST_WIDE_INT size) /* Similarly for ar.pfs. */ SET_HARD_REG_BIT (mask, AR_PFS_REGNUM); - current_frame_info.reg_save_ar_pfs = find_gr_spill (1); - if (current_frame_info.reg_save_ar_pfs == 0) + current_frame_info.r[reg_save_ar_pfs] = find_gr_spill (reg_save_ar_pfs, 1); + if (current_frame_info.r[reg_save_ar_pfs] == 0) { extra_spill_size += 8; n_spilled += 1; @@ -2394,9 +2447,9 @@ ia64_compute_frame_size (HOST_WIDE_INT size) /* Similarly for gp. Note that if we're calling setjmp, the stacked registers are clobbered, so we fall back to the stack. */ - current_frame_info.reg_save_gp - = (current_function_calls_setjmp ? 0 : find_gr_spill (1)); - if (current_frame_info.reg_save_gp == 0) + current_frame_info.r[reg_save_gp] + = (current_function_calls_setjmp ? 0 : find_gr_spill (reg_save_gp, 1)); + if (current_frame_info.r[reg_save_gp] == 0) { SET_HARD_REG_BIT (mask, GR_REG (1)); spill_size += 8; @@ -2405,18 +2458,19 @@ ia64_compute_frame_size (HOST_WIDE_INT size) } else { - if (regs_ever_live[BR_REG (0)] && ! call_used_regs[BR_REG (0)]) + if (df_regs_ever_live_p (BR_REG (0)) && ! call_used_regs[BR_REG (0)]) { SET_HARD_REG_BIT (mask, BR_REG (0)); extra_spill_size += 8; n_spilled += 1; } - if (regs_ever_live[AR_PFS_REGNUM]) + if (df_regs_ever_live_p (AR_PFS_REGNUM)) { SET_HARD_REG_BIT (mask, AR_PFS_REGNUM); - current_frame_info.reg_save_ar_pfs = find_gr_spill (1); - if (current_frame_info.reg_save_ar_pfs == 0) + current_frame_info.r[reg_save_ar_pfs] + = find_gr_spill (reg_save_ar_pfs, 1); + if (current_frame_info.r[reg_save_ar_pfs] == 0) { extra_spill_size += 8; n_spilled += 1; @@ -2429,25 +2483,31 @@ ia64_compute_frame_size (HOST_WIDE_INT size) it is absolutely critical that FP get the only hard register that's guaranteed to be free, so we allocated it first. If all three did happen to be allocated hard regs, and are consecutive, rearrange them - into the preferred order now. */ - if (current_frame_info.reg_fp != 0 - && current_frame_info.reg_save_b0 == current_frame_info.reg_fp + 1 - && current_frame_info.reg_save_ar_pfs == current_frame_info.reg_fp + 2) + into the preferred order now. + + If we have already emitted code for any of those registers, + then it's already too late to change. */ + if (current_frame_info.r[reg_fp] != 0 + && current_frame_info.r[reg_save_b0] == current_frame_info.r[reg_fp] + 1 + && current_frame_info.r[reg_save_ar_pfs] == current_frame_info.r[reg_fp] + 2 + && emitted_frame_related_regs[reg_save_b0] == 0 + && emitted_frame_related_regs[reg_save_ar_pfs] == 0 + && emitted_frame_related_regs[reg_fp] == 0) { - current_frame_info.reg_save_b0 = current_frame_info.reg_fp; - current_frame_info.reg_save_ar_pfs = current_frame_info.reg_fp + 1; - current_frame_info.reg_fp = current_frame_info.reg_fp + 2; + current_frame_info.r[reg_save_b0] = current_frame_info.r[reg_fp]; + current_frame_info.r[reg_save_ar_pfs] = current_frame_info.r[reg_fp] + 1; + current_frame_info.r[reg_fp] = current_frame_info.r[reg_fp] + 2; } /* See if we need to store the predicate register block. */ for (regno = PR_REG (0); regno <= PR_REG (63); regno++) - if (regs_ever_live[regno] && ! call_used_regs[regno]) + if (df_regs_ever_live_p (regno) && ! call_used_regs[regno]) break; if (regno <= PR_REG (63)) { SET_HARD_REG_BIT (mask, PR_REG (0)); - current_frame_info.reg_save_pr = find_gr_spill (1); - if (current_frame_info.reg_save_pr == 0) + current_frame_info.r[reg_save_pr] = find_gr_spill (reg_save_pr, 1); + if (current_frame_info.r[reg_save_pr] == 0) { extra_spill_size += 8; n_spilled += 1; @@ -2456,30 +2516,32 @@ ia64_compute_frame_size (HOST_WIDE_INT size) /* ??? Mark them all as used so that register renaming and such are free to use them. */ for (regno = PR_REG (0); regno <= PR_REG (63); regno++) - regs_ever_live[regno] = 1; + df_set_regs_ever_live (regno, true); } /* If we're forced to use st8.spill, we're forced to save and restore ar.unat as well. The check for existing liveness allows inline asm to touch ar.unat. */ if (spilled_gr_p || cfun->machine->n_varargs - || regs_ever_live[AR_UNAT_REGNUM]) + || df_regs_ever_live_p (AR_UNAT_REGNUM)) { - regs_ever_live[AR_UNAT_REGNUM] = 1; + df_set_regs_ever_live (AR_UNAT_REGNUM, true); SET_HARD_REG_BIT (mask, AR_UNAT_REGNUM); - current_frame_info.reg_save_ar_unat = find_gr_spill (spill_size == 0); - if (current_frame_info.reg_save_ar_unat == 0) + current_frame_info.r[reg_save_ar_unat] + = find_gr_spill (reg_save_ar_unat, spill_size == 0); + if (current_frame_info.r[reg_save_ar_unat] == 0) { extra_spill_size += 8; n_spilled += 1; } } - if (regs_ever_live[AR_LC_REGNUM]) + if (df_regs_ever_live_p (AR_LC_REGNUM)) { SET_HARD_REG_BIT (mask, AR_LC_REGNUM); - current_frame_info.reg_save_ar_lc = find_gr_spill (spill_size == 0); - if (current_frame_info.reg_save_ar_lc == 0) + current_frame_info.r[reg_save_ar_lc] + = find_gr_spill (reg_save_ar_lc, spill_size == 0); + if (current_frame_info.r[reg_save_ar_lc] == 0) { extra_spill_size += 8; n_spilled += 1; @@ -2713,16 +2775,6 @@ spill_restore_mem (rtx reg, HOST_WIDE_INT cfa_off) insn = emit_insn (seq); } spill_fill_data.init_after = insn; - - /* If DISP is 0, we may or may not have a further adjustment - afterward. If we do, then the load/store insn may be modified - to be a post-modify. If we don't, then this copy may be - eliminated by copyprop_hardreg_forward, which makes this - insn garbage, which runs afoul of the sanity check in - propagate_one_insn. So mark this insn as legal to delete. */ - if (disp == 0) - REG_NOTES(insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, - REG_NOTES (insn)); } mem = gen_rtx_MEM (GET_MODE (reg), spill_fill_data.iter_reg[iter]); @@ -2850,6 +2902,22 @@ ia64_expand_prologue (void) ia64_compute_frame_size (get_frame_size ()); last_scratch_gr_reg = 15; + if (dump_file) + { + fprintf (dump_file, "ia64 frame related registers " + "recorded in current_frame_info.r[]:\n"); +#define PRINTREG(a) if (current_frame_info.r[a]) \ + fprintf(dump_file, "%s = %d\n", #a, current_frame_info.r[a]) + PRINTREG(reg_fp); + PRINTREG(reg_save_b0); + PRINTREG(reg_save_pr); + PRINTREG(reg_save_ar_pfs); + PRINTREG(reg_save_ar_unat); + PRINTREG(reg_save_ar_lc); + PRINTREG(reg_save_gp); +#undef PRINTREG + } + /* If there is no epilogue, then we don't need some prologue insns. We need to avoid emitting the dead prologue insns, because flow will complain about them. */ @@ -2892,12 +2960,12 @@ ia64_expand_prologue (void) there is a frame pointer. loc79 gets wasted in this case, as it is renamed to a register that will never be used. See also the try_locals code in find_gr_spill. */ - if (current_frame_info.reg_fp) + if (current_frame_info.r[reg_fp]) { const char *tmp = reg_names[HARD_FRAME_POINTER_REGNUM]; reg_names[HARD_FRAME_POINTER_REGNUM] - = reg_names[current_frame_info.reg_fp]; - reg_names[current_frame_info.reg_fp] = tmp; + = reg_names[current_frame_info.r[reg_fp]]; + reg_names[current_frame_info.r[reg_fp]] = tmp; } /* We don't need an alloc instruction if we've used no outputs or locals. */ @@ -2915,8 +2983,11 @@ ia64_expand_prologue (void) { current_frame_info.need_regstk = 0; - if (current_frame_info.reg_save_ar_pfs) - regno = current_frame_info.reg_save_ar_pfs; + if (current_frame_info.r[reg_save_ar_pfs]) + { + regno = current_frame_info.r[reg_save_ar_pfs]; + reg_emitted (reg_save_ar_pfs); + } else regno = next_scratch_gr_reg (); ar_pfs_save_reg = gen_rtx_REG (DImode, regno); @@ -2926,7 +2997,7 @@ ia64_expand_prologue (void) GEN_INT (current_frame_info.n_local_regs), GEN_INT (current_frame_info.n_output_regs), GEN_INT (current_frame_info.n_rotate_regs))); - RTX_FRAME_RELATED_P (insn) = (current_frame_info.reg_save_ar_pfs != 0); + RTX_FRAME_RELATED_P (insn) = (current_frame_info.r[reg_save_ar_pfs] != 0); } /* Set up frame pointer, stack pointer, and spill iterators. */ @@ -2984,9 +3055,12 @@ ia64_expand_prologue (void) /* Must copy out ar.unat before doing any integer spills. */ if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_UNAT_REGNUM)) { - if (current_frame_info.reg_save_ar_unat) - ar_unat_save_reg - = gen_rtx_REG (DImode, current_frame_info.reg_save_ar_unat); + if (current_frame_info.r[reg_save_ar_unat]) + { + ar_unat_save_reg + = gen_rtx_REG (DImode, current_frame_info.r[reg_save_ar_unat]); + reg_emitted (reg_save_ar_unat); + } else { alt_regno = next_scratch_gr_reg (); @@ -2996,11 +3070,11 @@ ia64_expand_prologue (void) reg = gen_rtx_REG (DImode, AR_UNAT_REGNUM); insn = emit_move_insn (ar_unat_save_reg, reg); - RTX_FRAME_RELATED_P (insn) = (current_frame_info.reg_save_ar_unat != 0); + RTX_FRAME_RELATED_P (insn) = (current_frame_info.r[reg_save_ar_unat] != 0); /* Even if we're not going to generate an epilogue, we still need to save the register so that EH works. */ - if (! epilogue_p && current_frame_info.reg_save_ar_unat) + if (! epilogue_p && current_frame_info.r[reg_save_ar_unat]) emit_insn (gen_prologue_use (ar_unat_save_reg)); } else @@ -3026,9 +3100,10 @@ ia64_expand_prologue (void) if (TEST_HARD_REG_BIT (current_frame_info.mask, PR_REG (0))) { reg = gen_rtx_REG (DImode, PR_REG (0)); - if (current_frame_info.reg_save_pr != 0) + if (current_frame_info.r[reg_save_pr] != 0) { - alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_pr); + alt_reg = gen_rtx_REG (DImode, current_frame_info.r[reg_save_pr]); + reg_emitted (reg_save_pr); insn = emit_move_insn (alt_reg, reg); /* ??? Denote pr spill/fill by a DImode move that modifies all @@ -3056,7 +3131,7 @@ ia64_expand_prologue (void) /* Handle AR regs in numerical order. All of them get special handling. */ if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_UNAT_REGNUM) - && current_frame_info.reg_save_ar_unat == 0) + && current_frame_info.r[reg_save_ar_unat] == 0) { reg = gen_rtx_REG (DImode, AR_UNAT_REGNUM); do_spill (gen_movdi_x, ar_unat_save_reg, cfa_off, reg); @@ -3067,7 +3142,7 @@ ia64_expand_prologue (void) only thing we have to do now is copy that register to a stack slot if we'd not allocated a local register for the job. */ if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_PFS_REGNUM) - && current_frame_info.reg_save_ar_pfs == 0) + && current_frame_info.r[reg_save_ar_pfs] == 0) { reg = gen_rtx_REG (DImode, AR_PFS_REGNUM); do_spill (gen_movdi_x, ar_pfs_save_reg, cfa_off, reg); @@ -3077,9 +3152,10 @@ ia64_expand_prologue (void) if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_LC_REGNUM)) { reg = gen_rtx_REG (DImode, AR_LC_REGNUM); - if (current_frame_info.reg_save_ar_lc != 0) + if (current_frame_info.r[reg_save_ar_lc] != 0) { - alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_ar_lc); + alt_reg = gen_rtx_REG (DImode, current_frame_info.r[reg_save_ar_lc]); + reg_emitted (reg_save_ar_lc); insn = emit_move_insn (alt_reg, reg); RTX_FRAME_RELATED_P (insn) = 1; @@ -3102,9 +3178,10 @@ ia64_expand_prologue (void) if (TEST_HARD_REG_BIT (current_frame_info.mask, BR_REG (0))) { reg = gen_rtx_REG (DImode, BR_REG (0)); - if (current_frame_info.reg_save_b0 != 0) + if (current_frame_info.r[reg_save_b0] != 0) { - alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_b0); + alt_reg = gen_rtx_REG (DImode, current_frame_info.r[reg_save_b0]); + reg_emitted (reg_save_b0); insn = emit_move_insn (alt_reg, reg); RTX_FRAME_RELATED_P (insn) = 1; @@ -3123,17 +3200,12 @@ ia64_expand_prologue (void) } } - if (current_frame_info.reg_save_gp) + if (current_frame_info.r[reg_save_gp]) { + reg_emitted (reg_save_gp); insn = emit_move_insn (gen_rtx_REG (DImode, - current_frame_info.reg_save_gp), + current_frame_info.r[reg_save_gp]), pic_offset_table_rtx); - /* We don't know for sure yet if this is actually needed, since - we've not split the PIC call patterns. If all of the calls - are indirect, and not followed by any uses of the gp, then - this save is dead. Allow it to go away. */ - REG_NOTES (insn) - = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, REG_NOTES (insn)); } /* We should now be at the base of the gr/br/fr spill area. */ @@ -3217,8 +3289,11 @@ ia64_expand_epilogue (int sibcall_p) /* Restore the predicate registers. */ if (TEST_HARD_REG_BIT (current_frame_info.mask, PR_REG (0))) { - if (current_frame_info.reg_save_pr != 0) - alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_pr); + if (current_frame_info.r[reg_save_pr] != 0) + { + alt_reg = gen_rtx_REG (DImode, current_frame_info.r[reg_save_pr]); + reg_emitted (reg_save_pr); + } else { alt_regno = next_scratch_gr_reg (); @@ -3236,9 +3311,12 @@ ia64_expand_epilogue (int sibcall_p) after the GRs have been restored. */ if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_UNAT_REGNUM)) { - if (current_frame_info.reg_save_ar_unat != 0) - ar_unat_save_reg - = gen_rtx_REG (DImode, current_frame_info.reg_save_ar_unat); + if (current_frame_info.r[reg_save_ar_unat] != 0) + { + ar_unat_save_reg + = gen_rtx_REG (DImode, current_frame_info.r[reg_save_ar_unat]); + reg_emitted (reg_save_ar_unat); + } else { alt_regno = next_scratch_gr_reg (); @@ -3251,9 +3329,10 @@ ia64_expand_epilogue (int sibcall_p) else ar_unat_save_reg = NULL_RTX; - if (current_frame_info.reg_save_ar_pfs != 0) + if (current_frame_info.r[reg_save_ar_pfs] != 0) { - alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_ar_pfs); + reg_emitted (reg_save_ar_pfs); + alt_reg = gen_rtx_REG (DImode, current_frame_info.r[reg_save_ar_pfs]); reg = gen_rtx_REG (DImode, AR_PFS_REGNUM); emit_move_insn (reg, alt_reg); } @@ -3269,8 +3348,11 @@ ia64_expand_epilogue (int sibcall_p) if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_LC_REGNUM)) { - if (current_frame_info.reg_save_ar_lc != 0) - alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_ar_lc); + if (current_frame_info.r[reg_save_ar_lc] != 0) + { + alt_reg = gen_rtx_REG (DImode, current_frame_info.r[reg_save_ar_lc]); + reg_emitted (reg_save_ar_lc); + } else { alt_regno = next_scratch_gr_reg (); @@ -3285,8 +3367,11 @@ ia64_expand_epilogue (int sibcall_p) /* Restore the return pointer. */ if (TEST_HARD_REG_BIT (current_frame_info.mask, BR_REG (0))) { - if (current_frame_info.reg_save_b0 != 0) - alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_b0); + if (current_frame_info.r[reg_save_b0] != 0) + { + alt_reg = gen_rtx_REG (DImode, current_frame_info.r[reg_save_b0]); + reg_emitted (reg_save_b0); + } else { alt_regno = next_scratch_gr_reg (); @@ -3409,7 +3494,8 @@ ia64_expand_epilogue (int sibcall_p) register, we may have swapped the names of r2 and HARD_FRAME_POINTER_REGNUM, so we have to make sure we're using the string "r2" when emitting the register name for the assembler. */ - if (current_frame_info.reg_fp && current_frame_info.reg_fp == GR_REG (2)) + if (current_frame_info.r[reg_fp] + && current_frame_info.r[reg_fp] == GR_REG (2)) fp = HARD_FRAME_POINTER_REGNUM; /* We must emit an alloc to force the input registers to become output @@ -3442,11 +3528,11 @@ ia64_direct_return (void) return (current_frame_info.total_size == 0 && current_frame_info.n_spilled == 0 - && current_frame_info.reg_save_b0 == 0 - && current_frame_info.reg_save_pr == 0 - && current_frame_info.reg_save_ar_pfs == 0 - && current_frame_info.reg_save_ar_unat == 0 - && current_frame_info.reg_save_ar_lc == 0); + && current_frame_info.r[reg_save_b0] == 0 + && current_frame_info.r[reg_save_pr] == 0 + && current_frame_info.r[reg_save_ar_pfs] == 0 + && current_frame_info.r[reg_save_ar_unat] == 0 + && current_frame_info.r[reg_save_ar_lc] == 0); } return 0; } @@ -3472,8 +3558,11 @@ ia64_split_return_addr_rtx (rtx dest) if (TEST_HARD_REG_BIT (current_frame_info.mask, BR_REG (0))) { - if (current_frame_info.reg_save_b0 != 0) - src = gen_rtx_REG (DImode, current_frame_info.reg_save_b0); + if (current_frame_info.r[reg_save_b0] != 0) + { + src = gen_rtx_REG (DImode, current_frame_info.r[reg_save_b0]); + reg_emitted (reg_save_b0); + } else { HOST_WIDE_INT off; @@ -3520,21 +3609,14 @@ int ia64_hard_regno_rename_ok (int from, int to) { /* Don't clobber any of the registers we reserved for the prologue. */ - if (to == current_frame_info.reg_fp - || to == current_frame_info.reg_save_b0 - || to == current_frame_info.reg_save_pr - || to == current_frame_info.reg_save_ar_pfs - || to == current_frame_info.reg_save_ar_unat - || to == current_frame_info.reg_save_ar_lc) - return 0; + enum ia64_frame_regs r; - if (from == current_frame_info.reg_fp - || from == current_frame_info.reg_save_b0 - || from == current_frame_info.reg_save_pr - || from == current_frame_info.reg_save_ar_pfs - || from == current_frame_info.reg_save_ar_unat - || from == current_frame_info.reg_save_ar_lc) - return 0; + for (r = reg_fp; r <= reg_save_ar_lc; r++) + if (to == current_frame_info.r[r] + || from == current_frame_info.r[r] + || to == emitted_frame_related_regs[r] + || from == emitted_frame_related_regs[r]) + return 0; /* Don't use output registers outside the register frame. */ if (OUT_REGNO_P (to) && to >= OUT_REG (current_frame_info.n_output_regs)) @@ -3592,36 +3674,36 @@ ia64_output_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED) mask = 0; grsave = grsave_prev = 0; - if (current_frame_info.reg_save_b0 != 0) + if (current_frame_info.r[reg_save_b0] != 0) { mask |= 8; - grsave = grsave_prev = current_frame_info.reg_save_b0; + grsave = grsave_prev = current_frame_info.r[reg_save_b0]; } - if (current_frame_info.reg_save_ar_pfs != 0 + if (current_frame_info.r[reg_save_ar_pfs] != 0 && (grsave_prev == 0 - || current_frame_info.reg_save_ar_pfs == grsave_prev + 1)) + || current_frame_info.r[reg_save_ar_pfs] == grsave_prev + 1)) { mask |= 4; if (grsave_prev == 0) - grsave = current_frame_info.reg_save_ar_pfs; - grsave_prev = current_frame_info.reg_save_ar_pfs; + grsave = current_frame_info.r[reg_save_ar_pfs]; + grsave_prev = current_frame_info.r[reg_save_ar_pfs]; } - if (current_frame_info.reg_fp != 0 + if (current_frame_info.r[reg_fp] != 0 && (grsave_prev == 0 - || current_frame_info.reg_fp == grsave_prev + 1)) + || current_frame_info.r[reg_fp] == grsave_prev + 1)) { mask |= 2; if (grsave_prev == 0) grsave = HARD_FRAME_POINTER_REGNUM; - grsave_prev = current_frame_info.reg_fp; + grsave_prev = current_frame_info.r[reg_fp]; } - if (current_frame_info.reg_save_pr != 0 + if (current_frame_info.r[reg_save_pr] != 0 && (grsave_prev == 0 - || current_frame_info.reg_save_pr == grsave_prev + 1)) + || current_frame_info.r[reg_save_pr] == grsave_prev + 1)) { mask |= 1; if (grsave_prev == 0) - grsave = current_frame_info.reg_save_pr; + grsave = current_frame_info.r[reg_save_pr]; } if (mask && TARGET_GNU_AS) @@ -3657,12 +3739,13 @@ ia64_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED, { int i; - if (current_frame_info.reg_fp) + if (current_frame_info.r[reg_fp]) { const char *tmp = reg_names[HARD_FRAME_POINTER_REGNUM]; reg_names[HARD_FRAME_POINTER_REGNUM] - = reg_names[current_frame_info.reg_fp]; - reg_names[current_frame_info.reg_fp] = tmp; + = reg_names[current_frame_info.r[reg_fp]]; + reg_names[current_frame_info.r[reg_fp]] = tmp; + reg_emitted (reg_fp); } if (! TARGET_REG_NAMES) { @@ -3683,11 +3766,11 @@ ia64_dbx_register_number (int regno) /* In ia64_expand_prologue we quite literally renamed the frame pointer from its home at loc79 to something inside the register frame. We must perform the same renumbering here for the debug info. */ - if (current_frame_info.reg_fp) + if (current_frame_info.r[reg_fp]) { if (regno == HARD_FRAME_POINTER_REGNUM) - regno = current_frame_info.reg_fp; - else if (regno == current_frame_info.reg_fp) + regno = current_frame_info.r[reg_fp]; + else if (regno == current_frame_info.r[reg_fp]) regno = HARD_FRAME_POINTER_REGNUM; } @@ -5093,6 +5176,13 @@ ia64_override_options (void) init_machine_status = ia64_init_machine_status; } +/* Initialize the record of emitted frame related registers. */ + +void ia64_init_expanders (void) +{ + memset (&emitted_frame_related_regs, 0, sizeof (emitted_frame_related_regs)); +} + static struct machine_function * ia64_init_machine_status (void) { @@ -6650,11 +6740,12 @@ ia64_set_sched_flags (spec_info_t spec_info) mask |= BE_IN_CONTROL; } - gcc_assert (*flags & USE_GLAT); - if (mask) { - *flags |= USE_DEPS_LIST | DETACH_LIFE_INFO | DO_SPECULATION; + *flags |= USE_DEPS_LIST | DO_SPECULATION; + + if (mask & BE_IN_SPEC) + *flags |= NEW_BBS; spec_info->mask = mask; spec_info->flags = 0; @@ -8338,7 +8429,7 @@ emit_predicate_relation_info (void) /* Skip p0, which may be thought to be live due to (reg:DI p0) grabbing the entire block of predicate registers. */ for (r = PR_REG (2); r < PR_REG (64); r += 2) - if (REGNO_REG_SET_P (bb->il.rtl->global_live_at_start, r)) + if (REGNO_REG_SET_P (df_get_live_in (bb), r)) { rtx p = gen_rtx_REG (BImode, r); rtx n = emit_insn_after (gen_pred_rel_mutex (p), head); @@ -8388,13 +8479,9 @@ ia64_reorg (void) /* If optimizing, we'll have split before scheduling. */ if (optimize == 0) - split_all_insns (0); - - /* ??? update_life_info_in_dirty_blocks fails to terminate during - non-optimizing bootstrap. */ - update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES, PROP_DEATH_NOTES); + split_all_insns (); - if (optimize && ia64_flag_schedule_insns2) + if (optimize && ia64_flag_schedule_insns2 && dbg_cnt (ia64_sched2)) { timevar_push (TV_SCHED2); ia64_final_schedule = 1; @@ -8469,6 +8556,8 @@ ia64_reorg (void) _1mlx_ = get_cpu_unit_code ("1b_1mlx."); } schedule_ebbs (); + /* We cannot reuse this one because it has been corrupted by the + evil glat. */ finish_bundle_states (); if (ia64_tune == PROCESSOR_ITANIUM) { @@ -8485,6 +8574,8 @@ ia64_reorg (void) else emit_all_insn_group_barriers (dump_file); + df_analyze (); + /* A call must not be the last instruction in a function, so that the return address is still within the function, so that unwinding works properly. Note that IA-64 differs from dwarf2 on this point. */ @@ -8521,6 +8612,7 @@ ia64_reorg (void) variable_tracking_main (); timevar_pop (TV_VAR_TRACKING); } + df_finish_pass (); } /* Return true if REGNO is used by the epilogue. */ @@ -8567,24 +8659,18 @@ ia64_epilogue_uses (int regno) int ia64_eh_uses (int regno) { + enum ia64_frame_regs r; + if (! reload_completed) return 0; - if (current_frame_info.reg_save_b0 - && regno == current_frame_info.reg_save_b0) - return 1; - if (current_frame_info.reg_save_pr - && regno == current_frame_info.reg_save_pr) - return 1; - if (current_frame_info.reg_save_ar_pfs - && regno == current_frame_info.reg_save_ar_pfs) - return 1; - if (current_frame_info.reg_save_ar_unat - && regno == current_frame_info.reg_save_ar_unat) - return 1; - if (current_frame_info.reg_save_ar_lc - && regno == current_frame_info.reg_save_ar_lc) - return 1; + if (regno == 0) + return 0; + + for (r = reg_save_b0; r <= reg_save_ar_lc; r++) + if (regno == current_frame_info.r[r] + || regno == emitted_frame_related_regs[r]) + return 1; return 0; } @@ -8737,7 +8823,7 @@ process_set (FILE *asm_out_file, rtx pat, rtx insn, bool unwind, bool frame) /* If this is the final destination for ar.pfs, then this must be the alloc in the prologue. */ - if (dest_regno == current_frame_info.reg_save_ar_pfs) + if (dest_regno == current_frame_info.r[reg_save_ar_pfs]) { if (unwind) fprintf (asm_out_file, "\t.save ar.pfs, r%d\n", @@ -8802,28 +8888,28 @@ process_set (FILE *asm_out_file, rtx pat, rtx insn, bool unwind, bool frame) { case BR_REG (0): /* Saving return address pointer. */ - gcc_assert (dest_regno == current_frame_info.reg_save_b0); + gcc_assert (dest_regno == current_frame_info.r[reg_save_b0]); if (unwind) fprintf (asm_out_file, "\t.save rp, r%d\n", ia64_dbx_register_number (dest_regno)); return 1; case PR_REG (0): - gcc_assert (dest_regno == current_frame_info.reg_save_pr); + gcc_assert (dest_regno == current_frame_info.r[reg_save_pr]); if (unwind) fprintf (asm_out_file, "\t.save pr, r%d\n", ia64_dbx_register_number (dest_regno)); return 1; case AR_UNAT_REGNUM: - gcc_assert (dest_regno == current_frame_info.reg_save_ar_unat); + gcc_assert (dest_regno == current_frame_info.r[reg_save_ar_unat]); if (unwind) fprintf (asm_out_file, "\t.save ar.unat, r%d\n", ia64_dbx_register_number (dest_regno)); return 1; case AR_LC_REGNUM: - gcc_assert (dest_regno == current_frame_info.reg_save_ar_lc); + gcc_assert (dest_regno == current_frame_info.r[reg_save_ar_lc]); if (unwind) fprintf (asm_out_file, "\t.save ar.lc, r%d\n", ia64_dbx_register_number (dest_regno)); @@ -8880,31 +8966,31 @@ process_set (FILE *asm_out_file, rtx pat, rtx insn, bool unwind, bool frame) switch (src_regno) { case BR_REG (0): - gcc_assert (!current_frame_info.reg_save_b0); + gcc_assert (!current_frame_info.r[reg_save_b0]); if (unwind) fprintf (asm_out_file, "\t%s rp, %ld\n", saveop, off); return 1; case PR_REG (0): - gcc_assert (!current_frame_info.reg_save_pr); + gcc_assert (!current_frame_info.r[reg_save_pr]); if (unwind) fprintf (asm_out_file, "\t%s pr, %ld\n", saveop, off); return 1; case AR_LC_REGNUM: - gcc_assert (!current_frame_info.reg_save_ar_lc); + gcc_assert (!current_frame_info.r[reg_save_ar_lc]); if (unwind) fprintf (asm_out_file, "\t%s ar.lc, %ld\n", saveop, off); return 1; case AR_PFS_REGNUM: - gcc_assert (!current_frame_info.reg_save_ar_pfs); + gcc_assert (!current_frame_info.r[reg_save_ar_pfs]); if (unwind) fprintf (asm_out_file, "\t%s ar.pfs, %ld\n", saveop, off); return 1; case AR_UNAT_REGNUM: - gcc_assert (!current_frame_info.reg_save_ar_unat); + gcc_assert (!current_frame_info.r[reg_save_ar_unat]); if (unwind) fprintf (asm_out_file, "\t%s ar.unat, %ld\n", saveop, off); return 1; |