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:
Richard Sandiford 2007-10-18 17:03:59 +00:00 committed by Richard Sandiford
parent e34537aa38
commit e8b7a1372c
3 changed files with 58 additions and 17 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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.