On 6/27/25 12:16 AM, Andrew Pinski wrote:
Since after a tail call function (even if it is tail called in the end),
the current function does not care about the local memory any more so
there is no reason to do a copy of the argument. This is only true for the
first usage of the decl, the rest requires a copy (c-c++-common/pr42909-3.c 
checks that).

Bootstrapped and tested on aarch64-linux-gnu.

        PR middle-end/42909
gcc/ChangeLog:

        * calls.cc (initialize_argument_information): For tail
        calls allow to reuse the argument if it is not addressable
        nor static if the first use of the decl. Disallow tails if
        that argument is not an incoming argument.

gcc/testsuite/ChangeLog:

        * c-c++-common/pr42909-1.c: New testcase
        * c-c++-common/pr42909-2.c: New testcase
        * c-c++-common/pr42909-3.c: New testcase
        * c-c++-common/pr42909-4.c: New testcase

Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com>
---
  gcc/calls.cc                           | 33 ++++++++++++++++++----
  gcc/testsuite/c-c++-common/pr42909-1.c | 19 +++++++++++++
  gcc/testsuite/c-c++-common/pr42909-2.c | 19 +++++++++++++
  gcc/testsuite/c-c++-common/pr42909-3.c | 38 ++++++++++++++++++++++++++
  gcc/testsuite/c-c++-common/pr42909-4.c | 20 ++++++++++++++
  5 files changed, 124 insertions(+), 5 deletions(-)
  create mode 100644 gcc/testsuite/c-c++-common/pr42909-1.c
  create mode 100644 gcc/testsuite/c-c++-common/pr42909-2.c
  create mode 100644 gcc/testsuite/c-c++-common/pr42909-3.c
  create mode 100644 gcc/testsuite/c-c++-common/pr42909-4.c


@@ -1428,15 +1430,37 @@ initialize_argument_information (int num_actuals 
ATTRIBUTE_UNUSED,
          const bool callee_copies
            = reference_callee_copied (args_so_far_pnt, arg);
          tree base;
-
+         bool can_reuse_arg = false;
+         bool can_reuse_with_tail_call = call_from_thunk_p;
          /* If we're compiling a thunk, pass directly the address of an object
             already in memory, instead of making a copy.  Likewise if we want
-            to make the copy in the callee instead of the caller.  */
+            to make the copy in the callee instead of the caller. */
Whitespace nit at the comment close. Guessing you didn't mean to make that change.


          if ((call_from_thunk_p || callee_copies)
              && TREE_CODE (args[i].tree_value) != WITH_SIZE_EXPR
              && ((base = get_base_address (args[i].tree_value)), true)
              && TREE_CODE (base) != SSA_NAME
              && (!DECL_P (base) || MEM_P (DECL_RTL (base))))
+           can_reuse_arg = true;
+
+         /* If we're compiling a tail call, pass the address of an object
+            already in memory, instead of a copy if the argument is a local
+            variable. Since after the tail call, the memory belongs to the 
caller,
+            this is safe even if we don't expand the call in the end as a tail 
call.
+            The first use of the decl can reuse it, the rest uses requires a 
copy.  */
What about a set before any use?  Does everything still work in that case?

Assuming the right things happen if there's an assignment to the argument before the first use, then this is OK. Otherwise I think you need more changes.

jeff



Reply via email to