Commit 390ea488 by Richard Sandiford Committed by Richard Sandiford

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
parent fbb96ac5
2007-08-08 Richard Sandiford <richard@codesourcery.com> 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. * config/mips/mips.c (mips_symbolic_address_p): Delete.
(mips_symbol_insns_1): New function, split out from... (mips_symbol_insns_1): New function, split out from...
(mips_symbol_insns): ...here. Take a mode argument. Treat loads (mips_symbol_insns): ...here. Take a mode argument. Treat loads
......
...@@ -171,7 +171,7 @@ extern int mips_idiv_insns (void); ...@@ -171,7 +171,7 @@ extern int mips_idiv_insns (void);
extern int fp_register_operand (rtx, enum machine_mode); extern int fp_register_operand (rtx, enum machine_mode);
extern int lo_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 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 rtx mips_unspec_address (rtx, enum mips_symbol_type);
extern bool mips_legitimize_address (rtx *, enum machine_mode); extern bool mips_legitimize_address (rtx *, enum machine_mode);
extern void mips_move_integer (rtx, rtx, unsigned HOST_WIDE_INT); extern void mips_move_integer (rtx, rtx, unsigned HOST_WIDE_INT);
......
...@@ -2113,24 +2113,50 @@ mips_force_temporary (rtx dest, rtx value) ...@@ -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 /* If MODE is MAX_MACHINE_MODE, ADDR appears as a move operand, otherwise
and is used to load the high part into a register. */ 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 TEMP is as for mips_force_temporary and is used to load the high
mips_split_symbol (rtx temp, rtx addr) 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; rtx high;
if (!TARGET_MIPS16) context = (mode == MAX_MACHINE_MODE
high = mips_force_temporary (temp, gen_rtx_HIGH (Pmode, copy_rtx (addr))); ? SYMBOL_CONTEXT_LEA
else if (!can_create_pseudo_p ()) : 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))); if (symbol_type == SYMBOL_GP_RELATIVE)
high = temp; {
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 return true;
high = mips16_gp_pseudo_reg ();
return gen_rtx_LO_SUM (Pmode, high, addr);
} }
...@@ -2321,8 +2347,6 @@ mips_legitimize_tls_address (rtx loc) ...@@ -2321,8 +2347,6 @@ mips_legitimize_tls_address (rtx loc)
bool bool
mips_legitimize_address (rtx *xloc, enum machine_mode mode) mips_legitimize_address (rtx *xloc, enum machine_mode mode)
{ {
enum mips_symbol_type symbol_type;
if (mips_tls_operand_p (*xloc)) if (mips_tls_operand_p (*xloc))
{ {
*xloc = mips_legitimize_tls_address (*xloc); *xloc = mips_legitimize_tls_address (*xloc);
...@@ -2330,13 +2354,8 @@ mips_legitimize_address (rtx *xloc, enum machine_mode mode) ...@@ -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. */ /* 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) if (mips_split_symbol (NULL, *xloc, mode, xloc))
&& mips_symbol_insns (symbol_type, mode) > 0 return true;
&& mips_split_p[symbol_type])
{
*xloc = mips_split_symbol (0, *xloc);
return true;
}
if (GET_CODE (*xloc) == PLUS && GET_CODE (XEXP (*xloc, 1)) == CONST_INT) 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) ...@@ -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. */ /* 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; return;
} }
...@@ -2534,8 +2553,7 @@ mips_legitimize_const_move (enum machine_mode mode, rtx dest, rtx src) ...@@ -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 /* When using explicit relocs, constant pool references are sometimes
not legitimate addresses. */ not legitimate addresses. */
if (!memory_operand (src, VOIDmode)) mips_split_symbol (dest, XEXP (src, 0), mode, &XEXP (src, 0));
src = replace_equiv_address (src, mips_split_symbol (dest, XEXP (src, 0)));
emit_move_insn (dest, src); emit_move_insn (dest, src);
} }
......
...@@ -3299,11 +3299,14 @@ ...@@ -3299,11 +3299,14 @@
;; Likewise, for symbolic operands. ;; Likewise, for symbolic operands.
(define_split (define_split
[(set (match_operand:P 0 "register_operand") [(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"))] (clobber (match_operand:P 2 "register_operand"))]
"" "mips_split_symbol (operands[2], operands[1], MAX_MACHINE_MODE, NULL)"
[(set (match_dup 0) (match_dup 1))] [(set (match_dup 0) (match_dup 3))]
{ operands[1] = mips_split_symbol (operands[2], operands[1]); }) {
mips_split_symbol (operands[2], operands[1],
MAX_MACHINE_MODE, &operands[3]);
})
;; 64-bit integer moves ;; 64-bit integer moves
......
...@@ -154,16 +154,6 @@ ...@@ -154,16 +154,6 @@
return !LUI_INT (op) && !SMALL_INT (op) && !SMALL_INT_UNSIGNED (op); 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" (define_predicate "move_operand"
(match_operand 0 "general_operand") (match_operand 0 "general_operand")
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment