diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 56be9e7fec68..39b16d64db8d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2001-08-18 Richard Henderson + + * 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 * config/ia64/ia64.c (ia64_sched_reorder2): Also skip past diff --git a/gcc/config/ia64/ia64-protos.h b/gcc/config/ia64/ia64-protos.h index e9c2c5cc9467..03d2952aa227 100644 --- a/gcc/config/ia64/ia64-protos.h +++ b/gcc/config/ia64/ia64-protos.h @@ -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)); diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index aee3ee27284d..08660a79aa6b 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -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. */ diff --git a/gcc/config/ia64/ia64.h b/gcc/config/ia64/ia64.h index d1a1feded618..97e609fd21e8 100644 --- a/gcc/config/ia64/ia64.h +++ b/gcc/config/ia64/ia64.h @@ -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}}, diff --git a/gcc/config/ia64/ia64.md b/gcc/config/ia64/ia64.md index f5af33f14a34..5c1b9302b50e 100644 --- a/gcc/config/ia64/ia64.md +++ b/gcc/config/ia64/ia64.md @@ -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")]) diff --git a/gcc/flow.c b/gcc/flow.c index 1cf81d0f7530..6a316e24cc94 100644 --- a/gcc/flow.c +++ b/gcc/flow.c @@ -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); } diff --git a/gcc/regclass.c b/gcc/regclass.c index 021756a68e90..50b446d10e9c 100644 --- a/gcc/regclass.c +++ b/gcc/regclass.c @@ -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]