Cosmetic
[libfirm] / ir / ana / field_temperature.c
1 /*
2  * Project:     libFIRM
3  * File name:   ir/ana/field_temperature.c
4  * Purpose:     Compute an estimate of field temperature, i.e., field access heuristic.
5  * Author:      Goetz Lindenmaier
6  * Modified by:
7  * Created:     21.7.2004
8  * CVS-ID:      $Id$
9  * Copyright:   (c) 2004 Universität Karlsruhe
10  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
11  */
12
13 #include <math.h>
14
15 #include "field_temperature.h"
16
17 #include "trouts.h"
18 #include "execution_frequency.h"
19
20 #include "irnode_t.h"
21 #include "irgraph_t.h"
22 #include "irprog_t.h"
23 #include "entity_t.h"
24 #include "irgwalk.h"
25
26 #include "array.h"
27 #include "set.h"
28 #include "hashptr.h"
29
30
31 /* *************************************************************************** */
32 /* initialize, global variables.                                               */
33 /* *************************************************************************** */
34
35 /* *************************************************************************** */
36 /* Another hash table, this time containing temperature values.                */
37 /* *************************************************************************** */
38
39 typedef struct {
40   firm_kind *kind;   /* An entity or type. */
41   double    val1;
42 } temperature_tp;
43
44 /* We use this set for all types and entities.  */
45 static set *temperature_set = NULL;
46
47 static int temp_cmp(const void *e1, const void *e2, size_t size) {
48   temperature_tp *ef1 = (temperature_tp *)e1;
49   temperature_tp *ef2 = (temperature_tp *)e2;
50   return (ef1->kind != ef2->kind);
51 }
52
53 static INLINE unsigned int tem_hash(void *e) {
54   void *v = (void *) ((temperature_tp *)e)->kind;
55   return HASH_PTR(v);
56 }
57
58 double get_entity_acc_estimated_n_loads (entity *ent) {
59   return 0;
60 }
61 double get_entity_acc_estimated_n_stores(entity *ent) {
62   return 0;
63 }
64
65 void set_entity_acc_estimated_n_loads (entity *ent, double val) {
66 }
67 void set_entity_acc_estimated_n_stores(entity *ent, double val) {
68 }
69
70 double get_type_acc_estimated_n_instances(type *tp) {
71   return 0;
72 }
73 void set_type_acc_estimated_n_instances(type *tp, double val) {
74 }
75
76 /*
77 static INLINE void set_region_exec_freq(void *reg, double freq) {
78   reg_exec_freq ef;
79   ef.reg  = reg;
80   ef.freq = freq;
81   set_insert(exec_freq_set, &ef, sizeof(ef), exec_freq_hash(&ef));
82 }
83
84 INLINE double get_region_exec_freq(void *reg) {
85   reg_exec_freq ef, *found;
86   ef.reg  = reg;
87   assert(exec_freq_set);
88   found = set_find(exec_freq_set, &ef, sizeof(ef), exec_freq_hash(&ef));
89   if (found)
90     return found->freq;
91   else
92     return 0;
93 }
94 */
95
96
97 /* *************************************************************************** */
98 /*   Access routines for irnodes                                               */
99 /* *************************************************************************** */
100
101 /* The entities that can be accessed by this Sel node. */
102 int get_Sel_n_accessed_entities(ir_node *sel) {
103   return 1;
104 }
105
106 entity *get_Sel_accessed_entity(ir_node *sel, int pos) {
107   return get_Sel_entity(sel);
108 }
109
110 /* *************************************************************************** */
111 /* The heuristic                                                               */
112 /* *************************************************************************** */
113
114 int get_irn_loop_call_depth(ir_node *n) {
115   ir_graph *irg = get_irn_irg(n);
116   return get_irg_loop_depth(irg);
117 }
118
119 int get_irn_loop_depth(ir_node *n) {
120   ir_loop *l = get_irn_loop(get_nodes_block(n));
121   if (l)
122     return get_loop_depth(l);
123   else
124     return 0;
125 }
126
127 int get_irn_recursion_depth(ir_node *n) {
128   ir_graph *irg = get_irn_irg(n);
129   return get_irg_recursion_depth(irg);
130 }
131
132
133 /**   @@@ the second version of the heuristic. */
134 int get_weighted_loop_depth(ir_node *n) {
135   int loop_call_depth = get_irn_loop_call_depth(n);
136   int loop_depth      = get_irn_loop_depth(n);
137   int recursion_depth = get_irn_recursion_depth(n);
138
139   return loop_call_depth + loop_depth + recursion_depth;
140 }
141
142
143 /* *************************************************************************** */
144 /* The 2. heuristic                                                            */
145 /* *************************************************************************** */
146
147 static int default_recursion_weight = 5;
148
149
150 /* The final evaluation of a node.  In this function we can
151    adapt the heuristic.  Combine execution freqency with
152    recursion depth.
153    @@@ the second version of the heuristic. */
154 double get_irn_final_cost(ir_node *n) {
155   double cost_loop   = get_irn_exec_freq(n);
156   double cost_method = get_irg_method_execution_frequency(get_irn_irg(n));
157   int    rec_depth   = get_irn_recursion_depth(n);
158   double cost_rec    = pow(default_recursion_weight, rec_depth);
159   return cost_loop*(cost_method + cost_rec);
160 }
161
162 double get_type_estimated_n_instances(type *tp) {
163   int i, n_allocs = get_type_n_allocs(tp);
164   double n_instances = 0;
165   for (i = 0; i < n_allocs; ++i) {
166     ir_node *alloc = get_type_alloc(tp, i);
167     n_instances += get_irn_final_cost(alloc);
168   }
169   return n_instances;
170 }
171
172 double get_type_estimated_mem_consumption_bytes(type *tp) {
173   assert(0);
174 }
175
176 int get_type_estimated_n_fields(type *tp) {
177   int s = 0;
178   switch(get_type_tpop_code(tp)) {
179
180   case tpo_primitive:
181   case tpo_pointer:
182   case tpo_enumeration:
183     s = 1;
184     break;
185
186   case tpo_class:
187     s = 1; /* dispatch pointer */
188     /* fall through */
189   case tpo_struct: {
190     int i, n_mem = get_compound_n_members(tp);
191     for (i = 0; i < n_mem; ++i) {
192       entity *mem = get_compound_member(tp, i);
193       if (get_entity_allocation(mem) == allocation_automatic) {
194         s += get_type_estimated_n_fields(get_entity_type(mem));
195       }
196     }
197   } break;
198
199   case tpo_array: {
200     long n_elt = DEFAULT_N_ARRAY_ELEMENTS;
201     assert(get_array_n_dimensions(tp) == 1 && "other not implemented");
202     if ((get_irn_op(get_array_lower_bound(tp, 0)) == op_Const) &&
203         (get_irn_op(get_array_upper_bound(tp, 0)) == op_Const)   ) {
204       n_elt = get_array_upper_bound_int(tp, 0) - get_array_upper_bound_int(tp, 0);
205     }
206     s = n_elt;
207   } break;
208
209   default: DDMT(tp); assert(0);
210   }
211
212   return s;
213 }
214
215 int get_type_estimated_size_bytes(type *tp) {
216   int s = 0;
217
218   switch(get_type_tpop_code(tp)) {
219
220   case tpo_primitive:
221   case tpo_pointer:
222   case tpo_enumeration:
223     s = get_mode_size_bytes(get_type_mode(tp));
224     break;
225
226   case tpo_class:
227     s = get_mode_size_bytes(mode_P_mach); /* dispatch pointer */
228     /* fall through */
229   case tpo_struct: {
230     int i, n_mem = get_compound_n_members(tp);
231     for (i = 0; i < n_mem; ++i) {
232       entity *mem = get_compound_member(tp, i);
233       s += get_type_estimated_size_bytes(get_entity_type(mem));
234
235       if (get_entity_allocation(mem) == allocation_automatic) {
236       } /* allocation_automatic */
237     }
238   } break;
239
240   case tpo_array: {
241     int elt_s = get_type_estimated_size_bytes(get_array_element_type(tp));
242     long n_elt = DEFAULT_N_ARRAY_ELEMENTS;
243     assert(get_array_n_dimensions(tp) == 1 && "other not implemented");
244     if ((get_irn_op(get_array_lower_bound(tp, 0)) == op_Const) &&
245         (get_irn_op(get_array_upper_bound(tp, 0)) == op_Const)   ) {
246       n_elt = get_array_upper_bound_int(tp, 0) - get_array_lower_bound_int(tp, 0);
247     }
248     s = n_elt * elt_s;
249     break;
250   }
251
252   default: DDMT(tp); assert(0);
253   }
254
255   return s;
256 }
257
258 double get_type_estimated_n_casts(type *tp) {
259   int i, n_casts = get_type_n_casts(tp);
260   double n_instances = 0;
261   for (i = 0; i < n_casts; ++i) {
262     ir_node *cast = get_type_cast(tp, i);
263     n_instances += get_irn_final_cost(cast);
264   }
265   return n_instances;
266 }
267
268 double get_class_estimated_n_upcasts(type *clss) {
269   double n_instances = 0;
270   int i, j, n_casts, n_pointertypes;
271
272   n_casts = get_type_n_casts(clss);
273   for (i = 0; i < n_casts; ++i) {
274     ir_node *cast = get_type_cast(clss, i);
275     if (get_irn_opcode(cast) != iro_Cast) continue;  /* Could be optimized away. */
276
277     if (is_Cast_upcast(cast))
278       n_instances += get_irn_final_cost(cast);
279   }
280
281   n_pointertypes = get_type_n_pointertypes_to(clss);
282   for (j = 0; j < n_pointertypes; ++j) {
283     n_instances += get_class_estimated_n_upcasts(get_type_pointertype_to(clss, j));
284   }
285
286   return n_instances;
287 }
288
289 double get_class_estimated_n_downcasts(type *clss) {
290   double n_instances = 0;
291   int i, j, n_casts, n_pointertypes;
292
293   n_casts = get_type_n_casts(clss);
294   for (i = 0; i < n_casts; ++i) {
295     ir_node *cast = get_type_cast(clss, i);
296     if (get_irn_opcode(cast) != iro_Cast) continue;  /* Could be optimized away. */
297
298     if (is_Cast_downcast(cast))
299       n_instances += get_irn_final_cost(cast);
300   }
301
302   n_pointertypes = get_type_n_pointertypes_to(clss);
303   for (j = 0; j < n_pointertypes; ++j) {
304     n_instances += get_class_estimated_n_downcasts(get_type_pointertype_to(clss, j));
305   }
306
307   return n_instances;
308 }
309
310
311 double get_class_estimated_dispatch_writes(type *clss) {
312   return get_type_estimated_n_instances(clss);
313 }
314
315 /** Returns the number of reads of the dispatch pointer. */
316 double get_class_estimated_dispatch_reads (type *clss) {
317   int i, n_mems = get_class_n_members(clss);
318   double n_calls = 0;
319   for (i = 0; i < n_mems; ++i) {
320     entity *mem = get_class_member(clss, i);
321     n_calls += get_entity_estimated_n_dyncalls(mem);
322   }
323   return n_calls;
324 }
325
326 double get_class_estimated_n_dyncalls(type *clss) {
327   return get_class_estimated_dispatch_reads(clss) +
328          get_class_estimated_dispatch_writes(clss);
329 }
330
331 double get_entity_estimated_n_loads(entity *ent) {
332   int i, n_acc = get_entity_n_accesses(ent);
333   double n_loads = 0;
334   for (i = 0; i < n_acc; ++i) {
335     ir_node *acc = get_entity_access(ent, i);
336     if (get_irn_op(acc) == op_Load) {
337       n_loads += get_irn_final_cost(acc);
338     }
339   }
340   return n_loads;
341 }
342
343 double get_entity_estimated_n_stores(entity *ent) {
344   int i, n_acc = get_entity_n_accesses(ent);
345   double n_stores = 0;
346   for (i = 0; i < n_acc; ++i) {
347     ir_node *acc = get_entity_access(ent, i);
348     if (get_irn_op(acc) == op_Store)
349       n_stores += get_irn_final_cost(acc);
350   }
351   return n_stores;
352 }
353
354 /* @@@ Should we evaluate the callee array?  */
355 double get_entity_estimated_n_calls(entity *ent) {
356   int i, n_acc = get_entity_n_accesses(ent);
357   double n_calls = 0;
358   for (i = 0; i < n_acc; ++i) {
359     ir_node *acc = get_entity_access(ent, i);
360     if (get_irn_op(acc) == op_Call)
361
362       n_calls += get_irn_final_cost(acc);
363   }
364   return n_calls;
365 }
366
367 double get_entity_estimated_n_dyncalls(entity *ent) {
368   int i, n_acc = get_entity_n_accesses(ent);
369   double n_calls = 0;
370   for (i = 0; i < n_acc; ++i) {
371     ir_node *acc = get_entity_access(ent, i);
372
373     /* Call->Sel(ent) combination */
374     if ((get_irn_op(acc) == op_Call)  &&
375         (get_irn_op(get_Call_ptr(acc)) == op_Sel)) {
376       n_calls += get_irn_final_cost(acc);
377
378     /* MemOp->Sel combination for static, overwritten entities */
379     } else if (is_memop(acc) && (get_irn_op(get_memop_ptr(acc)) == op_Sel)) {
380       entity *ent = get_Sel_entity(get_memop_ptr(acc));
381       if (is_Class_type(get_entity_owner(ent))) {
382         /* We might call this for inner entities in compounds. */
383         if (get_entity_n_overwrites(ent) > 0 ||
384             get_entity_n_overwrittenby(ent) > 0) {
385           n_calls += get_irn_final_cost(acc);
386         }
387       }
388     }
389
390   }
391   return n_calls;
392 }
393
394 /* ------------------------------------------------------------------------- */
395 /* Accumulate information in the type hierarchy.                             */
396 /* This should go to co_read_profiling.c                                     */
397 /* ------------------------------------------------------------------------- */
398
399 static void acc_temp (type *tp) {
400   assert(is_Class_type(tp));
401
402   int i, n_subtypes = get_class_n_subtypes(tp);
403
404   /* Recursive descend. */
405   for (i = 0; i < n_subtypes; ++i) {
406     type *stp = get_class_subtype(tp, i);
407     if (type_not_visited(stp)) {
408       acc_temp(stp);
409     }
410   }
411
412   /* Deal with entity numbers. */
413   int n_members = get_class_n_members(tp);
414   for (i = 0; i < n_members; ++i) {
415     entity *mem = get_class_member(tp, i);
416     double acc_loads  = get_entity_estimated_n_loads (mem);
417     double acc_writes = get_entity_estimated_n_stores(mem);
418     int j, n_ov = get_entity_n_overwrittenby(mem);
419     for (j = 0; j < n_ov; ++j) {
420       entity *ov_mem = get_entity_overwrittenby(mem, j);
421       acc_loads  += get_entity_acc_estimated_n_loads (ov_mem);
422       acc_writes += get_entity_acc_estimated_n_stores(ov_mem);
423     }
424     set_entity_acc_estimated_n_loads (mem, acc_loads);
425     set_entity_acc_estimated_n_stores(mem, acc_writes);
426   }
427
428   /* Deal with type numbers. */
429   double inst = get_type_estimated_n_instances(tp);
430   for (i = 0; i < n_subtypes; ++i) {
431     type *stp = get_class_subtype(tp, i);
432     inst += get_type_acc_estimated_n_instances(stp);
433   }
434   set_type_acc_estimated_n_instances(tp, inst);
435
436   mark_type_visited(tp);
437 }
438
439 void accumulate_temperatures(void) {
440   int i, n_types = get_irp_n_types();
441   free_accumulated_temperatures();
442
443   inc_master_type_visited();
444   for (i = 0; i < n_types; ++i) {
445     type *tp = get_irp_type(i);
446     if (is_Class_type(tp)) { /* For others there is nothing to accumulate. */
447       int j, n_subtypes = get_class_n_subtypes(tp);
448       int has_unmarked_subtype = false;
449       for (j = 0; j < n_subtypes && !has_unmarked_subtype; ++j) {
450         type *stp = get_class_subtype(tp, j);
451         if (type_not_visited(stp)) has_unmarked_subtype = true;
452       }
453
454       if (!has_unmarked_subtype)
455         acc_temp(tp);
456     }
457   }
458
459   irp->temperature_state = temperature_consistent;
460 }
461
462
463 void free_accumulated_temperatures(void) {
464   if (temperature_set) del_set(temperature_set);
465   temperature_set = NULL;
466   irp->temperature_state = temperature_none;
467 }
468
469 /* ------------------------------------------------------------------------- */
470 /* Auxiliary                                                                 */
471 /* ------------------------------------------------------------------------- */
472
473 int is_jack_rts_name(ident *name) {
474   return  0;
475   if (id_is_prefix(new_id_from_str("java/"), name)) return 1;
476   if (id_is_prefix(new_id_from_str("["),     name)) return 1;
477   if (id_is_prefix(new_id_from_str("gnu/"),  name)) return 1;
478   if (id_is_prefix(new_id_from_str("java/"), name)) return 1;
479   if (id_is_prefix(new_id_from_str("CStringToCoreString"), name)) return 1;
480
481   return 0;
482 }
483
484
485 int is_jack_rts_class(type *t) {
486   ident *name = get_type_ident(t);
487   return is_jack_rts_name(name);
488 }
489
490 #include "entity_t.h"  // for the assertion.
491
492 int is_jack_rts_entity(entity *e) {
493   ident *name;
494
495   assert(e->ld_name);
496   name = get_entity_ld_ident(e);
497
498   return is_jack_rts_name(name);
499 }