- Refactored finish/after_ra phases a bit, stacknode fixup and stack bias
[libfirm] / ir / be / bespill.c
1 /*
2  * Author:      Daniel Grund, Sebastian Hack, Matthias Braun
3  * Date:                29.09.2005
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 "pset.h"
14 #include "irnode_t.h"
15 #include "ircons_t.h"
16 #include "iredges_t.h"
17 #include "irprintf.h"
18 #include "ident_t.h"
19 #include "type_t.h"
20 #include "entity_t.h"
21 #include "debug.h"
22 #include "irgwalk.h"
23 #include "array.h"
24 #include "pdeq.h"
25 #include "unionfind.h"
26 #include "execfreq.h"
27
28 #include "belive_t.h"
29 #include "besched_t.h"
30 #include "bespill.h"
31 #include "belive_t.h"
32 #include "benode_t.h"
33 #include "bechordal_t.h"
34 #include "bejavacoal.h"
35 #include "benodesets.h"
36
37 // only rematerialise when costs are less than REMAT_COST_LIMIT
38 // TODO determine a good value here...
39 #define REMAT_COST_LIMIT        20
40
41 typedef struct _reloader_t reloader_t;
42
43 struct _reloader_t {
44         reloader_t *next;
45         ir_node *reloader;
46 };
47
48 typedef struct _spill_info_t {
49         /** the value that should get spilled */
50         ir_node *spilled_node;
51         /** list of places where the value should get reloaded */
52         reloader_t *reloaders;
53
54         /** the spill node, or a PhiM node */
55         ir_node *spill;
56         /** if we had the value of a phi spilled before but not the phi itself then
57          * this field contains the spill for the phi value */
58         ir_node *old_spill;
59 } spill_info_t;
60
61 struct _spill_env_t {
62         const arch_register_class_t *cls;
63         const arch_env_t *arch_env;
64         const be_chordal_env_t *chordal_env;
65         struct obstack obst;
66         set *spills;                            /**< all spill_info_t's, which must be placed */
67         pset *mem_phis;                         /**< set of all special spilled phis. allocated and freed separately */
68
69         DEBUG_ONLY(firm_dbg_module_t *dbg;)
70 };
71
72 /**
73  * Compare two spill infos.
74  */
75 static int cmp_spillinfo(const void *x, const void *y, size_t size) {
76         const spill_info_t *xx = x;
77         const spill_info_t *yy = y;
78         return xx->spilled_node != yy->spilled_node;
79 }
80
81 /**
82  * Returns spill info for a specific value (the value that is to be spilled)
83  */
84 static spill_info_t *get_spillinfo(const spill_env_t *env, ir_node *value) {
85         spill_info_t info, *res;
86         int hash = nodeset_hash(value);
87
88         info.spilled_node = value;
89         res = set_find(env->spills, &info, sizeof(info), hash);
90
91         if (res == NULL) {
92                 info.reloaders = NULL;
93                 info.spill = NULL;
94                 info.old_spill = NULL;
95                 res = set_insert(env->spills, &info, sizeof(info), hash);
96         }
97
98         return res;
99 }
100
101 DEBUG_ONLY(
102 /* Sets the debug module of a spill environment. */
103 void be_set_spill_env_dbg_module(spill_env_t *env, firm_dbg_module_t *dbg) {
104         env->dbg = dbg;
105 }
106 )
107
108 /* Creates a new spill environment. */
109 spill_env_t *be_new_spill_env(const be_chordal_env_t *chordal_env) {
110         spill_env_t *env        = xmalloc(sizeof(env[0]));
111         env->spills                     = new_set(cmp_spillinfo, 1024);
112         env->cls                        = chordal_env->cls;
113         env->chordal_env        = chordal_env;
114         env->arch_env       = env->chordal_env->birg->main_env->arch_env;
115         env->mem_phis           = pset_new_ptr_default();
116         obstack_init(&env->obst);
117         return env;
118 }
119
120 /* Deletes a spill environment. */
121 void be_delete_spill_env(spill_env_t *env) {
122         del_set(env->spills);
123         del_pset(env->mem_phis);
124         obstack_free(&env->obst, NULL);
125         free(env);
126 }
127
128 /**
129  *  ____  _                  ____      _                 _
130  * |  _ \| | __ _  ___ ___  |  _ \ ___| | ___   __ _  __| |___
131  * | |_) | |/ _` |/ __/ _ \ | |_) / _ \ |/ _ \ / _` |/ _` / __|
132  * |  __/| | (_| | (_|  __/ |  _ <  __/ | (_) | (_| | (_| \__ \
133  * |_|   |_|\__,_|\___\___| |_| \_\___|_|\___/ \__,_|\__,_|___/
134  *
135  */
136
137 void be_add_reload(spill_env_t *env, ir_node *to_spill, ir_node *before) {
138         spill_info_t *info;
139         reloader_t *rel;
140
141         assert(sched_is_scheduled(before));
142         assert(arch_irn_consider_in_reg_alloc(env->arch_env, env->cls, to_spill));
143
144         info = get_spillinfo(env, to_spill);
145
146         if(is_Phi(to_spill)) {
147                 int i, arity;
148                 // create spillinfos for the phi arguments
149                 for(i = 0, arity = get_irn_arity(to_spill); i < arity; ++i) {
150                         ir_node *arg = get_irn_n(to_spill, i);
151                         get_spillinfo(env, arg);
152                 }
153         }
154
155         rel           = obstack_alloc(&env->obst, sizeof(rel[0]));
156         rel->reloader = before;
157         rel->next     = info->reloaders;
158         info->reloaders = rel;
159 }
160
161 void be_add_reload_on_edge(spill_env_t *env, ir_node *to_spill, ir_node *block, int pos) {
162         ir_node *predblock, *last;
163
164         /* simply add the reload to the beginning of the block if we only have 1 predecessor
165          * (we don't need to check for phis as there can't be any in a block with only 1 pred)
166          */
167         if(get_Block_n_cfgpreds(block) == 1) {
168                 assert(!is_Phi(sched_first(block)));
169                 be_add_reload(env, to_spill, sched_first(block));
170                 return;
171         }
172
173         /* We have to reload the value in pred-block */
174         predblock = get_Block_cfgpred_block(block, pos);
175         last = sched_last(predblock);
176
177         /* we might have projs and keepanys behind the jump... */
178         while(is_Proj(last) || be_is_Keep(last)) {
179                 last = sched_prev(last);
180                 assert(!sched_is_end(last));
181         }
182         assert(is_cfop(last));
183
184         // add the reload before the (cond-)jump
185         be_add_reload(env, to_spill, last);
186 }
187
188 void be_spill_phi(spill_env_t *env, ir_node *node) {
189         spill_info_t* spill;
190         int i, arity;
191
192         assert(is_Phi(node));
193
194         pset_insert_ptr(env->mem_phis, node);
195
196         // create spillinfos for the phi arguments
197         spill = get_spillinfo(env, node);
198         for(i = 0, arity = get_irn_arity(node); i < arity; ++i) {
199                 ir_node *arg = get_irn_n(node, i);
200                 get_spillinfo(env, arg);
201         }
202
203         // if we had a spill for the phi value before, then remove this spill from
204         // schedule, as we will remove it in the insert spill/reload phase
205         if(spill->spill != NULL && !is_Phi(spill->spill)) {
206                 //sched_remove(spill->spill);
207                 spill->old_spill = spill->spill;
208                 spill->spill = NULL;
209         }
210 }
211
212 /*
213  *   ____                _         ____        _ _ _
214  *  / ___|_ __ ___  __ _| |_ ___  / ___| _ __ (_) | |___
215  * | |   | '__/ _ \/ _` | __/ _ \ \___ \| '_ \| | | / __|
216  * | |___| | |  __/ (_| | ||  __/  ___) | |_) | | | \__ \
217  *  \____|_|  \___|\__,_|\__\___| |____/| .__/|_|_|_|___/
218  *                                      |_|
219  */
220
221 /**
222  * Schedules a node after an instruction. (That is the place after all projs and phis
223  * that are scheduled after the instruction)
224  * This function also skips phi nodes at the beginning of a block
225  */
226 static void sched_add_after_insn(ir_node *sched_after, ir_node *node) {
227         ir_node *next = sched_next(sched_after);
228         while(is_Proj(next) || is_Phi(next)) {
229                 next = sched_next(next);
230         }
231         assert(next != NULL);
232
233         if(sched_is_end(next)) {
234                 sched_add_after(sched_last(get_nodes_block(sched_after)), node);
235         } else {
236                 sched_add_before(next, node);
237         }
238 }
239
240 /**
241  * Creates a spill.
242  *
243  * @param senv      the spill environment
244  * @param irn       the node that should be spilled
245  * @param ctx_irn   an user of the spilled node
246  *
247  * @return a be_Spill node
248  */
249 static void spill_irn(spill_env_t *env, spill_info_t *spillinfo) {
250         ir_node *to_spill = spillinfo->spilled_node;
251
252         DBG((env->dbg, LEVEL_1, "%+F\n", to_spill));
253
254         /* Trying to spill an already spilled value, no need for a new spill
255          * node then, we can simply connect to the same one for this reload
256          *
257          * (although rematerialization code should handle most of these cases
258          * this can still happen when spilling Phis)
259          */
260         if(be_is_Reload(to_spill)) {
261                 spillinfo->spill = get_irn_n(to_spill, be_pos_Reload_mem);
262                 return;
263         }
264
265         if (arch_irn_is(env->arch_env, to_spill, dont_spill)) {
266                 if (env->chordal_env->opts->vrfy_option == BE_CH_VRFY_WARN)
267                         ir_fprintf(stderr, "Verify warning: spilling 'dont_spill' node %+F\n", to_spill);
268                 else if (env->chordal_env->opts->vrfy_option == BE_CH_VRFY_ASSERT)
269                         assert(0 && "Attempt to spill a node marked 'dont_spill'");
270         }
271
272         spillinfo->spill = be_spill(env->arch_env, to_spill);
273         sched_add_after_insn(to_spill, spillinfo->spill);
274 }
275
276 static void spill_node(spill_env_t *env, spill_info_t *spillinfo);
277
278 /**
279  * If the first usage of a Phi result would be out of memory
280  * there is no sense in allocating a register for it.
281  * Thus we spill it and all its operands to the same spill slot.
282  * Therefore the phi/dataB becomes a phi/Memory
283  *
284  * @param senv      the spill environment
285  * @param phi       the Phi node that should be spilled
286  * @param ctx_irn   an user of the spilled node
287  */
288 static void spill_phi(spill_env_t *env, spill_info_t *spillinfo) {
289         ir_node *phi = spillinfo->spilled_node;
290         int i;
291         int arity = get_irn_arity(phi);
292         ir_node     *block    = get_nodes_block(phi);
293         ir_node     **ins;
294
295         assert(is_Phi(phi));
296
297         /* build a new PhiM */
298         ins = alloca(sizeof(ir_node*) * arity);
299         for(i = 0; i < arity; ++i) {
300                 ins[i] = get_irg_bad(env->chordal_env->irg);
301         }
302         spillinfo->spill = new_r_Phi(env->chordal_env->irg, block, arity, ins, mode_M);
303
304         for(i = 0; i < arity; ++i) {
305                 ir_node *arg = get_irn_n(phi, i);
306                 spill_info_t *arg_info = get_spillinfo(env, arg);
307
308                 spill_node(env, arg_info);
309
310                 set_irn_n(spillinfo->spill, i, arg_info->spill);
311         }
312
313         // rewire reloads from old_spill to phi
314         if(spillinfo->old_spill != NULL) {
315                 const ir_edge_t *edge, *next;
316                 foreach_out_edge_safe(spillinfo->old_spill, edge, next) {
317                         ir_node* reload = get_edge_src_irn(edge);
318                         assert(be_is_Reload(reload) || is_Phi(reload));
319                         set_irn_n(reload, get_edge_src_pos(edge), spillinfo->spill);
320                 }
321                 spillinfo->old_spill = NULL;
322         }
323 }
324
325 /**
326  * Spill a node.
327  *
328  * @param senv      the spill environment
329  * @param to_spill  the node that should be spilled
330  */
331 static void spill_node(spill_env_t *env, spill_info_t *spillinfo) {
332         ir_node *to_spill;
333
334         // the node should be tagged for spilling already...
335         if(spillinfo->spill != NULL)
336                 return;
337
338         to_spill = spillinfo->spilled_node;
339         if (is_Phi(to_spill) && pset_find_ptr(env->mem_phis, spillinfo->spilled_node)) {
340                 spill_phi(env, spillinfo);
341         } else {
342                 spill_irn(env, spillinfo);
343         }
344 }
345
346 /*
347  *
348  *  ____                      _            _       _ _
349  * |  _ \ ___ _ __ ___   __ _| |_ ___ _ __(_) __ _| (_)_______
350  * | |_) / _ \ '_ ` _ \ / _` | __/ _ \ '__| |/ _` | | |_  / _ \
351  * |  _ <  __/ | | | | | (_| | ||  __/ |  | | (_| | | |/ /  __/
352  * |_| \_\___|_| |_| |_|\__,_|\__\___|_|  |_|\__,_|_|_/___\___|
353  *
354  */
355
356 /**
357  * Tests whether value @p arg is available before node @p reloader
358  * @returns 1 if value is available, 0 otherwise
359  */
360 static int is_value_available(spill_env_t *env, ir_node *arg, ir_node *reloader) {
361         if(is_Unknown(arg) || arg == new_NoMem())
362                 return 1;
363
364         if(be_is_Spill(arg))
365                 return 1;
366
367         if(arg == get_irg_frame(env->chordal_env->irg))
368                 return 1;
369
370         /* the following test does not work while spilling,
371          * because the liveness info is not adapted yet to the effects of the
372          * additional spills/reloads.
373          *
374          * So we can only do this test for ignore registers (of our register class)
375          */
376         if(arch_get_irn_reg_class(env->arch_env, arg, -1) == env->chordal_env->cls
377            && arch_irn_is(env->arch_env, arg, ignore)) {
378                 int i, arity;
379
380                 /* we want to remat before the insn reloader
381                  * thus an arguments is alive if
382                  *   - it interferes with the reloaders result
383                  *   - or it is (last-) used by reloader itself
384                  */
385                 if (values_interfere(env->chordal_env->lv, reloader, arg)) {
386                         return 1;
387                 }
388
389                 arity = get_irn_arity(reloader);
390                 for (i = 0; i < arity; ++i) {
391                         ir_node *rel_arg = get_irn_n(reloader, i);
392                         if (rel_arg == arg)
393                                 return 1;
394                 }
395         }
396
397         return 0;
398 }
399
400 /**
401  * Checks whether the node can principally be rematerialized
402  */
403 static int is_remat_node(spill_env_t *env, ir_node *node) {
404         const arch_env_t *arch_env = env->arch_env;
405
406         assert(!be_is_Spill(node));
407
408         if(arch_irn_is(arch_env, node, rematerializable)) {
409                 return 1;
410         }
411
412         if(be_is_StackParam(node))
413                 return 1;
414
415         return 0;
416 }
417
418 /**
419  * Check if a node is rematerializable. This tests for the following conditions:
420  *
421  * - The node itself is rematerializable
422  * - All arguments of the node are available or also rematerialisable
423  * - The costs for the rematerialisation operation is less or equal a limit
424  *
425  * Returns the costs needed for rematerialisation or something
426  * > REMAT_COST_LIMIT if remat is not possible.
427  */
428 static int check_remat_conditions_costs(spill_env_t *env, ir_node *spilled, ir_node *reloader, int parentcosts) {
429         int i, arity;
430         int argremats;
431         int costs = 0;
432
433         if(!is_remat_node(env, spilled))
434                 return REMAT_COST_LIMIT;
435
436         if(be_is_Reload(spilled)) {
437                 costs += 2;
438         } else {
439                 costs += arch_get_op_estimated_cost(env->arch_env, spilled);
440         }
441         if(parentcosts + costs >= REMAT_COST_LIMIT) {
442                 return REMAT_COST_LIMIT;
443         }
444
445         argremats = 0;
446         for(i = 0, arity = get_irn_arity(spilled); i < arity; ++i) {
447                 ir_node *arg = get_irn_n(spilled, i);
448
449                 if(is_value_available(env, arg, reloader))
450                         continue;
451
452                 // we have to rematerialize the argument as well...
453                 if(argremats >= 1) {
454                         /* we only support rematerializing 1 argument at the moment,
455                          * so that we don't have to care about register pressure
456                          */
457                         return REMAT_COST_LIMIT;
458                 }
459                 argremats++;
460
461                 costs += check_remat_conditions_costs(env, arg, reloader, parentcosts + costs);
462                 if(parentcosts + costs >= REMAT_COST_LIMIT)
463                         return REMAT_COST_LIMIT;
464         }
465
466         return costs;
467 }
468
469 static int check_remat_conditions(spill_env_t *env, ir_node *spilled, ir_node *reloader) {
470         int costs = check_remat_conditions_costs(env, spilled, reloader, 1);
471
472         return costs < REMAT_COST_LIMIT;
473 }
474
475 /**
476  * Re-materialize a node.
477  *
478  * @param senv      the spill environment
479  * @param spilled   the node that was spilled
480  * @param reloader  a irn that requires a reload
481  */
482 static ir_node *do_remat(spill_env_t *env, ir_node *spilled, ir_node *reloader) {
483         int i, arity;
484         ir_node *res;
485         ir_node *bl = get_nodes_block(reloader);
486         ir_node **ins;
487
488         ins = alloca(get_irn_arity(spilled) * sizeof(ins[0]));
489         for(i = 0, arity = get_irn_arity(spilled); i < arity; ++i) {
490                 ir_node *arg = get_irn_n(spilled, i);
491
492                 if(is_value_available(env, arg, reloader)) {
493                         ins[i] = arg;
494                 } else {
495                         ins[i] = do_remat(env, arg, reloader);
496                 }
497         }
498
499         /* create a copy of the node */
500         res = new_ir_node(get_irn_dbg_info(spilled), env->chordal_env->irg, bl,
501                 get_irn_op(spilled),
502                 get_irn_mode(spilled),
503                 get_irn_arity(spilled),
504                 ins);
505         copy_node_attr(spilled, res);
506
507         DBG((env->dbg, LEVEL_1, "Insert remat %+F before reloader %+F\n", res, reloader));
508
509         /* insert in schedule */
510         assert(!is_Block(reloader));
511         sched_add_before(reloader, res);
512
513         return res;
514 }
515
516 /*
517  *  ___                     _     ____      _                 _
518  * |_ _|_ __  ___  ___ _ __| |_  |  _ \ ___| | ___   __ _  __| |___
519  *  | || '_ \/ __|/ _ \ '__| __| | |_) / _ \ |/ _ \ / _` |/ _` / __|
520  *  | || | | \__ \  __/ |  | |_  |  _ <  __/ | (_) | (_| | (_| \__ \
521  * |___|_| |_|___/\___|_|   \__| |_| \_\___|_|\___/ \__,_|\__,_|___/
522  *
523  */
524
525 void be_insert_spills_reloads(spill_env_t *env) {
526         const arch_env_t *arch_env = env->arch_env;
527         spill_info_t *si;
528
529         /* process each spilled node */
530         DBG((env->dbg, LEVEL_1, "Insert spills and reloads:\n"));
531         for(si = set_first(env->spills); si; si = set_next(env->spills)) {
532                 reloader_t *rld;
533                 ir_mode *mode = get_irn_mode(si->spilled_node);
534                 pset *values = pset_new_ptr(16);
535
536                 /* go through all reloads for this spill */
537                 for(rld = si->reloaders; rld; rld = rld->next) {
538                         ir_node *new_val;
539
540                         if (check_remat_conditions(env, si->spilled_node, rld->reloader)) {
541                                 new_val = do_remat(env, si->spilled_node, rld->reloader);
542                         } else {
543                                 /* make sure we have a spill */
544                                 spill_node(env, si);
545
546                                 /* do a reload */
547                                 new_val = be_reload(arch_env, env->cls, rld->reloader, mode, si->spill);
548                         }
549
550                         DBG((env->dbg, LEVEL_1, " %+F of %+F before %+F\n", new_val, si->spilled_node, rld->reloader));
551                         pset_insert_ptr(values, new_val);
552                 }
553
554                 if(pset_count(values) > 0) {
555                         /* introduce copies, rewire the uses */
556                         pset_insert_ptr(values, si->spilled_node);
557                         be_ssa_constr_set_ignore(env->chordal_env->dom_front, env->chordal_env->lv, values, env->mem_phis);
558                 }
559
560                 del_pset(values);
561
562                 si->reloaders = NULL;
563         }
564
565         be_remove_dead_nodes_from_schedule(env->chordal_env->irg);
566         be_liveness_recompute(env->chordal_env->lv);
567 }