Commit 730a27a2 by John David Anglin

pa.c (hppa_profile_hook): Allocate stack space for register parameters.

	* config/pa/pa.c (hppa_profile_hook): Allocate stack space for
	register parameters.  Remove code to initialize argument pointer
	on TARGET_64BIT.  Optimize call to _mcount when it can be reached
	using a pc-relative branch.  Cleanup conditional code.
	* config/pa/pa.md (call_mcount): New expander.
	(call_mcount_nonpic): New insn.
	(call_mcount_pic): New insn and split.
	(call_mcount_pic_post_reload): New insn.
	(call_mcount_64bit): New insn and split.
	(call_mcount_64bit_post_reload): New insn.

From-SVN: r238414
parent a9356b12
2016-07-16 John David Anglin <danglin@gcc.gnu.org>
* config/pa/pa.c (hppa_profile_hook): Allocate stack space for
register parameters. Remove code to initialize argument pointer
on TARGET_64BIT. Optimize call to _mcount when it can be reached
using a pc-relative branch. Cleanup conditional code.
* config/pa/pa.md (call_mcount): New expander.
(call_mcount_nonpic): New insn.
(call_mcount_pic): New insn and split.
(call_mcount_pic_post_reload): New insn.
(call_mcount_64bit): New insn and split.
(call_mcount_64bit_post_reload): New insn.
2016-07-15 Georg-Johann Lay <avr@gjlay.de>
* config/avr/predicates.md (const_m255_to_m1_operand): New.
......
......@@ -4532,63 +4532,78 @@ hppa_profile_hook (int label_no)
lcla2 and load_offset_label_address insn patterns. */
rtx reg = gen_reg_rtx (SImode);
rtx_code_label *label_rtx = gen_label_rtx ();
rtx begin_label_rtx;
rtx mcount = gen_rtx_MEM (Pmode, gen_rtx_SYMBOL_REF (Pmode, "_mcount"));
int reg_parm_stack_space = REG_PARM_STACK_SPACE (NULL_TREE);
rtx arg_bytes, begin_label_rtx;
rtx_insn *call_insn;
char begin_label_name[16];
bool use_mcount_pcrel_call;
/* If we can reach _mcount with a pc-relative call, we can optimize
loading the address of the current function. This requires linker
long branch stub support. */
if (!TARGET_PORTABLE_RUNTIME
&& !TARGET_LONG_CALLS
&& (TARGET_SOM || flag_function_sections))
use_mcount_pcrel_call = TRUE;
else
use_mcount_pcrel_call = FALSE;
ASM_GENERATE_INTERNAL_LABEL (begin_label_name, FUNC_BEGIN_PROLOG_LABEL,
label_no);
begin_label_rtx = gen_rtx_SYMBOL_REF (SImode, ggc_strdup (begin_label_name));
if (TARGET_64BIT)
emit_move_insn (arg_pointer_rtx,
gen_rtx_PLUS (word_mode, virtual_outgoing_args_rtx,
GEN_INT (64)));
emit_move_insn (gen_rtx_REG (word_mode, 26), gen_rtx_REG (word_mode, 2));
/* The address of the function is loaded into %r25 with an instruction-
relative sequence that avoids the use of relocations. The sequence
is split so that the load_offset_label_address instruction can
occupy the delay slot of the call to _mcount. */
if (TARGET_PA_20)
emit_insn (gen_lcla2 (reg, label_rtx));
else
emit_insn (gen_lcla1 (reg, label_rtx));
emit_insn (gen_load_offset_label_address (gen_rtx_REG (SImode, 25),
reg, begin_label_rtx, label_rtx));
#if !NO_DEFERRED_PROFILE_COUNTERS
{
rtx count_label_rtx, addr, r24;
char count_label_name[16];
if (!use_mcount_pcrel_call)
{
/* The address of the function is loaded into %r25 with an instruction-
relative sequence that avoids the use of relocations. The sequence
is split so that the load_offset_label_address instruction can
occupy the delay slot of the call to _mcount. */
if (TARGET_PA_20)
emit_insn (gen_lcla2 (reg, label_rtx));
else
emit_insn (gen_lcla1 (reg, label_rtx));
funcdef_nos.safe_push (label_no);
ASM_GENERATE_INTERNAL_LABEL (count_label_name, "LP", label_no);
count_label_rtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (count_label_name));
emit_insn (gen_load_offset_label_address (gen_rtx_REG (SImode, 25),
reg,
begin_label_rtx,
label_rtx));
}
addr = force_reg (Pmode, count_label_rtx);
r24 = gen_rtx_REG (Pmode, 24);
emit_move_insn (r24, addr);
if (!NO_DEFERRED_PROFILE_COUNTERS)
{
rtx count_label_rtx, addr, r24;
char count_label_name[16];
call_insn =
emit_call_insn (gen_call (gen_rtx_MEM (Pmode,
gen_rtx_SYMBOL_REF (Pmode,
"_mcount")),
GEN_INT (TARGET_64BIT ? 24 : 12)));
funcdef_nos.safe_push (label_no);
ASM_GENERATE_INTERNAL_LABEL (count_label_name, "LP", label_no);
count_label_rtx = gen_rtx_SYMBOL_REF (Pmode,
ggc_strdup (count_label_name));
use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), r24);
}
#else
addr = force_reg (Pmode, count_label_rtx);
r24 = gen_rtx_REG (Pmode, 24);
emit_move_insn (r24, addr);
call_insn =
emit_call_insn (gen_call (gen_rtx_MEM (Pmode,
gen_rtx_SYMBOL_REF (Pmode,
"_mcount")),
GEN_INT (TARGET_64BIT ? 16 : 8)));
arg_bytes = GEN_INT (TARGET_64BIT ? 24 : 12);
if (use_mcount_pcrel_call)
call_insn = emit_call_insn (gen_call_mcount (mcount, arg_bytes,
begin_label_rtx));
else
call_insn = emit_call_insn (gen_call (mcount, arg_bytes));
#endif
use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), r24);
}
else
{
arg_bytes = GEN_INT (TARGET_64BIT ? 16 : 8);
if (use_mcount_pcrel_call)
call_insn = emit_call_insn (gen_call_mcount (mcount, arg_bytes,
begin_label_rtx));
else
call_insn = emit_call_insn (gen_call (mcount, arg_bytes));
}
use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), gen_rtx_REG (SImode, 25));
use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), gen_rtx_REG (SImode, 26));
......@@ -4596,6 +4611,10 @@ hppa_profile_hook (int label_no)
/* Indicate the _mcount call cannot throw, nor will it execute a
non-local goto. */
make_reg_eh_region_note_nothrow_nononlocal (call_insn);
/* Allocate space for fixed arguments. */
if (reg_parm_stack_space > crtl->outgoing_args_size)
crtl->outgoing_args_size = reg_parm_stack_space;
}
/* Fetch the return address for the frame COUNT steps up from
......
......@@ -8207,6 +8207,170 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
(cond [(and (const_int 0) (eq (const_int 0) (pc))) (const_int 12)]
(symbol_ref "pa_attr_length_indirect_call (insn)")))])
/* Expand special pc-relative call to _mcount. */
(define_expand "call_mcount"
[(parallel [(call (match_operand:SI 0 "" "")
(match_operand 1 "" ""))
(set (reg:SI 25)
(plus:SI (reg:SI 2)
(minus:SI (match_operand 2 "" "")
(plus:SI (pc) (const_int 4)))))
(clobber (reg:SI 2))])]
"!TARGET_PORTABLE_RUNTIME"
"
{
rtx op = XEXP (operands[0], 0);
rtx nb = operands[1];
rtx lab = operands[2];
if (TARGET_64BIT)
{
rtx r4 = gen_rtx_REG (word_mode, 4);
emit_move_insn (arg_pointer_rtx,
gen_rtx_PLUS (word_mode, virtual_outgoing_args_rtx,
GEN_INT (64)));
emit_call_insn (gen_call_mcount_64bit (op, nb, lab, r4));
}
else
{
if (flag_pic)
{
rtx r4 = gen_rtx_REG (word_mode, 4);
emit_call_insn (gen_call_mcount_pic (op, nb, lab, r4));
}
else
emit_call_insn (gen_call_mcount_nonpic (op, nb, lab));
}
DONE;
}")
(define_insn "call_mcount_nonpic"
[(call (mem:SI (match_operand 0 "call_operand_address" ""))
(match_operand 1 "" "i"))
(set (reg:SI 25)
(plus:SI (reg:SI 2)
(minus:SI (match_operand 2 "" "")
(plus:SI (pc) (const_int 4)))))
(clobber (reg:SI 2))]
"!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
"*
{
pa_output_arg_descriptor (insn);
return \"{bl|b,l} %0,%%r2\;ldo %2-.-4(%%r2),%%r25\";
}"
[(set_attr "type" "multi")
(set_attr "length" "8")])
(define_insn "call_mcount_pic"
[(call (mem:SI (match_operand 0 "call_operand_address" ""))
(match_operand 1 "" "i"))
(set (reg:SI 25)
(plus:SI (reg:SI 2)
(minus:SI (match_operand 2 "" "")
(plus:SI (pc) (const_int 4)))))
(clobber (reg:SI 2))
(clobber (match_operand 3))
(use (reg:SI 19))]
"!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
"#")
(define_split
[(parallel [(call (mem:SI (match_operand 0 "call_operand_address" ""))
(match_operand 1 "" ""))
(set (reg:SI 25)
(plus:SI (reg:SI 2)
(minus:SI (match_operand 2 "" "")
(plus:SI (pc) (const_int 4)))))
(clobber (reg:SI 2))
(clobber (match_operand 3))
(use (reg:SI 19))])]
"!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT && reload_completed"
[(set (match_dup 3) (reg:SI 19))
(parallel [(call (mem:SI (match_dup 0))
(match_dup 1))
(set (reg:SI 25)
(plus:SI (reg:SI 2)
(minus:SI (match_dup 2)
(plus:SI (pc) (const_int 4)))))
(clobber (reg:SI 2))
(use (reg:SI 19))])
(set (reg:SI 19) (match_dup 3))]
"")
(define_insn "*call_mcount_pic_post_reload"
[(call (mem:SI (match_operand 0 "call_operand_address" ""))
(match_operand 1 "" "i"))
(set (reg:SI 25)
(plus:SI (reg:SI 2)
(minus:SI (match_operand 2 "" "")
(plus:SI (pc) (const_int 4)))))
(clobber (reg:SI 2))
(use (reg:SI 19))]
"!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
"*
{
pa_output_arg_descriptor (insn);
return \"{bl|b,l} %0,%%r2\;ldo %2-.-4(%%r2),%%r25\";
}"
[(set_attr "type" "multi")
(set_attr "length" "8")])
(define_insn "call_mcount_64bit"
[(call (mem:SI (match_operand 0 "call_operand_address" ""))
(match_operand 1 "" "i"))
(set (reg:SI 25)
(plus:SI (reg:SI 2)
(minus:SI (match_operand 2 "" "")
(plus:SI (pc) (const_int 4)))))
(clobber (reg:DI 2))
(clobber (match_operand 3))
(use (reg:DI 27))
(use (reg:DI 29))]
"TARGET_64BIT"
"#")
(define_split
[(parallel [(call (mem:SI (match_operand 0 "call_operand_address" ""))
(match_operand 1 "" ""))
(set (reg:SI 25)
(plus:SI (reg:SI 2)
(minus:SI (match_operand 2 "" "")
(plus:SI (pc) (const_int 4)))))
(clobber (reg:DI 2))
(clobber (match_operand 3))
(use (reg:DI 27))
(use (reg:DI 29))])]
"TARGET_64BIT && reload_completed"
[(set (match_dup 3) (reg:DI 27))
(parallel [(call (mem:SI (match_dup 0))
(match_dup 1))
(set (reg:SI 25)
(plus:SI (reg:SI 2)
(minus:SI (match_dup 2)
(plus:SI (pc) (const_int 4)))))
(clobber (reg:DI 2))
(use (reg:DI 27))
(use (reg:DI 29))])
(set (reg:DI 27) (match_dup 3))]
"")
(define_insn "*call_mcount_64bit_post_reload"
[(call (mem:SI (match_operand 0 "call_operand_address" ""))
(match_operand 1 "" "i"))
(set (reg:SI 25)
(plus:SI (reg:SI 2)
(minus:SI (match_operand 2 "" "")
(plus:SI (pc) (const_int 4)))))
(clobber (reg:DI 2))
(use (reg:DI 27))
(use (reg:DI 29))]
"TARGET_64BIT"
"{bl|b,l} %0,%%r2\;ldo %2-.-4(%%r2),%%r25"
[(set_attr "type" "multi")
(set_attr "length" "8")])
;; Call subroutine returning any type.
(define_expand "untyped_call"
......
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