Bugfixes
[libfirm] / ir / ana / phiclass.c
1 /**
2  * @author Daniel Grund
3  * @date 09.08.2005
4  */
5
6 #include <stdlib.h>
7
8 #include "debug.h"
9 #include "irgwalk.h"
10 #include "irop_t.h"
11 #include "iredges_t.h"
12 #include "phiclass_t.h"
13
14 #define DEBUG_LVL SET_LEVEL_0
15 static firm_dbg_module_t *dbg = NULL;
16
17 size_t phi_irn_data_offset = 0;
18
19 static void phi_class_build(ir_node *irn, pset *pc) {
20         int i, max;
21         const ir_edge_t *edge;
22
23         /* If irn has a phi class assigned already
24          * return immediately to stop recursion */
25         if (_get_phi_class(irn)) {
26                 DBG((dbg, LEVEL_2, "  already done for %+F\n", irn));
27                 return;
28         }
29
30         /* The initial call to phi_class_build doesn't
31          * provide a pset, so alloc it */
32         if (!pc) {
33                 DBG((dbg, LEVEL_1, "Computing phi class for %+F\n", irn));
34                 assert(is_Phi(irn));
35                 pc = pset_new_ptr(4);
36         }
37
38         /* Add the irn to the phi class */
39         DBG((dbg, LEVEL_1, "  adding %+F\n", irn));
40         pset_insert_ptr(pc, irn);
41         _set_phi_class(irn, pc);
42
43         /* Check the 'neighbour' irns */
44         if (is_Phi(irn) && mode_is_datab(get_irn_mode(irn))) {
45                 /* Add all args of the phi to the phi-class. */
46                  for (i=0, max=get_irn_arity(irn); i<max; ++i) {
47                         DBG((dbg, LEVEL_2, "  checking arg %+F\n", get_irn_n(irn, i)));
48                         phi_class_build(get_irn_n(irn, i), pc);
49                  }
50         }
51
52         /* Add a user of the irn to the class,
53          * iff it is a phi node  */
54         foreach_out_edge(irn, edge) {
55                 ir_node *user = edge->src;
56                 DBG((dbg, LEVEL_2, "  checking user %+F\n", user));
57                 if (is_Phi(user) && mode_is_datab(get_irn_mode(user)))
58                         phi_class_build(user, pc);
59         }
60 }
61
62 static void phi_class_construction_walker(ir_node *node, void *env) {
63         if (is_Phi(node) && mode_is_datab(get_irn_mode(node)))
64                 phi_class_build(node, NULL);
65 }
66
67 static void phi_class_destruction_walker(ir_node *node, void *env) {
68         pset *clss = _get_phi_class(node);
69         if (clss) {
70                 //TODOdel_pset(clss);
71                 _set_phi_class(node, NULL);
72         }
73 }
74
75 void phi_class_compute(ir_graph *irg) {
76         irg_walk_graph(irg, phi_class_destruction_walker, NULL, NULL);
77         irg_walk_graph(irg, phi_class_construction_walker, NULL, NULL);
78 }
79
80 pset *phi_class_compute_by_phis(pset *all_phi_nodes) {
81         int i;
82         ir_node *phi;
83         pset *all_phi_classes = pset_new_ptr_default();
84
85         if (pset_count(all_phi_nodes)) {
86                 ir_graph *irg = get_irn_irg(pset_first(all_phi_nodes));
87                 pset_break(all_phi_nodes);
88                 irg_walk_graph(irg, phi_class_destruction_walker, NULL, NULL);
89
90                 for (i = 0, phi=pset_first(all_phi_nodes); phi; phi=pset_next(all_phi_nodes)) {
91                         assert(is_Phi(phi) && mode_is_datab(get_irn_mode(phi)));
92                         phi_class_build(phi, NULL);
93                         pset_insert_ptr(all_phi_classes, _get_phi_class(phi));
94                 }
95         }
96
97         return all_phi_classes;
98 }
99
100 void phi_class_free(ir_graph *irg) {
101         irg_walk_graph(irg, phi_class_destruction_walker, NULL, NULL);
102 }
103
104 pset *get_phi_class(const ir_node *irn) {
105         return get_irn_phi_info(irn)->phi_class;
106 }
107
108 void phi_class_init(void) {
109         dbg = firm_dbg_register("ir.ana.phiclass");
110         firm_dbg_set_mask(dbg, DEBUG_LVL);
111         phi_irn_data_offset = register_additional_node_data(sizeof(phi_info_t));
112 }