mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-15 07:40:29 +08:00
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:
parent
dc329d2938
commit
870f9ec0bc
@ -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.
|
||||
|
@ -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):
|
||||
|
@ -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"
|
||||
|
Loading…
x
Reference in New Issue
Block a user