On Mon, Jun 2, 2025 at 4:07 PM Richard Sandiford
<richard.sandif...@arm.com> wrote:
>
> "H.J. Lu" <hjl.to...@gmail.com> writes:
> > Since not all CALL instructions in RTL passes have a REG_CALL_DECL note,
> > update get_call_fndecl to also check function symbol for function
> > declaration so that it can be used on CALL instructions like
> >
> > (call_insn 39 38 61 7 (set (reg:SI 0 ax)
> >         (call (mem:QI (symbol_ref:DI ("foo") [flags 0x3]
> > <function_decl 0x7fffe96da900 foo>) [0 foo S1 A8])
> >             (const_int 0 [0]))) "pr92080-15.c":24:9 1480 {*call_value}
> >      (expr_list:REG_DEAD (reg:SI 5 di)
> >         (expr_list:REG_DEAD (reg:SI 4 si)
> >             (expr_list:REG_EH_REGION (const_int 0 [0])
> >                 (nil))))
> >     (expr_list:SI (use (reg:SI 5 di))
> >         (expr_list:SI (use (reg:SI 4 si))
> >             (nil))))
> >
> > PR other/120494
> > * rtlanal.cc (get_call_fndecl): Also check function symbol to
> > get function declaration.
>
> What's your use case for this?  I think we should instead move to making
> the notes more generally available, since looking at the call rtx won't
> work for targets that need indirect calls (e.g. for -mlong-calls).

I am working on a pass which needs to check if CALL insn is a recursive call.
Currently I have

* Get the declaration of the function called by INSN.  If INDIRECT_P
   is true, also get indirect declaration.  */

static tree
get_call_fndecl_from_rtx (const rtx_insn *insn, bool indirect_p = false)
{
  rtx note = find_reg_note (insn, REG_CALL_DECL, NULL_RTX);
  if (note)
    {
      rtx datum = XEXP (note, 0);
      if (datum)
        return SYMBOL_REF_DECL (datum);
    }
  rtx call = get_call_rtx_from (insn);
  rtx fnaddr = XEXP (call, 0);
  rtx addr = XEXP (fnaddr, 0);
  if (GET_CODE (addr) == SYMBOL_REF)
    {
      tree fndecl = SYMBOL_REF_DECL (addr);
      if (fndecl && TREE_CODE (fndecl) == FUNCTION_DECL)
        return fndecl;
    }
  return indirect_p ? MEM_EXPR (fnaddr) : nullptr;
}

          if (CALL_P (insn))
            {
              tree fndecl = get_call_fndecl_from_rtx (insn);
              if (fndecl == current_function_decl
                  && decl_binds_to_current_def_p (fndecl))
                {
                  recursive_call_p = true;
                  break;
                }
            }

If get_call_fndecl works without a REG_CALL_DECL note, I can use it
instead of writing my own.


> Thanks,
> Richard
>
> >
> > --
> > H.J.
> >
> > From 6e20aad0c0b02c688f93ebc20b160f31c23adc82 Mon Sep 17 00:00:00 2001
> > From: "H.J. Lu" <hjl.to...@gmail.com>
> > Date: Sat, 31 May 2025 08:42:21 +0800
> > Subject: [PATCH] Also check function symbol for function declaration
> >
> > Since not all CALL instructions in RTL passes have a REG_CALL_DECL note,
> > update get_call_fndecl to also check function symbol for function
> > declaration so that it can be used on CALL instructions like
> >
> > (call_insn 39 38 61 7 (set (reg:SI 0 ax)
> >         (call (mem:QI (symbol_ref:DI ("foo") [flags 0x3] <function_decl 
> > 0x7fffe96da900 foo>) [0 foo S1 A8])
> >             (const_int 0 [0]))) "pr92080-15.c":24:9 1480 {*call_value}
> >      (expr_list:REG_DEAD (reg:SI 5 di)
> >         (expr_list:REG_DEAD (reg:SI 4 si)
> >             (expr_list:REG_EH_REGION (const_int 0 [0])
> >                 (nil))))
> >     (expr_list:SI (use (reg:SI 5 di))
> >         (expr_list:SI (use (reg:SI 4 si))
> >             (nil))))
> >
> >        PR other/120494
> >        * rtlanal.cc (get_call_fndecl): Also check function symbol to
> >        get function declaration.
> >
> > Signed-off-by: H.J. Lu <hjl.to...@gmail.com>
> > ---
> >  gcc/rtlanal.cc | 31 +++++++++++++++++++++----------
> >  1 file changed, 21 insertions(+), 10 deletions(-)
> >
> > diff --git a/gcc/rtlanal.cc b/gcc/rtlanal.cc
> > index 900f53e252a..b0983f8ebfc 100644
> > --- a/gcc/rtlanal.cc
> > +++ b/gcc/rtlanal.cc
> > @@ -833,17 +833,28 @@ get_call_rtx_from (const rtx_insn *insn)
> >  tree
> >  get_call_fndecl (const rtx_insn *insn)
> >  {
> > -  rtx note, datum;
> > -
> > +  rtx note;
> >    note = find_reg_note (insn, REG_CALL_DECL, NULL_RTX);
> > -  if (note == NULL_RTX)
> > -    return NULL_TREE;
> > -
> > -  datum = XEXP (note, 0);
> > -  if (datum != NULL_RTX)
> > -    return SYMBOL_REF_DECL (datum);
> > -
> > -  return NULL_TREE;
> > +  if (note)
> > +    {
> > +      rtx datum = XEXP (note, 0);
> > +      if (datum)
> > +     return SYMBOL_REF_DECL (datum);
> > +    }
> > +  rtx call = get_call_rtx_from (insn);
> > +  rtx addr = XEXP (call, 0);
> > +  tree fndecl = nullptr;
> > +  if (MEM_P (addr))
> > +    {
> > +      addr = XEXP (addr, 0);
> > +      if (GET_CODE (addr) == SYMBOL_REF)
> > +     {
> > +       tree decl = SYMBOL_REF_DECL (addr);
> > +       if (decl && TREE_CODE (decl) == FUNCTION_DECL)
> > +         fndecl = decl;
> > +     }
> > +    }
> > +  return fndecl;
> >  }
> >
> >  /* Return the value of the integer term in X, if one is apparent;



-- 
H.J.

Reply via email to