give Bad nodes a mode
[libfirm] / ir / be / bespillslots.c
1 /*
2  * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief       Spillslot coalescer.
23  * @author      Matthias Braun
24  * @date        26.07.2006
25  * @version     $Id$
26  */
27 #include "config.h"
28
29 #include <stdlib.h>
30
31 #include "set.h"
32 #include "array.h"
33 #include "irgwalk.h"
34 #include "ircons.h"
35 #include "irprintf.h"
36 #include "execfreq.h"
37 #include "unionfind.h"
38 #include "irdump_t.h"
39
40 #include "benode.h"
41 #include "besched.h"
42 #include "bespill.h"
43 #include "bespillslots.h"
44 #include "bechordal_t.h"
45 #include "bestatevent.h"
46 #include "bemodule.h"
47 #include "beintlive_t.h"
48 #include "beirg.h"
49 #include "bearch.h"
50
51 #define DBG_COALESCING      1
52 #define DBG_INTERFERENCES   2
53
54 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
55
56 typedef struct spill_t {
57         ir_node       *spill;
58         const ir_mode *mode;      /**< mode of the spilled value */
59         int            alignment; /**< alignment for the spilled value */
60         int            spillslot; /**< index into spillslot_unionfind structure */
61 } spill_t;
62
63 typedef struct affinity_edge_t {
64         double affinity;
65         int    slot1;
66         int    slot2;
67 } affinity_edge_t;
68
69 struct be_fec_env_t {
70         struct obstack         obst;
71         ir_graph              *irg;
72         set                   *spills;
73         ir_node              **reloads;
74         affinity_edge_t      **affinity_edges;
75         set                   *memperms;
76         set_frame_entity_func  set_frame_entity;
77         bool                   at_begin;  /**< frame entities should be allocate at
78                                                the beginning of the stackframe */
79 };
80
81 /** Compare 2 affinity edges (used in quicksort) */
82 static int cmp_affinity(const void *d1, const void *d2)
83 {
84         const affinity_edge_t * const *e1 = (const affinity_edge_t**)d1;
85         const affinity_edge_t * const *e2 = (const affinity_edge_t**)d2;
86
87         /* sort in descending order */
88         return (*e1)->affinity < (*e2)->affinity ? 1 : -1;
89 }
90
91 static int cmp_spill(const void* d1, const void* d2, size_t size)
92 {
93         const spill_t* s1 = (const spill_t*)d1;
94         const spill_t* s2 = (const spill_t*)d2;
95         (void) size;
96
97         return s1->spill != s2->spill;
98 }
99
100 static spill_t *get_spill(be_fec_env_t *env, ir_node *node)
101 {
102         spill_t spill, *res;
103         int hash = hash_irn(node);
104
105         spill.spill = node;
106         res = (spill_t*)set_find(env->spills, &spill, sizeof(spill), hash);
107
108         return res;
109 }
110
111
112 static inline ir_node *get_memory_edge(const ir_node *node)
113 {
114         int i, arity;
115
116         arity = get_irn_arity(node);
117         for (i = arity - 1; i >= 0; --i) {
118                 ir_node *arg = get_irn_n(node, i);
119                 if (get_irn_mode(arg) == mode_M)
120                         return arg;
121         }
122
123         return NULL;
124 }
125
126 static spill_t *collect_spill(be_fec_env_t *env, ir_node *node,
127                                       const ir_mode *mode, int align)
128 {
129         spill_t spill, *res;
130         int     hash = hash_irn(node);
131
132         /* insert into set of spills if not already there */
133         spill.spill = node;
134         res         = (spill_t*)set_find(env->spills, &spill, sizeof(spill), hash);
135
136         if (res == NULL) {
137                 spill.spillslot = set_count(env->spills);
138                 spill.mode      = mode;
139                 spill.alignment = align;
140                 res             = (spill_t*)set_insert(env->spills, &spill, sizeof(spill), hash);
141                 DB((dbg, DBG_COALESCING, "Slot %d: %+F\n", spill.spillslot, node));
142         } else {
143                 assert(res->mode == mode);
144                 assert(res->alignment == align);
145         }
146
147         return res;
148 }
149
150 static spill_t *collect_memphi(be_fec_env_t *env, ir_node *node,
151                                const ir_mode *mode, int align)
152 {
153         int i, arity;
154         spill_t spill, *res;
155         int hash = hash_irn(node);
156         const ir_exec_freq *exec_freq = be_get_irg_exec_freq(env->irg);
157
158         assert(is_Phi(node));
159
160         spill.spill = node;
161         res = (spill_t*)set_find(env->spills, &spill, sizeof(spill), hash);
162         if (res != NULL) {
163                 assert(res->mode == mode);
164                 assert(res->alignment == align);
165                 return res;
166         }
167
168         spill.spillslot = set_count(env->spills);
169         spill.mode      = mode;
170         spill.alignment = align;
171         DB((dbg, DBG_COALESCING, "Slot %d: %+F\n", spill.spillslot, node));
172         res             = (spill_t*)set_insert(env->spills, &spill, sizeof(spill), hash);
173
174         /* collect attached spills and mem-phis */
175         arity = get_irn_arity(node);
176         for (i = 0; i < arity; ++i) {
177                 affinity_edge_t *affinty_edge;
178                 ir_node *arg = get_irn_n(node, i);
179                 spill_t *arg_spill;
180
181                 if (is_Phi(arg)) {
182                         arg_spill = collect_memphi(env, arg, mode, align);
183                 } else {
184                         arg_spill = collect_spill(env, arg, mode, align);
185                 }
186
187                 /* add an affinity edge */
188                 affinty_edge           = OALLOC(&env->obst, affinity_edge_t);
189                 affinty_edge->affinity = get_block_execfreq(exec_freq, get_nodes_block(arg));
190                 affinty_edge->slot1    = res->spillslot;
191                 affinty_edge->slot2    = arg_spill->spillslot;
192                 ARR_APP1(affinity_edge_t*, env->affinity_edges, affinty_edge);
193         }
194
195         return res;
196 }
197
198 void be_node_needs_frame_entity(be_fec_env_t *env, ir_node *node,
199                                 const ir_mode *mode, int align)
200 {
201         ir_node *spillnode = get_memory_edge(node);
202         spill_t *spill;
203
204         assert(spillnode != NULL);
205
206         /* walk upwards and collect all phis and spills on this way */
207         if (is_Phi(spillnode)) {
208                 spill = collect_memphi(env, spillnode, mode, align);
209         } else {
210                 spill = collect_spill(env, spillnode, mode, align);
211         }
212
213         ARR_APP1(ir_node *, env->reloads, node);
214 }
215
216
217
218 static int merge_interferences(be_fec_env_t *env, bitset_t** interferences,
219                                int* spillslot_unionfind, int s1, int s2)
220 {
221         int res;
222         int i;
223         int spillcount;
224
225         /* merge spillslots and interferences */
226         res = uf_union(spillslot_unionfind, s1, s2);
227         /* we assume that we always merge s2 to s1 so swap s1, s2 if necessary */
228         if (res != s1) {
229                 int t = s1;
230                 s1 = s2;
231                 s2 = t;
232         }
233
234         bitset_or(interferences[s1], interferences[s2]);
235
236         /* update other interferences */
237         spillcount = set_count(env->spills);
238         for (i = 0; i < spillcount; ++i) {
239                 bitset_t *intfs = interferences[i];
240                 if (bitset_is_set(intfs, s2))
241                         bitset_set(intfs, s1);
242         }
243
244         return res;
245 }
246
247 static int my_values_interfere2(ir_graph *irg, const ir_node *a,
248                                 const ir_node *b)
249 {
250         be_lv_t *lv = be_get_irg_liveness(irg);
251
252     int a2b = _value_dominates(a, b);
253     int b2a = _value_dominates(b, a);
254
255     /* If there is no dominance relation, they do not interfere. */
256     if ((a2b | b2a) > 0) {
257         const ir_edge_t *edge;
258         ir_node *bb;
259
260         /*
261          * Adjust a and b so, that a dominates b if
262          * a dominates b or vice versa.
263          */
264         if (b2a) {
265             const ir_node *t = a;
266             a = b;
267             b = t;
268         }
269
270         bb = get_nodes_block(b);
271
272         /*
273          * If a is live end in b's block it is
274          * live at b's definition (a dominates b)
275          */
276         if (be_is_live_end(lv, bb, a))
277             return 1;
278
279         /*
280          * Look at all usages of a.
281          * If there's one usage of a in the block of b, then
282          * we check, if this use is dominated by b, if that's true
283          * a and b interfere. Note that b must strictly dominate the user,
284          * since if b is the last user of in the block, b and a do not
285          * interfere.
286          * Uses of a not in b's block can be disobeyed, because the
287          * check for a being live at the end of b's block is already
288          * performed.
289          */
290         foreach_out_edge(a, edge) {
291             const ir_node *user = get_edge_src_irn(edge);
292                         if (is_Sync(user)) {
293                                 const ir_edge_t *edge2;
294                                 foreach_out_edge(user, edge2) {
295                                         const ir_node *user2 = get_edge_src_irn(edge2);
296                                         assert(!is_Sync(user2));
297                                         if (get_nodes_block(user2) == bb && !is_Phi(user2) &&
298                                            _value_strictly_dominates(b, user2))
299                                                 return 1;
300                                 }
301                         } else {
302                                 if (get_nodes_block(user) == bb && !is_Phi(user) &&
303                                                 _value_strictly_dominates(b, user))
304                 return 1;
305                         }
306         }
307     }
308
309         return 0;
310 }
311
312 /**
313  * same as values_interfere but with special handling for Syncs
314  */
315 static int my_values_interfere(ir_graph *irg, ir_node *a, ir_node *b)
316 {
317         if (is_Sync(a)) {
318                 int i, arity = get_irn_arity(a);
319                 for (i = 0; i < arity; ++i) {
320                         ir_node *in = get_irn_n(a, i);
321                         if (my_values_interfere(irg, in, b))
322                                 return 1;
323                 }
324                 return 0;
325         } else if (is_Sync(b)) {
326                 int i, arity = get_irn_arity(b);
327                 for (i = 0; i < arity; ++i) {
328                         ir_node *in = get_irn_n(b, i);
329                         /* a is not a sync, so no need for my_values_interfere */
330                         if (my_values_interfere2(irg, a, in))
331                                 return 1;
332                 }
333                 return 0;
334         }
335
336         return my_values_interfere2(irg, a, b);
337 }
338
339 /**
340  * A greedy coalescing algorithm for spillslots:
341  *  1. Sort the list of affinity edges
342  *  2. Try to merge slots with affinity edges (most expensive slots first)
343  *  3. Try to merge everything else that is possible
344  */
345 static void do_greedy_coalescing(be_fec_env_t *env)
346 {
347         int spillcount;
348         spill_t **spilllist;
349         spill_t *spill;
350         int i, i2;
351         int affinity_edge_count;
352         bitset_t **interferences;
353         int* spillslot_unionfind;
354         struct obstack data;
355
356         spillcount = set_count(env->spills);
357         if (spillcount == 0)
358                 return;
359
360         obstack_init(&data);
361
362         DB((dbg, DBG_COALESCING, "Coalescing %d spillslots\n", spillcount));
363
364         interferences       = OALLOCN(&data, bitset_t*, spillcount);
365         spillslot_unionfind = OALLOCN(&data, int,       spillcount);
366         spilllist           = OALLOCN(&data, spill_t*,  spillcount);
367
368         uf_init(spillslot_unionfind, spillcount);
369
370         DEBUG_ONLY(
371                 memset(spilllist, 0, spillcount * sizeof(spilllist[0]));
372         );
373
374         i = 0;
375         foreach_set(env->spills, spill_t*, spill) {
376                 assert(spill->spillslot < spillcount);
377                 spilllist[spill->spillslot] = spill;
378                 ++i;
379         }
380
381         for (i = 0; i < spillcount; ++i) {
382                 interferences[i] = bitset_obstack_alloc(&data, spillcount);
383         }
384
385         /* construct interferences */
386         for (i = 0; i < spillcount; ++i) {
387                 ir_node *spill1 = spilllist[i]->spill;
388
389                 if (is_NoMem(spill1))
390                         continue;
391
392                 for (i2 = i+1; i2 < spillcount; ++i2) {
393                         ir_node *spill2 = spilllist[i2]->spill;
394
395                         if (is_NoMem(spill2))
396                                 continue;
397
398                         if (my_values_interfere(env->irg, spill1, spill2)) {
399                                 DB((dbg, DBG_INTERFERENCES,
400                                      "Slot %d and %d interfere\n", i, i2));
401
402                                 bitset_set(interferences[i], i2);
403                                 bitset_set(interferences[i2], i);
404                         }
405                 }
406         }
407
408         /* sort affinity edges */
409         affinity_edge_count = ARR_LEN(env->affinity_edges);
410         qsort(env->affinity_edges, affinity_edge_count,
411               sizeof(env->affinity_edges[0]), cmp_affinity);
412
413         /*dump_interference_graph(env, interferences, "before"); */
414
415         /* try to merge affine nodes */
416         for (i = 0; i < affinity_edge_count; ++i) {
417                 const affinity_edge_t *edge = env->affinity_edges[i];
418                 int s1 = uf_find(spillslot_unionfind, edge->slot1);
419                 int s2 = uf_find(spillslot_unionfind, edge->slot2);
420
421                 /* test if values interfere */
422                 if (bitset_is_set(interferences[s1], s2)) {
423                         assert(bitset_is_set(interferences[s2], s1));
424                         continue;
425                 }
426
427                 DB((dbg, DBG_COALESCING,
428                      "Merging %d and %d because of affinity edge\n", s1, s2));
429
430                 merge_interferences(env, interferences, spillslot_unionfind, s1, s2);
431         }
432
433         /* try to merge as much remaining spillslots as possible */
434         for (i = 0; i < spillcount; ++i) {
435                 int s1 = uf_find(spillslot_unionfind, i);
436                 if (s1 != i)
437                         continue;
438
439                 for (i2 = i+1; i2 < spillcount; ++i2) {
440                         int s2 = uf_find(spillslot_unionfind, i2);
441                         if (s2 != i2)
442                                 continue;
443
444                         /* test if values interfere
445                          * we have to test n1-n2 and n2-n1, because only 1 side gets updated
446                          * when node merging occurs
447                          */
448                         if (bitset_is_set(interferences[s1], s2)) {
449                                 assert(bitset_is_set(interferences[s2], s1));
450                                 continue;
451                         }
452
453                         DB((dbg, DBG_COALESCING,
454                              "Merging %d and %d because it is possible\n", s1, s2));
455
456                         if (merge_interferences(env, interferences, spillslot_unionfind, s1, s2) != 0) {
457                                 /* we can break the loop here, because s2 is the new supernode
458                                  * now and we'll test s2 again later anyway */
459                                 break;
460                         }
461                 }
462         }
463
464         /* assign spillslots to spills */
465         for (i = 0; i < spillcount; ++i) {
466                 spill_t *spill = spilllist[i];
467
468                 spill->spillslot = uf_find(spillslot_unionfind, i);
469         }
470
471         /*dump_interference_graph(env, interferences, "after");*/
472         obstack_free(&data, 0);
473 }
474
475
476
477 typedef struct spill_slot_t {
478         int size;
479         int align;
480         ir_entity *entity;
481 } spill_slot_t;
482
483 typedef struct memperm_entry_t {
484         ir_node* node;
485         int pos;
486         ir_entity *in;
487         ir_entity *out;
488         struct memperm_entry_t *next;
489 } memperm_entry_t;
490
491 typedef struct memperm_t {
492         ir_node *block;
493         int entrycount;
494         memperm_entry_t *entries;
495 } memperm_t;
496
497 static int cmp_memperm(const void* d1, const void* d2, size_t size)
498 {
499         const memperm_t* e1 = (const memperm_t*)d1;
500         const memperm_t* e2 = (const memperm_t*)d2;
501         (void) size;
502
503         return e1->block != e2->block;
504 }
505
506 static memperm_t *get_memperm(be_fec_env_t *env, ir_node *block)
507 {
508         memperm_t entry, *res;
509         int hash;
510
511         entry.block = block;
512         hash        = hash_irn(block);
513
514         res = (memperm_t*)set_find(env->memperms, &entry, sizeof(entry), hash);
515
516         if (res == NULL) {
517                 entry.entrycount = 0;
518                 entry.entries = NULL;
519                 res = (memperm_t*)set_insert(env->memperms, &entry, sizeof(entry), hash);
520         }
521
522         return res;
523 }
524
525 static ir_entity* create_stack_entity(be_fec_env_t *env, spill_slot_t *slot)
526 {
527         ir_graph  *irg   = env->irg;
528         ir_type   *frame = get_irg_frame_type(irg);
529         ir_entity *res   = frame_alloc_area(frame, slot->size, slot->align,
530                                             env->at_begin);
531
532         /* adjust size of the entity type... */
533         ir_type *enttype = get_entity_type(res);
534         set_type_size_bytes(enttype, slot->size);
535
536         slot->entity = res;
537
538         return res;
539 }
540
541 /**
542  * Enlarges a spillslot (if necessary) so that it can carry a value of size
543  * @p othersize and alignment @p otheralign.
544  */
545 static void enlarge_spillslot(spill_slot_t *slot, int otheralign, int othersize)
546 {
547         if (othersize > slot->size) {
548                 slot->size = othersize;
549         }
550         if (otheralign > slot->align) {
551                 if (otheralign % slot->align != 0)
552                         slot->align *= otheralign;
553                 else
554                         slot->align = otheralign;
555         } else if (slot->align % otheralign != 0) {
556                 slot->align *= otheralign;
557         }
558 }
559
560 static void assign_spill_entity(be_fec_env_t *env,
561                                 ir_node *node, ir_entity *entity)
562 {
563         if (is_NoMem(node))
564                 return;
565         if (is_Sync(node)) {
566                 int i, arity;
567
568                 arity = get_irn_arity(node);
569                 for (i = 0; i < arity; ++i) {
570                         ir_node *in = get_irn_n(node, i);
571                         assert(!is_Phi(in));
572
573                         assign_spill_entity(env, in, entity);
574                 }
575                 return;
576         }
577
578         /* beware: we might have Stores with Memory Proj's, ia32 fisttp for
579            instance */
580         node = skip_Proj(node);
581         assert(arch_get_frame_entity(node) == NULL);
582         env->set_frame_entity(node, entity);
583 }
584
585 /**
586  * Create stack entities for the spillslots and assign them to the spill and
587  * reload nodes.
588  */
589 static void assign_spillslots(be_fec_env_t *env)
590 {
591         int           spillcount = set_count(env->spills);
592         spill_slot_t *spillslots = ALLOCANZ(spill_slot_t, spillcount);
593         spill_t      *spill;
594         size_t        i;
595
596         /* construct spillslots */
597         foreach_set(env->spills, spill_t*, spill) {
598                 int slotid = spill->spillslot;
599                 const ir_mode *mode = spill->mode;
600                 spill_slot_t *slot = & (spillslots[slotid]);
601                 int size = get_mode_size_bytes(mode);
602                 int align = spill->alignment;
603
604                 if (slot->align == 0 && slot->size == 0) {
605                         slot->align = align;
606                         slot->size = size;
607                 } else {
608                         enlarge_spillslot(slot, align, size);
609                 }
610         }
611
612         foreach_set(env->spills, spill_t*, spill) {
613                 ir_node      *node   = spill->spill;
614                 int           slotid = spill->spillslot;
615                 spill_slot_t *slot;
616
617                 slot = &spillslots[slotid];
618                 if (slot->entity == NULL) {
619                         create_stack_entity(env, slot);
620                 }
621
622                 if (is_Phi(node)) {
623                         int i, arity;
624                         ir_node *block = get_nodes_block(node);
625
626                         /* should be a PhiM */
627                         assert(is_Phi(node));
628
629                         for (i = 0, arity = get_irn_arity(node); i < arity; ++i) {
630                                 ir_node *arg = get_irn_n(node, i);
631                                 ir_node *predblock = get_Block_cfgpred_block(block, i);
632                                 spill_t *argspill;
633                                 int argslotid;
634
635                                 argspill = get_spill(env, arg);
636                                 assert(argspill != NULL);
637
638                                 argslotid = argspill->spillslot;
639                                 if (slotid != argslotid) {
640                                         memperm_t *memperm;
641                                         memperm_entry_t *entry;
642                                         spill_slot_t *argslot = &spillslots[argslotid];
643                                         if (argslot->entity == NULL) {
644                                                 create_stack_entity(env, argslot);
645                                         }
646
647                                         memperm = get_memperm(env, predblock);
648
649                                         entry = OALLOC(&env->obst, memperm_entry_t);
650                                         entry->node = node;
651                                         entry->pos = i;
652                                         entry->in = argslot->entity;
653                                         entry->out = slot->entity;
654                                         entry->next = memperm->entries;
655                                         memperm->entrycount++;
656                                         memperm->entries = entry;
657                                 }
658                         }
659                 } else {
660                         assign_spill_entity(env, node, slot->entity);
661                 }
662         }
663
664         for (i = 0; i < ARR_LEN(env->reloads); ++i) {
665                 ir_node            *reload    = env->reloads[i];
666                 ir_node            *spillnode = get_memory_edge(reload);
667                 spill_t            *spill     = get_spill(env, spillnode);
668                 const spill_slot_t *slot      = & spillslots[spill->spillslot];
669
670                 assert(slot->entity != NULL);
671
672                 env->set_frame_entity(reload, slot->entity);
673         }
674 }
675
676 /**
677  * Returns the last node in a block which is no control flow changing node
678  */
679 static ir_node *get_end_of_block_insertion_point(ir_node* block)
680 {
681         ir_node* ins = sched_last(block);
682         while (is_Proj(ins) && get_irn_mode(ins) == mode_X) {
683                 ins = sched_prev(ins);
684                 assert(ins != NULL);
685         }
686
687         if (is_cfop(ins)) {
688                 for (;;) {
689                         ir_node *prev = sched_prev(ins);
690                         if (!is_cfop(prev))
691                                 break;
692                         ins = prev;
693                 }
694         }
695
696         return ins;
697 }
698
699 static void create_memperms(be_fec_env_t *env)
700 {
701         memperm_t *memperm;
702
703         foreach_set(env->memperms, memperm_t*, memperm) {
704                 ir_node         **nodes = ALLOCAN(ir_node*, memperm->entrycount);
705                 memperm_entry_t  *entry;
706                 ir_node          *blockend;
707                 ir_node          *mempermnode;
708                 int               i;
709
710                 assert(memperm->entrycount > 0);
711
712                 for (entry = memperm->entries, i = 0; entry != NULL; entry = entry->next, ++i) {
713                         ir_node* arg = get_irn_n(entry->node, entry->pos);
714                         nodes[i] = arg;
715                 }
716
717                 mempermnode = be_new_MemPerm(memperm->block, memperm->entrycount,
718                                              nodes);
719
720                 /* insert node into schedule */
721                 blockend = get_end_of_block_insertion_point(memperm->block);
722                 sched_add_before(blockend, mempermnode);
723                 stat_ev_dbl("mem_perm", memperm->entrycount);
724
725                 i = 0;
726                 for (entry = memperm->entries; entry != NULL; entry = entry->next, ++i) {
727                         ir_node *proj;
728                         ir_node* arg = get_irn_n(entry->node, entry->pos);
729
730                         be_set_MemPerm_in_entity(mempermnode, i, entry->in);
731                         be_set_MemPerm_out_entity(mempermnode, i, entry->out);
732                         proj = new_r_Proj(mempermnode, get_irn_mode(arg), i);
733
734                         set_irn_n(entry->node, entry->pos, proj);
735                 }
736         }
737 }
738
739 static int count_spillslots(const be_fec_env_t *env)
740 {
741         const spill_t *spill;
742         int spillcount = set_count(env->spills);
743         bitset_t *counted = bitset_alloca(spillcount);
744         int slotcount;
745
746         slotcount = 0;
747         foreach_set(env->spills, spill_t*, spill) {
748                 int spillslot = spill->spillslot;
749                 if (!bitset_is_set(counted, spillslot)) {
750                         slotcount++;
751                         bitset_set(counted, spillslot);
752                 }
753         }
754
755         return slotcount;
756 }
757
758 be_fec_env_t *be_new_frame_entity_coalescer(ir_graph *irg)
759 {
760         be_fec_env_t *env = XMALLOCZ(be_fec_env_t);
761
762         be_liveness_assure_chk(be_assure_liveness(irg));
763
764         obstack_init(&env->obst);
765         env->irg            = irg;
766         env->spills         = new_set(cmp_spill, 10);
767         env->reloads        = NEW_ARR_F(ir_node*, 0);
768         env->affinity_edges = NEW_ARR_F(affinity_edge_t*, 0);
769         env->memperms       = new_set(cmp_memperm, 10);
770
771         return env;
772 }
773
774 void be_free_frame_entity_coalescer(be_fec_env_t *env)
775 {
776         del_set(env->memperms);
777         DEL_ARR_F(env->reloads);
778         DEL_ARR_F(env->affinity_edges);
779         del_set(env->spills);
780         obstack_free(&env->obst, NULL);
781
782         free(env);
783 }
784
785 void be_assign_entities(be_fec_env_t *env,
786                         set_frame_entity_func set_frame_entity,
787                         bool alloc_entities_at_begin)
788 {
789         env->set_frame_entity = set_frame_entity;
790         env->at_begin         = alloc_entities_at_begin;
791
792         stat_ev_dbl("spillslots", set_count(env->spills));
793
794         if (be_coalesce_spill_slots) {
795                 do_greedy_coalescing(env);
796         }
797
798         stat_ev_dbl("spillslots_after_coalescing", count_spillslots(env));
799
800         assign_spillslots(env);
801
802         create_memperms(env);
803 }
804
805 BE_REGISTER_MODULE_CONSTRUCTOR(be_init_spillslots)
806 void be_init_spillslots(void)
807 {
808         FIRM_DBG_REGISTER(dbg, "firm.be.spillslots");
809 }