From 08e7ceb3d3d4d3763bdb5cfbb1dd0a78b27f0e5d Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Thu, 12 Apr 2007 17:26:45 +0000 Subject: [PATCH] mips-protos.h (SYMBOL_GOT_LOCAL): Rename to... gcc/ * config/mips/mips-protos.h (SYMBOL_GOT_LOCAL): Rename to... (SYMBOL_GOT_PAGE_OFST): ...this. (SYMBOL_GOT_GLOBAL): Rename to... (SYMBOL_GOT_DISP): ...this. (SYMBOL_GOTOFF_GLOBAL): Rename to... (SYMBOL_GOTOFF_DISP): ...this. Update comments accordingly. * config/mips/mips.c (mips_global_symbol_p): New function. (mips_symbol_binds_local_p): Likewise. (mips_classify_symbol): Rename SYMBOL_GOT_GLOBAL to SYMBOL_GOT_DISP and SYMBOL_GOT_LOCAL to SYMBOL_GOT_PAGE_OFST. Use mips_global_symbol_p and mips_symbol_binds_local_p. (mips_symbolic_constant_p, mips_symbolic_address_p, mips_symbol_insns) (override_options): Rename SYMBOL_GOT_GLOBAL to SYMBOL_GOT_DISP, SYMBOL_GOT_LOCAL to SYMBOL_GOT_PAGE_OFST and SYMBOL_GOTOFF_GLOBAL to SYMBOL_GOTOFF_DISP. (mips_ok_for_lazy_binding_p): New function. (mips_load_call_address, mips_expand_call): Use it. (mips_dangerous_for_la25_p): Likewise. * config/mips/mips.md (*xgot_hi, *xgot_lo) (*got_disp): Use got_disp_operand instead of global_got_operand. Use SYMBOL_GOTOFF_DISP instead of SYMBOL_GOTOFF_GLOBAL. (*got_page): Use got_page_ofst_operand instead of local_got_operand. * config/mips/predicates.md (const_call_insn_operand): Use SYMBOL_GOT_DISP instead of SYMBOL_GOT_GLOBAL. (global_got_operand): Rename to... (got_disp_operand): ...this and use SYMBOL_GOT_DISP instead of SYMBOL_GOT_GLOBAL. (local_got_operand): Rename to... (got_page_ofst_operand): ...this and use SYMBOL_GOT_PAGE_OFST instead of SYMBOL_GOT_LOCAL. From-SVN: r123752 --- gcc/ChangeLog | 35 +++++++++ gcc/config/mips/mips-protos.h | 26 +++---- gcc/config/mips/mips.c | 168 +++++++++++++++++++++++------------------- gcc/config/mips/mips.md | 20 ++--- gcc/config/mips/predicates.md | 10 +-- 5 files changed, 157 insertions(+), 102 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d28edd5..fb65fb4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,40 @@ 2007-04-12 Richard Sandiford + * config/mips/mips-protos.h (SYMBOL_GOT_LOCAL): Rename to... + (SYMBOL_GOT_PAGE_OFST): ...this. + (SYMBOL_GOT_GLOBAL): Rename to... + (SYMBOL_GOT_DISP): ...this. + (SYMBOL_GOTOFF_GLOBAL): Rename to... + (SYMBOL_GOTOFF_DISP): ...this. Update comments accordingly. + * config/mips/mips.c (mips_global_symbol_p): New function. + (mips_symbol_binds_local_p): Likewise. + (mips_classify_symbol): Rename SYMBOL_GOT_GLOBAL to SYMBOL_GOT_DISP + and SYMBOL_GOT_LOCAL to SYMBOL_GOT_PAGE_OFST. Use mips_global_symbol_p + and mips_symbol_binds_local_p. + (mips_symbolic_constant_p, mips_symbolic_address_p, mips_symbol_insns) + (override_options): Rename SYMBOL_GOT_GLOBAL to SYMBOL_GOT_DISP, + SYMBOL_GOT_LOCAL to SYMBOL_GOT_PAGE_OFST and SYMBOL_GOTOFF_GLOBAL to + SYMBOL_GOTOFF_DISP. + (mips_ok_for_lazy_binding_p): New function. + (mips_load_call_address, mips_expand_call): Use it. + (mips_dangerous_for_la25_p): Likewise. + * config/mips/mips.md (*xgot_hi, *xgot_lo) + (*got_disp): Use got_disp_operand instead of + global_got_operand. Use SYMBOL_GOTOFF_DISP instead of + SYMBOL_GOTOFF_GLOBAL. + (*got_page): Use got_page_ofst_operand instead of + local_got_operand. + * config/mips/predicates.md (const_call_insn_operand): Use + SYMBOL_GOT_DISP instead of SYMBOL_GOT_GLOBAL. + (global_got_operand): Rename to... + (got_disp_operand): ...this and use SYMBOL_GOT_DISP instead of + SYMBOL_GOT_GLOBAL. + (local_got_operand): Rename to... + (got_page_ofst_operand): ...this and use SYMBOL_GOT_PAGE_OFST instead + of SYMBOL_GOT_LOCAL. + +2007-04-12 Richard Sandiford + * config/mips/mips.h (TARGET_SPLIT_CALLS): Check TARGET_CALL_CLOBBERED_GP. (TARGET_SIBCALLS): Check TARGET_USE_GOT instead of TARGET_ABICALLS. diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h index a9fa42e..91d0150 100644 --- a/gcc/config/mips/mips-protos.h +++ b/gcc/config/mips/mips-protos.h @@ -37,23 +37,23 @@ Boston, MA 02110-1301, USA. */ SYMBOL_CONSTANT_POOL The symbol refers to something in the mips16 constant pool. - SYMBOL_GOT_LOCAL - The symbol refers to local data that will be found using - the global offset table. + SYMBOL_GOT_PAGE_OFST + The symbol's value will be calculated by loading an address + from the GOT and then applying a 16-bit offset. - SYMBOL_GOT_GLOBAL - Likewise non-local data. + SYMBOL_GOT_DISP + The symbol's value will be loaded directly from the GOT. SYMBOL_GOTOFF_PAGE - An UNSPEC wrapper around a SYMBOL_GOT_LOCAL. It represents the - offset from _gp of a GOT page entry. + An UNSPEC wrapper around a SYMBOL_GOT_PAGE_OFST. It represents the + offset from _gp of the GOT entry. - SYMBOL_GOTOFF_GLOBAL - An UNSPEC wrapper around a SYMBOL_GOT_GLOBAL. It represents the + SYMBOL_GOTOFF_DISP + An UNSPEC wrapper around a SYMBOL_GOT_DISP. It represents the the offset from _gp of the symbol's GOT entry. SYMBOL_GOTOFF_CALL - Like SYMBOL_GOTOFF_GLOBAL, but used when calling a global function. + Like SYMBOL_GOTOFF_DISP, but used when calling a global function. The GOT entry is allowed to point to a stub rather than to the function itself. @@ -87,10 +87,10 @@ enum mips_symbol_type { SYMBOL_GENERAL, SYMBOL_SMALL_DATA, SYMBOL_CONSTANT_POOL, - SYMBOL_GOT_LOCAL, - SYMBOL_GOT_GLOBAL, + SYMBOL_GOT_PAGE_OFST, + SYMBOL_GOT_DISP, SYMBOL_GOTOFF_PAGE, - SYMBOL_GOTOFF_GLOBAL, + SYMBOL_GOTOFF_DISP, SYMBOL_GOTOFF_CALL, SYMBOL_GOTOFF_LOADGP, SYMBOL_TLS, diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 8615510..d7dbd2e 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -1212,19 +1212,45 @@ static struct mips_rtx_cost_data const mips_rtx_cost_data[PROCESSOR_MAX] = struct gcc_target targetm = TARGET_INITIALIZER; +/* Return true if SYMBOL_REF X is associated with a global symbol + (in the STB_GLOBAL sense). */ + +static bool +mips_global_symbol_p (rtx x) +{ + tree decl; + + decl = SYMBOL_REF_DECL (x); + if (!decl) + return !SYMBOL_REF_LOCAL_P (x); + + /* Weakref symbols are not TREE_PUBLIC, but their targets are global + or weak symbols. Relocations in the object file will be against + the target symbol, so it's that symbol's binding that matters here. */ + return DECL_P (decl) && (TREE_PUBLIC (decl) || DECL_WEAK (decl)); +} + +/* Return true if SYMBOL_REF X binds locally. */ + +static bool +mips_symbol_binds_local_p (rtx x) +{ + return (SYMBOL_REF_DECL (x) + ? targetm.binds_local_p (SYMBOL_REF_DECL (x)) + : SYMBOL_REF_LOCAL_P (x)); +} + /* Classify symbol X, which must be a SYMBOL_REF or a LABEL_REF. */ static enum mips_symbol_type mips_classify_symbol (rtx x) { - tree decl; - if (GET_CODE (x) == LABEL_REF) { if (TARGET_MIPS16) return SYMBOL_CONSTANT_POOL; if (TARGET_ABICALLS && !TARGET_ABSOLUTE_ABICALLS) - return SYMBOL_GOT_LOCAL; + return SYMBOL_GOT_PAGE_OFST; return SYMBOL_GENERAL; } @@ -1250,49 +1276,34 @@ mips_classify_symbol (rtx x) if (TARGET_ABICALLS) { - decl = SYMBOL_REF_DECL (x); - if (decl == 0) - { - if (!SYMBOL_REF_LOCAL_P (x)) - return SYMBOL_GOT_GLOBAL; - } - else - { - /* Don't use GOT accesses for locally-binding symbols if - TARGET_ABSOLUTE_ABICALLS. Otherwise, there are three - cases to consider: - - - o32 PIC (either with or without explicit relocs) - - n32/n64 PIC without explicit relocs - - n32/n64 PIC with explicit relocs - - In the first case, both local and global accesses will use an - R_MIPS_GOT16 relocation. We must correctly predict which of - the two semantics (local or global) the assembler and linker - will apply. The choice doesn't depend on the symbol's - visibility, so we deliberately ignore decl_visibility and - binds_local_p here. - - In the second case, the assembler will not use R_MIPS_GOT16 - relocations, but it chooses between local and global accesses - in the same way as for o32 PIC. - - In the third case we have more freedom since both forms of - access will work for any kind of symbol. However, there seems - little point in doing things differently. - - Note that weakref symbols are not TREE_PUBLIC, but their - targets are global or weak symbols. Relocations in the - object file will be against the target symbol, so it's - that symbol's binding that matters here. */ - if (DECL_P (decl) - && (TREE_PUBLIC (decl) || DECL_WEAK (decl)) - && !(TARGET_ABSOLUTE_ABICALLS && targetm.binds_local_p (decl))) - return SYMBOL_GOT_GLOBAL; - } + /* Don't use GOT accesses for locally-binding symbols; we can use + %hi and %lo instead. */ + if (TARGET_ABSOLUTE_ABICALLS && mips_symbol_binds_local_p (x)) + return SYMBOL_GENERAL; + + /* There are three cases to consider: + + - o32 PIC (either with or without explicit relocs) + - n32/n64 PIC without explicit relocs + - n32/n64 PIC with explicit relocs + + In the first case, both local and global accesses will use an + R_MIPS_GOT16 relocation. We must correctly predict which of + the two semantics (local or global) the assembler and linker + will apply. The choice depends on the symbol's binding rather + than its visibility. - if (!TARGET_ABSOLUTE_ABICALLS) - return SYMBOL_GOT_LOCAL; + In the second case, the assembler will not use R_MIPS_GOT16 + relocations, but it chooses between local and global accesses + in the same way as for o32 PIC. + + In the third case we have more freedom since both forms of + access will work for any kind of symbol. However, there seems + little point in doing things differently. */ + if (mips_global_symbol_p (x)) + return SYMBOL_GOT_DISP; + + return SYMBOL_GOT_PAGE_OFST; } return SYMBOL_GENERAL; @@ -1355,14 +1366,17 @@ mips_symbolic_constant_p (rtx x, enum mips_symbol_type *symbol_type) PC- or GP-relative offset is within the 16-bit limit. */ return offset_within_block_p (x, INTVAL (offset)); - case SYMBOL_GOT_LOCAL: + case SYMBOL_GOT_PAGE_OFST: case SYMBOL_GOTOFF_PAGE: - /* The linker should provide enough local GOT entries for a - 16-bit offset. Larger offsets may lead to GOT overflow. */ + /* If the symbol is global, the GOT entry will contain the symbol's + address, and we will apply a 16-bit offset after loading it. + If the symbol is local, the linker should provide enough local + GOT entries for a 16-bit offset, but larger offsets may lead + to GOT overflow. */ return SMALL_INT (offset); - case SYMBOL_GOT_GLOBAL: - case SYMBOL_GOTOFF_GLOBAL: + case SYMBOL_GOT_DISP: + case SYMBOL_GOTOFF_DISP: case SYMBOL_GOTOFF_CALL: case SYMBOL_GOTOFF_LOADGP: case SYMBOL_TLSGD: @@ -1450,15 +1464,15 @@ mips_symbolic_address_p (enum mips_symbol_type symbol_type, /* PC-relative addressing is only available for lw and ld. */ return GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8; - case SYMBOL_GOT_LOCAL: + case SYMBOL_GOT_PAGE_OFST: return true; - case SYMBOL_GOT_GLOBAL: + case SYMBOL_GOT_DISP: /* The address will have to be loaded from the GOT first. */ return false; case SYMBOL_GOTOFF_PAGE: - case SYMBOL_GOTOFF_GLOBAL: + case SYMBOL_GOTOFF_DISP: case SYMBOL_GOTOFF_CALL: case SYMBOL_GOTOFF_LOADGP: case SYMBOL_TLS: @@ -1623,8 +1637,8 @@ mips_symbol_insns (enum mips_symbol_type type) extended instruction. */ return 2; - case SYMBOL_GOT_LOCAL: - case SYMBOL_GOT_GLOBAL: + case SYMBOL_GOT_PAGE_OFST: + case SYMBOL_GOT_DISP: /* Unless -funit-at-a-time is in effect, we can't be sure whether the local/global classification is accurate. See override_options for details. @@ -1648,7 +1662,7 @@ mips_symbol_insns (enum mips_symbol_type type) return 3; case SYMBOL_GOTOFF_PAGE: - case SYMBOL_GOTOFF_GLOBAL: + case SYMBOL_GOTOFF_DISP: case SYMBOL_GOTOFF_CALL: case SYMBOL_GOTOFF_LOADGP: case SYMBOL_64_HIGH: @@ -3346,6 +3360,18 @@ mips_gen_conditional_trap (rtx *operands) operands[1])); } +/* Return true if calls to X can use R_MIPS_CALL* relocations. */ + +static bool +mips_ok_for_lazy_binding_p (rtx x) +{ + return (TARGET_USE_GOT + && GET_CODE (x) == SYMBOL_REF + && (TARGET_ABSOLUTE_ABICALLS + ? !mips_symbol_binds_local_p (x) + : mips_global_symbol_p (x))); +} + /* Load function address ADDR into register DEST. SIBCALL_P is true if the address is needed for a sibling call. */ @@ -3358,7 +3384,7 @@ mips_load_call_address (rtx dest, rtx addr, int sibcall_p) to the stub would be our caller's gp, not ours. */ if (TARGET_EXPLICIT_RELOCS && !(sibcall_p && TARGET_CALL_SAVED_GP) - && global_got_operand (addr, VOIDmode)) + && mips_ok_for_lazy_binding_p (addr)) { rtx high, lo_sum_symbol; @@ -3423,7 +3449,7 @@ mips_expand_call (rtx result, rtx addr, rtx args_size, rtx aux, int sibcall_p) insn = emit_call_insn (pattern); /* Lazy-binding stubs require $gp to be valid on entry. */ - if (global_got_operand (orig_addr, VOIDmode)) + if (mips_ok_for_lazy_binding_p (orig_addr)) use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx); } @@ -5115,26 +5141,26 @@ override_options (void) then lowered by mips_rewrite_small_data. */ mips_lo_relocs[SYMBOL_SMALL_DATA] = "%gp_rel("; - mips_split_p[SYMBOL_GOT_LOCAL] = true; + mips_split_p[SYMBOL_GOT_PAGE_OFST] = true; if (TARGET_NEWABI) { mips_lo_relocs[SYMBOL_GOTOFF_PAGE] = "%got_page("; - mips_lo_relocs[SYMBOL_GOT_LOCAL] = "%got_ofst("; + mips_lo_relocs[SYMBOL_GOT_PAGE_OFST] = "%got_ofst("; } else { mips_lo_relocs[SYMBOL_GOTOFF_PAGE] = "%got("; - mips_lo_relocs[SYMBOL_GOT_LOCAL] = "%lo("; + mips_lo_relocs[SYMBOL_GOT_PAGE_OFST] = "%lo("; } if (TARGET_XGOT) { /* The HIGH and LO_SUM are matched by special .md patterns. */ - mips_split_p[SYMBOL_GOT_GLOBAL] = true; + mips_split_p[SYMBOL_GOT_DISP] = true; - mips_split_p[SYMBOL_GOTOFF_GLOBAL] = true; - mips_hi_relocs[SYMBOL_GOTOFF_GLOBAL] = "%got_hi("; - mips_lo_relocs[SYMBOL_GOTOFF_GLOBAL] = "%got_lo("; + mips_split_p[SYMBOL_GOTOFF_DISP] = true; + mips_hi_relocs[SYMBOL_GOTOFF_DISP] = "%got_hi("; + mips_lo_relocs[SYMBOL_GOTOFF_DISP] = "%got_lo("; mips_split_p[SYMBOL_GOTOFF_CALL] = true; mips_hi_relocs[SYMBOL_GOTOFF_CALL] = "%call_hi("; @@ -5143,9 +5169,9 @@ override_options (void) else { if (TARGET_NEWABI) - mips_lo_relocs[SYMBOL_GOTOFF_GLOBAL] = "%got_disp("; + mips_lo_relocs[SYMBOL_GOTOFF_DISP] = "%got_disp("; else - mips_lo_relocs[SYMBOL_GOTOFF_GLOBAL] = "%got("; + mips_lo_relocs[SYMBOL_GOTOFF_DISP] = "%got("; mips_lo_relocs[SYMBOL_GOTOFF_CALL] = "%call16("; } } @@ -7604,13 +7630,7 @@ mips_cannot_change_mode_class (enum machine_mode from, bool mips_dangerous_for_la25_p (rtx x) { - rtx offset; - - if (TARGET_EXPLICIT_RELOCS) - return false; - - split_const (x, &x, &offset); - return global_got_operand (x, VOIDmode); + return !TARGET_EXPLICIT_RELOCS && mips_ok_for_lazy_binding_p (x); } /* Implement PREFERRED_RELOAD_CLASS. */ diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 7aa3dae..832b93b 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -3156,18 +3156,18 @@ } [(set_attr "length" "24")]) -;; Insns to fetch a global symbol from a big GOT. +;; Insns to fetch a symbol from a big GOT. (define_insn_and_split "*xgot_hi" [(set (match_operand:P 0 "register_operand" "=d") - (high:P (match_operand:P 1 "global_got_operand" "")))] + (high:P (match_operand:P 1 "got_disp_operand" "")))] "TARGET_EXPLICIT_RELOCS && TARGET_XGOT" "#" "&& reload_completed" [(set (match_dup 0) (high:P (match_dup 2))) (set (match_dup 0) (plus:P (match_dup 0) (match_dup 3)))] { - operands[2] = mips_unspec_address (operands[1], SYMBOL_GOTOFF_GLOBAL); + operands[2] = mips_unspec_address (operands[1], SYMBOL_GOTOFF_DISP); operands[3] = pic_offset_table_rtx; } [(set_attr "got" "xgot_high") @@ -3176,21 +3176,21 @@ (define_insn_and_split "*xgot_lo" [(set (match_operand:P 0 "register_operand" "=d") (lo_sum:P (match_operand:P 1 "register_operand" "d") - (match_operand:P 2 "global_got_operand" "")))] + (match_operand:P 2 "got_disp_operand" "")))] "TARGET_EXPLICIT_RELOCS && TARGET_XGOT" "#" "&& reload_completed" [(set (match_dup 0) (unspec:P [(match_dup 1) (match_dup 3)] UNSPEC_LOAD_GOT))] - { operands[3] = mips_unspec_address (operands[2], SYMBOL_GOTOFF_GLOBAL); } + { operands[3] = mips_unspec_address (operands[2], SYMBOL_GOTOFF_DISP); } [(set_attr "got" "load") (set_attr "mode" "")]) -;; Insns to fetch a global symbol from a normal GOT. +;; Insns to fetch a symbol from a normal GOT. (define_insn_and_split "*got_disp" [(set (match_operand:P 0 "register_operand" "=d") - (match_operand:P 1 "global_got_operand" ""))] + (match_operand:P 1 "got_disp_operand" ""))] "TARGET_EXPLICIT_RELOCS && !TARGET_XGOT" "#" "&& reload_completed" @@ -3198,16 +3198,16 @@ (unspec:P [(match_dup 2) (match_dup 3)] UNSPEC_LOAD_GOT))] { operands[2] = pic_offset_table_rtx; - operands[3] = mips_unspec_address (operands[1], SYMBOL_GOTOFF_GLOBAL); + operands[3] = mips_unspec_address (operands[1], SYMBOL_GOTOFF_DISP); } [(set_attr "got" "load") (set_attr "mode" "")]) -;; Insns for loading the high part of a local symbol. +;; Insns for loading the "page" part of a page/ofst address from the GOT. (define_insn_and_split "*got_page" [(set (match_operand:P 0 "register_operand" "=d") - (high:P (match_operand:P 1 "local_got_operand" "")))] + (high:P (match_operand:P 1 "got_page_ofst_operand" "")))] "TARGET_EXPLICIT_RELOCS" "#" "&& reload_completed" diff --git a/gcc/config/mips/predicates.md b/gcc/config/mips/predicates.md index 9a6756c..9f6cc95 100644 --- a/gcc/config/mips/predicates.md +++ b/gcc/config/mips/predicates.md @@ -118,7 +118,7 @@ addressing. */ return !TARGET_LONG_CALLS && !SYMBOL_REF_LONG_CALL_P (op); - case SYMBOL_GOT_GLOBAL: + case SYMBOL_GOT_DISP: /* Without explicit relocs, there is no special syntax for loading the address of a call destination into a register. Using "la $25,foo; jal $25" would prevent the lazy binding @@ -237,18 +237,18 @@ return mips_symbolic_constant_p (op, &type) && type == SYMBOL_GENERAL; }) -(define_predicate "global_got_operand" +(define_predicate "got_disp_operand" (match_code "const,symbol_ref,label_ref") { enum mips_symbol_type type; - return mips_symbolic_constant_p (op, &type) && type == SYMBOL_GOT_GLOBAL; + return mips_symbolic_constant_p (op, &type) && type == SYMBOL_GOT_DISP; }) -(define_predicate "local_got_operand" +(define_predicate "got_page_ofst_operand" (match_code "const,symbol_ref,label_ref") { enum mips_symbol_type type; - return mips_symbolic_constant_p (op, &type) && type == SYMBOL_GOT_LOCAL; + return mips_symbolic_constant_p (op, &type) && type == SYMBOL_GOT_PAGE_OFST; }) (define_predicate "stack_operand" -- 2.7.4