More missing config.h
[libfirm] / ir / be / beuses.c
1 /**
2  * @file   beuse.c
3  * @date   27.06.2005
4  * @author Sebastian Hack, Matthias Braun
5  *
6  * Methods to compute when a value will be used again.
7  *
8  * Copyright (C) 2005 Universitaet Karlsruhe
9  * Released under the GPL
10  */
11 #ifdef HAVE_CONFIG_H
12 #include "config.h"
13 #endif
14
15 #include <limits.h>
16 #include <stdlib.h>
17
18 #include "config.h"
19 #include "obst.h"
20 #include "pmap.h"
21 #include "debug.h"
22
23 #include "irgwalk.h"
24 #include "irnode_t.h"
25 #include "ircons_t.h"
26 #include "irgraph_t.h"
27 #include "iredges_t.h"
28 #include "irdom_t.h"
29
30 #include "be_t.h"
31 #include "beutil.h"
32 #include "belive_t.h"
33 #include "benode_t.h"
34 #include "besched_t.h"
35 #include "beirgmod.h"
36 #include "bearch.h"
37 #include "beuses_t.h"
38 #include "benodesets.h"
39
40 #define SCAN_INTERBLOCK_USES
41
42 typedef struct _be_use_t {
43         const ir_node *block;
44         const ir_node *node;
45         unsigned next_use;
46 } be_use_t;
47
48 struct _be_uses_t {
49         set *uses;
50         ir_graph *irg;
51         const ir_exec_freq *execfreqs;
52         const be_lv_t *lv;
53         DEBUG_ONLY(firm_dbg_module_t *dbg;)
54 };
55
56 static int cmp_use(const void *a, const void *b, size_t n)
57 {
58         const be_use_t *p = a;
59         const be_use_t *q = b;
60         return !(p->block == q->block && p->node == q->node);
61 }
62
63 static const be_use_t *get_or_set_use_block(be_uses_t *uses,
64                                             const ir_node *block,
65                                             const ir_node *def)
66 {
67         unsigned hash = HASH_COMBINE(nodeset_hash(block), nodeset_hash(def));
68         be_use_t temp;
69         be_use_t* result;
70
71         temp.block = block;
72         temp.node = def;
73         result = set_find(uses->uses, &temp, sizeof(temp), hash);
74
75         if(result == NULL) {
76                 // insert templ first as we might end in a loop in the get_next_use
77                 // call otherwise
78                 temp.next_use = USES_INFINITY;
79                 result = set_insert(uses->uses, &temp, sizeof(temp), hash);
80
81                 result->next_use = be_get_next_use(uses, sched_first(block), 0, def, 0);
82         }
83
84         return result;
85 }
86
87 static int is_real_use(const ir_node *node)
88 {
89         if(be_is_Spill(node))
90                 return 0;
91         /* we don't check for phi loops yet, so don't enable this
92         if(is_Phi(node))
93                 return 0;
94         */
95
96         return 1;
97 }
98
99 unsigned be_get_next_use(be_uses_t *uses, const ir_node *from,
100                          unsigned from_step, const ir_node *def,
101                          int skip_from_uses)
102 {
103         unsigned step = from_step;
104         ir_node *block = get_nodes_block(from);
105         const ir_node *node;
106         const ir_edge_t *edge;
107
108         if(skip_from_uses) {
109                 step++;
110                 from = sched_next(from);
111         }
112
113         sched_foreach_from(from, node) {
114                 int i, arity;
115
116                 arity = get_irn_arity(node);
117                 for (i = 0; i < arity; ++i) {
118                         const ir_node *operand = get_irn_n(node, i);
119
120                         if (operand == def) {
121                                 DBG((uses->dbg, LEVEL_3, "found use of %+F at %+F\n", operand, node));
122
123                                 if(!is_real_use(node)) {
124                                         return be_get_next_use(uses, node, step, node, 1);
125                                 } else {
126                                         return step;
127                                 }
128                         }
129                 }
130
131                 step++;
132         }
133
134         if(be_is_live_end(uses->lv, block, def)) {
135                 // TODO we really should continue searching the uses of the phi,
136                 // as a phi isn't a real use that implies a reload (because we could
137                 // easily spill the whole phi)
138                 return step;
139         }
140
141 #ifdef SCAN_INTERBLOCK_USES
142         {
143         double best_execfreq = -1;
144         unsigned next_use = USES_INFINITY;
145
146         foreach_block_succ(block, edge) {
147                 const be_use_t *use;
148                 const ir_node *succ_block = get_edge_src_irn(edge);
149                 double execfreq = get_block_execfreq(uses->execfreqs, succ_block);
150
151                 //execfreq_sum += execfreq;
152
153                 if(execfreq > best_execfreq) {
154                         best_execfreq = execfreq;
155
156                         if(!be_is_live_in(uses->lv, succ_block, def)) {
157                                 next_use = USES_INFINITY;
158                                 continue;
159                         }
160
161                         use = get_or_set_use_block(uses, succ_block, def);
162                         //if(USES_IS_INFINITE(use->next_use))
163                         //      continue;
164
165                         next_use = use->next_use;
166                 }
167
168                 //next_use += use->next_use / execfreq;
169         }
170
171         /*if(next_use == 0)
172                 return USES_INFINITY;*/
173
174         //next_use /= execfreq_sum;
175
176         return ((unsigned) next_use) + step;
177         }
178 #else
179         return USES_INFINITY;
180 #endif
181 }
182
183 be_uses_t *be_begin_uses(ir_graph *irg, const ir_exec_freq *execfreqs, const be_lv_t *lv)
184 {
185         be_uses_t *uses = xmalloc(sizeof(uses[0]));
186
187         edges_assure(irg);
188
189         uses->uses = new_set(cmp_use, 512);
190         uses->irg = irg;
191         uses->execfreqs = execfreqs;
192         uses->lv = lv;
193         FIRM_DBG_REGISTER(uses->dbg, "firm.be.uses");
194
195         return uses;
196 }
197
198 void be_end_uses(be_uses_t *uses)
199 {
200         del_set(uses->uses);
201         free(uses);
202 }