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 switch (get_irn_opcode(succ)) {
78 ir_node *ptr = get_Call_ptr(succ);
81 /* Hmm: not sure what this is, most likely a read */
82 bits |= ptr_access_read;
85 ir_op *op = get_irn_op(ptr);
88 if (op == op_SymConst && get_SymConst_kind(ptr) == symconst_addr_ent) {
89 meth_ent = get_SymConst_entity(ptr);
91 for (p = get_Call_n_params(succ) - 1; p >= 0; --p) {
92 if (get_Call_param(succ, p) == arg) {
93 /* an arg can be used more than once ! */
94 bits |= get_method_param_access(meth_ent, p);
98 else if (op == op_Sel && get_irp_callee_info_state() == irg_callee_info_consistent) {
99 /* is be a polymorphic call but callee information is available */
100 int i, n_params = get_Call_n_params(succ);
102 /* simply look into ALL possible callees */
103 for (i = get_Call_n_callees(succ) - 1; i >= 0; --i) {
104 meth_ent = get_Call_callee(succ, i);
106 /* unknown_entity is used to signal that we don't know what is called */
107 if (meth_ent == unknown_entity) {
108 bits |= ptr_access_all;
112 for (p = n_params - 1; p >= 0; --p) {
113 if (get_Call_param(succ, p) == arg) {
114 /* an arg can be used more than once ! */
115 bits |= get_method_param_access(meth_ent, p);
120 else /* can do anything */
121 bits |= ptr_access_all;
124 /* search stops here anyway */
128 /* We have reached a Store node => the reference is written or stored. */
129 if (get_Store_ptr(succ) == arg) {
131 bits |= ptr_access_write;
135 bits |= ptr_access_store;
138 /* search stops here anyway */
142 /* We have reached a Load node => the reference is read. */
143 bits |= ptr_access_read;
145 /* search stops here anyway */
149 /* our address is casted into something unknown. Break our search. */
150 bits = ptr_access_all;
157 /* If we know that, the argument will be read, write and stored, we
158 can break the recursion.*/
159 if (bits == ptr_access_all) {
160 bits = ptr_access_all;
165 * A calculation that do not lead to a reference mode ends our search.
166 * This is dangerous: It would allow to cast into integer and that cast back ...
167 * so, when we detect a Conv we go mad, see the Conv case above.
169 if (!mode_is_reference(get_irn_mode(succ)))
172 /* follow further the address calculation */
173 bits = analyze_arg(succ, bits);
175 set_irn_link(arg, NULL);
180 * Check if a argument of the ir graph with mode
181 * reference is read, write or both.
183 * @param irg The ir graph to analyze.
185 static void analyze_ent_args(entity *ent)
188 ir_node *irg_args, *arg;
193 ptr_access_kind *rw_info;
195 mtp = get_entity_type(ent);
196 nparams = get_method_n_params(mtp);
198 ent->attr.mtd_attr.param_access = NEW_ARR_F(ptr_access_kind, nparams);
200 /* If the method haven't parameters we have
206 irg = get_entity_irg(ent);
208 /* we have not yet analyzed the graph, set ALL access for pointer args */
209 for (i = nparams - 1; i >= 0; --i)
210 ent->attr.mtd_attr.param_access[i] =
211 is_Pointer_type(get_method_param_type(mtp, i)) ? ptr_access_all : ptr_access_none;
214 /* no graph, no better info */
218 assure_irg_outs(irg);
220 irg_args = get_irg_args(irg);
222 /* A array to save the information for each argument with
224 NEW_ARR_A(ptr_access_kind, rw_info, nparams);
226 /* We initialize the element with none state. */
227 for (i = nparams - 1; i >= 0; --i)
228 rw_info[i] = ptr_access_none;
230 /* search for arguments with mode reference
232 for (i = get_irn_n_outs(irg_args) - 1; i >= 0; --i) {
233 arg = get_irn_out(irg_args, i);
234 arg_mode = get_irn_mode(arg);
235 proj_nr = get_Proj_proj(arg);
237 if (mode_is_reference(arg_mode))
238 rw_info[proj_nr] |= analyze_arg(arg, rw_info[proj_nr]);
241 /* copy the temporary info */
242 memcpy(ent->attr.mtd_attr.param_access, rw_info,
243 nparams * sizeof(ent->attr.mtd_attr.param_access[0]));
246 printf("\n%s:\n", get_entity_name(ent));
247 for (i = 0; i < nparams; ++i) {
248 if (is_Pointer_type(get_method_param_type(mtp, i)))
249 if (ent->attr.mtd_attr.param_access[i] != ptr_access_none) {
250 printf(" Pointer Arg %d access: ", i);
251 if (ent->attr.mtd_attr.param_access[i] & ptr_access_read)
253 if (ent->attr.mtd_attr.param_access[i] & ptr_access_write)
255 if (ent->attr.mtd_attr.param_access[i] & ptr_access_store)
264 * Analyze how pointer arguments of a given
265 * ir graph are accessed.
267 * @param irg The ir graph to analyze.
269 void analyze_irg_args(ir_graph *irg)
273 if (irg == get_const_code_irg())
276 ent = get_irg_entity(irg);
280 if (! ent->attr.mtd_attr.param_access)
281 analyze_ent_args(ent);
285 * Compute for a method with pointer parameter(s)
286 * if they will be read or written.
288 ptr_access_kind get_method_param_access(entity *ent, int pos)
290 ir_type *mtp = get_entity_type(ent);
291 int is_variadic = get_method_variadicity(mtp) == variadicity_variadic;
293 assert(0 <= pos && (is_variadic || pos < get_method_n_params(mtp)));
295 if (ent->attr.mtd_attr.param_access) {
296 if (pos < ARR_LEN(ent->attr.mtd_attr.param_access))
297 return ent->attr.mtd_attr.param_access[pos];
299 return ptr_access_all;
302 analyze_ent_args(ent);
304 if (pos < ARR_LEN(ent->attr.mtd_attr.param_access))
305 return ent->attr.mtd_attr.param_access[pos];
307 return ptr_access_all;
311 null_weight = 0, /**< If can't be anything optimized. */
312 binop_weight = 1, /**< If the argument have mode_weight and take part in binop. */
313 const_binop_weight = 1, /**< If the argument have mode_weight and take part in binop with a constant.*/
314 cmp_weight = 4, /**< If the argument take part in cmp. */
315 const_cmp_weight = 10 /**< If the argument take part in cmp with a constant. */
319 * Compute the weight of a method parameter
321 * @param arg The parameter them weight muss be computed.
323 static float calc_method_param_weight(ir_node *arg)
327 float weight = null_weight;
329 /* We mark the nodes to avoid endless recursion */
330 set_irn_link(arg, VISITED);
332 for (i = get_irn_n_outs(arg) - 1; i >= 0; i--) {
333 succ = get_irn_out(arg, i);
336 if (get_irn_link(succ) == VISITED)
339 /* We should not walk over the memory edge.*/
340 if (get_irn_mode(succ) == mode_M)
343 /* We have reached a cmp and we must increase the
344 weight with the cmp_weight.*/
345 if (get_irn_op(succ) == op_Cmp) {
347 if (get_Cmp_left(succ) == arg)
348 op = get_Cmp_right(succ);
350 op = get_Cmp_left(succ);
352 if (is_irn_constlike(op)) {
353 weight += const_cmp_weight;
356 weight += cmp_weight;
358 else if (is_binop(succ)) {
359 /* We have reached a binop and we must increase the
360 weight with the binop_weight. If the other operand of the
361 binop is a constant we increase the weight with const_binop_weight
362 and call the function recursive.
364 if (get_binop_left(succ) == arg)
365 op = get_binop_right(succ);
367 op = get_binop_left(succ);
369 if (is_irn_constlike(op)) {
370 weight += const_binop_weight;
371 weight += calc_method_param_weight(succ);
374 weight += binop_weight;
375 } else if (is_unop(succ)) {
376 /* We have reached a binop and we must increase the
377 weight with the const_binop_weight and call the function recursive.*/
378 weight += const_binop_weight;
379 weight += calc_method_param_weight(succ);
382 set_irn_link(arg, NULL);
387 * Set a weight for each argument of a ir_graph.
388 * The args with a greater weight are good for optimize.
390 * @param ent The entity of the ir_graph.
392 static void analyze_method_params_weight(entity *ent)
396 int nparams, i, proj_nr;
397 ir_node *irg_args, *arg;
399 mtp = get_entity_type(ent);
400 nparams = get_method_n_params(mtp);
402 /* allocate a new array. currently used as 'analysed' flag */
403 ent->attr.mtd_attr.param_weight = NEW_ARR_F(float, nparams);
405 /* If the method haven't parameters we have
411 irg = get_entity_irg(ent);
413 /* First we initialize the parameter weight with 0. */
414 for (i = nparams - 1; i >= 0; i--)
415 ent->attr.mtd_attr.param_weight[i] = null_weight;
418 /* no graph, no better info */
422 /* Call algorithm that computes the out edges */
423 assure_irg_outs(irg);
425 irg_args = get_irg_args(irg);
427 for (i = get_irn_n_outs(irg_args) - 1; i >= 0; --i) {
428 arg = get_irn_out(irg_args, i);
429 proj_nr = get_Proj_proj(arg);
430 ent->attr.mtd_attr.param_weight[proj_nr] += calc_method_param_weight(arg);
434 printf("\n%s:\n", get_entity_name(ent));
435 for (i = nparams - 1; i >= 0; --i)
436 printf("The weight of argument %i is %f \n", i, ent->param_weight[i]);
441 * Compute for a method with pointer parameter(s)
442 * if they will be read or written.
444 float get_method_param_weight(entity *ent, int pos)
446 ir_type *mtp = get_entity_type(ent);
447 int is_variadic = get_method_variadicity(mtp) == variadicity_variadic;
449 assert(0 <= pos && (is_variadic || pos < get_method_n_params(mtp)));
451 if (ent->attr.mtd_attr.param_weight) {
452 if (pos < ARR_LEN(ent->attr.mtd_attr.param_weight))
453 return ent->attr.mtd_attr.param_weight[pos];
458 analyze_method_params_weight(ent);
460 if (pos < ARR_LEN(ent->attr.mtd_attr.param_weight))
461 return ent->attr.mtd_attr.param_weight[pos];
468 * Analyze argument's weight of a given
471 * @param irg The ir graph to analyze.
473 void analyze_irg_args_weight(ir_graph *irg)
477 ent = get_irg_entity(irg);
481 if (! ent->attr.mtd_attr.param_weight)
482 analyze_method_params_weight(ent);