diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/config/ia64/ia64.c | 153 | ||||
-rw-r--r-- | gcc/config/ia64/ia64.md | 38 |
3 files changed, 133 insertions, 72 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 066519f..fd7d856 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,19 @@ 2000-08-11 Richard Henderson <rth@cygnus.com> + * config/ia64/ia64.c (do_spill): Pass cfa offset to move expander. + (do_restore): Likewise. + (gen_movdi_x, gen_fr_spill_x, gen_fr_restore_x): New. + (ia64_expand_prologue, ia64_expand_epilogue): Use them. + (rtx_needs_barrier): Track actual bit manipulation for + ar.unat moves, gr_spill, and gr_restore. + (emit_insn_group_barriers): Special case gr_spill/gr_restore. + (process_set): Don't handle varargs spills. + * config/ia64/ia64.md (gr_spill): Accept cfa offset. Emit + .mem.offset here instead of in process_set. + (gr_restore): Likewise. + +2000-08-11 Richard Henderson <rth@cygnus.com> + * config/ia64/ia64.h (PROMOTE_MODE): Only extend to SImode. 2000-08-11 Mark Elbrecht <snowball3@bigfoot.com> diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index bbce28d..f090402 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -103,8 +103,8 @@ static void ia64_compute_frame_size PARAMS ((HOST_WIDE_INT)); static void setup_spill_pointers PARAMS ((int, rtx, HOST_WIDE_INT)); static void finish_spill_pointers PARAMS ((void)); static rtx spill_restore_mem PARAMS ((rtx, HOST_WIDE_INT)); -static void do_spill PARAMS ((rtx (*)(rtx, rtx), rtx, HOST_WIDE_INT, rtx)); -static void do_restore PARAMS ((rtx (*)(rtx, rtx), rtx, HOST_WIDE_INT)); +static void do_spill PARAMS ((rtx (*)(rtx, rtx, rtx), rtx, HOST_WIDE_INT, rtx)); +static void do_restore PARAMS ((rtx (*)(rtx, rtx, rtx), rtx, HOST_WIDE_INT)); static enum machine_mode hfa_element_mode PARAMS ((tree, int)); static void fix_range PARAMS ((const char *)); @@ -1281,14 +1281,14 @@ spill_restore_mem (reg, cfa_off) static void do_spill (move_fn, reg, cfa_off, frame_reg) - rtx (*move_fn) PARAMS ((rtx, rtx)); + rtx (*move_fn) PARAMS ((rtx, rtx, rtx)); rtx reg, frame_reg; HOST_WIDE_INT cfa_off; { rtx mem, insn; mem = spill_restore_mem (reg, cfa_off); - insn = emit_insn ((*move_fn) (mem, reg)); + insn = emit_insn ((*move_fn) (mem, reg, GEN_INT (cfa_off))); if (frame_reg) { @@ -1324,13 +1324,41 @@ do_spill (move_fn, reg, cfa_off, frame_reg) static void do_restore (move_fn, reg, cfa_off) - rtx (*move_fn) PARAMS ((rtx, rtx)); + rtx (*move_fn) PARAMS ((rtx, rtx, rtx)); rtx reg; HOST_WIDE_INT cfa_off; { - emit_insn ((*move_fn) (reg, spill_restore_mem (reg, cfa_off))); + emit_insn ((*move_fn) (reg, spill_restore_mem (reg, cfa_off), + GEN_INT (cfa_off))); } +/* Wrapper functions that discards the CONST_INT spill offset. These + exist so that we can give gr_spill/gr_fill the offset they need and + use a consistant function interface. */ + +static rtx +gen_movdi_x (dest, src, offset) + rtx dest, src; + rtx offset ATTRIBUTE_UNUSED; +{ + return gen_movdi (dest, src); +} + +static rtx +gen_fr_spill_x (dest, src, offset) + rtx dest, src; + rtx offset ATTRIBUTE_UNUSED; +{ + return gen_fr_spill (dest, src); +} + +static rtx +gen_fr_restore_x (dest, src, offset) + rtx dest, src; + rtx offset ATTRIBUTE_UNUSED; +{ + return gen_fr_restore (dest, src); +} /* Called after register allocation to add any instructions needed for the prologue. Using a prologue insn is favored compared to putting all of the @@ -1532,11 +1560,7 @@ ia64_expand_prologue () for (regno = GR_ARG_FIRST + 7; n_varargs > 0; --n_varargs, --regno) { reg = gen_rtx_REG (DImode, regno); - - /* ??? These aren't really "frame related" in the unwind sense, - but marking them so gives us the chance to emit .mem.offset - markers so that we don't get assembler WAW warnings. */ - do_spill (gen_gr_spill, reg, cfa_off += 8, reg); + do_spill (gen_gr_spill, reg, cfa_off += 8, NULL_RTX); } /* Locate the bottom of the register save area. */ @@ -1571,7 +1595,7 @@ ia64_expand_prologue () alt_regno = next_scratch_gr_reg (); alt_reg = gen_rtx_REG (DImode, alt_regno); insn = emit_move_insn (alt_reg, reg); - do_spill (gen_movdi, alt_reg, cfa_off, reg); + do_spill (gen_movdi_x, alt_reg, cfa_off, reg); cfa_off -= 8; } } @@ -1581,7 +1605,7 @@ ia64_expand_prologue () && current_frame_info.reg_save_ar_unat == 0) { reg = gen_rtx_REG (DImode, AR_UNAT_REGNUM); - do_spill (gen_movdi, ar_unat_save_reg, cfa_off, reg); + do_spill (gen_movdi_x, ar_unat_save_reg, cfa_off, reg); cfa_off -= 8; } @@ -1592,7 +1616,7 @@ ia64_expand_prologue () && ! current_function_is_leaf) { reg = gen_rtx_REG (DImode, AR_PFS_REGNUM); - do_spill (gen_movdi, ar_pfs_save_reg, cfa_off, reg); + do_spill (gen_movdi_x, ar_pfs_save_reg, cfa_off, reg); cfa_off -= 8; } @@ -1615,7 +1639,7 @@ ia64_expand_prologue () alt_regno = next_scratch_gr_reg (); alt_reg = gen_rtx_REG (DImode, alt_regno); emit_move_insn (alt_reg, reg); - do_spill (gen_movdi, alt_reg, cfa_off, reg); + do_spill (gen_movdi_x, alt_reg, cfa_off, reg); cfa_off -= 8; } } @@ -1655,7 +1679,7 @@ ia64_expand_prologue () alt_regno = next_scratch_gr_reg (); alt_reg = gen_rtx_REG (DImode, alt_regno); emit_move_insn (alt_reg, reg); - do_spill (gen_movdi, alt_reg, cfa_off, reg); + do_spill (gen_movdi_x, alt_reg, cfa_off, reg); cfa_off -= 8; } } @@ -1668,7 +1692,7 @@ ia64_expand_prologue () alt_reg = gen_rtx_REG (DImode, alt_regno); reg = gen_rtx_REG (DImode, regno); emit_move_insn (alt_reg, reg); - do_spill (gen_movdi, alt_reg, cfa_off, reg); + do_spill (gen_movdi_x, alt_reg, cfa_off, reg); cfa_off -= 8; } @@ -1679,7 +1703,7 @@ ia64_expand_prologue () if (cfa_off & 15) abort (); reg = gen_rtx_REG (XFmode, regno); - do_spill (gen_fr_spill, reg, cfa_off, reg); + do_spill (gen_fr_spill_x, reg, cfa_off, reg); cfa_off -= 16; } @@ -1736,7 +1760,7 @@ ia64_expand_epilogue () { alt_regno = next_scratch_gr_reg (); alt_reg = gen_rtx_REG (DImode, alt_regno); - do_restore (gen_movdi, alt_reg, cfa_off); + do_restore (gen_movdi_x, alt_reg, cfa_off); cfa_off -= 8; } reg = gen_rtx_REG (DImode, PR_REG (0)); @@ -1757,7 +1781,7 @@ ia64_expand_epilogue () alt_regno = next_scratch_gr_reg (); ar_unat_save_reg = gen_rtx_REG (DImode, alt_regno); current_frame_info.gr_used_mask |= 1 << alt_regno; - do_restore (gen_movdi, ar_unat_save_reg, cfa_off); + do_restore (gen_movdi_x, ar_unat_save_reg, cfa_off); cfa_off -= 8; } } @@ -1774,7 +1798,7 @@ ia64_expand_epilogue () { alt_regno = next_scratch_gr_reg (); alt_reg = gen_rtx_REG (DImode, alt_regno); - do_restore (gen_movdi, alt_reg, cfa_off); + do_restore (gen_movdi_x, alt_reg, cfa_off); cfa_off -= 8; reg = gen_rtx_REG (DImode, AR_PFS_REGNUM); emit_move_insn (reg, alt_reg); @@ -1788,7 +1812,7 @@ ia64_expand_epilogue () { alt_regno = next_scratch_gr_reg (); alt_reg = gen_rtx_REG (DImode, alt_regno); - do_restore (gen_movdi, alt_reg, cfa_off); + do_restore (gen_movdi_x, alt_reg, cfa_off); cfa_off -= 8; } reg = gen_rtx_REG (DImode, AR_LC_REGNUM); @@ -1819,7 +1843,7 @@ ia64_expand_epilogue () { alt_regno = next_scratch_gr_reg (); alt_reg = gen_rtx_REG (DImode, alt_regno); - do_restore (gen_movdi, alt_reg, cfa_off); + do_restore (gen_movdi_x, alt_reg, cfa_off); cfa_off -= 8; } reg = gen_rtx_REG (DImode, BR_REG (0)); @@ -1831,7 +1855,7 @@ ia64_expand_epilogue () { alt_regno = next_scratch_gr_reg (); alt_reg = gen_rtx_REG (DImode, alt_regno); - do_restore (gen_movdi, alt_reg, cfa_off); + do_restore (gen_movdi_x, alt_reg, cfa_off); cfa_off -= 8; reg = gen_rtx_REG (DImode, regno); emit_move_insn (reg, alt_reg); @@ -1844,7 +1868,7 @@ ia64_expand_epilogue () if (cfa_off & 15) abort (); reg = gen_rtx_REG (XFmode, regno); - do_restore (gen_fr_restore, reg, cfa_off); + do_restore (gen_fr_restore_x, reg, cfa_off); cfa_off -= 16; } @@ -3172,7 +3196,8 @@ ia64_override_options () /* This is used for volatile asms which may require a stop bit immediately before and after them. */ #define REG_VOLATILE (FIRST_PSEUDO_REGISTER + 2) -#define NUM_REGS (FIRST_PSEUDO_REGISTER + 3) +#define AR_UNAT_BIT_0 (FIRST_PSEUDO_REGISTER + 3) +#define NUM_REGS (AR_UNAT_BIT_0 + 64) /* For each register, we keep track of how many times it has been written in the current instruction group. If a register is written @@ -3545,7 +3570,13 @@ rtx_needs_barrier (x, flags, pred) x = SUBREG_REG (x); /* FALLTHRU */ case REG: - need_barrier = rws_access_reg (x, flags, pred); + if (REGNO (x) == AR_UNAT_REGNUM) + { + for (i = 0; i < 64; ++i) + need_barrier |= rws_access_regno (AR_UNAT_BIT_0 + i, flags, pred); + } + else + need_barrier = rws_access_reg (x, flags, pred); break; case MEM: @@ -3601,11 +3632,19 @@ rtx_needs_barrier (x, flags, pred) case UNSPEC: switch (XINT (x, 1)) { - /* ??? For the st8.spill/ld8.fill instructions, we can ignore unat - dependencies as long as we don't have both a spill and fill in - the same instruction group. We need to check for that. */ case 1: /* st8.spill */ case 2: /* ld8.fill */ + { + HOST_WIDE_INT offset = INTVAL (XVECEXP (x, 0, 1)); + HOST_WIDE_INT bit = (offset >> 3) & 63; + + need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 0), flags, pred); + new_flags.is_write = (XINT (x, 1) == 1); + need_barrier |= rws_access_regno (AR_UNAT_BIT_0 + bit, + new_flags, pred); + break; + } + case 3: /* stf.spill */ case 4: /* ldf.spill */ case 8: /* popcnt */ @@ -3773,16 +3812,36 @@ emit_insn_group_barriers (insns) { rtx pat = PATTERN (insn); - /* We play dependency tricks with the epilogue in order to - get proper schedules. Undo this for dv analysis. */ - if (INSN_CODE (insn) == CODE_FOR_epilogue_deallocate_stack) - pat = XVECEXP (pat, 0, 0); - - /* ??? Similarly, the pattern we use for br.cloop - confuses the code above. The second element of the - vector is representative. */ - else if (INSN_CODE (insn) == CODE_FOR_doloop_end_internal) - pat = XVECEXP (pat, 0, 1); + /* Ug. Hack hacks hacked elsewhere. */ + switch (INSN_CODE (insn)) + { + /* We play dependency tricks with the epilogue in order + to get proper schedules. Undo this for dv analysis. */ + case CODE_FOR_epilogue_deallocate_stack: + pat = XVECEXP (pat, 0, 0); + break; + + /* The pattern we use for br.cloop confuses the code above. + The second element of the vector is representative. */ + case CODE_FOR_doloop_end_internal: + pat = XVECEXP (pat, 0, 1); + break; + + /* We include ar.unat in the rtl pattern so that sched2 + does not move the ar.unat save/restore after/before + a gr spill/fill. However, we special case these + insns based on their unspec number so as to model + their precise ar.unat bit operations. If we pass on + the use/clobber of the whole ar.unat register we'll + waste this effort. */ + case CODE_FOR_gr_spill_internal: + case CODE_FOR_gr_restore_internal: + pat = XVECEXP (pat, 0, 0); + break; + + default: + break; + } memset (rws_insn, 0, sizeof (rws_insn)); need_barrier |= rtx_needs_barrier (pat, flags, 0); @@ -4235,20 +4294,6 @@ process_set (asm_out_file, pat) case GR_REG (7): fprintf (asm_out_file, "\t.save.g 0x%x\n", 1 << (src_regno - GR_REG (4))); - /* FALLTHRU */ - - case GR_ARG_FIRST + 0: - case GR_ARG_FIRST + 1: - case GR_ARG_FIRST + 2: - case GR_ARG_FIRST + 3: - case GR_ARG_FIRST + 4: - case GR_ARG_FIRST + 5: - case GR_ARG_FIRST + 6: - case GR_ARG_FIRST + 7: - /* ??? These aren't really "frame related" in the unwind sense, - but marking them so gives us the chance to emit .mem.offset - markers so that we don't get assembler WAW warnings. */ - fprintf (asm_out_file, "\t.mem.offset %ld, 0\n", off); return 1; case BR_REG (1): diff --git a/gcc/config/ia64/ia64.md b/gcc/config/ia64/ia64.md index 3bce4e2..1b72bfd 100644 --- a/gcc/config/ia64/ia64.md +++ b/gcc/config/ia64/ia64.md @@ -3435,36 +3435,38 @@ ;; Modifies ar.unat (define_expand "gr_spill" - [(parallel - [(set (match_operand:DI 0 "memory_operand" "=m") - (unspec:DI [(match_operand:DI 1 "register_operand" "r")] 1)) - (clobber (match_dup 2))])] + [(parallel [(set (match_operand:DI 0 "memory_operand" "=m") + (unspec:DI [(match_operand:DI 1 "register_operand" "r") + (match_operand:DI 2 "const_int_operand" "")] 1)) + (clobber (match_dup 3))])] "" - "operands[2] = gen_rtx_REG (DImode, AR_UNAT_REGNUM);") + "operands[3] = gen_rtx_REG (DImode, AR_UNAT_REGNUM);") -(define_insn "*gr_spill_internal" +(define_insn "gr_spill_internal" [(set (match_operand:DI 0 "memory_operand" "=m") - (unspec:DI [(match_operand:DI 1 "register_operand" "r")] 1)) - (clobber (match_operand:DI 2 "register_operand" ""))] + (unspec:DI [(match_operand:DI 1 "register_operand" "r") + (match_operand:DI 2 "const_int_operand" "")] 1)) + (clobber (match_operand:DI 3 "register_operand" ""))] "" - "st8.spill %0 = %1%P0" + ".mem.offset %2, 0\;st8.spill %0 = %1%P0" [(set_attr "type" "M")]) ;; Reads ar.unat (define_expand "gr_restore" - [(parallel - [(set (match_operand:DI 0 "register_operand" "=r") - (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] 2)) - (use (match_dup 2))])] + [(parallel [(set (match_operand:DI 0 "register_operand" "=r") + (unspec:DI [(match_operand:DI 1 "memory_operand" "m") + (match_operand:DI 2 "const_int_operand" "")] 2)) + (use (match_dup 3))])] "" - "operands[2] = gen_rtx_REG (DImode, AR_UNAT_REGNUM);") + "operands[3] = gen_rtx_REG (DImode, AR_UNAT_REGNUM);") -(define_insn "*gr_restore_internal" +(define_insn "gr_restore_internal" [(set (match_operand:DI 0 "register_operand" "=r") - (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] 2)) - (use (match_operand:DI 2 "register_operand" ""))] + (unspec:DI [(match_operand:DI 1 "memory_operand" "m") + (match_operand:DI 2 "const_int_operand" "")] 2)) + (use (match_operand:DI 3 "register_operand" ""))] "" - "ld8.fill %0 = %1%P1" + ".mem.offset %2, 0\;ld8.fill %0 = %1%P1" [(set_attr "type" "M")]) (define_insn "fr_spill" |