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 > >>> >