diff options
author | Richard Sandiford <richard@codesourcery.com> | 2007-08-08 15:40:27 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2007-08-08 15:40:27 +0000 |
commit | 390ea488c1753eaf9c747ead8f653c9023058109 (patch) | |
tree | 3316463566d687eaeaa605c042e7ff6cca105e65 | |
parent | fbb96ac51d24dd44fb28ce484d8df3630aff6306 (diff) | |
download | gcc-390ea488c1753eaf9c747ead8f653c9023058109.zip gcc-390ea488c1753eaf9c747ead8f653c9023058109.tar.gz gcc-390ea488c1753eaf9c747ead8f653c9023058109.tar.bz2 |
mips-protos.h (mips_split_symbol): Add a mode and an "rtx *" argument.
gcc/
* config/mips/mips-protos.h (mips_split_symbol): Add a mode and
an "rtx *" argument. Return a bool.
* config/mips/mips.c (mips_split_symbol): Accept arbitrary source
values and return true if they can be split. Take the same kind of
mode argument as mips_symbol_insns. Add a "lo_sum_out" parameter
and store the lo_sum there if nonnull. Use the symbol type to
determine whether a $gp or HIGH is needed.
(mips_legitimize_address): Update call to mips_split_symbol and
simplify accordingly.
(mips_legitimize_const_move): Likewise.
* config/mips/mips.md: In the combine define_split,
check mips_split_symbol instead of splittable_symbolic_operand.
Update use of mips_split_symbol in the generator code.
* config/mips/predicates.md (splittable_symbolic_operand): Delete.
From-SVN: r127298
-rw-r--r-- | gcc/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/config/mips/mips-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/mips/mips.c | 68 | ||||
-rw-r--r-- | gcc/config/mips/mips.md | 11 | ||||
-rw-r--r-- | gcc/config/mips/predicates.md | 10 |
5 files changed, 68 insertions, 40 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a2e4f6a..63d49c3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,22 @@ 2007-08-08 Richard Sandiford <richard@codesourcery.com> + * config/mips/mips-protos.h (mips_split_symbol): Add a mode and + an "rtx *" argument. Return a bool. + * config/mips/mips.c (mips_split_symbol): Accept arbitrary source + values and return true if they can be split. Take the same kind of + mode argument as mips_symbol_insns. Add a "lo_sum_out" parameter + and store the lo_sum there if nonnull. Use the symbol type to + determine whether a $gp or HIGH is needed. + (mips_legitimize_address): Update call to mips_split_symbol and + simplify accordingly. + (mips_legitimize_const_move): Likewise. + * config/mips/mips.md: In the combine define_split, + check mips_split_symbol instead of splittable_symbolic_operand. + Update use of mips_split_symbol in the generator code. + * config/mips/predicates.md (splittable_symbolic_operand): Delete. + +2007-08-08 Richard Sandiford <richard@codesourcery.com> + * config/mips/mips.c (mips_symbolic_address_p): Delete. (mips_symbol_insns_1): New function, split out from... (mips_symbol_insns): ...here. Take a mode argument. Treat loads diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h index 13cbfbf..d2f5017 100644 --- a/gcc/config/mips/mips-protos.h +++ b/gcc/config/mips/mips-protos.h @@ -171,7 +171,7 @@ extern int mips_idiv_insns (void); extern int fp_register_operand (rtx, enum machine_mode); extern int lo_operand (rtx, enum machine_mode); extern bool mips_legitimate_address_p (enum machine_mode, rtx, int); -extern rtx mips_split_symbol (rtx, rtx); +extern bool mips_split_symbol (rtx, rtx, enum machine_mode, rtx *); extern rtx mips_unspec_address (rtx, enum mips_symbol_type); extern bool mips_legitimize_address (rtx *, enum machine_mode); extern void mips_move_integer (rtx, rtx, unsigned HOST_WIDE_INT); diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index b8e013e..2b620fb 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -2113,24 +2113,50 @@ mips_force_temporary (rtx dest, rtx value) } -/* Return a LO_SUM expression for ADDR. TEMP is as for mips_force_temporary - and is used to load the high part into a register. */ +/* If MODE is MAX_MACHINE_MODE, ADDR appears as a move operand, otherwise + it appears in a MEM of that mode. Return true if ADDR is a legitimate + constant in that context and can be split into a high part and a LO_SUM. + If so, and if LO_SUM_OUT is nonnull, emit the high part and return + the LO_SUM in *LO_SUM_OUT. Leave *LO_SUM_OUT unchanged otherwise. -rtx -mips_split_symbol (rtx temp, rtx addr) + TEMP is as for mips_force_temporary and is used to load the high + part into a register. */ + +bool +mips_split_symbol (rtx temp, rtx addr, enum machine_mode mode, rtx *lo_sum_out) { + enum mips_symbol_context context; + enum mips_symbol_type symbol_type; rtx high; - if (!TARGET_MIPS16) - high = mips_force_temporary (temp, gen_rtx_HIGH (Pmode, copy_rtx (addr))); - else if (!can_create_pseudo_p ()) + context = (mode == MAX_MACHINE_MODE + ? SYMBOL_CONTEXT_LEA + : SYMBOL_CONTEXT_MEM); + if (!mips_symbolic_constant_p (addr, context, &symbol_type) + || mips_symbol_insns (symbol_type, mode) == 0 + || !mips_split_p[symbol_type]) + return false; + + if (lo_sum_out) { - emit_insn (gen_load_const_gp (copy_rtx (temp))); - high = temp; + if (symbol_type == SYMBOL_GP_RELATIVE) + { + if (!can_create_pseudo_p ()) + { + emit_insn (gen_load_const_gp (copy_rtx (temp))); + high = temp; + } + else + high = mips16_gp_pseudo_reg (); + } + else + { + high = gen_rtx_HIGH (Pmode, copy_rtx (addr)); + high = mips_force_temporary (temp, high); + } + *lo_sum_out = gen_rtx_LO_SUM (Pmode, high, addr); } - else - high = mips16_gp_pseudo_reg (); - return gen_rtx_LO_SUM (Pmode, high, addr); + return true; } @@ -2321,8 +2347,6 @@ mips_legitimize_tls_address (rtx loc) bool mips_legitimize_address (rtx *xloc, enum machine_mode mode) { - enum mips_symbol_type symbol_type; - if (mips_tls_operand_p (*xloc)) { *xloc = mips_legitimize_tls_address (*xloc); @@ -2330,13 +2354,8 @@ mips_legitimize_address (rtx *xloc, enum machine_mode mode) } /* See if the address can split into a high part and a LO_SUM. */ - if (mips_symbolic_constant_p (*xloc, SYMBOL_CONTEXT_MEM, &symbol_type) - && mips_symbol_insns (symbol_type, mode) > 0 - && mips_split_p[symbol_type]) - { - *xloc = mips_split_symbol (0, *xloc); - return true; - } + if (mips_split_symbol (NULL, *xloc, mode, xloc)) + return true; if (GET_CODE (*xloc) == PLUS && GET_CODE (XEXP (*xloc, 1)) == CONST_INT) { @@ -2505,9 +2524,9 @@ mips_legitimize_const_move (enum machine_mode mode, rtx dest, rtx src) } /* Split moves of symbolic constants into high/low pairs. */ - if (splittable_symbolic_operand (src, mode)) + if (mips_split_symbol (dest, src, MAX_MACHINE_MODE, &src)) { - emit_insn (gen_rtx_SET (VOIDmode, dest, mips_split_symbol (dest, src))); + emit_insn (gen_rtx_SET (VOIDmode, dest, src)); return; } @@ -2534,8 +2553,7 @@ mips_legitimize_const_move (enum machine_mode mode, rtx dest, rtx src) /* When using explicit relocs, constant pool references are sometimes not legitimate addresses. */ - if (!memory_operand (src, VOIDmode)) - src = replace_equiv_address (src, mips_split_symbol (dest, XEXP (src, 0))); + mips_split_symbol (dest, XEXP (src, 0), mode, &XEXP (src, 0)); emit_move_insn (dest, src); } diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index e522f4e..2e3d522 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -3299,11 +3299,14 @@ ;; Likewise, for symbolic operands. (define_split [(set (match_operand:P 0 "register_operand") - (match_operand:P 1 "splittable_symbolic_operand")) + (match_operand:P 1)) (clobber (match_operand:P 2 "register_operand"))] - "" - [(set (match_dup 0) (match_dup 1))] - { operands[1] = mips_split_symbol (operands[2], operands[1]); }) + "mips_split_symbol (operands[2], operands[1], MAX_MACHINE_MODE, NULL)" + [(set (match_dup 0) (match_dup 3))] +{ + mips_split_symbol (operands[2], operands[1], + MAX_MACHINE_MODE, &operands[3]); +}) ;; 64-bit integer moves diff --git a/gcc/config/mips/predicates.md b/gcc/config/mips/predicates.md index 1171291..308dd63 100644 --- a/gcc/config/mips/predicates.md +++ b/gcc/config/mips/predicates.md @@ -154,16 +154,6 @@ return !LUI_INT (op) && !SMALL_INT (op) && !SMALL_INT_UNSIGNED (op); }) -;; A legitimate symbolic operand that takes more than one instruction -;; to load. -(define_predicate "splittable_symbolic_operand" - (match_code "const,symbol_ref,label_ref") -{ - enum mips_symbol_type symbol_type; - return (mips_symbolic_constant_p (op, SYMBOL_CONTEXT_LEA, &symbol_type) - && mips_split_p[symbol_type]); -}) - (define_predicate "move_operand" (match_operand 0 "general_operand") { |