ia64.c (do_spill): Pass cfa offset to move expander.

* 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.

From-SVN: r35648
This commit is contained in:
Richard Henderson 2000-08-11 16:10:10 -07:00 committed by Richard Henderson
parent dc329d2938
commit 870f9ec0bc
3 changed files with 132 additions and 71 deletions

View File

@ -1,3 +1,17 @@
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.

View File

@ -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);
/* 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;
/* ??? 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);
/* 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):

View File

@ -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"