From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-lf1-x130.google.com (mail-lf1-x130.google.com [IPv6:2a00:1450:4864:20::130]) by sourceware.org (Postfix) with ESMTPS id C7336384F4AE for ; Fri, 18 Nov 2022 13:17:44 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org C7336384F4AE Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-lf1-x130.google.com with SMTP id a29so8124766lfj.9 for ; Fri, 18 Nov 2022 05:17:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :from:to:cc:subject:date:message-id:reply-to; bh=dEpkR8UK9KOJvrmhJNZu9PfS2JIzIrvWI0Xt9usQV+8=; b=EeZs632rplVPFvWESueTCo7av6PkKQ2f+Fc5NTrWOp7PT47ykQ3pjhCWEyYZVOpJdR MzcyV0FnFmi0mC9T5LVcsXrjhzYEd1YxvGuPpH/19IhR9+nItMz8DE2Wc2m101h8njpv b6aO7iaDgPXhV9dG+zTHO1hkLZ3/TNAjAhXxt3PRAZPOzzuM5dx5aQLtUI8JxOKSQJdK MFKhgvIDewNOf4mE43EnRGVYQoM22F0BYWOhKFi0shB+15wYXz4E8+oT1WEj+Rot18sp GK+F0R6onuXwELXqD4oEtwl3SlI7ULbtg4UwAxy5GU6CHr14lye5thhcyMrdF0LNYNh3 DX1g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=dEpkR8UK9KOJvrmhJNZu9PfS2JIzIrvWI0Xt9usQV+8=; b=BaRXow303UoVnkLsJ84P9mg8B9b28c5UKcXWS2BkVJemdix5jhuxbEPKjyZu35ocSa HZiwbT6AZxEjZyMLrKDlA+EMPPZG3kLchvb4OFqlfa8MWx7xAVCXJlbIe28ieVLAIZb4 L2trYErBKtQwZfD/zHMz+emV8phuEOOEnKeQfR2G8aYYY16Xx2TG7phLkOzAqv2oyijc Kyea5Ai/4Y/FtzTSpnArRiTqBlr88YJ2L0RAaZq/1VN0fxZJhls1/xYZLzpGo9Ma1haq VLdNkGmoB1rnCV0gVV09T7qoABpOCtc6a0vsaAdfpUVzibotm4RXRL6UDS4Y4pmTpUdn 6A1Q== X-Gm-Message-State: ANoB5pkOW0F2Ks9YQ/ByEfzOvgYSOVAmcxocerohTtffNQq+mtqU/15e 9yiFHfHnmM/zPmN1PqwX2dBui4KZQPnHZZC6n2o= X-Google-Smtp-Source: AA0mqf7wKKg+D/L2ielM6Io2lfClqGFvlLpgno1NnJlxXoaTfNYaQdd2piapgC1wDrk6XJ5TED8pO3hQa8arX+rFIso= X-Received: by 2002:ac2:5dd3:0:b0:4a2:6e1d:f996 with SMTP id x19-20020ac25dd3000000b004a26e1df996mr2386771lfq.114.1668777462738; Fri, 18 Nov 2022 05:17:42 -0800 (PST) MIME-Version: 1.0 References: In-Reply-To: From: Richard Biener Date: Fri, 18 Nov 2022 14:17:30 +0100 Message-ID: Subject: Re: [PATCH] Add a new target hook: TARGET_START_CALL_ARGS To: Richard Sandiford , gcc-patches@gcc.gnu.org Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-7.0 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,GIT_PATCH_0,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: On Fri, Nov 11, 2022 at 5:29 PM Richard Sandiford via Gcc-patches wrote: > > 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 pseudos > 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. > > Tested on aarch64-linux-gnu and x86_64-linux-gnu. Also tested by > building cc1 for nvptx-none. OK to install? OK. Thanks, Richard. > Richard > > > gcc/ > * doc/gccint/target-macros/implementing-the-varargs-macros.rst: > Add TARGET_START_CALL_ARGS. > * doc/gccint/target-macros/tm.rst.in: 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 +- > .../implementing-the-varargs-macros.rst | 5 ++ > gcc/doc/gccint/target-macros/tm.rst.in | 53 +++++++++++++--- > gcc/hooks.cc | 5 -- > gcc/hooks.h | 1 - > gcc/target.def | 56 +++++++++++++---- > 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 51b664f1b4d..d3287bcc277 100644 > --- a/gcc/calls.cc > +++ b/gcc/calls.cc > @@ -3542,15 +3542,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; > @@ -3613,15 +3624,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; > @@ -3920,7 +3922,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 (); > @@ -4478,17 +4480,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. */ > > @@ -4606,6 +4600,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 > @@ -4712,10 +4720,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) > @@ -4735,7 +4740,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 2fe120b3873..0fa0aefe613 100644 > --- a/gcc/config/nvptx/nvptx.cc > +++ b/gcc/config/nvptx/nvptx.cc > @@ -1790,7 +1790,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) > { > @@ -1818,7 +1818,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/gccint/target-macros/implementing-the-varargs-macros.rst b/gcc/doc/gccint/target-macros/implementing-the-varargs-macros.rst > index 1c940945056..8dd1ffab1b4 100644 > --- a/gcc/doc/gccint/target-macros/implementing-the-varargs-macros.rst > +++ b/gcc/doc/gccint/target-macros/implementing-the-varargs-macros.rst > @@ -91,6 +91,11 @@ These machine description macros help implement varargs: > :end-before: [TARGET_STRICT_ARGUMENT_NAMING] > > > +.. include:: tm.rst.in > + :start-after: [TARGET_START_CALL_ARGS] > + :end-before: [TARGET_START_CALL_ARGS] > + > + > .. include:: tm.rst.in > :start-after: [TARGET_CALL_ARGS] > :end-before: [TARGET_CALL_ARGS] > diff --git a/gcc/doc/gccint/target-macros/tm.rst.in b/gcc/doc/gccint/target-macros/tm.rst.in > index a19fa38b811..04be4bda3f6 100644 > --- a/gcc/doc/gccint/target-macros/tm.rst.in > +++ b/gcc/doc/gccint/target-macros/tm.rst.in > @@ -4346,31 +4346,64 @@ > > [TARGET_SETUP_INCOMING_VARARGS] > > +[TARGET_START_CALL_ARGS] > +.. function:: void TARGET_START_CALL_ARGS (cumulative_args_t 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 ``TARGET_CALL_ARGS`` and ``TARGET_END_CALL_ARGS``. The significance > + of this position in the call expansion is that: > + > + * No argument registers are live. > + > + * Although a call sequence can in general involve subcalls (such as using > + ``memcpy`` to copy large arguments), no such subcall will occur between > + the call to this hook and the generation of the main call instruction. > + > + The single argument :samp:`complete_args` is the state of the target > + function's cumulative argument information after the final call to > + ``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. > + > +[TARGET_START_CALL_ARGS] > + > [TARGET_CALL_ARGS] > -.. function:: void TARGET_CALL_ARGS (rtx, tree) > +.. function:: void TARGET_CALL_ARGS (cumulative_args_t complete_args, rtx loc, tree 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 > ``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 > - ``NULL_TREE`` for libcalls. The ``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. > + > + :samp:`complete_args` is the state of the target function's cumulative > + argument information after the final call to ``TARGET_FUNCTION_ARG``. > + :samp:`loc` is the location of the argument. :samp:`type` is the type of > + the function being called, or ``NULL_TREE`` for libcalls. > + > For functions without arguments, the hook is called once with ``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. > > [TARGET_CALL_ARGS] > > [TARGET_END_CALL_ARGS] > -.. function:: void TARGET_END_CALL_ARGS (void) > +.. function:: void TARGET_END_CALL_ARGS (cumulative_args_t 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. :samp:`complete_args` is the > + state of the target function's cumulative argument information after > + the final call to ``TARGET_FUNCTION_ARG``. > + > Most ports do not need to implement anything for this hook. > > [TARGET_END_CALL_ARGS] > diff --git a/gcc/hooks.cc b/gcc/hooks.cc > index b29233f4f85..0f4e7ce1047 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 1056e1e9e4d..e2a742f4325 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 15fd939200b..e6a388f9675 100644 > --- a/gcc/target.def > +++ b/gcc/target.def > @@ -4732,32 +4732,64 @@ 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 ``TARGET_CALL_ARGS`` and ``TARGET_END_CALL_ARGS``. The significance\n\ > +of this position in the call expansion is that:\n\ > +\n\ > +* No argument registers are live.\n\ > +\n\ > +* Although a call sequence can in general involve subcalls (such as using\n\ > + ``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\ > +\n\ > +The single argument :samp:`complete_args` is the state of the target\n\ > +function's cumulative argument information after the final call to\n\ > +``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\ > ``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\ > -``NULL_TREE`` for libcalls. The ``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\ > +:samp:`complete_args` is the state of the target function's cumulative\n\ > +argument information after the final call to ``TARGET_FUNCTION_ARG``.\n\ > +:samp:`loc` is the location of the argument. :samp:`type` is the type of\n\ > +the function being called, or ``NULL_TREE`` for libcalls.\n\ > +\n\ > For functions without arguments, the hook is called once with ``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. :samp:`complete_args` is the\n\ > +state of the target function's cumulative argument information after\n\ > +the final call to ``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 12a58456b39..f8b9a01b817 100644 > --- a/gcc/targhooks.cc > +++ b/gcc/targhooks.cc > @@ -773,12 +773,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 a6a423c1abb..1c43cefdcae 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.25.1 >