diff options
Diffstat (limited to '0150-Backport-SME-Add-a-new-target-hook-TARGET_START_CALL.patch')
-rw-r--r-- | 0150-Backport-SME-Add-a-new-target-hook-TARGET_START_CALL.patch | 461 |
1 files changed, 461 insertions, 0 deletions
diff --git a/0150-Backport-SME-Add-a-new-target-hook-TARGET_START_CALL.patch b/0150-Backport-SME-Add-a-new-target-hook-TARGET_START_CALL.patch new file mode 100644 index 0000000..4c71f2a --- /dev/null +++ b/0150-Backport-SME-Add-a-new-target-hook-TARGET_START_CALL.patch @@ -0,0 +1,461 @@ +From 58adede22d9ff2368b5c24ec3fc0e53bd3ddc8bd Mon Sep 17 00:00:00 2001 +From: Richard Sandiford <richard.sandiford@arm.com> +Date: Tue, 5 Dec 2023 09:44:52 +0000 +Subject: [PATCH 051/157] [Backport][SME] Add a new target hook: + TARGET_START_CALL_ARGS + +Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=672fad57c1f99ff893019e2da4620e26b9b31dd2 + +We have the following two hooks into the call expansion code: + +- TARGET_CALL_ARGS is called for each argument before arguments + are moved into hard registers. + +- TARGET_END_CALL_ARGS is called after the end of the call + sequence (specifically, after any return value has been + moved to a pseudo). + +This patch adds a TARGET_START_CALL_ARGS hook that is called before +the TARGET_CALL_ARGS sequence. This means that TARGET_START_CALL_REGS +and TARGET_END_CALL_REGS bracket the region in which argument registers +might be live. They also bracket a region in which the only call +emiitted by target-independent code is the call to the target function +itself. (For example, TARGET_START_CALL_ARGS happens after any use of +memcpy to copy arguments, and TARGET_END_CALL_ARGS happens before any +use of memcpy to copy the result.) + +Also, the patch adds the cumulative argument structure as an argument +to the hooks, so that the target can use it to record and retrieve +information about the call as a whole. + +The TARGET_CALL_ARGS docs said: + + While generating RTL for a function call, this target hook is invoked once + for each argument passed to the function, either a register returned by + ``TARGET_FUNCTION_ARG`` or a memory location. It is called just +- before the point where argument registers are stored. + +The last bit was true for normal calls, but for libcalls the hook was +invoked earlier, before stack arguments have been copied. I don't think +this caused a practical difference for nvptx (the only port to use the +hooks) since I wouldn't expect any libcalls to take stack parameters. + +gcc/ + * doc/tm.texi.in: Add TARGET_START_CALL_ARGS. + * doc/tm.texi: Regenerate. + * target.def (start_call_args): New hook. + (call_args, end_call_args): Add a parameter for the cumulative + argument information. + * hooks.h (hook_void_rtx_tree): Delete. + * hooks.cc (hook_void_rtx_tree): Likewise. + * targhooks.h (hook_void_CUMULATIVE_ARGS): Declare. + (hook_void_CUMULATIVE_ARGS_rtx_tree): Likewise. + * targhooks.cc (hook_void_CUMULATIVE_ARGS): New function. + (hook_void_CUMULATIVE_ARGS_rtx_tree): Likewise. + * calls.cc (expand_call): Call start_call_args before computing + and storing stack parameters. Pass the cumulative argument + information to call_args and end_call_args. + (emit_library_call_value_1): Likewise. + * config/nvptx/nvptx.cc (nvptx_call_args): Add a cumulative + argument parameter. + (nvptx_end_call_args): Likewise. +--- + gcc/calls.cc | 61 +++++++++++++++++++++------------------ + gcc/config/nvptx/nvptx.cc | 4 +-- + gcc/doc/tm.texi | 53 +++++++++++++++++++++++++++------- + gcc/doc/tm.texi.in | 2 ++ + gcc/hooks.cc | 5 ---- + gcc/hooks.h | 1 - + gcc/target.def | 59 +++++++++++++++++++++++++++++-------- + gcc/targhooks.cc | 10 +++++++ + gcc/targhooks.h | 5 ++-- + 9 files changed, 140 insertions(+), 60 deletions(-) + +diff --git a/gcc/calls.cc b/gcc/calls.cc +index c1db66883..4a8535cc6 100644 +--- a/gcc/calls.cc ++++ b/gcc/calls.cc +@@ -3507,15 +3507,26 @@ expand_call (tree exp, rtx target, int ignore) + sibcall_failure = 1; + } + ++ /* Set up the next argument register. For sibling calls on machines ++ with register windows this should be the incoming register. */ ++ if (pass == 0) ++ next_arg_reg = targetm.calls.function_incoming_arg ++ (args_so_far, function_arg_info::end_marker ()); ++ else ++ next_arg_reg = targetm.calls.function_arg ++ (args_so_far, function_arg_info::end_marker ()); ++ ++ targetm.calls.start_call_args (args_so_far); ++ + bool any_regs = false; + for (i = 0; i < num_actuals; i++) + if (args[i].reg != NULL_RTX) + { + any_regs = true; +- targetm.calls.call_args (args[i].reg, funtype); ++ targetm.calls.call_args (args_so_far, args[i].reg, funtype); + } + if (!any_regs) +- targetm.calls.call_args (pc_rtx, funtype); ++ targetm.calls.call_args (args_so_far, pc_rtx, funtype); + + /* Figure out the register where the value, if any, will come back. */ + valreg = 0; +@@ -3578,15 +3589,6 @@ expand_call (tree exp, rtx target, int ignore) + later safely search backwards to find the CALL_INSN. */ + before_call = get_last_insn (); + +- /* Set up next argument register. For sibling calls on machines +- with register windows this should be the incoming register. */ +- if (pass == 0) +- next_arg_reg = targetm.calls.function_incoming_arg +- (args_so_far, function_arg_info::end_marker ()); +- else +- next_arg_reg = targetm.calls.function_arg +- (args_so_far, function_arg_info::end_marker ()); +- + if (pass == 1 && (return_flags & ERF_RETURNS_ARG)) + { + int arg_nr = return_flags & ERF_RETURN_ARG_MASK; +@@ -3879,7 +3881,7 @@ expand_call (tree exp, rtx target, int ignore) + for (i = 0; i < num_actuals; ++i) + free (args[i].aligned_regs); + +- targetm.calls.end_call_args (); ++ targetm.calls.end_call_args (args_so_far); + + insns = get_insns (); + end_sequence (); +@@ -4437,17 +4439,9 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value, + } + #endif + +- /* When expanding a normal call, args are stored in push order, +- which is the reverse of what we have here. */ +- bool any_regs = false; +- for (int i = nargs; i-- > 0; ) +- if (argvec[i].reg != NULL_RTX) +- { +- targetm.calls.call_args (argvec[i].reg, NULL_TREE); +- any_regs = true; +- } +- if (!any_regs) +- targetm.calls.call_args (pc_rtx, NULL_TREE); ++ rtx call_cookie ++ = targetm.calls.function_arg (args_so_far, ++ function_arg_info::end_marker ()); + + /* Push the args that need to be pushed. */ + +@@ -4565,6 +4559,20 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value, + + fun = prepare_call_address (NULL, fun, NULL, &call_fusage, 0, 0); + ++ targetm.calls.start_call_args (args_so_far); ++ ++ /* When expanding a normal call, args are stored in push order, ++ which is the reverse of what we have here. */ ++ bool any_regs = false; ++ for (int i = nargs; i-- > 0; ) ++ if (argvec[i].reg != NULL_RTX) ++ { ++ targetm.calls.call_args (args_so_far, argvec[i].reg, NULL_TREE); ++ any_regs = true; ++ } ++ if (!any_regs) ++ targetm.calls.call_args (args_so_far, pc_rtx, NULL_TREE); ++ + /* Now load any reg parms into their regs. */ + + /* ARGNUM indexes the ARGVEC array in the order in which the arguments +@@ -4671,10 +4679,7 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value, + get_identifier (XSTR (orgfun, 0)), + build_function_type (tfom, NULL_TREE), + original_args_size.constant, args_size.constant, +- struct_value_size, +- targetm.calls.function_arg (args_so_far, +- function_arg_info::end_marker ()), +- valreg, ++ struct_value_size, call_cookie, valreg, + old_inhibit_defer_pop + 1, call_fusage, flags, args_so_far); + + if (flag_ipa_ra) +@@ -4694,7 +4699,7 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value, + valreg = gen_rtx_REG (TYPE_MODE (tfom), REGNO (valreg)); + } + +- targetm.calls.end_call_args (); ++ targetm.calls.end_call_args (args_so_far); + + /* For calls to `setjmp', etc., inform function.cc:setjmp_warnings + that it should complain if nonvolatile values are live. For +diff --git a/gcc/config/nvptx/nvptx.cc b/gcc/config/nvptx/nvptx.cc +index 3634a49de..7f2103ba6 100644 +--- a/gcc/config/nvptx/nvptx.cc ++++ b/gcc/config/nvptx/nvptx.cc +@@ -1780,7 +1780,7 @@ nvptx_get_drap_rtx (void) + argument to the next call. */ + + static void +-nvptx_call_args (rtx arg, tree fntype) ++nvptx_call_args (cumulative_args_t, rtx arg, tree fntype) + { + if (!cfun->machine->doing_call) + { +@@ -1808,7 +1808,7 @@ nvptx_call_args (rtx arg, tree fntype) + information we recorded. */ + + static void +-nvptx_end_call_args (void) ++nvptx_end_call_args (cumulative_args_t) + { + cfun->machine->doing_call = false; + free_EXPR_LIST_list (&cfun->machine->call_args); +diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi +index 369f4b8da..357c29a4d 100644 +--- a/gcc/doc/tm.texi ++++ b/gcc/doc/tm.texi +@@ -5392,26 +5392,59 @@ except the last are treated as named. + You need not define this hook if it always returns @code{false}. + @end deftypefn + +-@deftypefn {Target Hook} void TARGET_CALL_ARGS (rtx, @var{tree}) ++@deftypefn {Target Hook} void TARGET_START_CALL_ARGS (cumulative_args_t @var{complete_args}) ++This target hook is invoked while generating RTL for a function call, ++after the argument values have been computed, and after stack arguments ++have been initialized, but before register arguments have been moved into ++their ABI-defined hard register locations. It precedes calls to the related ++hooks @code{TARGET_CALL_ARGS} and @code{TARGET_END_CALL_ARGS}. ++The significance of this position in the call expansion is that: ++ ++@itemize @bullet ++@item ++No argument registers are live. ++@item ++Although a call sequence can in general involve subcalls (such as using ++@code{memcpy} to copy large arguments), no such subcall will occur between ++the call to this hook and the generation of the main call instruction. ++@end itemize ++ ++The single argument @var{complete_args} is the state of the target ++function's cumulative argument information after the final call to ++@code{TARGET_FUNCTION_ARG}. ++ ++The hook can be used for things like switching processor mode, in cases ++where different calls need different processor modes. Most ports do not ++need to implement anything for this hook. ++@end deftypefn ++ ++@deftypefn {Target Hook} void TARGET_CALL_ARGS (cumulative_args_t @var{complete_args}, rtx @var{loc}, tree @var{type}) + While generating RTL for a function call, this target hook is invoked once + for each argument passed to the function, either a register returned by + @code{TARGET_FUNCTION_ARG} or a memory location. It is called just +-before the point where argument registers are stored. The type of the +-function to be called is also passed as the second argument; it is +-@code{NULL_TREE} for libcalls. The @code{TARGET_END_CALL_ARGS} hook is +-invoked just after the code to copy the return reg has been emitted. +-This functionality can be used to perform special setup of call argument +-registers if a target needs it. ++before the point where argument registers are stored. ++ ++@var{complete_args} is the state of the target function's cumulative ++argument information after the final call to @code{TARGET_FUNCTION_ARG}. ++@var{loc} is the location of the argument. @var{type} is the type of ++the function being called, or @code{NULL_TREE} for libcalls. ++ + For functions without arguments, the hook is called once with @code{pc_rtx} + passed instead of an argument register. +-Most ports do not need to implement anything for this hook. ++ ++This functionality can be used to perform special setup of call argument ++registers, if a target needs it. Most ports do not need to implement ++anything for this hook. + @end deftypefn + +-@deftypefn {Target Hook} void TARGET_END_CALL_ARGS (void) ++@deftypefn {Target Hook} void TARGET_END_CALL_ARGS (cumulative_args_t @var{complete_args}) + This target hook is invoked while generating RTL for a function call, + just after the point where the return reg is copied into a pseudo. It + signals that all the call argument and return registers for the just +-emitted call are now no longer in use. ++emitted call are now no longer in use. @var{complete_args} is the ++state of the target function's cumulative argument information after ++the final call to @code{TARGET_FUNCTION_ARG}. ++ + Most ports do not need to implement anything for this hook. + @end deftypefn + +diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in +index 748b0777a..4ebc9afbf 100644 +--- a/gcc/doc/tm.texi.in ++++ b/gcc/doc/tm.texi.in +@@ -3774,6 +3774,8 @@ These machine description macros help implement varargs: + + @hook TARGET_STRICT_ARGUMENT_NAMING + ++@hook TARGET_START_CALL_ARGS ++ + @hook TARGET_CALL_ARGS + + @hook TARGET_END_CALL_ARGS +diff --git a/gcc/hooks.cc b/gcc/hooks.cc +index b29233f4f..0f4e7ce10 100644 +--- a/gcc/hooks.cc ++++ b/gcc/hooks.cc +@@ -280,11 +280,6 @@ hook_void_FILEptr_tree (FILE *, tree) + { + } + +-void +-hook_void_rtx_tree (rtx, tree) +-{ +-} +- + void + hook_void_constcharptr (const char *) + { +diff --git a/gcc/hooks.h b/gcc/hooks.h +index 1056e1e9e..e2a742f43 100644 +--- a/gcc/hooks.h ++++ b/gcc/hooks.h +@@ -83,7 +83,6 @@ extern void hook_void_FILEptr_constcharptr (FILE *, const char *); + extern void hook_void_FILEptr_constcharptr_const_tree (FILE *, const char *, + const_tree); + extern bool hook_bool_FILEptr_rtx_false (FILE *, rtx); +-extern void hook_void_rtx_tree (rtx, tree); + extern void hook_void_FILEptr_tree (FILE *, tree); + extern void hook_void_tree (tree); + extern void hook_void_tree_treeptr (tree, tree *); +diff --git a/gcc/target.def b/gcc/target.def +index cf9f96eba..a57e51b0d 100644 +--- a/gcc/target.def ++++ b/gcc/target.def +@@ -4784,32 +4784,67 @@ not generate any instructions in this case.", + int *pretend_args_size, int second_time), + default_setup_incoming_varargs) + ++DEFHOOK ++(start_call_args, ++ "This target hook is invoked while generating RTL for a function call,\n\ ++after the argument values have been computed, and after stack arguments\n\ ++have been initialized, but before register arguments have been moved into\n\ ++their ABI-defined hard register locations. It precedes calls to the related\n\ ++hooks @code{TARGET_CALL_ARGS} and @code{TARGET_END_CALL_ARGS}.\n\ ++The significance of this position in the call expansion is that:\n\ ++\n\ ++@itemize @bullet\n\ ++@item\n\ ++No argument registers are live.\n\ ++@item\n\ ++Although a call sequence can in general involve subcalls (such as using\n\ ++@code{memcpy} to copy large arguments), no such subcall will occur between\n\ ++the call to this hook and the generation of the main call instruction.\n\ ++@end itemize\n\ ++\n\ ++The single argument @var{complete_args} is the state of the target\n\ ++function's cumulative argument information after the final call to\n\ ++@code{TARGET_FUNCTION_ARG}.\n\ ++\n\ ++The hook can be used for things like switching processor mode, in cases\n\ ++where different calls need different processor modes. Most ports do not\n\ ++need to implement anything for this hook.", ++ void, (cumulative_args_t complete_args), ++ hook_void_CUMULATIVE_ARGS) ++ + DEFHOOK + (call_args, + "While generating RTL for a function call, this target hook is invoked once\n\ + for each argument passed to the function, either a register returned by\n\ + @code{TARGET_FUNCTION_ARG} or a memory location. It is called just\n\ +-before the point where argument registers are stored. The type of the\n\ +-function to be called is also passed as the second argument; it is\n\ +-@code{NULL_TREE} for libcalls. The @code{TARGET_END_CALL_ARGS} hook is\n\ +-invoked just after the code to copy the return reg has been emitted.\n\ +-This functionality can be used to perform special setup of call argument\n\ +-registers if a target needs it.\n\ ++before the point where argument registers are stored.\n\ ++\n\ ++@var{complete_args} is the state of the target function's cumulative\n\ ++argument information after the final call to @code{TARGET_FUNCTION_ARG}.\n\ ++@var{loc} is the location of the argument. @var{type} is the type of\n\ ++the function being called, or @code{NULL_TREE} for libcalls.\n\ ++\n\ + For functions without arguments, the hook is called once with @code{pc_rtx}\n\ + passed instead of an argument register.\n\ +-Most ports do not need to implement anything for this hook.", +- void, (rtx, tree), +- hook_void_rtx_tree) ++\n\ ++This functionality can be used to perform special setup of call argument\n\ ++registers, if a target needs it. Most ports do not need to implement\n\ ++anything for this hook.", ++ void, (cumulative_args_t complete_args, rtx loc, tree type), ++ hook_void_CUMULATIVE_ARGS_rtx_tree) + + DEFHOOK + (end_call_args, + "This target hook is invoked while generating RTL for a function call,\n\ + just after the point where the return reg is copied into a pseudo. It\n\ + signals that all the call argument and return registers for the just\n\ +-emitted call are now no longer in use.\n\ ++emitted call are now no longer in use. @var{complete_args} is the\n\ ++state of the target function's cumulative argument information after\n\ ++the final call to @code{TARGET_FUNCTION_ARG}.\n\ ++\n\ + Most ports do not need to implement anything for this hook.", +- void, (void), +- hook_void_void) ++ void, (cumulative_args_t complete_args), ++ hook_void_CUMULATIVE_ARGS) + + DEFHOOK + (push_argument, +diff --git a/gcc/targhooks.cc b/gcc/targhooks.cc +index 399d6f874..c88afa5db 100644 +--- a/gcc/targhooks.cc ++++ b/gcc/targhooks.cc +@@ -772,12 +772,22 @@ hook_int_CUMULATIVE_ARGS_arg_info_0 (cumulative_args_t, + return 0; + } + ++void ++hook_void_CUMULATIVE_ARGS (cumulative_args_t) ++{ ++} ++ + void + hook_void_CUMULATIVE_ARGS_tree (cumulative_args_t ca ATTRIBUTE_UNUSED, + tree ATTRIBUTE_UNUSED) + { + } + ++void ++hook_void_CUMULATIVE_ARGS_rtx_tree (cumulative_args_t, rtx, tree) ++{ ++} ++ + /* Default implementation of TARGET_PUSH_ARGUMENT. */ + + bool +diff --git a/gcc/targhooks.h b/gcc/targhooks.h +index ecce55ebe..c6e12fc2e 100644 +--- a/gcc/targhooks.h ++++ b/gcc/targhooks.h +@@ -138,8 +138,9 @@ extern bool hook_bool_CUMULATIVE_ARGS_arg_info_true + (cumulative_args_t, const function_arg_info &); + extern int hook_int_CUMULATIVE_ARGS_arg_info_0 + (cumulative_args_t, const function_arg_info &); +-extern void hook_void_CUMULATIVE_ARGS_tree +- (cumulative_args_t, tree); ++extern void hook_void_CUMULATIVE_ARGS (cumulative_args_t); ++extern void hook_void_CUMULATIVE_ARGS_tree (cumulative_args_t, tree); ++extern void hook_void_CUMULATIVE_ARGS_rtx_tree (cumulative_args_t, rtx, tree); + extern const char *hook_invalid_arg_for_unprototyped_fn + (const_tree, const_tree, const_tree); + extern void default_function_arg_advance +-- +2.33.0 + |