more analyses for cache optimization
[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 "field_temperature.h"
14
15 #include "irnode_t.h"
16 #include "irgraph_t.h"
17 #include "irprog_t.h"
18 #include "entity_t.h"
19 #include "irgwalk.h"
20
21 #include "array.h"
22
23 /* *************************************************************************** */
24 /* initialize, global variables.                                               */
25 /* *************************************************************************** */
26
27 /* A list of Load and Store operations that have no analyseable address. */
28 static ir_node **unrecognized_access = NULL;
29
30 static void add_unrecognized_access(ir_node *n) {
31   ARR_APP1(ir_node *, unrecognized_access, n);
32 }
33
34 /* *************************************************************************** */
35 /*   Access routines for entities                                              */
36 /* *************************************************************************** */
37
38 /* The entities that can be accessed by this Sel node. */
39 int get_Sel_n_accessed_entities(ir_node *sel) {
40   return 1;
41 }
42
43 entity *get_Sel_accessed_entity(ir_node *sel, int pos) {
44   return get_Sel_entity(sel);
45 }
46
47 int get_entity_n_accesses(entity *ent) {
48   assert(ent && is_entity(ent));
49
50   if (!ent->accesses) { ent->accesses = NEW_ARR_F(ir_node *, 0); }
51
52   return ARR_LEN(ent->accesses);
53 }
54
55 ir_node *get_entity_access(entity *ent, int pos) {
56   assert(0 <= pos && pos < get_entity_n_accesses(ent));
57
58   return ent->accesses[pos];
59 }
60
61 void add_entity_access(entity *ent, ir_node *n) {
62   assert(ent && is_entity(ent));
63   assert(n && is_ir_node(n));
64
65   if (!ent->accesses) ent->accesses = NEW_ARR_F(ir_node *, 0);
66
67   ARR_APP1(ir_node *, ent->accesses, n);
68 }
69
70 void set_entity_access(entity *ent, int pos, ir_node *n) {
71   assert(0 <= pos && pos < get_entity_n_accesses(ent));
72   assert(n && is_ir_node(n));
73
74   ent->accesses[pos] = n;
75 }
76
77
78 /* *************************************************************************** */
79 /*   Access routines for nodes                                                 */
80 /* *************************************************************************** */
81
82 /* An addr node is a SymConst or a Sel. */
83 int get_addr_n_entities(ir_node *addr) {
84   int n_ents;
85
86   switch (get_irn_opcode(addr)) {
87   case iro_Sel:
88     /* Treat jack array sels? */
89     n_ents = get_Sel_n_accessed_entities(addr);
90     break;
91   case iro_SymConst:
92     if (get_SymConst_kind(addr) == symconst_addr_ent) {
93       n_ents = 1;
94       break;
95     }
96   default:
97     //assert(0 && "unexpected address expression");
98     n_ents = 0;
99   }
100
101   return n_ents;
102 }
103
104 /* An addr node is a SymConst or a Sel. */
105 entity *get_addr_entity(ir_node *addr, int pos) {
106   entity *ent;
107
108   switch (get_irn_opcode(addr)) {
109   case iro_Sel:
110     /* Treat jack array sels? */
111     assert (0 <= pos && pos < get_Sel_n_accessed_entities(addr));
112     ent = get_Sel_accessed_entity(addr, pos);
113     break;
114   case iro_SymConst:
115     if (get_SymConst_kind(addr) == symconst_addr_ent) {
116       assert(pos == 0);
117       ent = get_SymConst_entity(addr);
118       break;
119     }
120   default:
121     ent = NULL;
122   }
123
124   return ent;
125 }
126
127 /* *************************************************************************** */
128 /* The analyses                                                                */
129 /* *************************************************************************** */
130
131 void init_field_temperature(void) {
132   assert(!unrecognized_access);
133   unrecognized_access = NEW_ARR_F(ir_node *, 0);
134 }
135
136
137 void chain_accesses(ir_node *n, void *env) {
138   int i, n_ents;
139   ir_node *addr;
140
141   if (get_irn_op(n) == op_Load) {
142     addr = get_Load_ptr(n);
143   } else if  (get_irn_op(n) == op_Store) {
144     addr = get_Store_ptr(n);
145   } else {
146     return;
147   }
148
149   n_ents = get_addr_n_entities(addr);
150   for (i = 0; i < n_ents; ++i) {
151     entity *ent = get_addr_entity(addr, i);
152     if (ent)
153       add_entity_access(ent, n);
154     else
155       add_unrecognized_access(n);
156   }
157 }
158
159
160 /* compute the field temperature. */
161 void compute_field_temperature(void) {
162
163   int i, n_irgs = get_irp_n_irgs();
164
165   init_field_temperature();
166
167   for (i=0; i < n_irgs; i++) {
168     current_ir_graph = get_irp_irg(i);
169     irg_walk_graph(current_ir_graph, NULL, chain_accesses, NULL);
170   }
171 }
172
173 /* free occupied memory, reset */
174 void free_field_temperature(void) {
175   DEL_ARR_F(unrecognized_access);
176   unrecognized_access = NULL;
177 }