From f6b73c1b8a22a9d6ded3c7fca8d31382af3a2f0c Mon Sep 17 00:00:00 2001 From: rth Date: Fri, 8 Aug 2003 23:49:57 +0000 Subject: [PATCH] PR target/11535 * config/ia64/ia64.c (ia64_initial_elimination_offset): Remove RETURN_ADDRESS_POINTER_REGNUM. (ia64_expand_prologue): Don't frob it. (ia64_output_function_epilogue): Likewise. (ia64_return_addr_rtx): New. (ia64_split_return_addr_rtx): New. * config/ia64/ia64-protos.h: Update. * config/ia64/ia64.h (FIRST_PSEUDO_REGISTER): Decrement. (RETURN_ADDRESS_POINTER_REGNUM): Remove. (GENERAL_REGNO_P): Don't check it. (AR_*_REGNUM): Renumber. (FIXED_REGISTERS): Remove RETURN_ADDRESS_POINTER_REGNUM. (CALL_USED_REGISTERS, CALL_REALLY_USED_REGISTERS): Likewise. (REG_ALLOC_ORDER, REG_CLASS_CONTENTS): Likewise. (ELIMINABLE_REGS, REGISTER_NAMES): Likewise. (RETURN_ADDR_RTX): Use ia64_return_addr_rtx. * config/ia64/ia64.md (UNSPEC_RET_ADDR): New. (movdi_ret_addr): New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@70263 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 22 ++++++++++++ gcc/config/ia64/ia64-protos.h | 3 ++ gcc/config/ia64/ia64.c | 84 +++++++++++++++++++++++++++++++++---------- gcc/config/ia64/ia64.h | 56 ++++++++++++----------------- gcc/config/ia64/ia64.md | 20 +++++++++++ 5 files changed, 134 insertions(+), 51 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fc9d95c..7663d3a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,25 @@ +2003-08-08 Richard Henderson + + PR target/11535 + * config/ia64/ia64.c (ia64_initial_elimination_offset): Remove + RETURN_ADDRESS_POINTER_REGNUM. + (ia64_expand_prologue): Don't frob it. + (ia64_output_function_epilogue): Likewise. + (ia64_return_addr_rtx): New. + (ia64_split_return_addr_rtx): New. + * config/ia64/ia64-protos.h: Update. + * config/ia64/ia64.h (FIRST_PSEUDO_REGISTER): Decrement. + (RETURN_ADDRESS_POINTER_REGNUM): Remove. + (GENERAL_REGNO_P): Don't check it. + (AR_*_REGNUM): Renumber. + (FIXED_REGISTERS): Remove RETURN_ADDRESS_POINTER_REGNUM. + (CALL_USED_REGISTERS, CALL_REALLY_USED_REGISTERS): Likewise. + (REG_ALLOC_ORDER, REG_CLASS_CONTENTS): Likewise. + (ELIMINABLE_REGS, REGISTER_NAMES): Likewise. + (RETURN_ADDR_RTX): Use ia64_return_addr_rtx. + * config/ia64/ia64.md (UNSPEC_RET_ADDR): New. + (movdi_ret_addr): New. + 2003-08-08 Geoffrey Keating * config.gcc (powerpc-*-darwin*): Don't build a soft-float multilib. diff --git a/gcc/config/ia64/ia64-protos.h b/gcc/config/ia64/ia64-protos.h index 030c5ed..4f89f48 100644 --- a/gcc/config/ia64/ia64-protos.h +++ b/gcc/config/ia64/ia64-protos.h @@ -139,6 +139,9 @@ extern void ia64_init_builtins PARAMS((void)); extern void ia64_override_options PARAMS((void)); extern int ia64_dbx_register_number PARAMS((int)); +extern rtx ia64_return_addr_rtx PARAMS ((HOST_WIDE_INT, rtx)); +extern void ia64_split_return_addr_rtx PARAMS ((rtx)); + #ifdef SDATA_SECTION_ASM_OP extern void sdata_section PARAMS ((void)); #endif diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index f2e27d0..5a10128 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -2197,10 +2197,6 @@ ia64_initial_elimination_offset (from, to) abort (); break; - case RETURN_ADDRESS_POINTER_REGNUM: - offset = 0; - break; - default: abort (); } @@ -2551,17 +2547,6 @@ ia64_expand_prologue () reg_names[current_frame_info.reg_fp] = tmp; } - /* Fix up the return address placeholder. */ - /* ??? We can fail if __builtin_return_address is used, and we didn't - allocate a register in which to save b0. I can't think of a way to - eliminate RETURN_ADDRESS_POINTER_REGNUM to a local register and - then be sure that I got the right one. Further, reload doesn't seem - to care if an eliminable register isn't used, and "eliminates" it - anyway. */ - if (regs_ever_live[RETURN_ADDRESS_POINTER_REGNUM] - && current_frame_info.reg_save_b0 != 0) - XINT (return_address_pointer_rtx, 0) = current_frame_info.reg_save_b0; - /* We don't need an alloc instruction if we've used no outputs or locals. */ if (current_frame_info.n_local_regs == 0 && current_frame_info.n_output_regs == 0 @@ -3118,6 +3103,72 @@ ia64_direct_return () return 0; } +/* Return the magic cookie that we use to hold the return address + during early compilation. */ + +rtx +ia64_return_addr_rtx (count, frame) + HOST_WIDE_INT count; + rtx frame ATTRIBUTE_UNUSED; +{ + if (count != 0) + return NULL; + return gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_RET_ADDR); +} + +/* Split this value after reload, now that we know where the return + address is saved. */ + +void +ia64_split_return_addr_rtx (dest) + rtx dest; +{ + rtx src; + + if (TEST_HARD_REG_BIT (current_frame_info.mask, BR_REG (0))) + { + if (current_frame_info.reg_save_b0 != 0) + src = gen_rtx_REG (DImode, current_frame_info.reg_save_b0); + else + { + HOST_WIDE_INT off; + unsigned int regno; + + /* Compute offset from CFA for BR0. */ + /* ??? Must be kept in sync with ia64_expand_prologue. */ + off = (current_frame_info.spill_cfa_off + + current_frame_info.spill_size); + for (regno = GR_REG (1); regno <= GR_REG (31); ++regno) + if (TEST_HARD_REG_BIT (current_frame_info.mask, regno)) + off -= 8; + + /* Convert CFA offset to a register based offset. */ + if (frame_pointer_needed) + src = hard_frame_pointer_rtx; + else + { + src = stack_pointer_rtx; + off += current_frame_info.total_size; + } + + /* Load address into scratch register. */ + if (CONST_OK_FOR_I (off)) + emit_insn (gen_adddi3 (dest, src, GEN_INT (off))); + else + { + emit_move_insn (dest, GEN_INT (off)); + emit_insn (gen_adddi3 (dest, src, dest)); + } + + src = gen_rtx_MEM (Pmode, dest); + } + } + else + src = gen_rtx_REG (DImode, BR_REG (0)); + + emit_move_insn (dest, src); +} + int ia64_hard_regno_rename_ok (from, to) int from; @@ -3267,9 +3318,6 @@ ia64_output_function_epilogue (file, size) { int i; - /* Reset from the function's potential modifications. */ - XINT (return_address_pointer_rtx, 0) = RETURN_ADDRESS_POINTER_REGNUM; - if (current_frame_info.reg_fp) { const char *tmp = reg_names[HARD_FRAME_POINTER_REGNUM]; diff --git a/gcc/config/ia64/ia64.h b/gcc/config/ia64/ia64.h index fe2c803..a8bc569 100644 --- a/gcc/config/ia64/ia64.h +++ b/gcc/config/ia64/ia64.h @@ -455,7 +455,7 @@ while (0) 64 predicate registers, 8 branch registers, one frame pointer, and several "application" registers. */ -#define FIRST_PSEUDO_REGISTER 335 +#define FIRST_PSEUDO_REGISTER 334 /* Ranges for the various kinds of registers. */ #define ADDL_REGNO_P(REGNO) ((unsigned HOST_WIDE_INT) (REGNO) <= 3) @@ -464,9 +464,7 @@ while (0) #define PR_REGNO_P(REGNO) ((REGNO) >= 256 && (REGNO) <= 319) #define BR_REGNO_P(REGNO) ((REGNO) >= 320 && (REGNO) <= 327) #define GENERAL_REGNO_P(REGNO) \ - (GR_REGNO_P (REGNO) \ - || (REGNO) == FRAME_POINTER_REGNUM \ - || (REGNO) == RETURN_ADDRESS_POINTER_REGNUM) + (GR_REGNO_P (REGNO) || (REGNO) == FRAME_POINTER_REGNUM) #define GR_REG(REGNO) ((REGNO) + 0) #define FR_REG(REGNO) ((REGNO) + 128) @@ -476,11 +474,11 @@ while (0) #define IN_REG(REGNO) ((REGNO) + 112) #define LOC_REG(REGNO) ((REGNO) + 32) -#define AR_CCV_REGNUM 330 -#define AR_UNAT_REGNUM 331 -#define AR_PFS_REGNUM 332 -#define AR_LC_REGNUM 333 -#define AR_EC_REGNUM 334 +#define AR_CCV_REGNUM 329 +#define AR_UNAT_REGNUM 330 +#define AR_PFS_REGNUM 331 +#define AR_LC_REGNUM 332 +#define AR_EC_REGNUM 333 #define IN_REGNO_P(REGNO) ((REGNO) >= IN_REG (0) && (REGNO) <= IN_REG (7)) #define LOC_REGNO_P(REGNO) ((REGNO) >= LOC_REG (0) && (REGNO) <= LOC_REG (79)) @@ -543,8 +541,8 @@ while (0) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ /* Branch registers. */ \ 0, 0, 0, 0, 0, 0, 0, 0, \ - /*FP RA CCV UNAT PFS LC EC */ \ - 1, 1, 1, 1, 1, 0, 1 \ + /*FP CCV UNAT PFS LC EC */ \ + 1, 1, 1, 1, 0, 1 \ } /* Like `FIXED_REGISTERS' but has 1 for each register that is clobbered @@ -578,8 +576,8 @@ while (0) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ /* Branch registers. */ \ 1, 0, 0, 0, 0, 0, 1, 1, \ - /*FP RA CCV UNAT PFS LC EC */ \ - 1, 1, 1, 1, 1, 0, 1 \ + /*FP CCV UNAT PFS LC EC */ \ + 1, 1, 1, 1, 0, 1 \ } /* Like `CALL_USED_REGISTERS' but used to overcome a historical @@ -616,8 +614,8 @@ while (0) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ /* Branch registers. */ \ 1, 0, 0, 0, 0, 0, 1, 1, \ - /*FP RA CCV UNAT PFS LC EC */ \ - 0, 0, 1, 0, 1, 0, 0 \ + /*FP CCV UNAT PFS LC EC */ \ + 0, 1, 0, 1, 0, 0 \ } @@ -763,7 +761,7 @@ while (0) /* Special branch registers. */ \ R_BR (0), \ /* Other fixed registers. */ \ - FRAME_POINTER_REGNUM, RETURN_ADDRESS_POINTER_REGNUM, \ + FRAME_POINTER_REGNUM, \ AR_CCV_REGNUM, AR_UNAT_REGNUM, AR_PFS_REGNUM, AR_LC_REGNUM, \ AR_EC_REGNUM \ } @@ -892,11 +890,11 @@ enum reg_class /* AR_M_REGS. */ \ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, \ 0x00000000, 0x00000000, 0x00000000, 0x00000000, \ - 0x00000000, 0x00000000, 0x0C00 }, \ + 0x00000000, 0x00000000, 0x0600 }, \ /* AR_I_REGS. */ \ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, \ 0x00000000, 0x00000000, 0x00000000, 0x00000000, \ - 0x00000000, 0x00000000, 0x7000 }, \ + 0x00000000, 0x00000000, 0x3800 }, \ /* ADDL_REGS. */ \ { 0x0000000F, 0x00000000, 0x00000000, 0x00000000, \ 0x00000000, 0x00000000, 0x00000000, 0x00000000, \ @@ -904,7 +902,7 @@ enum reg_class /* GR_REGS. */ \ { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \ 0x00000000, 0x00000000, 0x00000000, 0x00000000, \ - 0x00000000, 0x00000000, 0x0300 }, \ + 0x00000000, 0x00000000, 0x0100 }, \ /* FR_REGS. */ \ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, \ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \ @@ -912,15 +910,15 @@ enum reg_class /* GR_AND_BR_REGS. */ \ { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \ 0x00000000, 0x00000000, 0x00000000, 0x00000000, \ - 0x00000000, 0x00000000, 0x03FF }, \ + 0x00000000, 0x00000000, 0x01FF }, \ /* GR_AND_FR_REGS. */ \ { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \ - 0x00000000, 0x00000000, 0x0300 }, \ + 0x00000000, 0x00000000, 0x0100 }, \ /* ALL_REGS. */ \ { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \ - 0xFFFFFFFF, 0xFFFFFFFF, 0x7FFF }, \ + 0xFFFFFFFF, 0xFFFFFFFF, 0x3FFF }, \ } /* A C expression whose value is a register class containing hard register @@ -1142,7 +1140,7 @@ enum reg_class DYNAMIC_CHAIN_ADDRESS and SETUP_FRAME_ADDRESS (for the reg stack flush). */ #define RETURN_ADDR_RTX(COUNT, FRAME) \ - ((COUNT) == 0 ? return_address_pointer_rtx : const0_rtx) + ia64_return_addr_rtx (COUNT, FRAME) /* A C expression whose value is RTL representing the location of the incoming return address at the beginning of any function, before the prologue. This @@ -1203,13 +1201,6 @@ enum reg_class REGNO_POINTER_ALIGN (ARG_POINTER_REGNUM) = 64; \ } while (0) -/* The register number for the return address register. For IA-64, this - is not actually a pointer as the name suggests, but that's a name that - gen_rtx_REG already takes care to keep unique. We modify - return_address_pointer_rtx in ia64_expand_prologue to reference the - final output regnum. */ -#define RETURN_ADDRESS_POINTER_REGNUM 329 - /* Register numbers used for passing a function's static chain pointer. */ /* ??? The ABI sez the static chain should be passed as a normal parameter. */ #define STATIC_CHAIN_REGNUM 15 @@ -1233,7 +1224,6 @@ enum reg_class {ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \ {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ {FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \ - {RETURN_ADDRESS_POINTER_REGNUM, BR_REG (0)}, \ } /* A C expression that returns nonzero if the compiler is allowed to try to @@ -1879,8 +1869,8 @@ do { \ "p60", "p61", "p62", "p63", \ /* Branch registers. */ \ "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", \ - /* Frame pointer. Return address. */ \ - "sfp", "retaddr", "ar.ccv", "ar.unat", "ar.pfs", "ar.lc", "ar.ec", \ + /* Frame pointer. Application registers. */ \ + "sfp", "ar.ccv", "ar.unat", "ar.pfs", "ar.lc", "ar.ec", \ } /* If defined, a C initializer for an array of structures containing a name and diff --git a/gcc/config/ia64/ia64.md b/gcc/config/ia64/ia64.md index faff0ee..0d0999f 100644 --- a/gcc/config/ia64/ia64.md +++ b/gcc/config/ia64/ia64.md @@ -73,6 +73,7 @@ (UNSPEC_BUNDLE_SELECTOR 23) (UNSPEC_ADDP4 24) (UNSPEC_PROLOGUE_USE 25) + (UNSPEC_RET_ADDR 26) ]) (define_constants @@ -410,6 +411,25 @@ operands[3] = pic_offset_table_rtx; }) +;; This is used as a placeholder for the return address during early +;; compilation. We won't know where we've placed this until during +;; reload, at which point it can wind up in b0, a general register, +;; or memory. The only safe destination under these conditions is a +;; general register. + +(define_insn_and_split "*movdi_ret_addr" + [(set (match_operand:DI 0 "register_operand" "=r") + (unspec:DI [(const_int 0)] UNSPEC_RET_ADDR))] + "" + "#" + "reload_completed" + [(const_int 0)] +{ + ia64_split_return_addr_rtx (operands[0]); + DONE; +} + [(set_attr "itanium_class" "ialu")]) + (define_insn "*load_symptr_high" [(set (match_operand:DI 0 "register_operand" "=r") (plus:DI (high:DI (match_operand 1 "got_symbolic_operand" "s")) -- 2.7.4