On Fri, 8 Nov 2024, Richard Sandiford wrote:

> For the aarch64 simd clones patches, it would be useful to be able to
> push a function declaration onto the cfun stack, even though it has no
> function body associated with it.  That is, we want cfun to be null,
> current_function_decl to be the decl itself, and the target and
> optimisation flags to reflect the declaration.
> 
> This patch adds a push/pop_function_decl pair to do that.
> 
> I think the more direct way of doing what I want to do under the
> existing interface would have been:
> 
>   push_cfun (nullptr);
>   invoke_set_current_function_hook (fndecl);
>   pop_cfun ();
> 
> where invoke_set_current_function_hook would need to become public.
> But it seemed safer to use the higher-level routines, since it makes
> sure that the target/optimisation changes are synchronised with the
> function changes.  In particular, if cfun was null before the
> sequence above, the pop_cfun would leave the flags unchanged,
> rather than restore them to the state before the push_cfun.
> 
> I realise this might seem a bit clunky though, so please let me know
> if you think there's a cleaner way.  I did briefly consider trying
> to clean up all the cfun/current_function_decl stuff, but I don't think
> I'll have time for that before stage 1.
> 
> Bootstrapped & regression-tested on aarch64-linux-gnu.  OK for trunk?

I think this is reasonable, thus OK unless you hear otherwise over
the weekend.

Richard.

> Thanks,
> Richard
> 
> 
> gcc/
>       * function.h (push_function_decl, pop_function_decl): Declare.
>       * function.cc (set_function_decl): New function, extracted from...
>       (set_cfun): ...here.
>       (push_function_decl): New function, extracted from...
>       (push_cfun): ...here.
>       (pop_cfun_1): New function, extracted from...
>       (pop_cfun): ...here.
>       (pop_function_decl): New function.
> ---
>  gcc/function.cc | 80 +++++++++++++++++++++++++++++++++++++++++--------
>  gcc/function.h  |  2 ++
>  2 files changed, 69 insertions(+), 13 deletions(-)
> 
> diff --git a/gcc/function.cc b/gcc/function.cc
> index 73490f0da10..bf74e1ea208 100644
> --- a/gcc/function.cc
> +++ b/gcc/function.cc
> @@ -4707,40 +4707,74 @@ invoke_set_current_function_hook (tree fndecl)
>      }
>  }
>  
> -/* cfun should never be set directly; use this function.  */
> +/* Set cfun to NEW_CFUN and switch to the optimization and target options
> +   associated with NEW_FNDECL.
>  
> -void
> -set_cfun (struct function *new_cfun, bool force)
> +   FORCE says whether we should do the switch even if NEW_CFUN is the current
> +   function, e.g. because there has been a change in optimization or target
> +   options.  */
> +
> +static void
> +set_function_decl (function *new_cfun, tree new_fndecl, bool force)
>  {
>    if (cfun != new_cfun || force)
>      {
>        cfun = new_cfun;
> -      invoke_set_current_function_hook (new_cfun ? new_cfun->decl : 
> NULL_TREE);
> +      invoke_set_current_function_hook (new_fndecl);
>        redirect_edge_var_map_empty ();
>      }
>  }
>  
> +/* cfun should never be set directly; use this function.  */
> +
> +void
> +set_cfun (struct function *new_cfun, bool force)
> +{
> +  set_function_decl (new_cfun, new_cfun ? new_cfun->decl : NULL_TREE, force);
> +}
> +
>  /* Initialized with NOGC, making this poisonous to the garbage collector.  */
>  
>  static vec<function *> cfun_stack;
>  
> -/* Push the current cfun onto the stack, and set cfun to new_cfun.  Also set
> -   current_function_decl accordingly.  */
> +/* Push the current cfun onto the stack, then switch to function NEW_CFUN
> +   and FUNCTION_DECL NEW_FNDECL.  FORCE is as for set_function_decl.  */
>  
> -void
> -push_cfun (struct function *new_cfun)
> +static void
> +push_function_decl (function *new_cfun, tree new_fndecl, bool force)
>  {
>    gcc_assert ((!cfun && !current_function_decl)
>             || (cfun && current_function_decl == cfun->decl));
>    cfun_stack.safe_push (cfun);
> -  current_function_decl = new_cfun ? new_cfun->decl : NULL_TREE;
> -  set_cfun (new_cfun);
> +  current_function_decl = new_fndecl;
> +  set_function_decl (new_cfun, new_fndecl, force);
>  }
>  
> -/* Pop cfun from the stack.  Also set current_function_decl accordingly.  */
> +/* Push the current cfun onto the stack and switch to function declaration
> +   NEW_FNDECL, which might or might not have a function body.  FORCE is as 
> for
> +   set_function_decl.  */
>  
>  void
> -pop_cfun (void)
> +push_function_decl (tree new_fndecl, bool force)
> +{
> +  force |= current_function_decl != new_fndecl;
> +  push_function_decl (DECL_STRUCT_FUNCTION (new_fndecl), new_fndecl, force);
> +}
> +
> +/* Push the current cfun onto the stack, and set cfun to new_cfun.  Also set
> +   current_function_decl accordingly.  */
> +
> +void
> +push_cfun (struct function *new_cfun)
> +{
> +  push_function_decl (new_cfun, new_cfun ? new_cfun->decl : NULL_TREE, 
> false);
> +}
> +
> +/* A common subroutine for pop_cfun and pop_function_decl.  FORCE is as
> +   for set_function_decl.  */
> +
> +static void
> +pop_cfun_1 (bool force)
>  {
>    struct function *new_cfun = cfun_stack.pop ();
>    /* When in_dummy_function, we do have a cfun but current_function_decl is
> @@ -4750,10 +4784,30 @@ pop_cfun (void)
>    gcc_checking_assert (in_dummy_function
>                      || !cfun
>                      || current_function_decl == cfun->decl);
> -  set_cfun (new_cfun);
> +  set_cfun (new_cfun, force);
>    current_function_decl = new_cfun ? new_cfun->decl : NULL_TREE;
>  }
>  
> +/* Pop cfun from the stack.  Also set current_function_decl accordingly.  */
> +
> +void
> +pop_cfun (void)
> +{
> +  pop_cfun_1 (false);
> +}
> +
> +/* Undo push_function_decl.  */
> +
> +void
> +pop_function_decl (void)
> +{
> +  /* If the previous cfun was null, the options should be reset to the
> +     global set.  Checking the current cfun against the new (popped) cfun
> +     wouldn't catch this if the current function decl has no function
> +     struct.  */
> +  pop_cfun_1 (!cfun_stack.last ());
> +}
> +
>  /* Return value of funcdef and increase it.  */
>  int
>  get_next_funcdef_no (void)
> diff --git a/gcc/function.h b/gcc/function.h
> index 243f5dd1b8c..92ba93c3f70 100644
> --- a/gcc/function.h
> +++ b/gcc/function.h
> @@ -701,6 +701,8 @@ extern void number_blocks (tree);
>  extern void set_cfun (struct function *new_cfun, bool force = false);
>  extern void push_cfun (struct function *new_cfun);
>  extern void pop_cfun (void);
> +extern void push_function_decl (tree, bool = false);
> +extern void pop_function_decl (void);
>  
>  extern int get_next_funcdef_no (void);
>  extern int get_last_funcdef_no (void);
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)

Reply via email to