Skip to content

Commit

Permalink
arc: Update PROFILE_HOOK to support Linux's ftrace
Browse files Browse the repository at this point in the history
Ftrace is a Linux internal tracer which helps developers to find what
is going on inisde the kernel. The way this works is the _mcount
function call (placed at the start of every kernel function, produced
by the -pg switch in gcc), starts of pointing to a simple return in
the stack.

The ARCv2 ABI does not enable us to perform full function tracing (aka
ftrace_graph with entry and exit) due to the fact that the
blink (return address) is pushed first on the stack. However,
providing the location of blink in the current stack enables some
ftrace capabilities.

This patch updates the ARC's profile hook for Linux targets, by
providing two arguments to `_mcount` profile function. First argument
is blink value, and the second argument is the blink location in the
current function stack.

As PROFILE_HOOK is called in the expand, and the stack layout is known
after register allocation, we use an unspec to mark the mcount second
argument move which needs to be updated latter on.

gcc/

	* config/arc/arc-protos.h (arc_get_arg_ptr): Declare.
	(arc_profile_hook): Likewise.
	* config/arc/arc.cc (arc_profile_hook): New function.
	(arc_get_arg_ptr): Likewise.
	* config/arc/arc.md (UNSPEC_ARC_MCOUNT): New define.
	(mcount_stack): New pattern.
	* config/arc/linux.h (PROFILE_HOOK): Update hook.

Signed-off-by: Claudiu Zissulescu <claziss@gmail.com>
  • Loading branch information
claziss committed Oct 18, 2023
1 parent 4305c12 commit c52b7ec
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 7 deletions.
2 changes: 2 additions & 0 deletions gcc/config/arc/arc-protos.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ extern bool arc_check_mov_const (HOST_WIDE_INT );
extern bool arc_split_mov_const (rtx *);
extern bool arc_can_use_return_insn (void);
extern bool arc_split_move_p (rtx *);
extern unsigned int arc_get_arg_ptr (void);
#endif /* RTX_CODE */


Expand Down Expand Up @@ -97,5 +98,6 @@ extern void arc_eh_return_address_location (rtx);
extern bool arc_is_jli_call_p (rtx);
extern void arc_file_end (void);
extern bool arc_is_secure_call_p (rtx);
extern void arc_profile_hook (void);

rtl_opt_pass * make_pass_arc_predicate_delay_insns (gcc::context *ctxt);
41 changes: 41 additions & 0 deletions gcc/config/arc/arc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10988,6 +10988,47 @@ arc_insn_cost (rtx_insn *insn, bool speed)
return cost;
}

/* Worker for PROFILE_HOOK. The ARC profile hook uses the blink
register and a constant which is the location of the current blink
stack slot. First, the second argument (the blink stack slot
location) is initialized with minus one, and, latter, when the
stack structure is known, this argument is updated with the right
value (see arc_get_arg_ptr). */

void
arc_profile_hook (void)
{
rtx fun, r0, r1;

/* First argument is BLINK. */
r0 = get_hard_reg_initial_val (Pmode, RETURN_ADDR_REGNUM);

/* This hook is called in the expand, thus, the stack size is
unknown. We need to mark the move instruction, and properly
update it after reload. */
r1 = gen_reg_rtx (SImode);
emit_insn (gen_mcount_stack (r1, constm1_rtx));

fun = gen_rtx_SYMBOL_REF (Pmode, "_mcount");
emit_library_call (fun, LCT_NORMAL, VOIDmode, r0, Pmode, r1, SImode);
}

/* Returns the location of BLINK in the stack, which is the location
indicated by the ARG_POINTER_REGNUM. */

unsigned int
arc_get_arg_ptr (void)
{
struct arc_frame_info *frame_info;

if (!cfun->machine->frame_info.initialized)
arc_compute_frame_size ();

frame_info = &cfun->machine->frame_info;

return frame_info->total_size - frame_info->pretend_size;
}

#undef TARGET_USE_ANCHORS_FOR_SYMBOL_P
#define TARGET_USE_ANCHORS_FOR_SYMBOL_P arc_use_anchors_for_symbol_p

Expand Down
18 changes: 18 additions & 0 deletions gcc/config/arc/arc.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@
UNSPEC_ARC_VMAC2HU
UNSPEC_ARC_VMPY2H
UNSPEC_ARC_VMPY2HU
UNSPEC_ARC_MCOUNT

VUNSPEC_ARC_RTIE
VUNSPEC_ARC_SYNC
Expand Down Expand Up @@ -6596,6 +6597,23 @@ archs4x, archs4xd"
[(set_attr "length" "8")]
)

;; This pattern is used by profile hook to initialize the mcount
;; second argument with the right value where the blink is located in
;; current stack.
(define_insn_and_split "mcount_stack"
[(set (match_operand:SI 0 "register_operand" "=r")
(unspec:SI [(match_operand:SI 1 "immediate_operand" "i")]
UNSPEC_ARC_MCOUNT))]
""
"#"
"reload_completed"
[(set (match_dup 0) (match_dup 1))]
"
{
operands[1] = GEN_INT (arc_get_arg_ptr ());
}"
[(set_attr "length" "8")])

;; include the arc-FPX instructions
(include "fpx.md")

Expand Down
8 changes: 1 addition & 7 deletions gcc/config/arc/linux.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,7 @@ along with GCC; see the file COPYING3. If not see

/* Emit rtl for profiling. Output assembler code to FILE
to call "_mcount" for profiling a function entry. */
#define PROFILE_HOOK(LABEL) \
{ \
rtx fun, rt; \
rt = get_hard_reg_initial_val (Pmode, RETURN_ADDR_REGNUM); \
fun = gen_rtx_SYMBOL_REF (Pmode, "_mcount"); \
emit_library_call (fun, LCT_NORMAL, VOIDmode, rt, Pmode); \
}
#define PROFILE_HOOK(LABEL) arc_profile_hook()

/* Enter/Leave ops are default off for linux targets. */
#undef TARGET_CODE_DENSITY_FRAME_DEFAULT
Expand Down

0 comments on commit c52b7ec

Please sign in to comment.