public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Accessing const parameter of GIMPLE_CALL
@ 2022-01-16 13:22 Shubham Narlawar
  2022-01-16 23:53 ` David Malcolm
  0 siblings, 1 reply; 9+ messages in thread
From: Shubham Narlawar @ 2022-01-16 13:22 UTC (permalink / raw)
  To: GCC Development

Hello,

My aim is to iterate over gimple call stmt parameters and check
whether it is constant or constant expression and mark/store them for
some gimple transformation.

I have an intrinsic function call of the following -

__builtin_xyz(void*, 7, addr + 10);

I want to find its parameters which are either constant or constant
expression i.e. 7 and addr + 10 from above case.

[1] I tried below macro but there is very less usage in the entire source code -

tree fn_ptr = gimple_call_fn (dyn_cast<gcall *> (stmt));        //stmt
= gimple_call
function_args_iterator iter;
tree argtype;

if (TREE_CODE (fn_ptr) == ADDR_EXPR)
{
  FOREACH_FUNCTION_ARGS (fn_ptr, argtype, iter)
    {
        if (TREE_CONSTANT (argtype))
           // Found a constant expression parameter
    }
}

The problem is I am getting only one parameter tree but there are 2
constants in the above function call. Even if "addr + 10" is treated
differently, I want to mark it for the transformation.

a. Is the above correct method to iterate over function call parameters?
b. Is there a different way to achieve the above goal?

Thanks and Regards,
Shubham

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Accessing const parameter of GIMPLE_CALL
  2022-01-16 13:22 Accessing const parameter of GIMPLE_CALL Shubham Narlawar
@ 2022-01-16 23:53 ` David Malcolm
  2022-01-17  8:25   ` Richard Biener
  2022-01-17 19:18   ` Shubham Narlawar
  0 siblings, 2 replies; 9+ messages in thread
From: David Malcolm @ 2022-01-16 23:53 UTC (permalink / raw)
  To: Shubham Narlawar, GCC Development

On Sun, 2022-01-16 at 18:52 +0530, Shubham Narlawar via Gcc wrote:
> Hello,

Hi; various notes inline below...

> 
> My aim is to iterate over gimple call stmt parameters and check
> whether it is constant or constant expression and mark/store them for
> some gimple transformation.
> 
> I have an intrinsic function call of the following -
> 
> __builtin_xyz(void*, 7, addr + 10);
> 
> I want to find its parameters which are either constant or constant
> expression i.e. 7 and addr + 10 from above case.

Gimple "flattens" all tree-like operations into a sequence of simple
operations, so I would expect the gimple for this to look something
like this:

   _tmp = addr + 10;
   __builtin_xyx (7, _tmp);

Your email doesn't specify *when* your code runs.

The IR for a function goes through several stages:

- an initial gimple IR without a CFG
- gimple with a CFG, but not in SSA
- gimple-SSA with a CFG
  (most of the gimple optimization passes operate in this form of the
IR)
- gimple with a CFG, but no longer in CFG form, immediately before
conversion to RTL-with-CFG form
- RTL-with-CFG
- RTL-without a CFG
- assembler

Are you doing it as part of a plugin, or modifying an existing pass? 
In either case, it's a good idea to dump the gimple and see what the
code has been turned into.  You'll probably find the following options
useful:
  -fdump-tree-all -fdump-gimple-all

or alternatively just turn it on for the pass that you're working on.

> 
> [1] I tried below macro but there is very less usage in the entire
> source code -
> 
> tree fn_ptr = gimple_call_fn (dyn_cast<gcall *> (stmt));        //stmt

gimple_call_fn returns the function that will be called, a pointer. 
This is very general, for handling things like jumps through function
pointers, but here you have the common case of a callsite that calls a
specific function, so "fn_ptr" here is:
   &__builtin_xyx
i.e. an ADDR_EXPR where operand 0 is the FUNCTION_DECL for the builtin.

> = gimple_call
> function_args_iterator iter;
> tree argtype;
> 
> if (TREE_CODE (fn_ptr) == ADDR_EXPR)
> {
>   FOREACH_FUNCTION_ARGS (fn_ptr, argtype, iter)

Looking in tree.h, FOREACH_FUNCTION_ARGS takes a FUNCTION_TYPE as its
first argument, but the code above is passing it the ADDR_EXPR wrapping
the FUNCTION_DECL.

Unfortunately, because these things are all of type "tree", this kind
of type mismatch doesn't get caught - unless you build gcc from source
(with --enable-checking=debug) in which case all these accesses are
checked at the compiler's run time (which is probably a good thing to
do if you're hoping to work on gcc for GSoC).

You can get the FUNCTION_TYPE of a FUNCTION_DECL via TREE_TYPE
(fndecl), or alternatively, gimple_call_fntype (call) will get the type
of the function expected at the call stmt (useful if there was a type
mismatch).

That said, FOREACH_FUNCTION_ARGS iterates through the types of the
params of the FUNCTION_TYPE, but it sounds like you want to be
iterating through the arguments at this particular *callsite*.

For that you can use
  gimple_call_num_args (call);
and
  gimple_call_arg (call, idx);

>     {
>         if (TREE_CONSTANT (argtype))
>            // Found a constant expression parameter
>     }
> }
> 
> The problem is I am getting only one parameter tree but there are 2
> constants in the above function call. Even if "addr + 10" is treated
> differently, I want to mark it for the transformation.

I think you're seeing the function pointer being called, ather than the
params.

> 
> a. Is the above correct method to iterate over function call
> parameters?

As noted above, it depends on whether you want to iterate over the
types of the parameters in the function's decl, or over the expressions
of the arguments at the callsite.  I believe the above explains how to
do each of these.

> b. Is there a different way to achieve the above goal?

If you're looking to get familiar with GCC's insides, I recommend
stepping through it in the debugger, rather than relying on injecting
print statements and recompiling, since the former makes it much easier
to spot mistakes like the one above (which we all make).

I've written a guide to debugging GCC here:

https://dmalcolm.fedorapeople.org/gcc/newbies-guide/debugging.html


Hope this is helpful
Dave


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Accessing const parameter of GIMPLE_CALL
  2022-01-16 23:53 ` David Malcolm
@ 2022-01-17  8:25   ` Richard Biener
  2022-01-17 19:18     ` Shubham Narlawar
  2022-01-17 19:18   ` Shubham Narlawar
  1 sibling, 1 reply; 9+ messages in thread
From: Richard Biener @ 2022-01-17  8:25 UTC (permalink / raw)
  To: David Malcolm; +Cc: Shubham Narlawar, GCC Development

On Mon, Jan 17, 2022 at 12:54 AM David Malcolm via Gcc <gcc@gcc.gnu.org> wrote:
>
> On Sun, 2022-01-16 at 18:52 +0530, Shubham Narlawar via Gcc wrote:
> > Hello,
>
> Hi; various notes inline below...
>
> >
> > My aim is to iterate over gimple call stmt parameters and check
> > whether it is constant or constant expression and mark/store them for
> > some gimple transformation.
> >
> > I have an intrinsic function call of the following -
> >
> > __builtin_xyz(void*, 7, addr + 10);
> >
> > I want to find its parameters which are either constant or constant
> > expression i.e. 7 and addr + 10 from above case.
>
> Gimple "flattens" all tree-like operations into a sequence of simple
> operations, so I would expect the gimple for this to look something
> like this:
>
>    _tmp = addr + 10;
>    __builtin_xyx (7, _tmp);
>
> Your email doesn't specify *when* your code runs.
>
> The IR for a function goes through several stages:
>
> - an initial gimple IR without a CFG
> - gimple with a CFG, but not in SSA
> - gimple-SSA with a CFG
>   (most of the gimple optimization passes operate in this form of the
> IR)
> - gimple with a CFG, but no longer in CFG form, immediately before
> conversion to RTL-with-CFG form
> - RTL-with-CFG
> - RTL-without a CFG
> - assembler
>
> Are you doing it as part of a plugin, or modifying an existing pass?
> In either case, it's a good idea to dump the gimple and see what the
> code has been turned into.  You'll probably find the following options
> useful:
>   -fdump-tree-all -fdump-gimple-all
>
> or alternatively just turn it on for the pass that you're working on.
>
> >
> > [1] I tried below macro but there is very less usage in the entire
> > source code -
> >
> > tree fn_ptr = gimple_call_fn (dyn_cast<gcall *> (stmt));        //stmt
>
> gimple_call_fn returns the function that will be called, a pointer.
> This is very general, for handling things like jumps through function
> pointers, but here you have the common case of a callsite that calls a
> specific function, so "fn_ptr" here is:
>    &__builtin_xyx
> i.e. an ADDR_EXPR where operand 0 is the FUNCTION_DECL for the builtin.
>
> > = gimple_call
> > function_args_iterator iter;
> > tree argtype;
> >
> > if (TREE_CODE (fn_ptr) == ADDR_EXPR)
> > {
> >   FOREACH_FUNCTION_ARGS (fn_ptr, argtype, iter)
>
> Looking in tree.h, FOREACH_FUNCTION_ARGS takes a FUNCTION_TYPE as its
> first argument, but the code above is passing it the ADDR_EXPR wrapping
> the FUNCTION_DECL.
>
> Unfortunately, because these things are all of type "tree", this kind
> of type mismatch doesn't get caught - unless you build gcc from source
> (with --enable-checking=debug) in which case all these accesses are
> checked at the compiler's run time (which is probably a good thing to
> do if you're hoping to work on gcc for GSoC).
>
> You can get the FUNCTION_TYPE of a FUNCTION_DECL via TREE_TYPE
> (fndecl), or alternatively, gimple_call_fntype (call) will get the type
> of the function expected at the call stmt (useful if there was a type
> mismatch).
>
> That said, FOREACH_FUNCTION_ARGS iterates through the types of the
> params of the FUNCTION_TYPE, but it sounds like you want to be
> iterating through the arguments at this particular *callsite*.
>
> For that you can use
>   gimple_call_num_args (call);
> and
>   gimple_call_arg (call, idx);
>
> >     {
> >         if (TREE_CONSTANT (argtype))
> >            // Found a constant expression parameter
> >     }
> > }
> >
> > The problem is I am getting only one parameter tree but there are 2
> > constants in the above function call. Even if "addr + 10" is treated
> > differently, I want to mark it for the transformation.
>
> I think you're seeing the function pointer being called, ather than the
> params.

I think you are iterating over the functions formal argument types
rather than a specific call parameters.  To look at the actual
parameters use sth like

  for (unsigned i = 0; i < gimple_call_num_args (stmt); ++i)
    {
       tree arg = gimple_call_arg (stmt, i);
       if (CONSTANT_CLASS_P (arg))
         ...
    }

and replace CONSTANT_CLASS_P with is_gimple_ip_invariant ()
if you also want to handle symbolic constants like &global_var
as constant.

Richard.

> >
> > a. Is the above correct method to iterate over function call
> > parameters?
>
> As noted above, it depends on whether you want to iterate over the
> types of the parameters in the function's decl, or over the expressions
> of the arguments at the callsite.  I believe the above explains how to
> do each of these.
>
> > b. Is there a different way to achieve the above goal?
>
> If you're looking to get familiar with GCC's insides, I recommend
> stepping through it in the debugger, rather than relying on injecting
> print statements and recompiling, since the former makes it much easier
> to spot mistakes like the one above (which we all make).
>
> I've written a guide to debugging GCC here:
>
> https://dmalcolm.fedorapeople.org/gcc/newbies-guide/debugging.html
>
>
> Hope this is helpful
> Dave
>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Accessing const parameter of GIMPLE_CALL
  2022-01-16 23:53 ` David Malcolm
  2022-01-17  8:25   ` Richard Biener
@ 2022-01-17 19:18   ` Shubham Narlawar
  1 sibling, 0 replies; 9+ messages in thread
From: Shubham Narlawar @ 2022-01-17 19:18 UTC (permalink / raw)
  To: David Malcolm; +Cc: GCC Development

On Mon, Jan 17, 2022 at 5:23 AM David Malcolm <dmalcolm@redhat.com> wrote:
>
> On Sun, 2022-01-16 at 18:52 +0530, Shubham Narlawar via Gcc wrote:
> > Hello,
>
> Hi; various notes inline below...
>
> >
> > My aim is to iterate over gimple call stmt parameters and check
> > whether it is constant or constant expression and mark/store them for
> > some gimple transformation.
> >
> > I have an intrinsic function call of the following -
> >
> > __builtin_xyz(void*, 7, addr + 10);
> >
> > I want to find its parameters which are either constant or constant
> > expression i.e. 7 and addr + 10 from above case.
>
> Gimple "flattens" all tree-like operations into a sequence of simple
> operations, so I would expect the gimple for this to look something
> like this:
>
>    _tmp = addr + 10;
>    __builtin_xyx (7, _tmp);

Hi David,

Yeah. Correct.

>
> Your email doesn't specify *when* your code runs.
>
> The IR for a function goes through several stages:
>
> - an initial gimple IR without a CFG
> - gimple with a CFG, but not in SSA
> - gimple-SSA with a CFG
>   (most of the gimple optimization passes operate in this form of the
> IR)
> - gimple with a CFG, but no longer in CFG form, immediately before
> conversion to RTL-with-CFG form
> - RTL-with-CFG
> - RTL-without a CFG
> - assembler
>
> Are you doing it as part of a plugin, or modifying an existing pass?
> In either case, it's a good idea to dump the gimple and see what the
> code has been turned into.  You'll probably find the following options
> useful:
>   -fdump-tree-all -fdump-gimple-all
>
> or alternatively just turn it on for the pass that you're working on.

I am doing it as a plugin and it is placed just after
"pass_build_cgraph_edges" i.e. Call Graph Construction.

>
> >
> > [1] I tried below macro but there is very less usage in the entire
> > source code -
> >
> > tree fn_ptr = gimple_call_fn (dyn_cast<gcall *> (stmt));        //stmt
>
> gimple_call_fn returns the function that will be called, a pointer.
> This is very general, for handling things like jumps through function
> pointers, but here you have the common case of a callsite that calls a
> specific function, so "fn_ptr" here is:
>    &__builtin_xyx
> i.e. an ADDR_EXPR where operand 0 is the FUNCTION_DECL for the builtin.

Got it.

>
> > = gimple_call
> > function_args_iterator iter;
> > tree argtype;
> >
> > if (TREE_CODE (fn_ptr) == ADDR_EXPR)
> > {
> >   FOREACH_FUNCTION_ARGS (fn_ptr, argtype, iter)
>
> Looking in tree.h, FOREACH_FUNCTION_ARGS takes a FUNCTION_TYPE as its
> first argument, but the code above is passing it the ADDR_EXPR wrapping
> the FUNCTION_DECL.

Understood.

>
> Unfortunately, because these things are all of type "tree", this kind
> of type mismatch doesn't get caught - unless you build gcc from source
> (with --enable-checking=debug) in which case all these accesses are
> checked at the compiler's run time (which is probably a good thing to
> do if you're hoping to work on gcc for GSoC).

I am working on gcc version 10.2.0 and there is no such flag as
"--enable-checking" but there is "--enable-gcc-checking".

>
> You can get the FUNCTION_TYPE of a FUNCTION_DECL via TREE_TYPE
> (fndecl), or alternatively, gimple_call_fntype (call) will get the type
> of the function expected at the call stmt (useful if there was a type
> mismatch).
>
> That said, FOREACH_FUNCTION_ARGS iterates through the types of the
> params of the FUNCTION_TYPE, but it sounds like you want to be
> iterating through the arguments at this particular *callsite*.
>
> For that you can use
>   gimple_call_num_args (call);
> and
>   gimple_call_arg (call, idx);

Yes. This is exactly what I was looking for!

>
> >     {
> >         if (TREE_CONSTANT (argtype))
> >            // Found a constant expression parameter
> >     }
> > }
> >
> > The problem is I am getting only one parameter tree but there are 2
> > constants in the above function call. Even if "addr + 10" is treated
> > differently, I want to mark it for the transformation.
>
> I think you're seeing the function pointer being called, ather than the
> params.

Yes.

>
> >
> > a. Is the above correct method to iterate over function call
> > parameters?
>
> As noted above, it depends on whether you want to iterate over the
> types of the parameters in the function's decl, or over the expressions
> of the arguments at the callsite.  I believe the above explains how to
> do each of these.

Yes. Above clears all my queries and thanks for detailed explanation.
It has helped a lot!

>
> > b. Is there a different way to achieve the above goal?
>
> If you're looking to get familiar with GCC's insides, I recommend
> stepping through it in the debugger, rather than relying on injecting
> print statements and recompiling, since the former makes it much easier
> to spot mistakes like the one above (which we all make).

Sure.

>
> I've written a guide to debugging GCC here:
>
> https://dmalcolm.fedorapeople.org/gcc/newbies-guide/debugging.html

Thanks for sharing! It is helpful blog

Regards,
Shubham

>
>
> Hope this is helpful
> Dave
>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Accessing const parameter of GIMPLE_CALL
  2022-01-17  8:25   ` Richard Biener
@ 2022-01-17 19:18     ` Shubham Narlawar
  2022-01-17 20:49       ` Martin Sebor
  2022-01-18  8:50       ` Richard Biener
  0 siblings, 2 replies; 9+ messages in thread
From: Shubham Narlawar @ 2022-01-17 19:18 UTC (permalink / raw)
  To: Richard Biener; +Cc: David Malcolm, GCC Development

On Mon, Jan 17, 2022 at 1:55 PM Richard Biener
<richard.guenther@gmail.com> wrote:
>
> On Mon, Jan 17, 2022 at 12:54 AM David Malcolm via Gcc <gcc@gcc.gnu.org> wrote:
> >
> > On Sun, 2022-01-16 at 18:52 +0530, Shubham Narlawar via Gcc wrote:
> > > Hello,
> >
> > Hi; various notes inline below...
> >
> > >
> > > My aim is to iterate over gimple call stmt parameters and check
> > > whether it is constant or constant expression and mark/store them for
> > > some gimple transformation.
> > >
> > > I have an intrinsic function call of the following -
> > >
> > > __builtin_xyz(void*, 7, addr + 10);
> > >
> > > I want to find its parameters which are either constant or constant
> > > expression i.e. 7 and addr + 10 from above case.
> >
> > Gimple "flattens" all tree-like operations into a sequence of simple
> > operations, so I would expect the gimple for this to look something
> > like this:
> >
> >    _tmp = addr + 10;
> >    __builtin_xyx (7, _tmp);
> >
> > Your email doesn't specify *when* your code runs.
> >
> > The IR for a function goes through several stages:
> >
> > - an initial gimple IR without a CFG
> > - gimple with a CFG, but not in SSA
> > - gimple-SSA with a CFG
> >   (most of the gimple optimization passes operate in this form of the
> > IR)
> > - gimple with a CFG, but no longer in CFG form, immediately before
> > conversion to RTL-with-CFG form
> > - RTL-with-CFG
> > - RTL-without a CFG
> > - assembler
> >
> > Are you doing it as part of a plugin, or modifying an existing pass?
> > In either case, it's a good idea to dump the gimple and see what the
> > code has been turned into.  You'll probably find the following options
> > useful:
> >   -fdump-tree-all -fdump-gimple-all
> >
> > or alternatively just turn it on for the pass that you're working on.
> >
> > >
> > > [1] I tried below macro but there is very less usage in the entire
> > > source code -
> > >
> > > tree fn_ptr = gimple_call_fn (dyn_cast<gcall *> (stmt));        //stmt
> >
> > gimple_call_fn returns the function that will be called, a pointer.
> > This is very general, for handling things like jumps through function
> > pointers, but here you have the common case of a callsite that calls a
> > specific function, so "fn_ptr" here is:
> >    &__builtin_xyx
> > i.e. an ADDR_EXPR where operand 0 is the FUNCTION_DECL for the builtin.
> >
> > > = gimple_call
> > > function_args_iterator iter;
> > > tree argtype;
> > >
> > > if (TREE_CODE (fn_ptr) == ADDR_EXPR)
> > > {
> > >   FOREACH_FUNCTION_ARGS (fn_ptr, argtype, iter)
> >
> > Looking in tree.h, FOREACH_FUNCTION_ARGS takes a FUNCTION_TYPE as its
> > first argument, but the code above is passing it the ADDR_EXPR wrapping
> > the FUNCTION_DECL.
> >
> > Unfortunately, because these things are all of type "tree", this kind
> > of type mismatch doesn't get caught - unless you build gcc from source
> > (with --enable-checking=debug) in which case all these accesses are
> > checked at the compiler's run time (which is probably a good thing to
> > do if you're hoping to work on gcc for GSoC).
> >
> > You can get the FUNCTION_TYPE of a FUNCTION_DECL via TREE_TYPE
> > (fndecl), or alternatively, gimple_call_fntype (call) will get the type
> > of the function expected at the call stmt (useful if there was a type
> > mismatch).
> >
> > That said, FOREACH_FUNCTION_ARGS iterates through the types of the
> > params of the FUNCTION_TYPE, but it sounds like you want to be
> > iterating through the arguments at this particular *callsite*.
> >
> > For that you can use
> >   gimple_call_num_args (call);
> > and
> >   gimple_call_arg (call, idx);
> >
> > >     {
> > >         if (TREE_CONSTANT (argtype))
> > >            // Found a constant expression parameter
> > >     }
> > > }
> > >
> > > The problem is I am getting only one parameter tree but there are 2
> > > constants in the above function call. Even if "addr + 10" is treated
> > > differently, I want to mark it for the transformation.
> >
> > I think you're seeing the function pointer being called, ather than the
> > params.
>
> I think you are iterating over the functions formal argument types
> rather than a specific call parameters.  To look at the actual
> parameters use sth like
>
>   for (unsigned i = 0; i < gimple_call_num_args (stmt); ++i)
>     {
>        tree arg = gimple_call_arg (stmt, i);
>        if (CONSTANT_CLASS_P (arg))
>          ...
>     }
>
> and replace CONSTANT_CLASS_P with is_gimple_ip_invariant ()
> if you also want to handle symbolic constants like &global_var
> as constant.

Understood. I was iterating on formal parameters. But the above solves
the problem. CONSTANT_CLASS_P() and is_gimple_ip_invariant() are
helpful on integer constant.

In below gimple dump w.r.t code snippet shared by you from above -

def_stmt    _14 = (unsigned int) _13;
__builtin_xyz(instrn_buffer.3_11, 12, _14);

Here, all actual parameters are represented by tree whose classes are -

instrn_buffer.3_11 - tcc_exceptional
12 - tcc_constant
_14 - tcc_exceptional

The 1st and 3rd parameters are denoted by tcc_exceptional which fits
no category of tree, but I want to collect such 3rd parameter i.e. to
identify it whether it is variable or expression. Is it possible to do
it?

I want to mark _14 for gimple transformation if -
a. it is a variable like above _14 representing a constant.
b. it is a expression _14 + 7 i.e. again at gimple level, it is case (a)
c. it is a phi node which represents constant when there is a case of
ternary operator usage.

How to identify such an actual parameter of gimple call?

The aim of the above scenario is to identify such
variables/expressions and then apply constant folding and propagation.
If constant folding and propagation are not happening on actual
parameters of intrinsic call, then I need to write some plugin to do
it. My plugin is placed just after "pass_build_cgraph_edges" i.e.
Callgraph Construction.

Thanks for the helpful suggestions.

Regards,
Shubham


>
> Richard.
>
> > >
> > > a. Is the above correct method to iterate over function call
> > > parameters?
> >
> > As noted above, it depends on whether you want to iterate over the
> > types of the parameters in the function's decl, or over the expressions
> > of the arguments at the callsite.  I believe the above explains how to
> > do each of these.
> >
> > > b. Is there a different way to achieve the above goal?
> >
> > If you're looking to get familiar with GCC's insides, I recommend
> > stepping through it in the debugger, rather than relying on injecting
> > print statements and recompiling, since the former makes it much easier
> > to spot mistakes like the one above (which we all make).
> >
> > I've written a guide to debugging GCC here:
> >
> > https://dmalcolm.fedorapeople.org/gcc/newbies-guide/debugging.html
> >
> >
> > Hope this is helpful
> > Dave
> >

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Accessing const parameter of GIMPLE_CALL
  2022-01-17 19:18     ` Shubham Narlawar
@ 2022-01-17 20:49       ` Martin Sebor
  2022-01-18 18:45         ` Shubham Narlawar
  2022-01-18  8:50       ` Richard Biener
  1 sibling, 1 reply; 9+ messages in thread
From: Martin Sebor @ 2022-01-17 20:49 UTC (permalink / raw)
  To: Shubham Narlawar, Richard Biener; +Cc: GCC Development

On 1/17/22 12:18, Shubham Narlawar via Gcc wrote:
> On Mon, Jan 17, 2022 at 1:55 PM Richard Biener
> <richard.guenther@gmail.com> wrote:
>>
>> On Mon, Jan 17, 2022 at 12:54 AM David Malcolm via Gcc <gcc@gcc.gnu.org> wrote:
>>>
>>> On Sun, 2022-01-16 at 18:52 +0530, Shubham Narlawar via Gcc wrote:
>>>> Hello,
>>>
>>> Hi; various notes inline below...
>>>
>>>>
>>>> My aim is to iterate over gimple call stmt parameters and check
>>>> whether it is constant or constant expression and mark/store them for
>>>> some gimple transformation.
>>>>
>>>> I have an intrinsic function call of the following -
>>>>
>>>> __builtin_xyz(void*, 7, addr + 10);
>>>>
>>>> I want to find its parameters which are either constant or constant
>>>> expression i.e. 7 and addr + 10 from above case.
>>>
>>> Gimple "flattens" all tree-like operations into a sequence of simple
>>> operations, so I would expect the gimple for this to look something
>>> like this:
>>>
>>>     _tmp = addr + 10;
>>>     __builtin_xyx (7, _tmp);
>>>
>>> Your email doesn't specify *when* your code runs.
>>>
>>> The IR for a function goes through several stages:
>>>
>>> - an initial gimple IR without a CFG
>>> - gimple with a CFG, but not in SSA
>>> - gimple-SSA with a CFG
>>>    (most of the gimple optimization passes operate in this form of the
>>> IR)
>>> - gimple with a CFG, but no longer in CFG form, immediately before
>>> conversion to RTL-with-CFG form
>>> - RTL-with-CFG
>>> - RTL-without a CFG
>>> - assembler
>>>
>>> Are you doing it as part of a plugin, or modifying an existing pass?
>>> In either case, it's a good idea to dump the gimple and see what the
>>> code has been turned into.  You'll probably find the following options
>>> useful:
>>>    -fdump-tree-all -fdump-gimple-all
>>>
>>> or alternatively just turn it on for the pass that you're working on.
>>>
>>>>
>>>> [1] I tried below macro but there is very less usage in the entire
>>>> source code -
>>>>
>>>> tree fn_ptr = gimple_call_fn (dyn_cast<gcall *> (stmt));        //stmt
>>>
>>> gimple_call_fn returns the function that will be called, a pointer.
>>> This is very general, for handling things like jumps through function
>>> pointers, but here you have the common case of a callsite that calls a
>>> specific function, so "fn_ptr" here is:
>>>     &__builtin_xyx
>>> i.e. an ADDR_EXPR where operand 0 is the FUNCTION_DECL for the builtin.
>>>
>>>> = gimple_call
>>>> function_args_iterator iter;
>>>> tree argtype;
>>>>
>>>> if (TREE_CODE (fn_ptr) == ADDR_EXPR)
>>>> {
>>>>    FOREACH_FUNCTION_ARGS (fn_ptr, argtype, iter)
>>>
>>> Looking in tree.h, FOREACH_FUNCTION_ARGS takes a FUNCTION_TYPE as its
>>> first argument, but the code above is passing it the ADDR_EXPR wrapping
>>> the FUNCTION_DECL.
>>>
>>> Unfortunately, because these things are all of type "tree", this kind
>>> of type mismatch doesn't get caught - unless you build gcc from source
>>> (with --enable-checking=debug) in which case all these accesses are
>>> checked at the compiler's run time (which is probably a good thing to
>>> do if you're hoping to work on gcc for GSoC).
>>>
>>> You can get the FUNCTION_TYPE of a FUNCTION_DECL via TREE_TYPE
>>> (fndecl), or alternatively, gimple_call_fntype (call) will get the type
>>> of the function expected at the call stmt (useful if there was a type
>>> mismatch).
>>>
>>> That said, FOREACH_FUNCTION_ARGS iterates through the types of the
>>> params of the FUNCTION_TYPE, but it sounds like you want to be
>>> iterating through the arguments at this particular *callsite*.
>>>
>>> For that you can use
>>>    gimple_call_num_args (call);
>>> and
>>>    gimple_call_arg (call, idx);
>>>
>>>>      {
>>>>          if (TREE_CONSTANT (argtype))
>>>>             // Found a constant expression parameter
>>>>      }
>>>> }
>>>>
>>>> The problem is I am getting only one parameter tree but there are 2
>>>> constants in the above function call. Even if "addr + 10" is treated
>>>> differently, I want to mark it for the transformation.
>>>
>>> I think you're seeing the function pointer being called, ather than the
>>> params.
>>
>> I think you are iterating over the functions formal argument types
>> rather than a specific call parameters.  To look at the actual
>> parameters use sth like
>>
>>    for (unsigned i = 0; i < gimple_call_num_args (stmt); ++i)
>>      {
>>         tree arg = gimple_call_arg (stmt, i);
>>         if (CONSTANT_CLASS_P (arg))
>>           ...
>>      }
>>
>> and replace CONSTANT_CLASS_P with is_gimple_ip_invariant ()
>> if you also want to handle symbolic constants like &global_var
>> as constant.
> 
> Understood. I was iterating on formal parameters. But the above solves
> the problem. CONSTANT_CLASS_P() and is_gimple_ip_invariant() are
> helpful on integer constant.
> 
> In below gimple dump w.r.t code snippet shared by you from above -
> 
> def_stmt    _14 = (unsigned int) _13;
> __builtin_xyz(instrn_buffer.3_11, 12, _14);
> 
> Here, all actual parameters are represented by tree whose classes are -
> 
> instrn_buffer.3_11 - tcc_exceptional
> 12 - tcc_constant
> _14 - tcc_exceptional
> 
> The 1st and 3rd parameters are denoted by tcc_exceptional which fits
> no category of tree, but I want to collect such 3rd parameter i.e. to
> identify it whether it is variable or expression. Is it possible to do
> it?
> 
> I want to mark _14 for gimple transformation if -
> a. it is a variable like above _14 representing a constant.
> b. it is a expression _14 + 7 i.e. again at gimple level, it is case (a)
> c. it is a phi node which represents constant when there is a case of
> ternary operator usage.
> 
> How to identify such an actual parameter of gimple call?
> 
> The aim of the above scenario is to identify such
> variables/expressions and then apply constant folding and propagation.
> If constant folding and propagation are not happening on actual
> parameters of intrinsic call, then I need to write some plugin to do
> it. My plugin is placed just after "pass_build_cgraph_edges" i.e.
> Callgraph Construction.

I use the following code.  It runs after pass_build_ssa, so a bit
later than pass_build_cgraph_edges:

       /* Use the range query to determine constant values in the absence
	 of constant proppagation (such as at -O0).  */
       value_range rng;
       if (!get_range_query (cfun)->range_of_expr (rng, ord, stmt)
	  || !rng.constant_p ()
	  || !rng.singleton_p (&ord))
	return false;

       wide_int lob = rng.lower_bound ();
       if (!wi::fits_uhwi_p (lob))
	return false;

       val = lob.to_shwi ();

Martin

> 
> Thanks for the helpful suggestions.
> 
> Regards,
> Shubham
> 
> 
>>
>> Richard.
>>
>>>>
>>>> a. Is the above correct method to iterate over function call
>>>> parameters?
>>>
>>> As noted above, it depends on whether you want to iterate over the
>>> types of the parameters in the function's decl, or over the expressions
>>> of the arguments at the callsite.  I believe the above explains how to
>>> do each of these.
>>>
>>>> b. Is there a different way to achieve the above goal?
>>>
>>> If you're looking to get familiar with GCC's insides, I recommend
>>> stepping through it in the debugger, rather than relying on injecting
>>> print statements and recompiling, since the former makes it much easier
>>> to spot mistakes like the one above (which we all make).
>>>
>>> I've written a guide to debugging GCC here:
>>>
>>> https://dmalcolm.fedorapeople.org/gcc/newbies-guide/debugging.html
>>>
>>>
>>> Hope this is helpful
>>> Dave
>>>


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Accessing const parameter of GIMPLE_CALL
  2022-01-17 19:18     ` Shubham Narlawar
  2022-01-17 20:49       ` Martin Sebor
@ 2022-01-18  8:50       ` Richard Biener
  2022-01-18 18:50         ` Shubham Narlawar
  1 sibling, 1 reply; 9+ messages in thread
From: Richard Biener @ 2022-01-18  8:50 UTC (permalink / raw)
  To: Shubham Narlawar; +Cc: David Malcolm, GCC Development

On Mon, Jan 17, 2022 at 8:19 PM Shubham Narlawar <gsocshubham@gmail.com> wrote:
>
> On Mon, Jan 17, 2022 at 1:55 PM Richard Biener
> <richard.guenther@gmail.com> wrote:
> >
> > On Mon, Jan 17, 2022 at 12:54 AM David Malcolm via Gcc <gcc@gcc.gnu.org> wrote:
> > >
> > > On Sun, 2022-01-16 at 18:52 +0530, Shubham Narlawar via Gcc wrote:
> > > > Hello,
> > >
> > > Hi; various notes inline below...
> > >
> > > >
> > > > My aim is to iterate over gimple call stmt parameters and check
> > > > whether it is constant or constant expression and mark/store them for
> > > > some gimple transformation.
> > > >
> > > > I have an intrinsic function call of the following -
> > > >
> > > > __builtin_xyz(void*, 7, addr + 10);
> > > >
> > > > I want to find its parameters which are either constant or constant
> > > > expression i.e. 7 and addr + 10 from above case.
> > >
> > > Gimple "flattens" all tree-like operations into a sequence of simple
> > > operations, so I would expect the gimple for this to look something
> > > like this:
> > >
> > >    _tmp = addr + 10;
> > >    __builtin_xyx (7, _tmp);
> > >
> > > Your email doesn't specify *when* your code runs.
> > >
> > > The IR for a function goes through several stages:
> > >
> > > - an initial gimple IR without a CFG
> > > - gimple with a CFG, but not in SSA
> > > - gimple-SSA with a CFG
> > >   (most of the gimple optimization passes operate in this form of the
> > > IR)
> > > - gimple with a CFG, but no longer in CFG form, immediately before
> > > conversion to RTL-with-CFG form
> > > - RTL-with-CFG
> > > - RTL-without a CFG
> > > - assembler
> > >
> > > Are you doing it as part of a plugin, or modifying an existing pass?
> > > In either case, it's a good idea to dump the gimple and see what the
> > > code has been turned into.  You'll probably find the following options
> > > useful:
> > >   -fdump-tree-all -fdump-gimple-all
> > >
> > > or alternatively just turn it on for the pass that you're working on.
> > >
> > > >
> > > > [1] I tried below macro but there is very less usage in the entire
> > > > source code -
> > > >
> > > > tree fn_ptr = gimple_call_fn (dyn_cast<gcall *> (stmt));        //stmt
> > >
> > > gimple_call_fn returns the function that will be called, a pointer.
> > > This is very general, for handling things like jumps through function
> > > pointers, but here you have the common case of a callsite that calls a
> > > specific function, so "fn_ptr" here is:
> > >    &__builtin_xyx
> > > i.e. an ADDR_EXPR where operand 0 is the FUNCTION_DECL for the builtin.
> > >
> > > > = gimple_call
> > > > function_args_iterator iter;
> > > > tree argtype;
> > > >
> > > > if (TREE_CODE (fn_ptr) == ADDR_EXPR)
> > > > {
> > > >   FOREACH_FUNCTION_ARGS (fn_ptr, argtype, iter)
> > >
> > > Looking in tree.h, FOREACH_FUNCTION_ARGS takes a FUNCTION_TYPE as its
> > > first argument, but the code above is passing it the ADDR_EXPR wrapping
> > > the FUNCTION_DECL.
> > >
> > > Unfortunately, because these things are all of type "tree", this kind
> > > of type mismatch doesn't get caught - unless you build gcc from source
> > > (with --enable-checking=debug) in which case all these accesses are
> > > checked at the compiler's run time (which is probably a good thing to
> > > do if you're hoping to work on gcc for GSoC).
> > >
> > > You can get the FUNCTION_TYPE of a FUNCTION_DECL via TREE_TYPE
> > > (fndecl), or alternatively, gimple_call_fntype (call) will get the type
> > > of the function expected at the call stmt (useful if there was a type
> > > mismatch).
> > >
> > > That said, FOREACH_FUNCTION_ARGS iterates through the types of the
> > > params of the FUNCTION_TYPE, but it sounds like you want to be
> > > iterating through the arguments at this particular *callsite*.
> > >
> > > For that you can use
> > >   gimple_call_num_args (call);
> > > and
> > >   gimple_call_arg (call, idx);
> > >
> > > >     {
> > > >         if (TREE_CONSTANT (argtype))
> > > >            // Found a constant expression parameter
> > > >     }
> > > > }
> > > >
> > > > The problem is I am getting only one parameter tree but there are 2
> > > > constants in the above function call. Even if "addr + 10" is treated
> > > > differently, I want to mark it for the transformation.
> > >
> > > I think you're seeing the function pointer being called, ather than the
> > > params.
> >
> > I think you are iterating over the functions formal argument types
> > rather than a specific call parameters.  To look at the actual
> > parameters use sth like
> >
> >   for (unsigned i = 0; i < gimple_call_num_args (stmt); ++i)
> >     {
> >        tree arg = gimple_call_arg (stmt, i);
> >        if (CONSTANT_CLASS_P (arg))
> >          ...
> >     }
> >
> > and replace CONSTANT_CLASS_P with is_gimple_ip_invariant ()
> > if you also want to handle symbolic constants like &global_var
> > as constant.
>
> Understood. I was iterating on formal parameters. But the above solves
> the problem. CONSTANT_CLASS_P() and is_gimple_ip_invariant() are
> helpful on integer constant.
>
> In below gimple dump w.r.t code snippet shared by you from above -
>
> def_stmt    _14 = (unsigned int) _13;
> __builtin_xyz(instrn_buffer.3_11, 12, _14);
>
> Here, all actual parameters are represented by tree whose classes are -
>
> instrn_buffer.3_11 - tcc_exceptional
> 12 - tcc_constant
> _14 - tcc_exceptional
>
> The 1st and 3rd parameters are denoted by tcc_exceptional which fits
> no category of tree, but I want to collect such 3rd parameter i.e. to
> identify it whether it is variable or expression. Is it possible to do
> it?

You can check TREE_CODE (arg) == SSA_NAME and look at
the defining stmts via SSA_NAME_DEF_STMT.  Note that prior to
the into SSA pass only temporaries created by the gimplification
process are SSA names and some SSA data structures like
immediate uses are not available.

> I want to mark _14 for gimple transformation if -
> a. it is a variable like above _14 representing a constant.
> b. it is a expression _14 + 7 i.e. again at gimple level, it is case (a)
> c. it is a phi node which represents constant when there is a case of
> ternary operator usage.
>
> How to identify such an actual parameter of gimple call?
>
> The aim of the above scenario is to identify such
> variables/expressions and then apply constant folding and propagation.
> If constant folding and propagation are not happening on actual
> parameters of intrinsic call, then I need to write some plugin to do
> it. My plugin is placed just after "pass_build_cgraph_edges" i.e.
> Callgraph Construction.
>
> Thanks for the helpful suggestions.
>
> Regards,
> Shubham
>
>
> >
> > Richard.
> >
> > > >
> > > > a. Is the above correct method to iterate over function call
> > > > parameters?
> > >
> > > As noted above, it depends on whether you want to iterate over the
> > > types of the parameters in the function's decl, or over the expressions
> > > of the arguments at the callsite.  I believe the above explains how to
> > > do each of these.
> > >
> > > > b. Is there a different way to achieve the above goal?
> > >
> > > If you're looking to get familiar with GCC's insides, I recommend
> > > stepping through it in the debugger, rather than relying on injecting
> > > print statements and recompiling, since the former makes it much easier
> > > to spot mistakes like the one above (which we all make).
> > >
> > > I've written a guide to debugging GCC here:
> > >
> > > https://dmalcolm.fedorapeople.org/gcc/newbies-guide/debugging.html
> > >
> > >
> > > Hope this is helpful
> > > Dave
> > >

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Accessing const parameter of GIMPLE_CALL
  2022-01-17 20:49       ` Martin Sebor
@ 2022-01-18 18:45         ` Shubham Narlawar
  0 siblings, 0 replies; 9+ messages in thread
From: Shubham Narlawar @ 2022-01-18 18:45 UTC (permalink / raw)
  To: Martin Sebor; +Cc: Richard Biener, GCC Development

On Tue, Jan 18, 2022 at 2:19 AM Martin Sebor <msebor@gmail.com> wrote:
>
> On 1/17/22 12:18, Shubham Narlawar via Gcc wrote:
> > On Mon, Jan 17, 2022 at 1:55 PM Richard Biener
> > <richard.guenther@gmail.com> wrote:
> >>
> >> On Mon, Jan 17, 2022 at 12:54 AM David Malcolm via Gcc <gcc@gcc.gnu.org> wrote:
> >>>
> >>> On Sun, 2022-01-16 at 18:52 +0530, Shubham Narlawar via Gcc wrote:
> >>>> Hello,
> >>>
> >>> Hi; various notes inline below...
> >>>
> >>>>
> >>>> My aim is to iterate over gimple call stmt parameters and check
> >>>> whether it is constant or constant expression and mark/store them for
> >>>> some gimple transformation.
> >>>>
> >>>> I have an intrinsic function call of the following -
> >>>>
> >>>> __builtin_xyz(void*, 7, addr + 10);
> >>>>
> >>>> I want to find its parameters which are either constant or constant
> >>>> expression i.e. 7 and addr + 10 from above case.
> >>>
> >>> Gimple "flattens" all tree-like operations into a sequence of simple
> >>> operations, so I would expect the gimple for this to look something
> >>> like this:
> >>>
> >>>     _tmp = addr + 10;
> >>>     __builtin_xyx (7, _tmp);
> >>>
> >>> Your email doesn't specify *when* your code runs.
> >>>
> >>> The IR for a function goes through several stages:
> >>>
> >>> - an initial gimple IR without a CFG
> >>> - gimple with a CFG, but not in SSA
> >>> - gimple-SSA with a CFG
> >>>    (most of the gimple optimization passes operate in this form of the
> >>> IR)
> >>> - gimple with a CFG, but no longer in CFG form, immediately before
> >>> conversion to RTL-with-CFG form
> >>> - RTL-with-CFG
> >>> - RTL-without a CFG
> >>> - assembler
> >>>
> >>> Are you doing it as part of a plugin, or modifying an existing pass?
> >>> In either case, it's a good idea to dump the gimple and see what the
> >>> code has been turned into.  You'll probably find the following options
> >>> useful:
> >>>    -fdump-tree-all -fdump-gimple-all
> >>>
> >>> or alternatively just turn it on for the pass that you're working on.
> >>>
> >>>>
> >>>> [1] I tried below macro but there is very less usage in the entire
> >>>> source code -
> >>>>
> >>>> tree fn_ptr = gimple_call_fn (dyn_cast<gcall *> (stmt));        //stmt
> >>>
> >>> gimple_call_fn returns the function that will be called, a pointer.
> >>> This is very general, for handling things like jumps through function
> >>> pointers, but here you have the common case of a callsite that calls a
> >>> specific function, so "fn_ptr" here is:
> >>>     &__builtin_xyx
> >>> i.e. an ADDR_EXPR where operand 0 is the FUNCTION_DECL for the builtin.
> >>>
> >>>> = gimple_call
> >>>> function_args_iterator iter;
> >>>> tree argtype;
> >>>>
> >>>> if (TREE_CODE (fn_ptr) == ADDR_EXPR)
> >>>> {
> >>>>    FOREACH_FUNCTION_ARGS (fn_ptr, argtype, iter)
> >>>
> >>> Looking in tree.h, FOREACH_FUNCTION_ARGS takes a FUNCTION_TYPE as its
> >>> first argument, but the code above is passing it the ADDR_EXPR wrapping
> >>> the FUNCTION_DECL.
> >>>
> >>> Unfortunately, because these things are all of type "tree", this kind
> >>> of type mismatch doesn't get caught - unless you build gcc from source
> >>> (with --enable-checking=debug) in which case all these accesses are
> >>> checked at the compiler's run time (which is probably a good thing to
> >>> do if you're hoping to work on gcc for GSoC).
> >>>
> >>> You can get the FUNCTION_TYPE of a FUNCTION_DECL via TREE_TYPE
> >>> (fndecl), or alternatively, gimple_call_fntype (call) will get the type
> >>> of the function expected at the call stmt (useful if there was a type
> >>> mismatch).
> >>>
> >>> That said, FOREACH_FUNCTION_ARGS iterates through the types of the
> >>> params of the FUNCTION_TYPE, but it sounds like you want to be
> >>> iterating through the arguments at this particular *callsite*.
> >>>
> >>> For that you can use
> >>>    gimple_call_num_args (call);
> >>> and
> >>>    gimple_call_arg (call, idx);
> >>>
> >>>>      {
> >>>>          if (TREE_CONSTANT (argtype))
> >>>>             // Found a constant expression parameter
> >>>>      }
> >>>> }
> >>>>
> >>>> The problem is I am getting only one parameter tree but there are 2
> >>>> constants in the above function call. Even if "addr + 10" is treated
> >>>> differently, I want to mark it for the transformation.
> >>>
> >>> I think you're seeing the function pointer being called, ather than the
> >>> params.
> >>
> >> I think you are iterating over the functions formal argument types
> >> rather than a specific call parameters.  To look at the actual
> >> parameters use sth like
> >>
> >>    for (unsigned i = 0; i < gimple_call_num_args (stmt); ++i)
> >>      {
> >>         tree arg = gimple_call_arg (stmt, i);
> >>         if (CONSTANT_CLASS_P (arg))
> >>           ...
> >>      }
> >>
> >> and replace CONSTANT_CLASS_P with is_gimple_ip_invariant ()
> >> if you also want to handle symbolic constants like &global_var
> >> as constant.
> >
> > Understood. I was iterating on formal parameters. But the above solves
> > the problem. CONSTANT_CLASS_P() and is_gimple_ip_invariant() are
> > helpful on integer constant.
> >
> > In below gimple dump w.r.t code snippet shared by you from above -
> >
> > def_stmt    _14 = (unsigned int) _13;
> > __builtin_xyz(instrn_buffer.3_11, 12, _14);
> >
> > Here, all actual parameters are represented by tree whose classes are -
> >
> > instrn_buffer.3_11 - tcc_exceptional
> > 12 - tcc_constant
> > _14 - tcc_exceptional
> >
> > The 1st and 3rd parameters are denoted by tcc_exceptional which fits
> > no category of tree, but I want to collect such 3rd parameter i.e. to
> > identify it whether it is variable or expression. Is it possible to do
> > it?
> >
> > I want to mark _14 for gimple transformation if -
> > a. it is a variable like above _14 representing a constant.
> > b. it is a expression _14 + 7 i.e. again at gimple level, it is case (a)
> > c. it is a phi node which represents constant when there is a case of
> > ternary operator usage.
> >
> > How to identify such an actual parameter of gimple call?
> >
> > The aim of the above scenario is to identify such
> > variables/expressions and then apply constant folding and propagation.
> > If constant folding and propagation are not happening on actual
> > parameters of intrinsic call, then I need to write some plugin to do
> > it. My plugin is placed just after "pass_build_cgraph_edges" i.e.
> > Callgraph Construction.
>
> I use the following code.  It runs after pass_build_ssa, so a bit
> later than pass_build_cgraph_edges:
>
>        /* Use the range query to determine constant values in the absence
>          of constant proppagation (such as at -O0).  */
>        value_range rng;
>        if (!get_range_query (cfun)->range_of_expr (rng, ord, stmt)
>           || !rng.constant_p ()
>           || !rng.singleton_p (&ord))
>         return false;
>
>        wide_int lob = rng.lower_bound ();
>        if (!wi::fits_uhwi_p (lob))
>         return false;
>
>        val = lob.to_shwi ();

Understood. This is helpful.

Thanks for sharing.

>
> Martin
>
> >
> > Thanks for the helpful suggestions.
> >
> > Regards,
> > Shubham
> >
> >
> >>
> >> Richard.
> >>
> >>>>
> >>>> a. Is the above correct method to iterate over function call
> >>>> parameters?
> >>>
> >>> As noted above, it depends on whether you want to iterate over the
> >>> types of the parameters in the function's decl, or over the expressions
> >>> of the arguments at the callsite.  I believe the above explains how to
> >>> do each of these.
> >>>
> >>>> b. Is there a different way to achieve the above goal?
> >>>
> >>> If you're looking to get familiar with GCC's insides, I recommend
> >>> stepping through it in the debugger, rather than relying on injecting
> >>> print statements and recompiling, since the former makes it much easier
> >>> to spot mistakes like the one above (which we all make).
> >>>
> >>> I've written a guide to debugging GCC here:
> >>>
> >>> https://dmalcolm.fedorapeople.org/gcc/newbies-guide/debugging.html
> >>>
> >>>
> >>> Hope this is helpful
> >>> Dave
> >>>
>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Accessing const parameter of GIMPLE_CALL
  2022-01-18  8:50       ` Richard Biener
@ 2022-01-18 18:50         ` Shubham Narlawar
  0 siblings, 0 replies; 9+ messages in thread
From: Shubham Narlawar @ 2022-01-18 18:50 UTC (permalink / raw)
  To: Richard Biener; +Cc: David Malcolm, GCC Development

On Tue, Jan 18, 2022 at 2:20 PM Richard Biener
<richard.guenther@gmail.com> wrote:
>
> On Mon, Jan 17, 2022 at 8:19 PM Shubham Narlawar <gsocshubham@gmail.com> wrote:
> >
> > On Mon, Jan 17, 2022 at 1:55 PM Richard Biener
> > <richard.guenther@gmail.com> wrote:
> > >
> > > On Mon, Jan 17, 2022 at 12:54 AM David Malcolm via Gcc <gcc@gcc.gnu.org> wrote:
> > > >
> > > > On Sun, 2022-01-16 at 18:52 +0530, Shubham Narlawar via Gcc wrote:
> > > > > Hello,
> > > >
> > > > Hi; various notes inline below...
> > > >
> > > > >
> > > > > My aim is to iterate over gimple call stmt parameters and check
> > > > > whether it is constant or constant expression and mark/store them for
> > > > > some gimple transformation.
> > > > >
> > > > > I have an intrinsic function call of the following -
> > > > >
> > > > > __builtin_xyz(void*, 7, addr + 10);
> > > > >
> > > > > I want to find its parameters which are either constant or constant
> > > > > expression i.e. 7 and addr + 10 from above case.
> > > >
> > > > Gimple "flattens" all tree-like operations into a sequence of simple
> > > > operations, so I would expect the gimple for this to look something
> > > > like this:
> > > >
> > > >    _tmp = addr + 10;
> > > >    __builtin_xyx (7, _tmp);
> > > >
> > > > Your email doesn't specify *when* your code runs.
> > > >
> > > > The IR for a function goes through several stages:
> > > >
> > > > - an initial gimple IR without a CFG
> > > > - gimple with a CFG, but not in SSA
> > > > - gimple-SSA with a CFG
> > > >   (most of the gimple optimization passes operate in this form of the
> > > > IR)
> > > > - gimple with a CFG, but no longer in CFG form, immediately before
> > > > conversion to RTL-with-CFG form
> > > > - RTL-with-CFG
> > > > - RTL-without a CFG
> > > > - assembler
> > > >
> > > > Are you doing it as part of a plugin, or modifying an existing pass?
> > > > In either case, it's a good idea to dump the gimple and see what the
> > > > code has been turned into.  You'll probably find the following options
> > > > useful:
> > > >   -fdump-tree-all -fdump-gimple-all
> > > >
> > > > or alternatively just turn it on for the pass that you're working on.
> > > >
> > > > >
> > > > > [1] I tried below macro but there is very less usage in the entire
> > > > > source code -
> > > > >
> > > > > tree fn_ptr = gimple_call_fn (dyn_cast<gcall *> (stmt));        //stmt
> > > >
> > > > gimple_call_fn returns the function that will be called, a pointer.
> > > > This is very general, for handling things like jumps through function
> > > > pointers, but here you have the common case of a callsite that calls a
> > > > specific function, so "fn_ptr" here is:
> > > >    &__builtin_xyx
> > > > i.e. an ADDR_EXPR where operand 0 is the FUNCTION_DECL for the builtin.
> > > >
> > > > > = gimple_call
> > > > > function_args_iterator iter;
> > > > > tree argtype;
> > > > >
> > > > > if (TREE_CODE (fn_ptr) == ADDR_EXPR)
> > > > > {
> > > > >   FOREACH_FUNCTION_ARGS (fn_ptr, argtype, iter)
> > > >
> > > > Looking in tree.h, FOREACH_FUNCTION_ARGS takes a FUNCTION_TYPE as its
> > > > first argument, but the code above is passing it the ADDR_EXPR wrapping
> > > > the FUNCTION_DECL.
> > > >
> > > > Unfortunately, because these things are all of type "tree", this kind
> > > > of type mismatch doesn't get caught - unless you build gcc from source
> > > > (with --enable-checking=debug) in which case all these accesses are
> > > > checked at the compiler's run time (which is probably a good thing to
> > > > do if you're hoping to work on gcc for GSoC).
> > > >
> > > > You can get the FUNCTION_TYPE of a FUNCTION_DECL via TREE_TYPE
> > > > (fndecl), or alternatively, gimple_call_fntype (call) will get the type
> > > > of the function expected at the call stmt (useful if there was a type
> > > > mismatch).
> > > >
> > > > That said, FOREACH_FUNCTION_ARGS iterates through the types of the
> > > > params of the FUNCTION_TYPE, but it sounds like you want to be
> > > > iterating through the arguments at this particular *callsite*.
> > > >
> > > > For that you can use
> > > >   gimple_call_num_args (call);
> > > > and
> > > >   gimple_call_arg (call, idx);
> > > >
> > > > >     {
> > > > >         if (TREE_CONSTANT (argtype))
> > > > >            // Found a constant expression parameter
> > > > >     }
> > > > > }
> > > > >
> > > > > The problem is I am getting only one parameter tree but there are 2
> > > > > constants in the above function call. Even if "addr + 10" is treated
> > > > > differently, I want to mark it for the transformation.
> > > >
> > > > I think you're seeing the function pointer being called, ather than the
> > > > params.
> > >
> > > I think you are iterating over the functions formal argument types
> > > rather than a specific call parameters.  To look at the actual
> > > parameters use sth like
> > >
> > >   for (unsigned i = 0; i < gimple_call_num_args (stmt); ++i)
> > >     {
> > >        tree arg = gimple_call_arg (stmt, i);
> > >        if (CONSTANT_CLASS_P (arg))
> > >          ...
> > >     }
> > >
> > > and replace CONSTANT_CLASS_P with is_gimple_ip_invariant ()
> > > if you also want to handle symbolic constants like &global_var
> > > as constant.
> >
> > Understood. I was iterating on formal parameters. But the above solves
> > the problem. CONSTANT_CLASS_P() and is_gimple_ip_invariant() are
> > helpful on integer constant.
> >
> > In below gimple dump w.r.t code snippet shared by you from above -
> >
> > def_stmt    _14 = (unsigned int) _13;
> > __builtin_xyz(instrn_buffer.3_11, 12, _14);
> >
> > Here, all actual parameters are represented by tree whose classes are -
> >
> > instrn_buffer.3_11 - tcc_exceptional
> > 12 - tcc_constant
> > _14 - tcc_exceptional
> >
> > The 1st and 3rd parameters are denoted by tcc_exceptional which fits
> > no category of tree, but I want to collect such 3rd parameter i.e. to
> > identify it whether it is variable or expression. Is it possible to do
> > it?
>
> You can check TREE_CODE (arg) == SSA_NAME and look at
> the defining stmts via SSA_NAME_DEF_STMT.  Note that prior to
> the into SSA pass only temporaries created by the gimplification
> process are SSA names and some SSA data structures like
> immediate uses are not available.

Thanks for the suggestion. This gets me what I wanted! With this my
analysis pass is complete - "of finding potential constant expressions
in builtin intrinsics".

SSA_NAME_DEF_STMT gets me stmt representing a parameter which is
either PARM_DECL or SSA_NAME. I think where immediate uses are not
available, the tree is represented as PARM_DECL.

Thanks everyone for the suggestions!

Regards,
Shubham


>
> > I want to mark _14 for gimple transformation if -
> > a. it is a variable like above _14 representing a constant.
> > b. it is a expression _14 + 7 i.e. again at gimple level, it is case (a)
> > c. it is a phi node which represents constant when there is a case of
> > ternary operator usage.
> >
> > How to identify such an actual parameter of gimple call?
> >
> > The aim of the above scenario is to identify such
> > variables/expressions and then apply constant folding and propagation.
> > If constant folding and propagation are not happening on actual
> > parameters of intrinsic call, then I need to write some plugin to do
> > it. My plugin is placed just after "pass_build_cgraph_edges" i.e.
> > Callgraph Construction.
> >
> > Thanks for the helpful suggestions.
> >
> > Regards,
> > Shubham
> >
> >
> > >
> > > Richard.
> > >
> > > > >
> > > > > a. Is the above correct method to iterate over function call
> > > > > parameters?
> > > >
> > > > As noted above, it depends on whether you want to iterate over the
> > > > types of the parameters in the function's decl, or over the expressions
> > > > of the arguments at the callsite.  I believe the above explains how to
> > > > do each of these.
> > > >
> > > > > b. Is there a different way to achieve the above goal?
> > > >
> > > > If you're looking to get familiar with GCC's insides, I recommend
> > > > stepping through it in the debugger, rather than relying on injecting
> > > > print statements and recompiling, since the former makes it much easier
> > > > to spot mistakes like the one above (which we all make).
> > > >
> > > > I've written a guide to debugging GCC here:
> > > >
> > > > https://dmalcolm.fedorapeople.org/gcc/newbies-guide/debugging.html
> > > >
> > > >
> > > > Hope this is helpful
> > > > Dave
> > > >

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2022-01-18 18:50 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-16 13:22 Accessing const parameter of GIMPLE_CALL Shubham Narlawar
2022-01-16 23:53 ` David Malcolm
2022-01-17  8:25   ` Richard Biener
2022-01-17 19:18     ` Shubham Narlawar
2022-01-17 20:49       ` Martin Sebor
2022-01-18 18:45         ` Shubham Narlawar
2022-01-18  8:50       ` Richard Biener
2022-01-18 18:50         ` Shubham Narlawar
2022-01-17 19:18   ` Shubham Narlawar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).