summaryrefslogtreecommitdiff
path: root/0150-Backport-SME-Add-a-new-target-hook-TARGET_START_CALL.patch
diff options
context:
space:
mode:
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.patch461
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
+