mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-22 15:11:15 +08:00
mips.c (mips_expand_call): Use FAKE_CALL_REGNO.
gcc/ * config/mips/mips.c (mips_expand_call): Use FAKE_CALL_REGNO. (mips_avoid_hazard): Allow multiple sets for HAZARD_DELAY, and pick the first. * config/mips/mips.md (load_call<mode>): Don't make the unspec depend on FAKE_CALL_REGNO. Set FAKE_CALL_REGNO. From-SVN: r129449
This commit is contained in:
parent
e34537aa38
commit
e8b7a1372c
@ -1,3 +1,11 @@
|
||||
2007-10-18 Richard Sandiford <rsandifo@nildram.co.uk>
|
||||
|
||||
* config/mips/mips.c (mips_expand_call): Use FAKE_CALL_REGNO.
|
||||
(mips_avoid_hazard): Allow multiple sets for HAZARD_DELAY,
|
||||
and pick the first.
|
||||
* config/mips/mips.md (load_call<mode>): Don't make the unspec
|
||||
depend on FAKE_CALL_REGNO. Set FAKE_CALL_REGNO.
|
||||
|
||||
2007-10-18 David Daney <ddaney@avtrex.com>
|
||||
|
||||
* config/mips/linux-unwind.h (mips_fallback_frame_state): Use new
|
||||
|
@ -308,7 +308,7 @@ static int m16_check_op (rtx, int, int, int);
|
||||
static bool mips_rtx_costs (rtx, int, int, int *);
|
||||
static int mips_address_cost (rtx);
|
||||
static void mips_emit_compare (enum rtx_code *, rtx *, rtx *, bool);
|
||||
static void mips_load_call_address (rtx, rtx, int);
|
||||
static bool mips_load_call_address (rtx, rtx, int);
|
||||
static bool mips_function_ok_for_sibcall (tree, tree);
|
||||
static void mips_block_move_straight (rtx, rtx, HOST_WIDE_INT);
|
||||
static void mips_adjust_block_mem (rtx, HOST_WIDE_INT, rtx *, rtx *);
|
||||
@ -4135,9 +4135,10 @@ mips_ok_for_lazy_binding_p (rtx x)
|
||||
}
|
||||
|
||||
/* Load function address ADDR into register DEST. SIBCALL_P is true
|
||||
if the address is needed for a sibling call. */
|
||||
if the address is needed for a sibling call. Return true if we
|
||||
used an explicit lazy-binding sequence. */
|
||||
|
||||
static void
|
||||
static bool
|
||||
mips_load_call_address (rtx dest, rtx addr, int sibcall_p)
|
||||
{
|
||||
/* If we're generating PIC, and this call is to a global function,
|
||||
@ -4157,9 +4158,13 @@ mips_load_call_address (rtx dest, rtx addr, int sibcall_p)
|
||||
emit_insn (gen_load_callsi (dest, high, lo_sum_symbol));
|
||||
else
|
||||
emit_insn (gen_load_calldi (dest, high, lo_sum_symbol));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
mips_emit_move (dest, addr);
|
||||
{
|
||||
mips_emit_move (dest, addr);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -4174,12 +4179,14 @@ void
|
||||
mips_expand_call (rtx result, rtx addr, rtx args_size, rtx aux, int sibcall_p)
|
||||
{
|
||||
rtx orig_addr, pattern, insn;
|
||||
bool lazy_p;
|
||||
|
||||
orig_addr = addr;
|
||||
lazy_p = false;
|
||||
if (!call_insn_operand (addr, VOIDmode))
|
||||
{
|
||||
addr = gen_reg_rtx (Pmode);
|
||||
mips_load_call_address (addr, orig_addr, sibcall_p);
|
||||
lazy_p = mips_load_call_address (addr, orig_addr, sibcall_p);
|
||||
}
|
||||
|
||||
if (TARGET_MIPS16
|
||||
@ -4210,9 +4217,15 @@ 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 (mips_ok_for_lazy_binding_p (orig_addr))
|
||||
use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
|
||||
/* Lazy-binding stubs require $gp to be valid on entry. We also pretend
|
||||
that they use FAKE_CALL_REGNO; see the load_call<mode> patterns for
|
||||
details. */
|
||||
if (lazy_p)
|
||||
{
|
||||
use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
|
||||
use_reg (&CALL_INSN_FUNCTION_USAGE (insn),
|
||||
gen_rtx_REG (Pmode, FAKE_CALL_REGNO));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -10748,7 +10761,7 @@ mips_avoid_hazard (rtx after, rtx insn, int *hilo_delay,
|
||||
rtx *delayed_reg, rtx lo_reg)
|
||||
{
|
||||
rtx pattern, set;
|
||||
int nops, ninsns;
|
||||
int nops, ninsns, hazard_set;
|
||||
|
||||
if (!INSN_P (insn))
|
||||
return;
|
||||
@ -10797,8 +10810,15 @@ mips_avoid_hazard (rtx after, rtx insn, int *hilo_delay,
|
||||
break;
|
||||
|
||||
case HAZARD_DELAY:
|
||||
set = single_set (insn);
|
||||
gcc_assert (set != 0);
|
||||
hazard_set = (int) get_attr_hazard_set (insn);
|
||||
if (hazard_set == 0)
|
||||
set = single_set (insn);
|
||||
else
|
||||
{
|
||||
gcc_assert (GET_CODE (PATTERN (insn)) == PARALLEL);
|
||||
set = XVECEXP (PATTERN (insn), 0, hazard_set - 1);
|
||||
}
|
||||
gcc_assert (set && GET_CODE (set) == SET);
|
||||
*delayed_reg = SET_DEST (set);
|
||||
break;
|
||||
}
|
||||
|
@ -438,6 +438,17 @@
|
||||
(const_string "hilo")]
|
||||
(const_string "none")))
|
||||
|
||||
;; Indicates which SET in an instruction pattern induces a hazard.
|
||||
;; Only meaningful when "hazard" is not "none". SINGLE means that
|
||||
;; the pattern has only one set while the other values are indexes
|
||||
;; into a PARALLEL vector.
|
||||
;;
|
||||
;; Hazardous instructions with multiple sets should generally put the
|
||||
;; hazardous set first. The only purpose of this attribute is to force
|
||||
;; each multi-set pattern to explicitly assert that this condition holds.
|
||||
(define_attr "hazard_set" "single,0"
|
||||
(const_string "single"))
|
||||
|
||||
;; Is it a single instruction?
|
||||
(define_attr "single_insn" "no,yes"
|
||||
(symbol_ref "get_attr_length (insn) == (TARGET_MIPS16 ? 2 : 4)"))
|
||||
@ -5606,19 +5617,21 @@
|
||||
;; we must not call it again.
|
||||
;;
|
||||
;; We represent this restriction using an imaginary fixed register that
|
||||
;; acts like a GOT version number. By making the register call-clobbered,
|
||||
;; we tell the target-independent code that the address could be changed
|
||||
;; by any call insn.
|
||||
;; is set by the GOT load and used by the call. By making this register
|
||||
;; call-clobbered, and by making the GOT load the only way of setting
|
||||
;; the register, we ensure that the load cannot be moved past a call.
|
||||
(define_insn "load_call<mode>"
|
||||
[(set (match_operand:P 0 "register_operand" "=d")
|
||||
(unspec:P [(match_operand:P 1 "register_operand" "r")
|
||||
(match_operand:P 2 "immediate_operand" "")
|
||||
(reg:P FAKE_CALL_REGNO)]
|
||||
UNSPEC_LOAD_CALL))]
|
||||
(match_operand:P 2 "immediate_operand" "")]
|
||||
UNSPEC_LOAD_CALL))
|
||||
(set (reg:P FAKE_CALL_REGNO)
|
||||
(unspec:P [(match_dup 2)] UNSPEC_LOAD_CALL))]
|
||||
"TARGET_USE_GOT"
|
||||
"<load>\t%0,%R2(%1)"
|
||||
[(set_attr "type" "load")
|
||||
(set_attr "mode" "<MODE>")
|
||||
(set_attr "hazard_set" "0")
|
||||
(set_attr "length" "4")])
|
||||
|
||||
;; Sibling calls. All these patterns use jump instructions.
|
||||
|
Loading…
x
Reference in New Issue
Block a user