3 * File name: ir/ana/analyze_irg_agrs.c
4 * Purpose: read/write analyze of graph argument, which have mode reference.
5 * Author: Beyhan Veliev
8 * Copyright: (c) 1998-2005 Universität Karlsruhe
9 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
13 * @file analyze_irg_agrs.c
37 #include "analyze_irg_args.h"
40 static void *VISITED = &v;
43 * Walk recursive the successors of a graph argument
44 * with mode reference and mark if it will be read,
47 * @param arg The graph argument with mode reference,
48 * that must be checked.
50 static unsigned analyze_arg(ir_node *arg, unsigned bits)
55 /* We must visit a node once to avoid endless recursion.*/
56 set_irn_link(arg, VISITED);
58 for (i = get_irn_n_outs(arg) - 1; i >= 0; --i) {
59 succ = get_irn_out(arg, i);
62 if (get_irn_link(succ) == VISITED)
65 /* We should not walk over the memory edge.*/
66 if (get_irn_mode(succ) == mode_M)
69 /* If we reach with the recursion a Call node and our reference
70 isn't the address of this Call we accept that the reference will
71 be read and written if the graph of the method represented by
72 "Call" isn't computed else we analyze that graph. If our
73 reference is the address of this
74 Call node that mean the reference will be read.*/
75 if (get_irn_op(succ) == op_Call) {
76 ir_node *Call_ptr = get_Call_ptr(succ);
78 if (Call_ptr == arg) {
79 /* Hmm: not sure what this is, most likely a read */
80 bits |= ptr_access_read;
82 else if (op_SymConst == get_irn_op(Call_ptr) &&
83 get_SymConst_kind(Call_ptr) == symconst_addr_ent) {
84 entity *meth_ent = get_SymConst_entity(Call_ptr);
86 for (p = get_Call_n_params(succ) - 1; p >= 0; --p){
87 if (get_Call_param(succ, p) == arg) {
88 /* an arg can be used more than once ! */
89 bits |= get_method_param_access(meth_ent, p);
92 } else /* can do anything */
93 bits |= ptr_access_all;
95 /* search stops here anyway */
98 else if (get_irn_op(succ) == op_Store) {
99 /* We have reached a Store node => the reference is written or stored. */
100 if (get_Store_ptr(succ) == arg) {
102 bits |= ptr_access_write;
106 bits |= ptr_access_store;
109 /* search stops here anyway */
112 else if (get_irn_op(succ) == op_Load) {
113 /* We have reached a Load node => the reference is read. */
114 bits |= ptr_access_read;
116 /* search stops here anyway */
119 else if (get_irn_op(succ) == op_Conv) {
120 /* our address is casted into something unknown. Break our search. */
121 bits = ptr_access_all;
125 /* If we know that, the argument will be read, write and stored, we
126 can break the recursion.*/
127 if (bits == ptr_access_all) {
128 bits = ptr_access_all;
133 * A calculation that do not lead to a reference mode ends our search.
134 * This is dangerous: It would allow to cast into integer and that cast back ...
135 * so, when we detect a Conv we go mad, see the Conv case above.
137 if (!mode_is_reference(get_irn_mode(succ)))
140 /* follow further the address calculation */
141 bits = analyze_arg(succ, bits);
143 set_irn_link(arg, NULL);
148 * Check if a argument of the ir graph with mode
149 * reference is read, write or both.
151 * @param irg The ir graph to analyze.
153 static void analyze_ent_args(entity *ent)
156 ir_node *irg_args, *arg;
161 ptr_access_kind *rw_info;
163 mtp = get_entity_type(ent);
164 nparams = get_method_n_params(mtp);
166 ent->param_access = NEW_ARR_F(ptr_access_kind, nparams);
168 /* If the method haven't parameters we have
174 irg = get_entity_irg(ent);
176 /* we have not yet analyzed the graph, set ALL access for pointer args */
177 for (i = nparams - 1; i >= 0; --i)
178 ent->param_access[i] =
179 is_Pointer_type(get_method_param_type(mtp, i)) ? ptr_access_all : ptr_access_none;
182 /* no graph, no better info */
186 /* Call algorithm that computes the out edges */
187 if (get_irg_outs_state(irg) != outs_consistent)
190 irg_args = get_irg_args(irg);
192 /* A array to save the information for each argument with
194 NEW_ARR_A(ptr_access_kind, rw_info, nparams);
196 /* We initialize the element with none state. */
197 for (i = nparams - 1; i >= 0; --i)
198 rw_info[i] = ptr_access_none;
200 /* search for arguments with mode reference
202 for (i = get_irn_n_outs(irg_args) - 1; i >= 0; --i) {
203 arg = get_irn_out(irg_args, i);
204 arg_mode = get_irn_mode(arg);
205 proj_nr = get_Proj_proj(arg);
207 if (mode_is_reference(arg_mode))
208 rw_info[proj_nr] |= analyze_arg(arg, rw_info[proj_nr]);
211 /* copy the temporary info */
212 memcpy(ent->param_access, rw_info, nparams * sizeof(ent->param_access[0]));
214 printf("\n%s:\n", get_entity_name(ent));
215 for (i = 0; i < nparams; ++i) {
216 if (is_Pointer_type(get_method_param_type(mtp, i)))
217 if (ent->param_access[i] != ptr_access_none) {
218 printf(" Pointer Arg %d access: ", i);
219 if (ent->param_access[i] & ptr_access_read)
221 if (ent->param_access[i] & ptr_access_write)
223 if (ent->param_access[i] & ptr_access_store)
231 * Analyze how pointer arguments of a given
232 * ir graph are accessed.
234 * @param irg The ir graph to analyze.
236 void analyze_irg_args(ir_graph *irg)
240 if (irg == get_const_code_irg())
243 ent = get_irg_entity(irg);
247 if (! ent->param_access)
248 analyze_ent_args(ent);
252 * Compute for a method with pointer parameter(s)
253 * if they will be read or written.
255 ptr_access_kind get_method_param_access(entity *ent, int pos)
257 type *mtp = get_entity_type(ent);
258 int is_variadic = get_method_variadicity(mtp) == variadicity_variadic;
260 assert(0 <= pos && (is_variadic || pos < get_method_n_params(mtp)));
262 if (ent->param_access) {
263 if (pos < ARR_LEN(ent->param_access))
264 return ent->param_access[pos];
266 return ptr_access_all;
269 analyze_ent_args(ent);
271 if (pos < ARR_LEN(ent->param_access))
272 return ent->param_access[pos];
274 return ptr_access_all;
278 null_weight = 0, /* If can't be anything optimized. */
279 binop_weight = 1, /* If the argument have mode_weight and take part in binop. */
280 const_binop_weight = 1, /* If the argument have mode_weight and take part in binop with a constant.*/
281 cmp_weight = 4, /* If the argument take part in cmp. */
282 const_cmp_weight = 10 /* If the argument take part in cmp with a constant. */
286 * Compute the weight of a method parameter
288 * @param arg The parameter them weight muss be computed.
290 static float calc_method_param_weight(ir_node *arg)
294 float weight = null_weight;
296 /* We mark the nodes to avoid endless recursion */
297 set_irn_link(arg, VISITED);
299 for (i = get_irn_n_outs(arg) - 1; i >= 0; i--) {
300 succ = get_irn_out(arg, i);
303 if (get_irn_link(succ) == VISITED)
306 /* We should not walk over the memory edge.*/
307 if (get_irn_mode(succ) == mode_M)
310 /* We have reached a cmp and we must increase the
311 weight with the cmp_weight.*/
312 if (get_irn_op(succ) == op_Cmp) {
314 if (get_Cmp_left(succ) == arg)
315 op = get_Cmp_right(succ);
317 op = get_Cmp_left(succ);
319 if (is_irn_constlike(op)) {
320 weight += const_cmp_weight;
323 weight += cmp_weight;
325 else if (is_binop(succ)) {
326 /* We have reached a binop and we must increase the
327 weight with the binop_weight. If the other operand of the
328 binop is a constant we increase the weight with const_binop_weight
329 and call the function recursive.
331 if (get_binop_left(succ) == arg)
332 op = get_binop_right(succ);
334 op = get_binop_left(succ);
336 if (is_irn_constlike(op)) {
337 weight += const_binop_weight;
338 weight += calc_method_param_weight(succ);
341 weight += binop_weight;
342 } else if (is_unop(succ)) {
343 /* We have reached a binop and we must increase the
344 weight with the const_binop_weight and call the function recursive.*/
345 weight += const_binop_weight;
346 weight += calc_method_param_weight(succ);
349 set_irn_link(arg, NULL);
354 * Set a weight for each argument of a ir_graph.
355 * The args with a greater weight are good for optimize.
357 * @param ent The entity of the ir_graph.
359 static void analyze_method_params_weight(entity *ent)
363 int nparams, i, proj_nr;
364 ir_node *irg_args, *arg;
366 mtp = get_entity_type(ent);
367 nparams = get_method_n_params(mtp);
369 /* If the method haven't parameters we have
375 ent->param_weight = NEW_ARR_F(float, nparams);
376 irg = get_entity_irg(ent);
378 /* First we initialize the parameter weight with 0. */
379 for (i = nparams - 1; i >= 0; i--)
380 ent->param_weight[i] = null_weight;
383 /* no graph, no better info */
387 /* Call algorithm that computes the out edges */
388 if (get_irg_outs_state(irg) != outs_consistent)
391 irg_args = get_irg_args(irg);
393 for (i = get_irn_n_outs(irg_args) - 1; i >= 0; --i) {
394 arg = get_irn_out(irg_args, i);
395 proj_nr = get_Proj_proj(arg);
396 ent->param_weight[proj_nr] += calc_method_param_weight(arg);
400 printf("\n%s:\n", get_entity_name(ent));
401 for (i = nparams - 1; i >= 0; --i)
402 printf("The weight of argument %i is %f \n", i, ent->param_weight[i]);
407 * Compute for a method with pointer parameter(s)
408 * if they will be read or written.
410 float get_method_param_weight(entity *ent, int pos)
412 type *mtp = get_entity_type(ent);
413 int is_variadic = get_method_variadicity(mtp) == variadicity_variadic;
415 assert(0 <= pos && (is_variadic || pos < get_method_n_params(mtp)));
417 if (ent->param_weight) {
418 if (pos < ARR_LEN(ent->param_weight))
419 return ent->param_weight[pos];
424 analyze_method_params_weight(ent);
426 if (pos < ARR_LEN(ent->param_weight))
427 return ent->param_weight[pos];
434 * Analyze argument's weight of a given
437 * @param irg The ir graph to analyze.
439 void analyze_irg_args_weight(ir_graph *irg)
443 ent = get_irg_entity(irg);
447 if(! ent->param_weight)
448 analyze_method_params_weight(ent);