diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h index d47b4756ad4..0460f1a6cb0 100644 --- a/gcc/config/arc/arc-protos.h +++ b/gcc/config/arc/arc-protos.h @@ -51,6 +51,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_compute_frame_size (void); #endif /* RTX_CODE */ extern bool arc_ccfsm_branch_deleted_p (void); @@ -107,6 +108,7 @@ 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_ifcvt (gcc::context *ctxt); rtl_opt_pass * make_pass_arc_predicate_delay_insns (gcc::context *ctxt); diff --git a/gcc/config/arc/arc.cc b/gcc/config/arc/arc.cc index ff01e665d5d..fe92775d40e 100644 --- a/gcc/config/arc/arc.cc +++ b/gcc/config/arc/arc.cc @@ -428,6 +428,10 @@ typedef struct GTY (()) machine_function rtx ccfsm_current_insn; char arc_reorg_started; char prescan_initialized; + /* Remember where mcount second arg is stored so we can update + it. */ + rtx_insn *set_mcount_arg_insn; + } machine_function; @@ -2840,7 +2844,7 @@ arc_compute_millicode_save_restore_regs (uint64_t gmask, /* Return the bytes needed to compute the frame pointer from the current stack pointer. */ -static unsigned int +unsigned int arc_compute_frame_size (void) { int regno; @@ -11786,6 +11790,28 @@ arc_insn_cost (rtx_insn *insn, bool speed) return cost; } +/* Worker for PROFILE_HOOK. + The ARC profile hook uses the blink register and the current stack + size value. */ + +void +arc_profile_hook (void) +{ + rtx fun, r0, r1; + + /* First argument is BLINK. */ + r0 = get_hard_reg_initial_val (Pmode, RETURN_ADDR_REGNUM); + + /* Stack total size. 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); +} + #undef TARGET_USE_ANCHORS_FOR_SYMBOL_P #define TARGET_USE_ANCHORS_FOR_SYMBOL_P arc_use_anchors_for_symbol_p diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md index aebe61d37b6..3d1b0b8af11 100644 --- a/gcc/config/arc/arc.md +++ b/gcc/config/arc/arc.md @@ -137,6 +137,7 @@ (define_c_enum "unspec" [ UNSPEC_ARC_VMAC2HU UNSPEC_ARC_VMPY2H UNSPEC_ARC_VMPY2HU + UNSPEC_ARC_MCOUNT VUNSPEC_ARC_RTIE VUNSPEC_ARC_SYNC @@ -6699,6 +6700,20 @@ (define_insn_and_split "eh_return" [(set_attr "length" "8")] ) +(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_compute_frame_size ()); + }" + [(set_attr "length" "8")]) + ;; include the arc-FPX instructions (include "fpx.md") diff --git a/gcc/config/arc/linux.h b/gcc/config/arc/linux.h index b2f3cac06d4..c4f61304851 100644 --- a/gcc/config/arc/linux.h +++ b/gcc/config/arc/linux.h @@ -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