summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog35
-rw-r--r--gcc/config/mips/mips-protos.h26
-rw-r--r--gcc/config/mips/mips.c168
-rw-r--r--gcc/config/mips/mips.md20
-rw-r--r--gcc/config/mips/predicates.md10
5 files changed, 157 insertions, 102 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d28edd58014..fb65fb48a2e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,40 @@
2007-04-12 Richard Sandiford <richard@codesourcery.com>
+ * 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<mode>, *xgot_lo<mode>)
+ (*got_disp<mode>): Use got_disp_operand instead of
+ global_got_operand. Use SYMBOL_GOTOFF_DISP instead of
+ SYMBOL_GOTOFF_GLOBAL.
+ (*got_page<mode>): 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 <richard@codesourcery.com>
+
* 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 a9fa42ee815..91d0150dbd7 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 86155109404..d7dbd2eb651 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 7aa3dae4927..832b93bd05a 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<mode>"
[(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<mode>"
[(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" "<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<mode>"
[(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" "<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<mode>"
[(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 9a6756c20a2..9f6cc955df2 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"