diff options
author | Richard Earnshaw <rearnsha@arm.com> | 2006-01-17 20:22:19 +0000 |
---|---|---|
committer | Richard Earnshaw <rearnsha@gcc.gnu.org> | 2006-01-17 20:22:19 +0000 |
commit | 020a40353445c2e9cf17496e777edeca59573ee1 (patch) | |
tree | 60167f7dda7e44bbe4c14acf58d1a28a6405087e | |
parent | a5a97921829bb7d51f71fdb05f5ef0d65be3f354 (diff) | |
download | gcc-020a40353445c2e9cf17496e777edeca59573ee1.zip gcc-020a40353445c2e9cf17496e777edeca59573ee1.tar.gz gcc-020a40353445c2e9cf17496e777edeca59573ee1.tar.bz2 |
re PR target/592 ([ARM/Thumb] Poor choice of PIC register)
PR target/592
PR middle-end/11135
* arm.h (struct machine_function): Add pic_reg.
* arm.c (arm_pic_register): Make unsigned.
(arm_override_options): Only set arm_pic_register if
TARGET_SINGLE_PIC_BASE.
(use_return_insn): Only test for a pic register if it is fixed.
(arm_compute_save_reg0_reg12_mask): Likewise.
(thumb_compute_save_reg_mask): Likewise.
(legitimate_pic_operand): Factor out some known invariants.
(legitimize_pic_address): If we don't have a fixed pic register,
then set up a pseudo in the function entry sequence. Handle the
pic base being in a pseudo.
(arm_load_pic_register): Handle the pic register being in a pseudo.
(arm_expand_prologue): Only set up the pic register if it is fixed.
(thumb_expand_prologue): Likewise.
* arm.md (pic_load_addr_based): Handle the pic base being a pseudo.
(pic_load_addr_based_insn): Likewise.
(builtin_setjmp_receiver): Don't restore the pic base if it isn't
fixed.
From-SVN: r109839
-rw-r--r-- | gcc/ChangeLog | 23 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 98 | ||||
-rw-r--r-- | gcc/config/arm/arm.h | 6 | ||||
-rw-r--r-- | gcc/config/arm/arm.md | 9 |
4 files changed, 104 insertions, 32 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 252bab0..0fb17c1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,26 @@ +2006-01-17 Richard Earnshaw <rearnsha@arm.com> + + PR target/592 + PR middle-end/11135 + * arm.h (struct machine_function): Add pic_reg. + * arm.c (arm_pic_register): Make unsigned. + (arm_override_options): Only set arm_pic_register if + TARGET_SINGLE_PIC_BASE. + (use_return_insn): Only test for a pic register if it is fixed. + (arm_compute_save_reg0_reg12_mask): Likewise. + (thumb_compute_save_reg_mask): Likewise. + (legitimate_pic_operand): Factor out some known invariants. + (legitimize_pic_address): If we don't have a fixed pic register, + then set up a pseudo in the function entry sequence. Handle the + pic base being in a pseudo. + (arm_load_pic_register): Handle the pic register being in a pseudo. + (arm_expand_prologue): Only set up the pic register if it is fixed. + (thumb_expand_prologue): Likewise. + * arm.md (pic_load_addr_based): Handle the pic base being a pseudo. + (pic_load_addr_based_insn): Likewise. + (builtin_setjmp_receiver): Don't restore the pic base if it isn't + fixed. + 2006-01-18 Ben Elliston <bje@au.ibm.com> * config/rs6000/rs6000.c (rs6000_hard_regno_mode_ok): Reject diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 8e3ade5..e5309e0 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -1,6 +1,6 @@ /* Output routines for GCC for ARM. Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl) and Martin Simmons (@harleqn.co.uk). More major hacks by Richard Earnshaw (rearnsha@arm.com). @@ -524,7 +524,7 @@ int arm_cpp_interwork = 0; enum machine_mode output_memory_reference_mode; /* The register number to be used for the PIC offset register. */ -int arm_pic_register = INVALID_REGNUM; +unsigned arm_pic_register = INVALID_REGNUM; /* Set to 1 when a return insn is output, this means that the epilogue is not needed. */ @@ -1096,7 +1096,7 @@ arm_override_options (void) /* If stack checking is disabled, we can use r10 as the PIC register, which keeps r9 available. */ - if (flag_pic) + if (flag_pic && TARGET_SINGLE_PIC_BASE) arm_pic_register = TARGET_APCS_STACK ? 9 : 10; if (TARGET_APCS_FLOAT) @@ -1547,7 +1547,9 @@ use_return_insn (int iscond, rtx sibling) if (saved_int_regs != 0 && saved_int_regs != (1 << LR_REGNUM)) return 0; - if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM]) + if (flag_pic + && arm_pic_register != INVALID_REGNUM + && regs_ever_live[PIC_OFFSET_TABLE_REGNUM]) return 0; } @@ -3171,16 +3173,14 @@ arm_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED) /* Addressing mode support functions. */ /* Return nonzero if X is a legitimate immediate operand when compiling - for PIC. */ + for PIC. We know that X satisfies CONSTANT_P and flag_pic is true. */ int legitimate_pic_operand_p (rtx x) { - if (CONSTANT_P (x) - && flag_pic - && (GET_CODE (x) == SYMBOL_REF - || (GET_CODE (x) == CONST - && GET_CODE (XEXP (x, 0)) == PLUS - && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF))) + if (GET_CODE (x) == SYMBOL_REF + || (GET_CODE (x) == CONST + && GET_CODE (XEXP (x, 0)) == PLUS + && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF)) return 0; return 1; @@ -3198,6 +3198,49 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg) rtx insn; int subregs = 0; + /* If this function doesn't have a pic register, create one now. + A lot of the logic here is made obscure by the fact that this + routine gets called as part of the rtx cost estimation + process. We don't want those calls to affect any assumptions + about the real function; and further, we can't call + entry_of_function() until we start the real expansion + process. */ + if (!current_function_uses_pic_offset_table) + { + gcc_assert (!no_new_pseudos); + if (arm_pic_register != INVALID_REGNUM) + { + cfun->machine->pic_reg = gen_rtx_REG (Pmode, arm_pic_register); + + /* Play games to avoid marking the function as needing pic + if we are being called as part of the cost-estimation + process. */ + if (!ir_type()) + current_function_uses_pic_offset_table = 1; + } + else + { + rtx seq; + + cfun->machine->pic_reg = gen_reg_rtx (Pmode); + + /* Play games to avoid marking the function as needing pic + if we are being called as part of the cost-estimation + process. */ + if (!ir_type()) + { + current_function_uses_pic_offset_table = 1; + start_sequence (); + + arm_load_pic_register (0UL); + + seq = get_insns (); + end_sequence (); + emit_insn_after (seq, entry_of_function ()); + } + } + } + if (reg == 0) { gcc_assert (!no_new_pseudos); @@ -3225,17 +3268,16 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg) || (GET_CODE (orig) == SYMBOL_REF && SYMBOL_REF_LOCAL_P (orig))) && NEED_GOT_RELOC) - pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, address); + pic_ref = gen_rtx_PLUS (Pmode, cfun->machine->pic_reg, address); else { pic_ref = gen_const_mem (Pmode, - gen_rtx_PLUS (Pmode, pic_offset_table_rtx, + gen_rtx_PLUS (Pmode, cfun->machine->pic_reg, address)); } insn = emit_move_insn (reg, pic_ref); #endif - current_function_uses_pic_offset_table = 1; /* Put a REG_EQUAL note on this insn, so that it can be optimized by loop. */ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig, @@ -3247,7 +3289,7 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg) rtx base, offset; if (GET_CODE (XEXP (orig, 0)) == PLUS - && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx) + && XEXP (XEXP (orig, 0), 0) == cfun->machine->pic_reg) return orig; if (GET_CODE (XEXP (orig, 0)) == UNSPEC @@ -3387,13 +3429,14 @@ arm_load_pic_register (unsigned long saved_regs ATTRIBUTE_UNUSED) if (TARGET_ARM) { - emit_insn (gen_pic_load_addr_arm (pic_offset_table_rtx, pic_rtx)); - emit_insn (gen_pic_add_dot_plus_eight (pic_offset_table_rtx, - pic_offset_table_rtx, labelno)); + emit_insn (gen_pic_load_addr_arm (cfun->machine->pic_reg, pic_rtx)); + emit_insn (gen_pic_add_dot_plus_eight (cfun->machine->pic_reg, + cfun->machine->pic_reg, labelno)); } else { - if (REGNO (pic_offset_table_rtx) > LAST_LO_REGNUM) + if (arm_pic_register != INVALID_REGNUM + && REGNO (cfun->machine->pic_reg) > LAST_LO_REGNUM) { /* We will have pushed the pic register, so we should always be able to find a work register. */ @@ -3403,14 +3446,14 @@ arm_load_pic_register (unsigned long saved_regs ATTRIBUTE_UNUSED) emit_insn (gen_movsi (pic_offset_table_rtx, pic_tmp)); } else - emit_insn (gen_pic_load_addr_thumb (pic_offset_table_rtx, pic_rtx)); - emit_insn (gen_pic_add_dot_plus_four (pic_offset_table_rtx, - pic_offset_table_rtx, labelno)); + emit_insn (gen_pic_load_addr_thumb (cfun->machine->pic_reg, pic_rtx)); + emit_insn (gen_pic_add_dot_plus_four (cfun->machine->pic_reg, + cfun->machine->pic_reg, labelno)); } /* Need to emit this whether or not we obey regdecls, since setjmp/longjmp can cause life info to screw up. */ - emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx)); + emit_insn (gen_rtx_USE (VOIDmode, cfun->machine->pic_reg)); #endif /* AOF_ASSEMBLER */ } @@ -3690,7 +3733,7 @@ thumb_legitimate_address_p (enum machine_mode mode, rtx x, int strict_p) /* This is PC relative data before arm_reorg runs. */ else if (GET_MODE_SIZE (mode) >= 4 && CONSTANT_P (x) && GET_CODE (x) == SYMBOL_REF - && CONSTANT_POOL_ADDRESS_P (x) && ! flag_pic) + && CONSTANT_POOL_ADDRESS_P (x) && !flag_pic) return 1; /* This is PC relative data after arm_reorg runs. */ @@ -9173,6 +9216,7 @@ arm_compute_save_reg0_reg12_mask (void) /* Also save the pic base register if necessary. */ if (flag_pic && !TARGET_SINGLE_PIC_BASE + && arm_pic_register != INVALID_REGNUM && current_function_uses_pic_offset_table) save_reg_mask |= 1 << PIC_OFFSET_TABLE_REGNUM; } @@ -9195,6 +9239,7 @@ arm_compute_save_reg0_reg12_mask (void) don't stack it even though it may be live. */ if (flag_pic && !TARGET_SINGLE_PIC_BASE + && arm_pic_register != INVALID_REGNUM && (regs_ever_live[PIC_OFFSET_TABLE_REGNUM] || current_function_uses_pic_offset_table)) save_reg_mask |= 1 << PIC_OFFSET_TABLE_REGNUM; @@ -9312,6 +9357,7 @@ thumb_compute_save_reg_mask (void) if (flag_pic && !TARGET_SINGLE_PIC_BASE + && arm_pic_register != INVALID_REGNUM && current_function_uses_pic_offset_table) mask |= 1 << PIC_OFFSET_TABLE_REGNUM; @@ -10822,7 +10868,7 @@ arm_expand_prologue (void) } - if (flag_pic) + if (flag_pic && arm_pic_register != INVALID_REGNUM) arm_load_pic_register (0UL); /* If we are profiling, make sure no instructions are scheduled before @@ -13584,7 +13630,7 @@ thumb_expand_prologue (void) live_regs_mask = thumb_compute_save_reg_mask (); /* Load the pic register before setting the frame pointer, so we can use r7 as a temporary work register. */ - if (flag_pic) + if (flag_pic && arm_pic_register != INVALID_REGNUM) arm_load_pic_register (live_regs_mask); if (!frame_pointer_needed && CALLER_INTERWORKING_SLOT_SIZE > 0) diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index b7b775c..e2826dc 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -1,6 +1,6 @@ /* Definitions of target machine for GNU compiler, for ARM. Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, - 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl) and Martin Simmons (@harleqn.co.uk). More major hacks by Richard Earnshaw (rearnsha@arm.com) @@ -1519,6 +1519,8 @@ typedef struct machine_function GTY(()) /* Records if sibcalls are blocked because an argument register is needed to preserve stack alignment. */ int sibcall_blocked; + /* The PIC register for this function. This might be a pseudo. */ + rtx pic_reg; /* Labels for per-function Thumb call-via stubs. One per potential calling register. We can never call via LR or PC. We can call via SP if a trampoline happens to be on the top of the stack. */ @@ -2206,7 +2208,7 @@ do { \ /* We decide which register to use based on the compilation options and the assembler in use; this is more general than the APCS restriction of using sb (r9) all the time. */ -extern int arm_pic_register; +extern unsigned arm_pic_register; /* The register number of the register used to address a table of static data addresses in memory. */ diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index a161d4d..239961a 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -1,6 +1,6 @@ ;;- Machine description for ARM for GNU compiler ;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000, -;; 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +;; 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. ;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl) ;; and Martin Simmons (@harleqn.co.uk). ;; More major hacks by Richard Earnshaw (rearnsha@arm.com). @@ -4448,7 +4448,7 @@ [(set (match_operand:SI 0 "s_register_operand" "") (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))] "TARGET_ARM && flag_pic" - "operands[2] = pic_offset_table_rtx;" + "operands[2] = cfun->machine->pic_reg;" ) (define_insn "*pic_load_addr_based_insn" @@ -4456,7 +4456,7 @@ (unspec:SI [(match_operand 1 "" "") (match_operand 2 "s_register_operand" "r")] UNSPEC_PIC_SYM))] - "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx" + "TARGET_EITHER && flag_pic && operands[2] == cfun->machine->pic_reg" "* #ifdef AOF_ASSEMBLER operands[1] = aof_pic_entry (operands[1]); @@ -4547,7 +4547,8 @@ { /* r3 is clobbered by set/longjmp, so we can use it as a scratch register. */ - arm_load_pic_register (3); + if (arm_pic_register != INVALID_REGNUM) + arm_load_pic_register (1UL << 3); DONE; }") |