Rewrite hppa profiling support.

* config/pa/pa.c (override_options): Remove PIC profiling warning.
	(hp_profile_labelno): Delete.
	(hp_profile_label_rtx): Delete.
	(hp_profile_label_name): Delete.
	(pa_add_gc_roots): Remove reference to hp_profile_label_rtx.
	(output_function_prologue): Remove profiling code and all tests on
	profile_flag.  Move store of PIC_OFFSET_TABLE_REGNUM now that
	merge_sp_adjust_with_store can work for PIC and profiling.
	(hppa_expand_epilogue): Remove profile_flag test.
	(hppa_can_use_return_insn_p): Likewise.
	(hppa_init_pic_save): Emit before tail_recursion_reentry, and
	cater for PROFILE_HOOK.
	(hppa_profile_hook): New function.
	* config/pa/pa.h (FUNCTION_PROFILER): Now does nothing.
	(PROFILE_HOOK): Define.
	(hppa_profile_hook): Declare.
	(PROFILE_BEFORE_PROLOGUE): Delete.
	(ASM_OUTPUT_REG_PUSH): Delete.
	(ASM_OUTPUT_REG_POP): Delete.
	* config/pa/pa.md (call_profiler): Turn it into a call insn, and
	don't `use' r24.  Accept function name operand, and use this and a
	locally generated label to calculate pc-rel offset to func start.

From-SVN: r41038
This commit is contained in:
Alan Modra 2001-04-03 06:57:31 +00:00 committed by Alan Modra
parent fe01b88e5a
commit 1c7a8112c5
4 changed files with 152 additions and 112 deletions

View File

@ -1,3 +1,28 @@
2001-04-03 Alan Modra <alan@linuxcare.com.au>
* config/pa/pa.c (override_options): Remove PIC profiling warning.
(hp_profile_labelno): Delete.
(hp_profile_label_rtx): Delete.
(hp_profile_label_name): Delete.
(pa_add_gc_roots): Remove reference to hp_profile_label_rtx.
(output_function_prologue): Remove profiling code and all tests on
profile_flag. Move store of PIC_OFFSET_TABLE_REGNUM now that
merge_sp_adjust_with_store can work for PIC and profiling.
(hppa_expand_epilogue): Remove profile_flag test.
(hppa_can_use_return_insn_p): Likewise.
(hppa_init_pic_save): Emit before tail_recursion_reentry, and
cater for PROFILE_HOOK.
(hppa_profile_hook): New function.
* config/pa/pa.h (FUNCTION_PROFILER): Now does nothing.
(PROFILE_HOOK): Define.
(hppa_profile_hook): Declare.
(PROFILE_BEFORE_PROLOGUE): Delete.
(ASM_OUTPUT_REG_PUSH): Delete.
(ASM_OUTPUT_REG_POP): Delete.
* config/pa/pa.md (call_profiler): Turn it into a call insn, and
don't `use' r24. Accept function name operand, and use this and a
locally generated label to calculate pc-rel offset to func start.
2001-04-02 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* $(HOST_PREFIX_1)errors.o, $(HOST_PREFIX_1)ggc-none.o,

View File

@ -76,9 +76,6 @@ enum architecture_type pa_arch;
/* String to hold which architecture we are generating code for. */
const char *pa_arch_string;
/* Set by the FUNCTION_PROFILER macro. */
int hp_profile_labelno;
/* Counts for the number of callee-saved general and floating point
registers which were saved by the current function's prologue. */
static int gr_saved, fr_saved;
@ -170,11 +167,6 @@ override_options ()
warning ("PIC code generation is not compatible with fast indirect calls\n");
}
if (flag_pic && profile_flag)
{
warning ("PIC code generation is not compatible with profiling\n");
}
if (! TARGET_GAS && write_symbols != NO_DEBUG)
{
warning ("-g is only supported when using GAS on this processor,");
@ -2886,8 +2878,6 @@ compute_frame_size (size, fregs_live)
return (fsize + STACK_BOUNDARY - 1) & ~(STACK_BOUNDARY - 1);
}
rtx hp_profile_label_rtx;
static char hp_profile_label_name[8];
void
output_function_prologue (file, size)
FILE *file;
@ -2903,7 +2893,7 @@ output_function_prologue (file, size)
to output the assembler directives which denote the start
of a function. */
fprintf (file, "\t.CALLINFO FRAME=%d", actual_fsize);
if (regs_ever_live[2] || profile_flag)
if (regs_ever_live[2])
fputs (",CALLS,SAVE_RP", file);
else
fputs (",NO_CALLS", file);
@ -2927,12 +2917,6 @@ output_function_prologue (file, size)
fputs ("\n\t.ENTRY\n", file);
/* Horrid hack. emit_function_prologue will modify this RTL in
place to get the expected results. */
if (profile_flag)
ASM_GENERATE_INTERNAL_LABEL (hp_profile_label_name, "LP",
hp_profile_labelno);
/* If we're using GAS and not using the portable runtime model, then
we don't need to accumulate the total number of code bytes. */
if (TARGET_GAS && ! TARGET_PORTABLE_RUNTIME)
@ -2983,7 +2967,7 @@ hppa_expand_prologue()
/* Save RP first. The calling conventions manual states RP will
always be stored into the caller's frame at sp-20 or sp - 16
depending on which ABI is in use. */
if (regs_ever_live[2] || profile_flag)
if (regs_ever_live[2])
store_reg (2, TARGET_64BIT ? -16 : -20, STACK_POINTER_REGNUM);
/* Allocate the local frame and set up the frame pointer if needed. */
@ -3030,10 +3014,7 @@ hppa_expand_prologue()
and allocating the stack frame at the same time. If so, just
make a note of it and defer allocating the frame until saving
the callee registers. */
if (VAL_14_BITS_P (actual_fsize)
&& local_fsize == 0
&& ! profile_flag
&& ! flag_pic)
if (VAL_14_BITS_P (actual_fsize) && local_fsize == 0)
merge_sp_adjust_with_store = 1;
/* Can not optimize. Adjust the stack frame by actual_fsize
bytes. */
@ -3042,77 +3023,6 @@ hppa_expand_prologue()
STACK_POINTER_REGNUM,
actual_fsize);
}
/* The hppa calling conventions say that %r19, the pic offset
register, is saved at sp - 32 (in this function's frame)
when generating PIC code. FIXME: What is the correct thing
to do for functions which make no calls and allocate no
frame? Do we need to allocate a frame, or can we just omit
the save? For now we'll just omit the save. */
if (flag_pic && !TARGET_64BIT)
store_reg (PIC_OFFSET_TABLE_REGNUM, -32, STACK_POINTER_REGNUM);
}
/* Profiling code.
Instead of taking one argument, the counter label, as most normal
mcounts do, _mcount appears to behave differently on the HPPA. It
takes the return address of the caller, the address of this routine,
and the address of the label. Also, it isn't magic, so
argument registers have to be preserved. */
if (profile_flag)
{
int pc_offset, i, arg_offset, basereg, offsetadj;
pc_offset = 4 + (frame_pointer_needed
? (VAL_14_BITS_P (actual_fsize) ? 12 : 20)
: (VAL_14_BITS_P (actual_fsize) ? 4 : 8));
/* When the function has a frame pointer, use it as the base
register for saving/restore registers. Else use the stack
pointer. Adjust the offset according to the frame size if
this function does not have a frame pointer. */
basereg = frame_pointer_needed ? FRAME_POINTER_REGNUM
: STACK_POINTER_REGNUM;
offsetadj = frame_pointer_needed ? 0 : actual_fsize;
/* Horrid hack. emit_function_prologue will modify this RTL in
place to get the expected results. sprintf here is just to
put something in the name. */
sprintf(hp_profile_label_name, "LP$%04d", -1);
hp_profile_label_rtx = gen_rtx_SYMBOL_REF (Pmode,
hp_profile_label_name);
if (current_function_returns_struct)
store_reg (STRUCT_VALUE_REGNUM, - 12 - offsetadj, basereg);
if (current_function_needs_context)
store_reg (STATIC_CHAIN_REGNUM, - 16 - offsetadj, basereg);
for (i = 26, arg_offset = -36 - offsetadj; i >= 23; i--, arg_offset -= 4)
if (regs_ever_live [i])
{
store_reg (i, arg_offset, basereg);
/* Deal with arg_offset not fitting in 14 bits. */
pc_offset += VAL_14_BITS_P (arg_offset) ? 4 : 8;
}
emit_move_insn (gen_rtx_REG (word_mode, 26), gen_rtx_REG (word_mode, 2));
emit_move_insn (tmpreg, gen_rtx_HIGH (Pmode, hp_profile_label_rtx));
emit_move_insn (gen_rtx_REG (Pmode, 24),
gen_rtx_LO_SUM (Pmode, tmpreg, hp_profile_label_rtx));
/* %r25 is set from within the output pattern. */
emit_insn (gen_call_profiler (GEN_INT (- pc_offset - 20)));
/* Restore argument registers. */
for (i = 26, arg_offset = -36 - offsetadj; i >= 23; i--, arg_offset -= 4)
if (regs_ever_live [i])
load_reg (i, arg_offset, basereg);
if (current_function_returns_struct)
load_reg (STRUCT_VALUE_REGNUM, -12 - offsetadj, basereg);
if (current_function_needs_context)
load_reg (STATIC_CHAIN_REGNUM, -16 - offsetadj, basereg);
}
/* Normal register save.
@ -3160,6 +3070,15 @@ hppa_expand_prologue()
actual_fsize);
}
/* The hppa calling conventions say that %r19, the pic offset
register, is saved at sp - 32 (in this function's frame)
when generating PIC code. FIXME: What is the correct thing
to do for functions which make no calls and allocate no
frame? Do we need to allocate a frame, or can we just omit
the save? For now we'll just omit the save. */
if (flag_pic && actual_fsize != 0 && !TARGET_64BIT)
store_reg (PIC_OFFSET_TABLE_REGNUM, -32, STACK_POINTER_REGNUM);
/* Align pointer properly (doubleword boundary). */
offset = (offset + 7) & ~7;
@ -3235,7 +3154,7 @@ hppa_expand_epilogue ()
/* Try to restore RP early to avoid load/use interlocks when
RP gets used in the return (bv) instruction. This appears to still
be necessary even when we schedule the prologue and epilogue. */
if (regs_ever_live [2] || profile_flag)
if (regs_ever_live [2])
{
ret_off = TARGET_64BIT ? -16 : -20;
if (frame_pointer_needed)
@ -3357,9 +3276,94 @@ void hppa_init_pic_save ()
insn = gen_rtx_SET (VOIDmode, PIC_OFFSET_TABLE_SAVE_RTX, picreg);
/* Emit the insn at the beginning of the function after the prologue. */
push_topmost_sequence ();
emit_insn_after (insn, last_parm_insn ? last_parm_insn : get_insns ());
pop_topmost_sequence ();
if (tail_recursion_reentry)
emit_insn_before (insn, tail_recursion_reentry);
else
/* We must have been called via PROFILE_HOOK. */
emit_insn (insn);
}
void
hppa_profile_hook (label_no)
int label_no ATTRIBUTE_UNUSED;
{
rtx call_insn;
/* No profiling for inline functions. We don't want extra calls to
_mcount when the inline function is expanded. Even if that made
sense, it wouldn't work here as there is no function label for
the inline expansion. */
if (DECL_INLINE (cfun->decl))
return;
if (TARGET_64BIT)
emit_move_insn (arg_pointer_rtx,
gen_rtx_PLUS (word_mode, virtual_outgoing_args_rtx,
GEN_INT (64)));
if (flag_pic && PIC_OFFSET_TABLE_SAVE_RTX == NULL_RTX)
hppa_init_pic_save ();
emit_move_insn (gen_rtx_REG (word_mode, 26), gen_rtx_REG (word_mode, 2));
#ifndef NO_PROFILE_COUNTERS
{
rtx count_label_rtx, addr, r24;
char label_name[16];
ASM_GENERATE_INTERNAL_LABEL (label_name, "LP", label_no);
count_label_rtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (label_name));
if (flag_pic)
{
rtx tmpreg;
current_function_uses_pic_offset_table = 1;
tmpreg = gen_rtx_REG (Pmode, 1);
emit_move_insn (tmpreg,
gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
gen_rtx_HIGH (Pmode, count_label_rtx)));
addr = gen_rtx_MEM (Pmode,
gen_rtx_LO_SUM (Pmode, tmpreg, count_label_rtx));
}
else
{
rtx tmpreg = gen_rtx_REG (Pmode, 1);
emit_move_insn (tmpreg, gen_rtx_HIGH (Pmode, count_label_rtx));
addr = gen_rtx_LO_SUM (Pmode, tmpreg, count_label_rtx);
}
r24 = gen_rtx_REG (Pmode, 24);
emit_move_insn (r24, addr);
/* %r25 is set from within the output pattern. */
call_insn =
emit_call_insn (gen_call_profiler (gen_rtx_SYMBOL_REF (Pmode, "_mcount"),
GEN_INT (TARGET_64BIT ? 24 : 12),
XEXP (DECL_RTL (cfun->decl), 0)));
use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), r24);
}
#else
/* %r25 is set from within the output pattern. */
call_insn =
emit_call_insn (gen_call_profiler (gen_rtx_SYMBOL_REF (Pmode, "_mcount"),
GEN_INT (TARGET_64BIT ? 16 : 8),
XEXP (DECL_RTL (cfun->decl), 0)));
#endif
/* Indicate the _mcount call cannot throw, nor will it execute a
non-local goto. */
REG_NOTES (call_insn)
= gen_rtx_EXPR_LIST (REG_EH_REGION, constm1_rtx, REG_NOTES (call_insn));
if (flag_pic)
{
use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), pic_offset_table_rtx);
if (TARGET_64BIT)
use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), arg_pointer_rtx);
emit_move_insn (pic_offset_table_rtx, PIC_OFFSET_TABLE_SAVE_RTX);
}
}
/* Fetch the return address for the frame COUNT steps up from
@ -3475,7 +3479,6 @@ hppa_can_use_return_insn_p ()
{
return (reload_completed
&& (compute_frame_size (get_frame_size (), 0) ? 0 : 1)
&& ! profile_flag
&& ! regs_ever_live[2]
&& ! frame_pointer_needed);
}
@ -7098,7 +7101,6 @@ pa_add_gc_roots ()
{
ggc_add_rtx_root (&hppa_compare_op0, 1);
ggc_add_rtx_root (&hppa_compare_op1, 1);
ggc_add_rtx_root (&hp_profile_label_rtx, 1);
ggc_add_root (&deferred_plabels, 1, sizeof (&deferred_plabels),
&mark_deferred_plabels);
}

View File

@ -883,16 +883,13 @@ extern enum cmp_type hppa_branch_type;
#define FUNCTION_PROLOGUE(FILE, SIZE) \
output_function_prologue (FILE, SIZE)
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry.
/* On HPPA, we emit profiling code as rtl via PROFILE_HOOK rather than
as assembly via FUNCTION_PROFILER. */
Because HPUX _mcount is so different, we actually emit the
profiling code in function_prologue. This just stores LABELNO for
that. */
#define FUNCTION_PROFILER(FILE, LABEL) /* nothing */
#define PROFILE_BEFORE_PROLOGUE
#define FUNCTION_PROFILER(FILE, LABELNO) \
{ extern int hp_profile_labelno; hp_profile_labelno = (LABELNO);}
#define PROFILE_HOOK(label_no) hppa_profile_hook (label_no)
void hppa_profile_hook PARAMS ((int label_no));
/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
the stack pointer does not matter. The value is tested only in
@ -1834,8 +1831,6 @@ while (0)
#define ASM_OUTPUT_ASCII(FILE, P, SIZE) \
output_ascii ((FILE), (P), (SIZE))
#define ASM_OUTPUT_REG_PUSH(FILE,REGNO)
#define ASM_OUTPUT_REG_POP(FILE,REGNO)
/* This is how to output an element of a case-vector that is absolute.
Note that this method makes filling these branch delay slots
impossible. */

View File

@ -5513,10 +5513,28 @@
;; from within its delay slot to set the value for the 2nd parameter to
;; the call.
(define_insn "call_profiler"
[(unspec_volatile [(const_int 0)] 0)
(use (match_operand:SI 0 "const_int_operand" ""))]
[(call (mem:SI (match_operand 0 "call_operand_address" ""))
(match_operand 1 "" ""))
(use (match_operand 2 "" ""))
(use (reg:SI 25))
(use (reg:SI 26))
(clobber (reg:SI 2))]
""
"{bl|b,l} _mcount,%%r2\;ldo %0(%%r2),%%r25"
"*
{
rtx xoperands[3];
output_arg_descriptor (insn);
xoperands[0] = operands[0];
xoperands[1] = operands[2];
xoperands[2] = gen_label_rtx ();
output_asm_insn (\"{bl|b,l} %0,%%r2\;ldo %1-%2(%%r2),%%r25\", xoperands);
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
CODE_LABEL_NUMBER (xoperands[2]));
return \"\";
}"
[(set_attr "type" "multi")
(set_attr "length" "8")])