On Tue, Jan 18, 2022 at 2:19 AM Martin Sebor <mse...@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.guent...@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
> >>>
>

Reply via email to