5 * File name: ir/ana/rta.c
6 * Purpose: Intraprozedural analyses to improve the call graph estimate.
11 * Copyright: (c) 1999-2004 Universität Karlsruhe
12 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
16 * Intraprozedurale Analyse zur Abschätzung der Aufrufrelation. Es
17 * die Menge der instantiierten Klassen bestimmt, und daraus existierende Methoden
28 #include "cgana.h" /* get_implementation */
34 /* #include "pmap.h" */
35 /* #include "array.h" */
37 /* #include "ircons.h" */
38 /* #include "irgmod.h" */
39 /* #include "irflag_t.h" */
41 /* #include "dbginfo_t.h" */
47 static eset *_live_classes = NULL;
48 static eset *_live_fields = NULL;
49 static eset *_called_methods = NULL;
51 /* cache computed results */
52 static eset *_live_graphs = NULL;
53 static eset *_dead_graphs = NULL;
57 static void rta_act (ir_node *node, void *env)
59 opcode op = get_irn_opcode (node);
64 ir_node *ptr = get_Call_ptr (node);
65 // TODO: test: ptr.op == Const
67 if (iro_Sel == get_irn_opcode (ptr)) {
68 ent = get_Sel_entity (ptr);
72 eset_insert (_called_methods, ent);
74 } else if (iro_Load == op) {
75 ir_node *ptr = get_Load_ptr (node);
78 if (iro_Sel == get_irn_opcode (ptr)) {
79 ent = get_Sel_entity (ptr);
82 eset_insert (_live_fields, ent);
84 } else if (iro_Store == op) {
85 ir_node *ptr = get_Store_ptr (node);
88 if (iro_Sel == get_irn_opcode (ptr)) {
89 ent = get_Sel_entity (ptr);
92 eset_insert (_live_fields, ent);
94 } else if (iro_Alloc == op) {
95 type *type = get_Alloc_type (node);
96 eset_insert (_live_classes, type);
100 static void rta_fill_graph (ir_graph* graph)
103 if (NULL != get_irg_end_block (graph)) {
104 irg_walk (get_irg_end_block (graph), rta_act, NULL, NULL);
109 static void rta_fill_all ()
112 int old_ip_view = interprocedural_view;
114 interprocedural_view = 0;
115 for (i = 0; i < get_irp_n_irgs(); i++) {
116 rta_fill_graph (get_irp_irg (i));
118 interprocedural_view = old_ip_view;
121 static int is_call_target (entity *method)
123 int is_target = FALSE;
127 /* The method could be the target of a polymorphic call if it is
128 called or if it overrides a method that is called. */
130 if (eset_contains (_called_methods, method)) {
134 n_over = get_entity_n_overwrittenby (method);
135 for (i = 0; !is_target && (i < n_over); i ++) {
136 entity *over = get_entity_overwrittenby (method, i);
137 is_target |= is_call_target (over);
144 static ir_graph *get_implementing_graph (entity *method)
146 ir_graph *graph = get_entity_irg (method);
150 int n_over = get_entity_n_overwrites (method);
152 for (i = 0; (NULL == graph) && (i < n_over); i ++) {
153 entity *over = get_entity_overwrites (method, i);
154 graph = get_implementing_graph (over);
158 assert (graph && "no graph");
163 static int has_live_call (entity *method, ir_graph *graph)
165 int has_call = FALSE;
168 if (get_irg_ent (graph) != method) {
172 if (is_call_target (method)) {
176 n_over = get_entity_n_overwrittenby (method);
177 for (i = 0; !has_call && (i < n_over); i ++) {
178 entity *over = get_entity_overwrittenby(method, i);
179 has_call |= has_live_call (over, graph);
185 static int has_graph (type *clazz, ir_graph *graph)
187 int has_the_graph = FALSE;
191 if (eset_contains (_live_classes, clazz)) {
192 int n_meth = get_class_n_members (clazz);
194 for (i = 0; i < n_meth; i ++) {
195 entity *member = get_class_member (clazz, i);
196 if (is_method_type (get_entity_type (member))) {
197 ir_graph *impl = get_entity_irg (member);
204 } /* _live_classes.contains (clazz) */
206 n_sub = get_class_n_subtypes (clazz);
207 for (i = 0; !has_the_graph && (i < n_sub); i ++) {
208 type *sub = get_class_subtype (clazz, i);
210 has_the_graph |= has_graph (sub, graph);
213 return (has_the_graph);
216 static int has_live_class (entity *method, ir_graph *graph)
218 int has_class = FALSE;
223 if (get_implementing_graph (method) != graph) {
227 clazz = get_entity_owner (method);
228 if (has_graph (clazz, graph)) {
232 n_over = get_entity_n_overwrittenby (method);
233 for (i = 0; !has_class && (i < n_over); i ++) {
234 entity *over = get_entity_overwrittenby (method, i);
235 has_class |= has_live_class (over, graph);
241 static int rta_check (ir_graph *graph)
243 return (rta_is_alive_graph (graph));
249 _live_classes = eset_create ();
250 _live_fields = eset_create ();
251 _called_methods = eset_create ();
253 _live_graphs = eset_create ();
254 _dead_graphs = eset_create ();
260 if (get_irp_main_irg ()) {
261 eset_insert (_live_graphs, get_irp_main_irg ());
270 int n_live_graphs = 0;
271 int n_graphs = get_irp_n_irgs();
273 for (i = 0; i < n_graphs; i++) {
274 ir_graph *graph = get_irp_irg(i);
276 if (rta_check (graph)) {
280 name = get_entity_name (get_irg_ent (graph));
282 fprintf (stdout, "LIVE %s\n", name);
286 fprintf (stdout, "RES %s: %i graphs, %i live\n", __FUNCTION__, n_graphs, n_live_graphs);
289 eset_destroy (_live_classes);
290 _live_classes = NULL;
294 eset_destroy (_live_fields);
298 if (_called_methods) {
299 eset_destroy (_called_methods);
300 _called_methods = NULL;
304 eset_destroy (_live_graphs);
309 eset_destroy (_dead_graphs);
314 int rta_is_alive_class (type *clazz)
316 return (eset_contains (_live_classes, clazz));
319 int rta_is_alive_graph (ir_graph *graph)
321 if (eset_contains (_live_graphs, graph)) {
325 if (eset_contains (_dead_graphs, graph)) {
329 entity *meth = get_irg_ent (graph);
331 if (has_live_call (meth, graph) && has_live_class (meth, graph)) {
332 eset_insert (_live_graphs, graph);
336 eset_insert (_dead_graphs, graph);
342 int rta_is_alive_field (entity *field)
344 return (eset_contains (_live_fields, field));
351 * Revision 1.3 2004/06/12 17:09:46 liekweg
352 * RTA works, outedges breaks. "Yay." --flo
354 * Revision 1.2 2004/06/11 18:25:39 liekweg
357 * Revision 1.1 2004/06/11 18:24:18 liekweg