5 File name: ir/ana/pto_comp.c
6 Purpose: Main Implementation of PTO
9 Created: Sat Nov 13 19:35:27 CET 2004
11 Copyright: (c) 1999-2004 Universität Karlsruhe
12 Licence: This file is protected by the GPL - GNU GENERAL PUBLIC LICENSE.
20 pto_comp: Main Implementation of PTO
23 # include <string.h> /* for memset */
25 # include "pto_comp.h"
26 # include "pto_util.h"
27 # include "pto_name.h"
31 # include "irnode_t.h"
34 # include "irmemwalk.h"
36 # include "pto_debug.h"
37 # include "pto_init.h"
43 /* Local Data Types: */
44 typedef struct pto_env_str {
50 /* Local Variables: */
55 /* Local Prototypes: */
56 static pto_t *get_pto (ir_node*, pto_env_t*);
57 static void pto_call (ir_graph*, ir_node*, pto_env_t*);
58 static void pto_raise (ir_node*, pto_env_t*);
59 static void pto_load (ir_node*, pto_env_t*);
60 static void pto_store (ir_node*, pto_env_t*);
61 static void pto_method (ir_node*, pto_env_t*);
62 static void pto_end_block (ir_node*, pto_env_t*);
64 /* ===================================================
66 =================================================== */
67 /* Transfer the actual arguments to the formal arguments */
68 static void set_graph_args (ir_graph *graph, ir_node *call, pto_env_t *env)
70 assert (iro_Call == get_irn_opcode (call));
72 type *meth = get_entity_type (get_irg_entity (graph));
73 ir_node **args = find_irg_args (graph);
74 int n_args = get_Call_n_params (call);
77 for (i = 0; i < n_args; i ++) {
78 if (NULL != args [i]) {
79 if (mode_P == get_type_mode (get_method_param_type (meth, i))) {
80 ir_node *call_arg = get_Call_param (call, i);
81 pto_t *pto = get_pto (call_arg, env);
83 set_node_pto (args [i], pto);
85 DBGPRINT (1, (stdout, "%s: arg [%i]: %s[%li] -> %s[%li] (%i)\n",
88 OPNAME (call_arg), OPNUM (call_arg),
89 OPNAME (args [i]), OPNUM (args [i]),
96 /* Transfer the graph's result to the call */
97 static int set_graph_result (ir_graph *graph, ir_node *call)
99 type *tp = get_entity_type (get_irg_entity (graph));
102 if (0 == get_method_n_ress (tp)) {
106 tp = get_method_res_type (tp, 0);
108 if (mode_P != get_type_mode (tp)) {
109 set_node_pto (call, NULL);
114 ir_node *end_block = get_irg_end_block (graph);
115 pto_t *ret_pto = get_node_pto (end_block);
117 pto_t *call_pto = get_node_pto (call);
121 change |= qset_insert_all (call_pto->values, ret_pto->values);
126 /* Propagation of PTO values */
127 static pto_t *get_pto_proj (ir_node *proj, pto_env_t *env)
129 ir_node *proj_in = get_Proj_pred (proj);
130 const long proj_proj = get_Proj_proj (proj);
131 const opcode in_op = get_irn_opcode (proj_in);
132 pto_t *in_pto = NULL;
133 pto_t *proj_pto = NULL; /* get_node_pto (proj); */
135 ir_node *proj_in_in = NULL;
138 case (iro_Start): /* ProjT (Start) */
139 assert (0 && "pto from ProjT(Start) requested");
142 case (iro_Proj): /* ProjT (Start), ProjT (Call) */
143 proj_in_in = get_Proj_pred (proj_in);
144 const opcode in_in_op = get_irn_opcode (proj_in_in);
145 const long proj_in_proj = get_Proj_proj (proj_in);
147 assert ((pn_Start_T_args == proj_in_proj) ||
148 (pn_Call_T_result == proj_in_proj));
151 case (iro_Start): /* ProjArg (ProjT (Start)) */
152 /* then the pto value must have been set to the node */
153 proj_pto = get_node_pto (proj);
157 case (iro_Call): /* ProjV (ProjT (Call)) */
158 if (NULL != proj_pto) {
161 in_pto = get_pto (proj_in, env);
162 set_node_pto (proj, in_pto);
168 default: assert (0 && "Proj(Proj(?))");
170 /* done with case (in_op == iro_Proj) */
172 case (iro_Load): /* ProjV (Load) */
173 assert (pn_Load_res == proj_proj);
175 case (iro_Call): /* ProjT (Call) */
177 case (iro_Alloc): /* ProjV (Alloc) */
178 if (NULL != proj_pto) {
181 in_pto = get_pto (proj_in, env);
184 set_node_pto (proj, in_pto);
188 fprintf (stderr, "%s: not handled: proj (%s[%li])\n",
190 get_op_name (get_irn_op (proj_in)),
191 get_irn_node_nr (proj_in));
192 assert (0 && "Proj(?)");
197 static pto_t *get_pto_phi (ir_node *phi, pto_env_t *env)
199 assert (mode_P == get_irn_mode (phi));
201 pto_t *pto = get_node_pto (phi);
204 assert (pto); /* must be initialised */
206 int n_ins = get_irn_arity (phi);
209 for (i = 0; i < n_ins; i ++) {
210 ir_node *in = get_irn_n (phi, i);
211 pto_t *in_pto = get_pto (in, env);
215 change |= qset_insert_all (pto->values, in_pto->values);
218 env->change |= change;
223 static pto_t *get_pto_sel (ir_node *sel, pto_env_t *env)
225 pto_t *pto = NULL; /* get_node_pto (sel); */
228 ir_node *in = get_Sel_ptr (sel);
230 pto = get_pto (in, env);
231 set_node_pto (sel, pto);
237 static pto_t *get_pto_ret (ir_node *ret, pto_env_t *env)
239 pto_t *pto = NULL; /* get_node_pto (ret); */
242 ir_node *in = get_Return_res (ret, 0);
244 pto = get_pto (in, env);
245 set_node_pto (ret, pto);
254 /* Dispatch to propagate PTO values */
255 static pto_t *get_pto (ir_node *node, pto_env_t *env)
257 const opcode op = get_irn_opcode (node);
259 DBGPRINT (2, (stdout, "%s (%s[%li])\n", __FUNCTION__,
260 OPNAME (node), OPNUM (node)));
263 case (iro_Cast): return (get_pto (get_Cast_op (node), env));
264 case (iro_Proj): return (get_pto_proj (node, env));
265 case (iro_Phi): return (get_pto_phi (node, env));
266 case (iro_Sel): return (get_pto_sel (node, env));
267 case (iro_Alloc): return (get_alloc_pto (node));
268 case (iro_Return): return (get_pto_ret (node, env));
270 case (iro_Call): /* FALLTHROUGH */
271 case (iro_Load): /* FALLTHROUGH */
272 case (iro_Const): /* FALLTHROUGH */
273 case (iro_SymConst):{
274 pto_t *pto = get_node_pto (node);
280 /* stopgap measure */
281 fprintf (stderr, "%s: not handled: node[%li].op = %s\n",
283 get_irn_node_nr (node),
284 get_op_name (get_irn_op (node)));
285 assert (0 && "something not handled");
291 /* Actions for the nodes: */
292 static void pto_load (ir_node *load, pto_env_t *pto_env)
295 DBGPRINT (2, (stdout, "%s (%s[%li]): pto = %p\n", __FUNCTION__,
296 OPNAME (load), OPNUM (load), (void*) get_node_pto (load)));
298 ir_node *ptr = get_Load_ptr (load);
300 if (is_dummy_load_ptr (ptr)) {
304 /* TODO: ONLY LOAD IFF LOAD.ENT.MODE == MODE_P */
306 entity *ent = get_ptr_ent (ptr);
308 if (mode_P == get_type_mode (get_entity_type (ent))) {
310 pto_t *ptr_pto = get_pto (ptr, pto_env);
316 DBGPRINT (1, (stdout, "%s (%s[%li]): ptr = %p\n", __FUNCTION__,
317 OPNAME (ptr), OPNUM (ptr), (void*) ptr_pto));
319 pto_env->change |= mod_load (load, ent, ptr_pto);
323 static void pto_store (ir_node *store, pto_env_t *pto_env)
326 DBGPRINT (2, (stdout, "%s (%s[%li]) (no pto)\n", __FUNCTION__,
327 OPNAME (store), OPNUM (store)));
329 ir_node *ptr = get_Store_ptr (store);
330 ir_node *val = get_Store_value (store);
332 if (mode_P != get_irn_mode (val)) {
336 entity *ent = get_ptr_ent (ptr);
338 pto_t *ptr_pto = get_pto (ptr, pto_env);
339 pto_t *val_pto = get_pto (val, pto_env);
344 DBGPRINT (2, (stdout, "%s (%s[%li]): ptr_pto = %p\n", __FUNCTION__,
345 OPNAME (ptr), OPNUM (ptr), (void*) ptr_pto));
346 DBGPRINT (2, (stdout, "%s (%s[%li]): val_pto = %p\n", __FUNCTION__,
347 OPNAME (val), OPNUM (val), (void*) val_pto));
349 pto_env->change |= mod_store (store, ent, ptr_pto, val_pto);
352 static void pto_method (ir_node *call, pto_env_t *pto_env)
354 DBGPRINT (2, (stdout, "%s:%i (%s[%li]): pto = %p\n",
355 __FUNCTION__, __LINE__, OPNAME (call), OPNUM (call),
356 (void*) get_node_pto (call)));
358 callEd_info_t *callEd_info = ecg_get_callEd_info (call);
360 if (NULL == callEd_info) {
361 DBGPRINT (2, (stdout, "%s:%i (%s[%li]), no graph\n",
362 __FUNCTION__, __LINE__, OPNAME (call), OPNUM (call)));
366 while (NULL != callEd_info) {
367 DBGPRINT (2, (stdout, "%s:%i (%s[%li]), graph %i\n",
368 __FUNCTION__, __LINE__, OPNAME (call), OPNUM (call), i ++));
370 pto_call (callEd_info->callEd, call, pto_env);
372 callEd_info = callEd_info->prev;
376 /* Perform the appropriate action on the given node */
377 static void pto_node_node (ir_node *node, pto_env_t *pto_env)
379 DBGPRINT (1, (stdout, "%s (%s[%li])\n", __FUNCTION__,
380 OPNAME (node), OPNUM (node)));
382 const opcode op = get_irn_opcode (node);
385 case (iro_Start): /* nothing */ break;
387 pto_load (node, pto_env);
391 pto_store (node, pto_env);
395 pto_method (node, pto_env);
399 pto_raise (node, pto_env);
411 pto_end_block (node, pto_env);
416 assert (mode_M == get_irn_mode (node));
420 /* uninteresting stuff: */
424 case (iro_DivMod): /* nothing to do */ break;
427 /* stopgap measure */
428 fprintf (stderr, "%s: not handled: node[%li].op = %s\n",
430 get_irn_node_nr (node),
431 get_op_name (get_irn_op (node)));
432 assert (0 && "something not handled");
437 /* Callback function to execute in pre-order */
438 static void pto_node_pre (ir_node *node, void *env)
443 /* Callback function to execute in post-order */
444 static void pto_node_post (ir_node *node, void *env)
446 pto_env_t *pto_env = (pto_env_t*) env;
448 pto_node_node (node, pto_env);
451 /* Perform a single pass over the given graph */
452 static void pto_graph_pass (ir_graph *graph, void *pto_env)
454 entity *ent = get_irg_entity (graph);
455 const char *ent_name = (char*) get_entity_name (ent);
456 const char *own_name = (char*) get_type_name (get_entity_owner (ent));
457 HERE3 ("start", own_name, ent_name);
459 irg_walk_mem (graph, pto_node_pre, pto_node_post, pto_env);
461 HERE3 ("end ", own_name, ent_name);
464 /* Continue PTO for one of the graphs called at a Call */
465 static void pto_call (ir_graph *graph, ir_node *call, pto_env_t *pto_env)
470 DBGPRINT (1, (stdout, "%s:%i (%s[%li])\n",
471 __FUNCTION__, __LINE__, OPNAME (call), OPNUM (call)));
473 /* only for debugging stuff: */
474 entity *ent = get_irg_entity (graph);
475 const char *ent_name = (char*) get_entity_name (ent);
476 const char *own_name = (char*) get_type_name (get_entity_owner (ent));
478 if (! get_irg_is_mem_visited (graph)) {
479 graph_info_t *ginfo = ecg_get_info (graph);
482 int ctx_idx = find_ctx_idx (call, ginfo, get_curr_ctx ());
483 ctx_info_t *call_ctx = get_ctx (ginfo, ctx_idx);
484 ctx_info_t *old_ctx = set_curr_ctx (call_ctx);
485 DBGPRINT (3, (stdout, "%s>CTX: ", -- spaces));
486 DBGEXE (3, ecg_print_ctx (call_ctx, stdout));
488 /* Initialise Alloc Names and Node values */
489 pto_reset_graph_pto (graph, ctx_idx);
491 /* Compute Arguments */
492 set_graph_args (graph, call, pto_env);
494 /* Visit/Iterate Graph */
495 pto_graph (graph, ctx_idx);
498 set_curr_ctx (old_ctx);
500 change |= set_graph_result (graph, call);
502 DBGPRINT (3, (stdout, "%s<CTX: ", spaces ++));
503 DBGEXE (3, ecg_print_ctx (call_ctx, stdout));
505 /* Don't need to reset alloc names unless we handle recursion here */
508 /* Get Return Value from Graph */
510 DBGPRINT (2, (stdout, "%s: recursion into \"%s.%s\"\n",
511 __FUNCTION__, own_name, ent_name));
514 /* Todo: Set 'Unknown' Value as Return Value when the graph is not
517 pto_env->change |= change;
520 static void pto_raise (ir_node *raise, pto_env_t *pto_env)
523 DBGPRINT (2, (stdout, "%s (%s[%li]): pto = %p\n", __FUNCTION__,
524 OPNAME (raise), OPNUM (raise), (void*) get_node_pto (raise)));
527 static void pto_end_block (ir_node *end_block, pto_env_t *pto_env)
529 /* perform end block */
530 type *tp = get_entity_type (get_irg_entity (get_irn_irg (end_block)));
532 if (0 == get_method_n_ress (tp)) {
536 tp = get_method_res_type (tp, 0);
538 if (mode_P != get_type_mode (tp)) {
542 DBGPRINT (2, (stdout, "%s (%s[%li]): pto = %p\n", __FUNCTION__,
543 OPNAME (end_block), OPNUM (end_block),
544 (void*) get_node_pto (end_block)));
546 pto_t *end_pto = get_node_pto (end_block);
550 int n_ins = get_irn_arity (end_block);
552 for (i = 0; i < n_ins; i ++) {
553 ir_node *in = get_irn_n (end_block, i);
555 if (iro_Return == get_irn_opcode (in)) {
556 pto_t *in_pto = get_pto (in, pto_env);
558 pto_env->change |= qset_insert_all (end_pto->values, in_pto->values);
563 /* ===================================================
564 Exported Implementation:
565 =================================================== */
566 /* Main loop: Initialise and iterate over the given graph */
567 void pto_graph (ir_graph *graph, int ctx_idx)
569 /* Also exported, since we need it in 'pto.c' */
570 pto_env_t *pto_env = xmalloc (sizeof (pto_env_t));
571 pto_env->ctx_idx = ctx_idx;
572 pto_env->change = TRUE;
574 /* HERE ("start"); */
576 DBGPRINT (2, (stdout, "%s: start for ctx %i\n",
580 /* todo (here): iterate, obey 'changed' attribute */
582 while (0 != pto_env->change) {
584 pto_env->change = FALSE;
585 pto_graph_pass (graph, pto_env);
588 DBGPRINT (1, (stdout, "%s: %i runs on \"%s.%s\"\n",
591 get_type_name (get_entity_owner (get_irg_entity (graph))),
592 get_entity_name (get_irg_entity (graph))));
595 memset (pto_env, 0x00, sizeof (pto_env_t));
600 /* Set the PTO value for the given non-alloc node */
601 void set_node_pto (ir_node *node, pto_t *pto)
603 assert (iro_Alloc != get_irn_opcode (node));
605 set_irn_link (node, (void*) pto);
608 /*Get the PTO value for the given non-alloc node */
609 pto_t *get_node_pto (ir_node *node)
611 assert (iro_Alloc != get_irn_opcode (node));
613 return ((pto_t*) get_irn_link (node));
616 /* Set the PTO value for the given alloc node */
617 void set_alloc_pto (ir_node *alloc, alloc_pto_t *alloc_pto)
619 assert (iro_Alloc == get_irn_opcode (alloc));
623 set_irn_link (alloc, (void*) alloc_pto);
626 /*Get the current PTO value for the given alloc node */
627 pto_t *get_alloc_pto (ir_node *alloc)
629 alloc_pto_t *alloc_pto = (alloc_pto_t*) get_irn_link (alloc);
631 assert (iro_Alloc == get_irn_opcode (alloc));
633 assert (alloc_pto -> curr_pto);
635 return (alloc_pto -> curr_pto);
641 Revision 1.8 2004/12/15 09:18:18 liekweg
644 Revision 1.7 2004/12/06 12:55:06 liekweg
647 Revision 1.6 2004/12/02 16:17:51 beck
648 fixed config.h include
650 Revision 1.5 2004/11/30 14:47:54 liekweg
651 fix initialisation; do correct iteration
653 Revision 1.4 2004/11/26 15:59:40 liekweg
654 verify pto_{load,store}
656 Revision 1.3 2004/11/24 14:53:55 liekweg
659 Revision 1.2 2004/11/20 21:21:56 liekweg
660 Finalise initialisation
662 Revision 1.1 2004/11/18 16:37:34 liekweg