flow.c (mark_regs_live_at_end): Use regs_invalidated_by_call.

* flow.c (mark_regs_live_at_end): Use regs_invalidated_by_call.
        * regclass.c (init_reg_sets_1): Fix typo.
        * config/ia64/ia64.c (ar_pfs_reg_operand): New.
        (ia64_expand_call): Pass ar.pfs to sibcall expanders.
        (ia64_compute_frame_size): Make ar.unat live when in use.
        (ia64_epilogue_uses): Reformat; do not check current_function_is_leaf
        for ar.pfs; remove ar.unat handling.
        * config/ia64/ia64.h (CALL_REALLY_USED_REGISTERS): ar.unat is
        call-saved.
        (PREDICATE_CODES): Add ar_pfs_reg_operand.
        * config/ia64/ia64-protos.h: Update decls.
        * config/ia64/ia64.md (sibcall_nopic): Use ar.pfs.
        (sibcall_pic): Likewise.

From-SVN: r45021
This commit is contained in:
Richard Henderson 2001-08-18 20:04:19 -07:00 committed by Richard Henderson
parent 8e8de25448
commit 6ca3c22fd1
7 changed files with 76 additions and 44 deletions

View File

@ -1,3 +1,19 @@
2001-08-18 Richard Henderson <rth@redhat.com>
* flow.c (mark_regs_live_at_end): Use regs_invalidated_by_call.
* regclass.c (init_reg_sets_1): Fix typo.
* config/ia64/ia64.c (ar_pfs_reg_operand): New.
(ia64_expand_call): Pass ar.pfs to sibcall expanders.
(ia64_compute_frame_size): Make ar.unat live when in use.
(ia64_epilogue_uses): Reformat; do not check current_function_is_leaf
for ar.pfs; remove ar.unat handling.
* config/ia64/ia64.h (CALL_REALLY_USED_REGISTERS): ar.unat is
call-saved.
(PREDICATE_CODES): Add ar_pfs_reg_operand.
* config/ia64/ia64-protos.h: Update decls.
* config/ia64/ia64.md (sibcall_nopic): Use ar.pfs.
(sibcall_pic): Likewise.
2001-08-18 Richard Henderson <rth@redhat.com>
* config/ia64/ia64.c (ia64_sched_reorder2): Also skip past

View File

@ -62,6 +62,7 @@ extern int not_postinc_memory_operand PARAMS((rtx, enum machine_mode));
extern int predicate_operator PARAMS((rtx, enum machine_mode));
extern int ar_lc_reg_operand PARAMS((rtx, enum machine_mode));
extern int ar_ccv_reg_operand PARAMS((rtx, enum machine_mode));
extern int ar_pfs_reg_operand PARAMS((rtx, enum machine_mode));
extern int general_tfmode_operand PARAMS((rtx, enum machine_mode));
extern int destination_tfmode_operand PARAMS((rtx, enum machine_mode));
extern int tfreg_or_fp01_operand PARAMS((rtx, enum machine_mode));

View File

@ -788,6 +788,18 @@ ar_ccv_reg_operand (op, mode)
&& REGNO (op) == AR_CCV_REGNUM);
}
/* Return 1 if this is the ar.pfs register. */
int
ar_pfs_reg_operand (op, mode)
register rtx op;
enum machine_mode mode;
{
return ((GET_MODE (op) == mode || mode == VOIDmode)
&& GET_CODE (op) == REG
&& REGNO (op) == AR_PFS_REGNUM);
}
/* Like general_operand, but don't allow (mem (addressof)). */
int
@ -1107,11 +1119,12 @@ ia64_expand_call (retval, addr, nextarg, sibcall_p)
rtx nextarg;
int sibcall_p;
{
rtx insn, b0, gp_save, narg_rtx;
rtx insn, b0, pfs, gp_save, narg_rtx;
int narg;
addr = XEXP (addr, 0);
b0 = gen_rtx_REG (DImode, R_BR (0));
pfs = gen_rtx_REG (DImode, AR_PFS_REGNUM);
if (! nextarg)
narg = 0;
@ -1124,7 +1137,7 @@ ia64_expand_call (retval, addr, nextarg, sibcall_p)
if (TARGET_NO_PIC || TARGET_AUTO_PIC)
{
if (sibcall_p)
insn = gen_sibcall_nopic (addr, narg_rtx, b0);
insn = gen_sibcall_nopic (addr, narg_rtx, b0, pfs);
else if (! retval)
insn = gen_call_nopic (addr, narg_rtx, b0);
else
@ -1151,7 +1164,7 @@ ia64_expand_call (retval, addr, nextarg, sibcall_p)
gen_rtx_MEM (DImode, plus_constant (addr, 8)));
if (sibcall_p)
insn = gen_sibcall_pic (dest, narg_rtx, b0);
insn = gen_sibcall_pic (dest, narg_rtx, b0, pfs);
else if (! retval)
insn = gen_call_pic (dest, narg_rtx, b0);
else
@ -1164,7 +1177,7 @@ ia64_expand_call (retval, addr, nextarg, sibcall_p)
else if (TARGET_CONST_GP)
{
if (sibcall_p)
insn = gen_sibcall_nopic (addr, narg_rtx, b0);
insn = gen_sibcall_nopic (addr, narg_rtx, b0, pfs);
else if (! retval)
insn = gen_call_nopic (addr, narg_rtx, b0);
else
@ -1174,7 +1187,7 @@ ia64_expand_call (retval, addr, nextarg, sibcall_p)
else
{
if (sibcall_p)
emit_call_insn (gen_sibcall_pic (addr, narg_rtx, b0));
emit_call_insn (gen_sibcall_pic (addr, narg_rtx, b0, pfs));
else
{
emit_move_insn (gp_save, pic_offset_table_rtx);
@ -1548,6 +1561,7 @@ ia64_compute_frame_size (size)
ar.unat as well. */
if (spilled_gr_p || cfun->machine->n_varargs)
{
regs_ever_live[AR_UNAT_REGNUM] = 1;
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)
@ -6633,42 +6647,39 @@ int
ia64_epilogue_uses (regno)
int regno;
{
/* When a function makes a call through a function descriptor, we
will write a (potentially) new value to "gp". After returning
from such a call, we need to make sure the function restores the
original gp-value, even if the function itself does not use the
gp anymore. */
if (regno == R_GR (1)
&& TARGET_CONST_GP
&& !(TARGET_AUTO_PIC || TARGET_NO_PIC))
return 1;
switch (regno)
{
case R_GR (1):
/* When a function makes a call through a function descriptor, we
will write a (potentially) new value to "gp". After returning
from such a call, we need to make sure the function restores the
original gp-value, even if the function itself does not use the
gp anymore. */
return (TARGET_CONST_GP && !(TARGET_AUTO_PIC || TARGET_NO_PIC));
/* For functions defined with the syscall_linkage attribute, all input
registers are marked as live at all function exits. This prevents the
register allocator from using the input registers, which in turn makes it
possible to restart a system call after an interrupt without having to
save/restore the input registers. This also prevents kernel data from
leaking to application code. */
case IN_REG (0): case IN_REG (1): case IN_REG (2): case IN_REG (3):
case IN_REG (4): case IN_REG (5): case IN_REG (6): case IN_REG (7):
/* For functions defined with the syscall_linkage attribute, all
input registers are marked as live at all function exits. This
prevents the register allocator from using the input registers,
which in turn makes it possible to restart a system call after
an interrupt without having to save/restore the input registers.
This also prevents kernel data from leaking to application code. */
return lookup_attribute ("syscall_linkage",
TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))) != NULL;
if (IN_REGNO_P (regno)
&& lookup_attribute ("syscall_linkage",
TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
return 1;
case R_BR (0):
/* Conditional return patterns can't represent the use of `b0' as
the return address, so we force the value live this way. */
return 1;
/* Conditional return patterns can't represent the use of `b0' as
the return address, so we force the value live this way. */
if (regno == R_BR (0))
return 1;
case AR_PFS_REGNUM:
/* Likewise for ar.pfs, which is used by br.ret. */
return 1;
if (regs_ever_live[AR_LC_REGNUM] && regno == AR_LC_REGNUM)
return 1;
if (! current_function_is_leaf && regno == AR_PFS_REGNUM)
return 1;
if (TEST_HARD_REG_BIT (current_frame_info.mask, AR_UNAT_REGNUM)
&& regno == AR_UNAT_REGNUM)
return 1;
return 0;
default:
return 0;
}
}
/* Return true if IDENTIFIER is a valid attribute for TYPE. */

View File

@ -635,11 +635,11 @@ while (0)
/* Like `CALL_USED_REGISTERS' but used to overcome a historical
problem which makes CALL_USED_REGISTERS *always* include
all the FIXED_REGISTERS. Until this problem has been
all the FIXED_REGISTERS. Until this problem has been
resolved this macro can be used to overcome this situation.
In particular, block_propagate() requires this list
be acurate, or we can remove registers which should be live.
This macro is used in regs_invalidated_by_call ()*/
This macro is used in regs_invalidated_by_call. */
#define CALL_REALLY_USED_REGISTERS \
{ /* General registers. */ \
@ -668,7 +668,7 @@ while (0)
/* Branch registers. */ \
1, 0, 0, 0, 0, 0, 1, 1, \
/*FP RA CCV UNAT PFS LC EC */ \
0, 0, 1, 1, 1, 0, 0 \
0, 0, 1, 0, 1, 0, 0 \
}
@ -2667,6 +2667,7 @@ do { \
{ "condop_operator", {PLUS, MINUS, IOR, XOR, AND}}, \
{ "ar_lc_reg_operand", {REG}}, \
{ "ar_ccv_reg_operand", {REG}}, \
{ "ar_pfs_reg_operand", {REG}}, \
{ "general_tfmode_operand", {SUBREG, REG, CONST_DOUBLE, MEM}}, \
{ "destination_tfmode_operand", {SUBREG, REG, MEM}}, \
{ "tfreg_or_fp01_operand", {REG, CONST_DOUBLE}},

View File

@ -4673,7 +4673,8 @@
(define_insn "sibcall_nopic"
[(call (mem:DI (match_operand:DI 0 "call_operand" "b,i"))
(match_operand 1 "" ""))
(use (match_operand:DI 2 "register_operand" "=b,b"))]
(use (match_operand:DI 2 "register_operand" "=b,b"))
(use (match_operand:DI 3 "ar_pfs_reg_operand" ""))]
""
"br%+.many %0"
[(set_attr "itanium_class" "br,scall")])
@ -4701,7 +4702,8 @@
[(call (mem:DI (match_operand:DI 0 "call_operand" "bi"))
(match_operand 1 "" ""))
(use (unspec [(reg:DI 1)] 9))
(use (match_operand:DI 2 "register_operand" "=b"))]
(use (match_operand:DI 2 "register_operand" "=b"))
(use (match_operand:DI 3 "ar_pfs_reg_operand" ""))]
""
"br%+.many %0"
[(set_attr "itanium_class" "br")])

View File

@ -4814,7 +4814,8 @@ mark_regs_live_at_end (set)
{
/* Mark all call-saved registers that we actually used. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (regs_ever_live[i] && ! call_used_regs[i] && ! LOCAL_REGNO (i))
if (regs_ever_live[i] && ! LOCAL_REGNO (i)
&& ! TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
SET_REGNO_REG_SET (set, i);
}

View File

@ -474,7 +474,7 @@ init_reg_sets_1 ()
;
#endif
else if (0
#ifdef CALL_REALLY_USED_REGS
#ifdef CALL_REALLY_USED_REGISTERS
|| call_really_used_regs[i]
#else
|| call_used_regs[i]