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;
58 Enter all method and field accesses and all class allocations into our tables.
60 static void rta_act (ir_node *node, void *env)
62 opcode op = get_irn_opcode (node);
67 ir_node *ptr = get_Call_ptr (node);
69 if (iro_Sel == get_irn_opcode (ptr)) {
70 ent = get_Sel_entity (ptr);
71 } else if (iro_Const == get_irn_opcode (ptr)) {
72 ent = get_tarval_entity (get_Const_tarval (ptr));
78 eset_insert (_called_methods, ent);
80 } else if (iro_Load == op) {
81 ir_node *ptr = get_Load_ptr (node);
84 if (iro_Sel == get_irn_opcode (ptr)) {
85 ent = get_Sel_entity (ptr);
88 eset_insert (_live_fields, ent);
90 } else if (iro_Store == op) {
91 ir_node *ptr = get_Store_ptr (node);
94 if (iro_Sel == get_irn_opcode (ptr)) {
95 ent = get_Sel_entity (ptr);
98 eset_insert (_live_fields, ent);
100 } else if (iro_Alloc == op) {
101 type *type = get_Alloc_type (node);
103 eset_insert (_live_classes, type);
108 Traverse the given graph to collect method and field accesses and object allocations.
110 static void rta_fill_graph (ir_graph* graph)
113 if (NULL != get_irg_end_block (graph)) {
114 irg_walk (get_irg_end_block (graph), rta_act, NULL, NULL);
120 Traverse all graphs to collect method and field accesses and object allocations.
122 static void rta_fill_all ()
125 int old_ip_view = interprocedural_view;
127 interprocedural_view = 0;
128 for (i = 0; i < get_irp_n_irgs(); i++) {
129 rta_fill_graph (get_irp_irg (i));
131 interprocedural_view = old_ip_view;
135 Find out whether the given method could be the target of a
138 static int is_call_target (const entity *method)
140 int is_target = FALSE;
144 /* The method could be the target of a polymorphic call if it is
145 called or if it overrides a method that is called. */
147 if (eset_contains (_called_methods, (entity*) method)) {
151 /* not called? check methods in superclass(es) */
152 n_over = get_entity_n_overwrittenby ((entity*) method);
153 for (i = 0; !is_target && (i < n_over); i ++) {
154 entity *over = get_entity_overwrittenby ((entity*) method, i);
155 is_target |= is_call_target (over);
162 Given a method, find the firm graph that implements that method.
164 static ir_graph *get_implementing_graph (const entity *method)
166 ir_graph *graph = get_entity_irg ((entity*) method);
170 int n_over = get_entity_n_overwrites ((entity*) method);
172 for (i = 0; (NULL == graph) && (i < n_over); i ++) {
173 entity *over = get_entity_overwrites ((entity*) method, i);
174 graph = get_implementing_graph (over);
178 assert (graph && "no graph");
184 Determine whether the give method or one of its overwriter have
185 been used in a call to the given graph.
187 static int has_live_call (entity *method, ir_graph *graph)
189 int has_call = FALSE;
192 /* stop searching if a overwriting method comes with a new graph */
193 if (get_irg_ent (graph) != method) {
197 /* maybe we're called (possibly through polymorphy)? */
198 if (is_call_target (method)) {
202 /* maybe we're overwritten by a method that is called? */
203 n_over = get_entity_n_overwrittenby ((entity*) method);
204 for (i = 0; !has_call && (i < n_over); i ++) {
205 entity *over = get_entity_overwrittenby((entity*) method, i);
206 has_call |= has_live_call (over, graph);
213 Determine whether the given class is live *and* uses the given
216 static int has_graph (type *clazz, ir_graph *graph)
218 int has_the_graph = FALSE;
222 if (eset_contains (_live_classes, clazz)) {
223 int n_meth = get_class_n_members (clazz);
225 for (i = 0; i < n_meth; i ++) {
226 entity *member = get_class_member (clazz, i);
227 if (is_method_type (get_entity_type (member))) {
228 ir_graph *impl = get_entity_irg (member);
235 } /* _live_classes.contains (clazz) */
237 /* our subclasses might be using that graph, no? */
238 n_sub = get_class_n_subtypes (clazz);
239 for (i = 0; !has_the_graph && (i < n_sub); i ++) {
240 type *sub = get_class_subtype (clazz, i);
242 has_the_graph |= has_graph (sub, graph);
245 return (has_the_graph);
249 Determine wether the given method could be used in a call to the
250 given graph on a live class.
252 static int has_live_class (entity *method, ir_graph *graph)
254 int has_class = FALSE;
259 /* const char *name = get_entity_name (method); */
261 /* stop searching when an overwriting method provides a new graph */
262 if (get_implementing_graph (method) != graph) {
266 clazz = get_entity_owner (method);
268 if (has_graph (clazz, graph)) { /* this also checks whether clazz is live*/
272 n_over = get_entity_n_overwrittenby (method);
273 for (i = 0; !has_class && (i < n_over); i ++) {
274 entity *over = get_entity_overwrittenby (method, i);
275 has_class |= has_live_class (over, graph);
281 static int rta_check (ir_graph *graph)
283 return (rta_is_alive_graph (graph));
289 _live_classes = eset_create ();
290 _live_fields = eset_create ();
291 _called_methods = eset_create ();
293 _live_graphs = eset_create ();
294 _dead_graphs = eset_create ();
300 if (get_irp_main_irg ()) {
301 eset_insert (_live_graphs, get_irp_main_irg ());
304 if (get_glob_type ()) {
305 eset_insert (_live_classes, get_glob_type ());
314 int n_live_graphs = 0;
315 int n_graphs = get_irp_n_irgs();
317 for (i = 0; i < n_graphs; i++) {
318 ir_graph *graph = get_irp_irg(i);
320 if (rta_check (graph)) {
321 const char *name = get_entity_name (get_irg_ent (graph));;
325 fprintf (stdout, "LIVE %s\n", name);
329 fprintf (stdout, "RES %s: %i graphs, %i live\n", __FUNCTION__, n_graphs, n_live_graphs);
332 eset_destroy (_live_classes);
333 _live_classes = NULL;
337 eset_destroy (_live_fields);
341 if (_called_methods) {
342 eset_destroy (_called_methods);
343 _called_methods = NULL;
347 eset_destroy (_live_graphs);
352 eset_destroy (_dead_graphs);
357 int rta_is_alive_class (type *clazz)
359 return (eset_contains (_live_classes, clazz));
362 int rta_is_alive_graph (ir_graph *graph)
364 if (eset_contains (_live_graphs, graph)) {
368 if (eset_contains (_dead_graphs, graph)) {
372 entity *meth = get_irg_ent (graph);
374 if (has_live_call (meth, graph) && has_live_class (meth, graph)) {
375 eset_insert (_live_graphs, graph);
379 eset_insert (_dead_graphs, graph);
385 int rta_is_alive_field (entity *field)
387 return (eset_contains (_live_fields, field));
394 * Revision 1.4 2004/06/12 19:35:04 liekweg
395 * Kommentare eingef"ugt --flo
397 * Revision 1.3 2004/06/12 17:09:46 liekweg
398 * RTA works, outedges breaks. "Yay." --flo
400 * Revision 1.2 2004/06/11 18:25:39 liekweg
403 * Revision 1.1 2004/06/11 18:24:18 liekweg