removed dependencies on chordal_env
[libfirm] / ir / be / bespillslots.c
1 /*
2  * Author:      Matthias Braun
3  * Date:                26.7.06
4  * Copyright:   (c) Universitaet Karlsruhe
5  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
6  */
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
10
11 #include <stdlib.h>
12
13 #include "set.h"
14
15 #include "irgwalk.h"
16 #include "ircons.h"
17 #include "irprintf.h"
18 #include "execfreq.h"
19 #include "unionfind.h"
20 #include "type.h"
21 #include "irdump_t.h"
22
23 #include "benode_t.h"
24 #include "besched.h"
25 #include "bespillslots.h"
26 #include "bechordal_t.h"
27 #include "bejavacoal.h"
28 #include "benodesets.h"
29 #include "bestatevent.h"
30 #include "bespilloptions.h"
31
32 #define DBG_COALESCING          1
33 #define DBG_INTERFERENCES       2
34
35 DEBUG_ONLY(
36 static firm_dbg_module_t *dbg = NULL;
37 )
38
39 typedef struct _spill_t {
40         ir_node *spill;
41         /** mode of the spilled value */
42         const ir_mode *mode;
43         /** alignment for the spilled value */
44         int alignment;
45         /** index into spillslot_unionfind unionfind structure */
46         int spillslot;
47 } spill_t;
48
49 typedef struct _affinity_edge_t {
50         double affinity;
51         int slot1, slot2;
52 } affinity_edge_t;
53
54 struct _be_fec_env_t {
55         struct obstack obst;
56         const arch_env_t *arch_env;
57         be_irg_t *birg;
58         set *spills;
59         ir_node **reloads;
60         affinity_edge_t **affinity_edges;
61         set *memperms;
62 };
63
64 /** Compare 2 affinity edges (used in quicksort) */
65 static int cmp_affinity(const void *d1, const void *d2)
66 {
67         const affinity_edge_t * const *e1 = d1;
68         const affinity_edge_t * const *e2 = d2;
69
70         // sort in descending order
71         return (*e1)->affinity < (*e2)->affinity ? 1 : -1;
72 }
73
74 static int cmp_spill(const void* d1, const void* d2, size_t size)
75 {
76         const spill_t* s1 = d1;
77         const spill_t* s2 = d2;
78         return s1->spill != s2->spill;
79 }
80
81 static spill_t *get_spill(be_fec_env_t *env, ir_node *node)
82 {
83         spill_t spill, *res;
84         int hash = nodeset_hash(node);
85
86         spill.spill = node;
87         res = set_find(env->spills, &spill, sizeof(spill), hash);
88
89         return res;
90 }
91
92 /*
93  *   ____      _ _           _     ____        _ _ _
94  *  / ___|___ | | | ___  ___| |_  / ___| _ __ (_) | |___
95  * | |   / _ \| | |/ _ \/ __| __| \___ \| '_ \| | | / __|
96  * | |__| (_) | | |  __/ (__| |_   ___) | |_) | | | \__ \
97  *  \____\___/|_|_|\___|\___|\__| |____/| .__/|_|_|_|___/
98  *                                      |_|
99  */
100
101 static ir_node *get_memory_edge(const ir_node *node)
102 {
103         int i, arity;
104
105         arity = get_irn_arity(node);
106         for(i = arity - 1; i >= 0; --i) {
107                 ir_node *arg = get_irn_n(node, i);
108                 if(get_irn_mode(arg) == mode_M)
109                         return arg;
110         }
111
112         return NULL;
113 }
114
115 static spill_t *collect_spill(be_fec_env_t *env, ir_node *node,
116                                       const ir_mode *mode, int align)
117 {
118         spill_t spill, *res;
119         int hash = nodeset_hash(node);
120
121         /* insert into set of spills if not already there */
122         spill.spill = node;
123         res = set_find(env->spills, &spill, sizeof(spill), hash);
124
125         if(res == NULL) {
126                 spill.spillslot = set_count(env->spills);
127                 spill.mode = mode;
128                 spill.alignment = align;
129                 res = set_insert(env->spills, &spill, sizeof(spill), hash);
130         } else {
131                 assert(res->mode == mode);
132                 assert(res->alignment == align);
133         }
134
135         return res;
136 }
137
138 static spill_t *collect_memphi(be_fec_env_t *env, ir_node *node,
139                                const ir_mode *mode, int align)
140 {
141         int i, arity;
142         spill_t spill, *res;
143         int hash = nodeset_hash(node);
144         const ir_exec_freq *exec_freq = be_get_birg_exec_freq(env->birg);
145
146         assert(is_Phi(node));
147
148         spill.spill = node;
149         res = set_find(env->spills, &spill, sizeof(spill), hash);
150         if(res != NULL) {
151                 assert(res->mode == mode);
152                 assert(res->alignment == align);
153                 return res;
154         }
155
156         spill.spillslot = set_count(env->spills);
157         spill.mode = mode;
158         spill.alignment = align;
159         res = set_insert(env->spills, &spill, sizeof(spill), hash);
160
161         // collect attached spills and mem-phis
162         arity = get_irn_arity(node);
163         for(i = 0; i < arity; ++i) {
164                 affinity_edge_t *affinty_edge;
165                 ir_node *arg = get_irn_n(node, i);
166                 spill_t *arg_spill;
167
168                 if(is_Phi(arg)) {
169                         arg_spill = collect_memphi(env, arg, mode, align);
170                 } else {
171                         arg_spill = collect_spill(env, arg, mode, align);
172                 }
173
174                 // add an affinity edge
175                 affinty_edge = obstack_alloc(&env->obst, sizeof(affinty_edge[0]));
176                 affinty_edge->affinity = get_block_execfreq(exec_freq, get_nodes_block(arg));
177                 affinty_edge->slot1 = res->spillslot;
178                 affinty_edge->slot2 = arg_spill->spillslot;
179                 ARR_APP1(affinity_edge_t*, env->affinity_edges, affinty_edge);
180         }
181
182         return res;
183 }
184
185 void be_node_needs_frame_entity(be_fec_env_t *env, ir_node *node,
186                                 const ir_mode *mode, int align)
187 {
188         ir_node *spillnode = get_memory_edge(node);
189         spill_t *spill;
190
191         assert(spillnode != NULL);
192
193         if (is_Phi(spillnode)) {
194                 spill = collect_memphi(env, spillnode, mode, align);
195         } else {
196                 spill = collect_spill(env, spillnode, mode, align);
197         }
198
199         ARR_APP1(ir_node *, env->reloads, node);
200 }
201
202 /*
203  *   ____            _                      ____  _       _
204  *  / ___|___   __ _| | ___  ___  ___ ___  / ___|| | ___ | |_ ___
205  * | |   / _ \ / _` | |/ _ \/ __|/ __/ _ \ \___ \| |/ _ \| __/ __|
206  * | |__| (_) | (_| | |  __/\__ \ (_|  __/  ___) | | (_) | |_\__ \
207  *  \____\___/ \__,_|_|\___||___/\___\___| |____/|_|\___/ \__|___/
208  */
209
210 static int merge_interferences(be_fec_env_t *env, bitset_t** interferences,
211                                int* spillslot_unionfind, int s1, int s2)
212 {
213         int res;
214         int i;
215         int spillcount;
216
217         // merge spillslots and interferences
218         res = uf_union(spillslot_unionfind, s1, s2);
219         // we assume that we always merge s2 to s1 so swap s1, s2 if necessary
220         if(res != 0) {
221                 int t = s1;
222                 s1 = s2;
223                 s2 = t;
224         }
225
226         bitset_or(interferences[s1], interferences[s2]);
227
228         // update other interferences
229         spillcount = set_count(env->spills);
230         for(i = 0; i < spillcount; ++i) {
231                 bitset_t *intfs = interferences[i];
232                 if(bitset_is_set(intfs, s2))
233                         bitset_set(intfs, s1);
234         }
235
236         return res;
237 }
238
239 #if 0
240 static void dump_interference_graph(be_fec_env_t *env, bitset_t **interferences, const char* suffix) {
241         char name[256];
242         int i;
243         int spillcount;
244         spill_t *spill;
245         FILE *f;
246         static int cnt = 0;
247
248         snprintf(name, sizeof(name), "%d-%s-spillslots-%s.vcg", cnt++, get_irg_dump_name(env->chordal_env->birg->irg), suffix);
249
250         f = fopen(name, "w");
251         assert(f != NULL);
252
253         fprintf(f, "graph: {\n");
254
255         spillcount = set_count(env->spills);
256         for(spill = set_first(env->spills), i = 0; spill != NULL; spill = set_next(env->spills), ++i) {
257                 int slotid = spill->spillslot;
258                 fprintf(f, "\tnode: { title: \"n%d\" label: \"%d\" }\n", i, slotid);
259         }
260
261         for(i = 0; i < ARR_LEN(env->affinity_edges); ++i) {
262                 affinity_edge_t *edge = env->affinity_edges[i];
263                 fprintf(f, "\tedge: { sourcename: \"n%d\" targetname: \"n%d\" color: green }\n", edge->slot1, edge->slot2);
264         }
265
266         for(i = 0; i < spillcount; ++i) {
267                 int i2;
268                 for(i2 = 0; i2 < spillcount; ++i2) {
269                         if(bitset_is_set(interferences[i], i2)) {
270                                 fprintf(f, "\tedge: { sourcename: \"n%d\" targetname: \"n%d\" color: red }\n", i, i2);
271                         }
272                 }
273         }
274
275         fprintf(f, "}\n");
276         fclose(f);
277 }
278 #endif
279
280 /**
281  * A greedy coalescing algorithm for spillslots:
282  *  1. Sort the list of affinity edges
283  *  2. Try to merge slots with affinity edges (most expensive slots first)
284  *  3. Try to merge everything else that is possible
285  */
286 static void do_greedy_coalescing(be_fec_env_t *env)
287 {
288         int spillcount;
289         spill_t **spilllist;
290         spill_t *spill;
291         int i, i2;
292         int affinity_edge_count;
293         bitset_t **interferences;
294         int* spillslot_unionfind;
295         const be_lv_t *lv = be_get_birg_liveness(env->birg);
296
297         spillcount = set_count(env->spills);
298         if(spillcount == 0)
299                 return;
300
301         DBG((dbg, DBG_COALESCING, "Coalescing %d spillslots\n", spillcount));
302
303         interferences = alloca(spillcount * sizeof(interferences[0]));
304         spillslot_unionfind = alloca(spillcount * sizeof(spillslot_unionfind[0]));
305         spilllist = alloca(spillcount * sizeof(spilllist[0]));
306
307         uf_init(spillslot_unionfind, 0, spillcount);
308
309         DEBUG_ONLY(
310                 memset(spilllist, 0, spillcount * sizeof(spilllist[0]));
311         );
312
313         for(spill = set_first(env->spills), i = 0; spill != NULL; spill = set_next(env->spills), ++i) {
314                 assert(spill->spillslot < spillcount);
315                 spilllist[spill->spillslot] = spill;
316         }
317
318         for(i = 0; i < spillcount; ++i) {
319                 interferences[i] = bitset_alloca(spillcount);
320         }
321
322         // construct interferences
323         for(i = 0; i < spillcount; ++i) {
324                 for(i2 = i+1; i2 < spillcount; ++i2) {
325                         if(values_interfere(lv, spilllist[i]->spill, spilllist[i2]->spill)) {
326                                 DBG((dbg, DBG_INTERFERENCES, "Slot %d and %d interfere\n", i, i2));
327                                 bitset_set(interferences[i], i2);
328                                 bitset_set(interferences[i2], i);
329                         }
330                 }
331         }
332
333         // sort affinity edges
334         affinity_edge_count = ARR_LEN(env->affinity_edges);
335         qsort(env->affinity_edges, affinity_edge_count, sizeof(env->affinity_edges[0]), cmp_affinity);
336
337         //dump_interference_graph(env, interferences, "before");
338
339         // try to merge affine nodes
340         for(i = 0; i < affinity_edge_count; ++i) {
341                 const affinity_edge_t *edge = env->affinity_edges[i];
342                 int s1 = uf_find(spillslot_unionfind, edge->slot1);
343                 int s2 = uf_find(spillslot_unionfind, edge->slot2);
344
345                 /* test if values interfere */
346                 if(bitset_is_set(interferences[s1], s2)) {
347                         assert(bitset_is_set(interferences[s2], s1));
348                         continue;
349                 }
350
351                 DBG((dbg, DBG_COALESCING, "Merging %d and %d because of affinity edge\n", s1, s2));
352
353                 merge_interferences(env, interferences, spillslot_unionfind, s1, s2);
354         }
355
356         // try to merge as much remaining spillslots as possible
357         for(i = 0; i < spillcount; ++i) {
358                 int s1 = uf_find(spillslot_unionfind, i);
359                 if(s1 != i)
360                         continue;
361
362                 for(i2 = i+1; i2 < spillcount; ++i2) {
363                         int s2 = uf_find(spillslot_unionfind, i2);
364                         if(s2 != i2)
365                                 continue;
366
367                         /* test if values interfere
368                          * we have to test n1-n2 and n2-n1, because only 1 side gets updated
369                          * when node merging occurs
370                          */
371                         if(bitset_is_set(interferences[s1], s2)) {
372                                 assert(bitset_is_set(interferences[s2], s1));
373                                 continue;
374                         }
375
376                         DBG((dbg, DBG_COALESCING, "Merging %d and %d because it is possible\n", s1, s2));
377
378                         if(merge_interferences(env, interferences, spillslot_unionfind, s1, s2) != 0) {
379                                 // we can break the loop here, because s2 is the new supernode now
380                                 // and we'll test s2 again later anyway
381                                 break;
382                         }
383                 }
384         }
385
386         // assign spillslots to spills
387         for(i = 0; i < spillcount; ++i) {
388                 spill_t *spill = spilllist[i];
389
390                 spill->spillslot = uf_find(spillslot_unionfind, i);
391         }
392
393         //dump_interference_graph(env, interferences, "after");
394 }
395
396 /*
397  *     _            _               _____       _   _ _   _
398  *    / \   ___ ___(_) __ _ _ __   | ____|_ __ | |_(_) |_(_) ___  ___
399  *   / _ \ / __/ __| |/ _` | '_ \  |  _| | '_ \| __| | __| |/ _ \/ __|
400  *  / ___ \\__ \__ \ | (_| | | | | | |___| | | | |_| | |_| |  __/\__ \
401  * /_/   \_\___/___/_|\__, |_| |_| |_____|_| |_|\__|_|\__|_|\___||___/
402  *                    |___/
403  */
404
405 typedef struct _spill_slot_t {
406         int size;
407         int align;
408         ir_entity *entity;
409 } spill_slot_t;
410
411 typedef struct _memperm_entry_t {
412         ir_node* node;
413         int pos;
414         ir_entity *in;
415         ir_entity *out;
416         struct _memperm_entry_t *next;
417 } memperm_entry_t;
418
419 typedef struct _memperm_t {
420         ir_node *block;
421         int entrycount;
422         memperm_entry_t *entries;
423 } memperm_t;
424
425 static int cmp_memperm(const void* d1, const void* d2, size_t size)
426 {
427         const memperm_t* e1 = d1;
428         const memperm_t* e2 = d2;
429         return e1->block != e2->block;
430 }
431
432 static memperm_t *get_memperm(be_fec_env_t *env, ir_node *block)
433 {
434         memperm_t entry, *res;
435         int hash;
436
437         entry.block = block;
438         hash = nodeset_hash(block);
439
440         res = set_find(env->memperms, &entry, sizeof(entry), hash);
441
442         if(res == NULL) {
443                 entry.entrycount = 0;
444                 entry.entries = NULL;
445                 res = set_insert(env->memperms, &entry, sizeof(entry), hash);
446         }
447
448         return res;
449 }
450
451 static ir_entity* create_stack_entity(be_fec_env_t *env, spill_slot_t *slot)
452 {
453         ir_graph *irg = be_get_birg_irg(env->birg);
454         ir_type *frame = get_irg_frame_type(irg);
455         ir_entity *res = frame_alloc_area(frame, slot->size, slot->align, 0);
456
457         // adjust size of the entity type...
458         ir_type *enttype = get_entity_type(res);
459         set_type_size_bytes(enttype, slot->size);
460
461         slot->entity = res;
462
463         return res;
464 }
465
466 /**
467  * Enlarges a spillslot (if necessary) so that it can carry a value of size
468  * @p othersize and alignment @p otheralign.
469  */
470 static void enlarge_spillslot(spill_slot_t *slot, int otheralign, int othersize)
471 {
472         if(othersize > slot->size) {
473                 slot->size = othersize;
474         }
475         if(otheralign > slot->align) {
476                 if(otheralign % slot->align != 0)
477                         slot->align *= otheralign;
478                 else
479                         slot->align = otheralign;
480         } else if(slot->align % otheralign != 0) {
481                 slot->align *= otheralign;
482         }
483 }
484
485 /**
486  * Create stack entities for the spillslots and assign them to the spill and
487  * reload nodes.
488  */
489 static void assign_spillslots(be_fec_env_t *env)
490 {
491         const arch_env_t *arch_env = env->arch_env;
492         int i;
493         int spillcount;
494         spill_t *spill;
495         spill_slot_t* spillslots;
496
497         spillcount = set_count(env->spills);
498         spillslots = alloca(spillcount * sizeof(spillslots[0]));
499
500         memset(spillslots, 0, spillcount * sizeof(spillslots[0]));
501
502         // construct spillslots
503         for(spill = set_first(env->spills); spill != NULL; spill = set_next(env->spills)) {
504                 int slotid = spill->spillslot;
505                 const ir_mode *mode = spill->mode;
506                 spill_slot_t *slot = & (spillslots[slotid]);
507                 int size = get_mode_size_bytes(mode);
508                 int align = spill->alignment;
509
510                 if(slot->align == 0 && slot->size == 0) {
511                         slot->align = align;
512                         slot->size = size;
513                 } else {
514                         enlarge_spillslot(slot, align, size);
515                 }
516         }
517
518         for(spill = set_first(env->spills); spill != NULL; spill = set_next(env->spills)) {
519                 spill_slot_t *slot;
520                 ir_node *node = spill->spill;
521                 int slotid = spill->spillslot;
522
523                 slot = &spillslots[slotid];
524                 if(slot->entity == NULL) {
525                         create_stack_entity(env, slot);
526                 }
527
528                 if(is_Phi(node)) {
529                         int i, arity;
530                         ir_node *block = get_nodes_block(node);
531
532                         // should be a PhiM
533                         assert(is_Phi(node));
534
535                         for(i = 0, arity = get_irn_arity(node); i < arity; ++i) {
536                                 ir_node *arg = get_irn_n(node, i);
537                                 ir_node *predblock = get_Block_cfgpred_block(block, i);
538                                 spill_t *argspill;
539                                 int argslotid;
540
541                                 argspill = get_spill(env, arg);
542                                 assert(argspill != NULL);
543
544                                 argslotid = argspill->spillslot;
545                                 if(slotid != argslotid) {
546                                         memperm_t *memperm;
547                                         memperm_entry_t *entry;
548                                         spill_slot_t *argslot = &spillslots[argslotid];
549                                         if(argslot->entity == NULL) {
550                                                 create_stack_entity(env, argslot);
551                                         }
552
553                                         memperm = get_memperm(env, predblock);
554
555                                         entry = obstack_alloc(&env->obst, sizeof(entry[0]));
556                                         entry->node = node;
557                                         entry->pos = i;
558                                         entry->in = argslot->entity;
559                                         entry->out = slot->entity;
560                                         entry->next = memperm->entries;
561                                         memperm->entrycount++;
562                                         memperm->entries = entry;
563                                 }
564                         }
565                 } else {
566                         arch_set_frame_entity(arch_env, node, slot->entity);
567                 }
568         }
569
570         for(i = 0; i < ARR_LEN(env->reloads); ++i) {
571                 ir_node* reload = env->reloads[i];
572                 ir_node* spillnode = get_memory_edge(reload);
573                 spill_t *spill = get_spill(env, spillnode);
574                 const spill_slot_t *slot = & spillslots[spill->spillslot];
575
576                 assert(slot->entity != NULL);
577
578                 arch_set_frame_entity(arch_env, reload, slot->entity);
579         }
580 }
581
582 /**
583  * Returns the last node in a block which is no control flow changing node
584  */
585 static ir_node *get_end_of_block_insertion_point(ir_node* block)
586 {
587         ir_node* ins = sched_last(block);
588         while(is_Proj(ins) && get_irn_mode(ins) == mode_X) {
589                 ins = sched_prev(ins);
590                 assert(ins != NULL);
591         }
592
593         if(is_cfop(ins)) {
594                 while(1) {
595                         ir_node *prev = sched_prev(ins);
596                         if(!is_cfop(prev))
597                                 break;
598                         ins = prev;
599                 }
600         }
601
602         return ins;
603 }
604
605 static void create_memperms(be_fec_env_t *env)
606 {
607         const arch_env_t *arch_env = env->arch_env;
608         ir_graph *irg = be_get_birg_irg(env->birg);
609         memperm_t *memperm;
610
611         for(memperm = set_first(env->memperms); memperm != NULL; memperm = set_next(env->memperms)) {
612                 int i;
613                 memperm_entry_t *entry;
614                 ir_node *blockend;
615                 ir_node** nodes = alloca(memperm->entrycount * sizeof(nodes[0]));
616                 ir_node* mempermnode;
617
618                 assert(memperm->entrycount > 0);
619
620                 for(entry = memperm->entries, i = 0; entry != NULL; entry = entry->next, ++i) {
621                         ir_node* arg = get_irn_n(entry->node, entry->pos);
622                         nodes[i] = arg;
623                 }
624
625                 mempermnode = be_new_MemPerm(arch_env, irg, memperm->block,
626                                              memperm->entrycount, nodes);
627
628                 // insert node into schedule
629                 blockend = get_end_of_block_insertion_point(memperm->block);
630                 sched_add_before(blockend, mempermnode);
631                 be_stat_ev("mem_perm", memperm->entrycount);
632
633                 i = 0;
634                 for(entry = memperm->entries; entry != NULL; entry = entry->next, ++i) {
635                         ir_node *proj;
636                         ir_node* arg = get_irn_n(entry->node, entry->pos);
637
638                         be_set_MemPerm_in_entity(mempermnode, i, entry->in);
639                         be_set_MemPerm_out_entity(mempermnode, i, entry->out);
640                         set_irg_current_block(irg, memperm->block);
641                         proj = new_Proj(mempermnode, get_irn_mode(arg), i);
642                         sched_add_before(blockend, proj);
643
644                         set_irn_n(entry->node, entry->pos, proj);
645                 }
646         }
647 }
648
649 static int count_spillslots(const be_fec_env_t *env)
650 {
651         const spill_t *spill;
652         int spillcount = set_count(env->spills);
653         bitset_t *counted = bitset_alloca(spillcount);
654         int slotcount;
655
656         slotcount = 0;
657         for(spill = set_first(env->spills); spill != NULL;
658             spill = set_next(env->spills)) {
659                 int spillslot = spill->spillslot;
660                 if(!bitset_is_set(counted, spillslot)) {
661                         slotcount++;
662                         bitset_set(counted, spillslot);
663                 }
664         }
665
666         return slotcount;
667 }
668
669 be_fec_env_t *be_new_frame_entity_coalescer(be_irg_t *birg)
670 {
671         const arch_env_t *arch_env = birg->main_env->arch_env;
672
673         be_fec_env_t *env = xmalloc(sizeof(env[0]));
674
675         be_assure_liveness(birg);
676
677         obstack_init(&env->obst);
678         env->arch_env = arch_env;
679         env->birg = birg;
680         env->spills = new_set(cmp_spill, 10);
681         env->reloads = NEW_ARR_F(ir_node*, 0);
682         env->affinity_edges = NEW_ARR_F(affinity_edge_t*, 0);
683         env->memperms = new_set(cmp_memperm, 10);
684         FIRM_DBG_REGISTER(dbg, "firm.be.spillslots");
685
686         return env;
687 }
688
689 void be_free_frame_entity_coalescer(be_fec_env_t *env)
690 {
691         del_set(env->memperms);
692         DEL_ARR_F(env->reloads);
693         DEL_ARR_F(env->affinity_edges);
694         del_set(env->spills);
695         obstack_free(&env->obst, NULL);
696
697         free(env);
698 }
699
700 void be_assign_entities(be_fec_env_t *env)
701 {
702         if(be_stat_ev_is_active()) {
703                 int count = set_count(env->spills);
704                 be_stat_ev("spillslots", count);
705         }
706
707         if(be_coalesce_spill_slots) {
708                 do_greedy_coalescing(env);
709         }
710
711         if(be_stat_ev_is_active()) {
712                 int count = count_spillslots(env);
713                 be_stat_ev("spillslots_after_coalescing", count);
714         }
715
716         assign_spillslots(env);
717
718         create_memperms(env);
719 }
720
721 /**
722  * This walker function searches for reloads and collects all the spills
723  * and memphis attached to them.
724  */
725 static void collect_spills_walker(ir_node *node, void *data)
726 {
727         be_fec_env_t *env = data;
728         const arch_env_t *arch_env = env->arch_env;
729         const ir_mode *mode;
730         const arch_register_class_t *cls;
731         int align;
732
733         /* classify returns classification of the irn the proj is attached to */
734         if (is_Proj(node))
735                 return;
736
737         if (!arch_irn_class_is(arch_env, node, reload))
738                 return;
739
740         mode = get_irn_mode(node);
741         cls = arch_get_irn_reg_class(arch_env, node, -1);
742         align = arch_isa_get_reg_class_alignment(arch_env_get_isa(arch_env), cls);
743
744         be_node_needs_frame_entity(env, node, mode, align);
745 }
746
747 void be_coalesce_spillslots(const be_chordal_env_t *chordal_env)
748 {
749         be_fec_env_t *env = be_new_frame_entity_coalescer(chordal_env->birg);
750
751         /* collect reloads */
752         irg_walk_graph(chordal_env->irg, NULL, collect_spills_walker, env);
753
754         be_assign_entities(env);
755
756         be_free_frame_entity_coalescer(env);
757 }