7721a0c67a595cccf816674296ac5b94e958e9c5
[libfirm] / ir / be / benode.c
1 /**
2  * @file   benode.c
3  * @date   17.05.2005
4  * @author Sebastian Hack
5  *
6  * Backend node support.
7  *
8  * This file provdies Perm, Copy, Spill and Reload nodes.
9  *
10  * Copyright (C) 2005 Universitaet Karlsruhe
11  * Released under the GPL
12  */
13
14 #ifdef HAVE_CONFIG_H
15 #include "config.h"
16 #endif
17
18 #include <stdlib.h>
19
20 #include "obst.h"
21 #include "set.h"
22 #include "pmap.h"
23 #include "util.h"
24 #include "debug.h"
25 #include "fourcc.h"
26
27 #include "irop_t.h"
28 #include "irmode_t.h"
29 #include "irnode_t.h"
30 #include "ircons_t.h"
31 #include "irprintf.h"
32
33 #include "be_t.h"
34 #include "belive_t.h"
35 #include "besched_t.h"
36 #include "benode_t.h"
37
38 #include "beirgmod.h"
39
40 #define DBG_LEVEL 0
41
42 #define BENODE_MAGIC FOURCC('B', 'E', 'N', 'O')
43
44 typedef enum _node_kind_t {
45         node_kind_spill,
46         node_kind_reload,
47         node_kind_perm,
48         node_kind_copy,
49         node_kind_last
50 } node_kind_t;
51
52 typedef struct {
53         node_kind_t kind;
54         const arch_register_class_t *cls;
55         ir_op *op;
56         int n_pos;
57         int *pos;
58 } be_op_t;
59
60 typedef struct {
61         const arch_register_t *reg;
62         arch_register_req_t   req;
63 } be_reg_data_t;
64
65 typedef struct {
66         unsigned      magic;
67         const be_op_t *op;
68         int           n_regs;
69         be_reg_data_t reg_data[1];
70 } be_node_attr_t;
71
72 typedef struct {
73         be_node_attr_t attr;
74         ir_node *spill_ctx;  /**< The node in whose context this spill was introduced. */
75         unsigned offset;     /**< The offset of the memory location the spill writes to
76                                                    in the spill area. */
77 } be_spill_attr_t;
78
79 static int templ_pos_Spill[] = {
80         0
81 };
82
83 static int templ_pos_Reload[] = {
84         -1
85 };
86
87 static int templ_pos_Copy[] = {
88         0, -1
89 };
90
91 static int dump_node(ir_node *irn, FILE *f, dump_reason_t reason);
92
93 static const ir_op_ops be_node_ops = {
94         NULL,
95         NULL,
96         NULL,
97         NULL,
98         NULL,
99         NULL,
100         NULL,
101         NULL,
102         NULL,
103         NULL,
104         NULL,
105         dump_node,
106         NULL
107 };
108
109 static INLINE int is_be_node(const ir_node *irn)
110 {
111         const be_node_attr_t *attr = (const be_node_attr_t *) &irn->attr;
112         return attr->magic == BENODE_MAGIC;
113 }
114
115 static INLINE int is_be_kind(const ir_node *irn, node_kind_t kind)
116 {
117         const be_node_attr_t *a = (const be_node_attr_t *) &irn->attr;
118         return a->magic == BENODE_MAGIC && a->op && a->op->kind == kind;
119 }
120
121 static INLINE void *get_attr_and_check(ir_node *irn, node_kind_t kind)
122 {
123         is_be_kind(irn, kind);
124         return &irn->attr;
125 }
126
127 static be_node_attr_t *init_node_attr(ir_node *irn,
128                                                                           const be_op_t *op,
129                                                                           const arch_register_class_t *cls,
130                                                                           int n_regs)
131
132 {
133         be_node_attr_t *attr = (be_node_attr_t *) &irn->attr;
134         int i;
135
136         attr->magic   = BENODE_MAGIC;
137         attr->n_regs  = n_regs;
138         attr->op      = op;
139
140         for(i = 0; i < n_regs; ++i) {
141                 be_reg_data_t *rd = attr->reg_data + i;
142
143                 rd->reg      = NULL;
144                 rd->req.cls  = cls;
145                 rd->req.type = arch_register_req_type_normal;
146         }
147
148         return attr;
149 }
150
151 #define ARRSIZE(x) (sizeof(x) / sizeof(x[0]))
152
153 static int cmp_op_map(const void *a, const void *b, size_t size)
154 {
155         const be_op_t *x = a;
156         const be_op_t *y = b;
157
158         return !(x->kind == y->kind && x->cls == y->cls);
159 }
160
161 static be_op_t *get_op(const be_node_factory_t *fact,
162                 const arch_register_class_t *cls, node_kind_t kind)
163 {
164         be_op_t templ;
165
166         templ.kind = kind;
167         templ.cls = cls;
168
169         return set_insert(fact->ops, &templ, sizeof(templ),
170                 HASH_PTR(cls) + 7 * kind);
171 }
172
173 ir_node *new_Spill(const be_node_factory_t *factory,
174                 const arch_register_class_t *cls,
175                 ir_graph *irg, ir_node *bl, ir_node *node_to_spill, ir_node *ctx)
176 {
177         be_spill_attr_t *a;
178         ir_node *irn;
179         ir_node *in[1];
180         be_op_t *bop = get_op(factory, cls, node_kind_spill);
181         ir_op *op    = bop->op;
182
183         assert(op && "Spill opcode must be present for this register class");
184         in[0]        = node_to_spill;
185         irn          = new_ir_node(NULL, irg, bl, op, mode_M, 1, in);
186         a            = (be_spill_attr_t *) init_node_attr(irn, bop, cls, 0);
187         a->spill_ctx = ctx;
188         a->offset    = 0;
189
190         return irn;
191 }
192
193 void set_Spill_offset(ir_node *irn, unsigned offset)
194 {
195         be_spill_attr_t *a = (be_spill_attr_t *) &irn->attr;
196         assert(is_be_kind(irn, node_kind_spill));
197         a->offset = offset;
198 }
199
200 static ir_node *find_a_spill_walker(ir_node *irn, unsigned visited_nr)
201 {
202         if(get_irn_visited(irn) < visited_nr) {
203                 set_irn_visited(irn, visited_nr);
204
205                 if(is_Phi(irn)) {
206                         int i, n;
207                         for(i = 0, n = get_irn_arity(irn); i < n; ++i) {
208                                 ir_node *n = find_a_spill_walker(get_irn_n(irn, i), visited_nr);
209                                 if(n != NULL)
210                                         return n;
211                         }
212                 }
213
214                 else if(is_be_kind(irn, node_kind_spill))
215                         return irn;
216         }
217
218         return NULL;
219 }
220
221 ir_node *get_Spill_context(const ir_node *irn) {
222         be_spill_attr_t *a = (be_spill_attr_t *) &irn->attr;
223         assert(is_be_kind(irn, node_kind_spill));
224         return a->spill_ctx;
225 }
226
227 /**
228  * Finds a spill for a reload.
229  * If the reload is directly using the spill, this is simple,
230  * else we perform DFS from the reload (over all PhiMs) and return
231  * the first spill node we find.
232  */
233 static INLINE ir_node *find_a_spill(ir_node *irn)
234 {
235         ir_graph *irg       = get_irn_irg(irn);
236         unsigned visited_nr = get_irg_visited(irg) + 1;
237
238         assert(is_be_kind(irn, node_kind_reload));
239         set_irg_visited(irg, visited_nr);
240         return find_a_spill_walker(irn, visited_nr);
241 }
242
243
244 unsigned get_Spill_offset(ir_node *irn)
245 {
246         be_node_attr_t *a = (be_node_attr_t *) &irn->attr;
247         assert(is_be_node(irn));
248
249         switch(a->op->kind) {
250         case node_kind_reload:
251                 assert(0 && "not yet implemented");
252                 return get_Spill_offset(find_a_spill(irn));
253         case node_kind_spill:
254                 return ((be_spill_attr_t *) a)->offset;
255         default:
256                 assert(0 && "Illegal node kind (spill/reload required)");
257         }
258
259         return 0;
260 }
261
262 ir_node *new_Reload(const be_node_factory_t *factory,
263                 const arch_register_class_t *cls, ir_graph *irg,
264                 ir_node *bl, ir_mode *mode, ir_node *spill_node)
265 {
266         ir_node *irn, *in[1];
267         be_op_t *bop = get_op(factory, cls, node_kind_reload);
268         ir_op *op    = bop->op;
269
270         assert(op && "Reload opcode must be present for this register class");
271         in[0] = spill_node;
272
273         irn  = new_ir_node(NULL, irg, bl, op, mode, 1, in);
274         init_node_attr(irn, bop, cls, 1);
275
276         return irn;
277 }
278
279 ir_node *new_Perm(const be_node_factory_t *factory,
280                 const arch_register_class_t *cls,
281                 ir_graph *irg, ir_node *bl, int arity, ir_node **in)
282 {
283         ir_node *irn;
284         be_op_t *bop = get_op(factory, cls, node_kind_perm);
285         ir_op *op    = bop->op;
286
287         irn  = new_ir_node(NULL, irg, bl, op, mode_T, arity, in);
288         init_node_attr(irn, bop, cls, arity);
289
290         return irn;
291 }
292
293 ir_node *new_Copy(const be_node_factory_t *factory,
294                 const arch_register_class_t *cls,
295                 ir_graph *irg, ir_node *bl, ir_node *in)
296 {
297         ir_node *irn, *ins[1];
298         be_op_t *bop = get_op(factory, cls, node_kind_copy);
299         ir_op *op    = bop->op;
300
301         ins[0] = in;
302
303         irn  = new_ir_node(NULL, irg, bl, op, get_irn_mode(in), 1, ins);
304         init_node_attr(irn, bop, cls, 1);
305
306         return irn;
307 }
308
309 ir_node *be_spill(
310                 const be_node_factory_t *factory,
311                 const arch_env_t *arch_env,
312                 ir_node *irn, ir_node *ctx)
313 {
314         const arch_register_class_t *cls = arch_get_irn_reg_class(arch_env, irn, -1);
315
316         ir_node *bl    = get_nodes_block(irn);
317         ir_graph *irg  = get_irn_irg(bl);
318         ir_node *spill = new_Spill(factory, cls, irg, bl, irn, ctx);
319         ir_node *insert;
320
321         /*
322          * search the right insertion point. a spill of a phi cannot be put
323          * directly after the phi, if there are some phis behind the one which
324          * is spilled.
325          */
326         insert = sched_next(irn);
327         while(is_Phi(insert) && !sched_is_end(insert))
328                 insert = sched_next(insert);
329
330         sched_add_before(insert, spill);
331         return spill;
332 }
333
334 ir_node *be_reload(const be_node_factory_t *factory,
335                                          const arch_env_t *arch_env,
336                                          const arch_register_class_t *cls,
337                                          ir_node *irn, int pos, ir_mode *mode, ir_node *spill)
338 {
339         ir_node *reload;
340
341         ir_node *bl   = get_nodes_block(irn);
342         ir_graph *irg = get_irn_irg(bl);
343
344         assert(is_Spill(spill)
345                         || (is_Phi(spill) && get_irn_mode(spill) == mode_M));
346
347         reload = new_Reload(factory, cls, irg, bl, mode, spill);
348
349         set_irn_n(irn, pos, reload);
350         sched_add_before(irn, reload);
351         return reload;
352 }
353
354 static INLINE arch_register_req_t *get_Perm_reqs(ir_node *perm)
355 {
356         be_node_attr_t *attr = (be_node_attr_t *) &perm->attr;
357         char *ptr            = (char *) &perm->attr;
358
359         ptr += sizeof(be_node_attr_t);
360         ptr += sizeof(arch_register_t *) * attr->n_regs;
361
362         return (arch_register_req_t *) ptr;
363 }
364
365 /**
366  * If the node is a proj, reset the node to the proj's target and return
367  * the proj number.
368  * @param node The address of a node pointer.
369  * @param def  A default value.
370  * @return     If *node is a Proj, *node is set to the Proj's target and
371  *             the Proj number is returned. Else *node remains the same and @p def
372  *             is returned.
373  */
374 static int redir_proj(const ir_node **node, int def)
375 {
376         const ir_node *n = *node;
377
378         if(is_Proj(n)) {
379                 *node = get_Proj_pred(n);
380                 def = -(get_Proj_proj(n) + 1);
381         }
382
383         return def;
384 }
385
386 static const arch_register_req_t *
387 be_node_get_irn_reg_req(const arch_irn_ops_t *_self,
388                 arch_register_req_t *req, const ir_node *irn, int pos)
389 {
390         be_op_t *bo;
391         const be_node_factory_t *factory =
392                 container_of(_self, const be_node_factory_t, irn_ops);
393
394         /* We cannot get output requirements for tuple nodes. */
395         if(get_irn_mode(irn) == mode_T && pos < 0)
396                 return NULL;
397
398         /*
399          * if we're interested in an output operand (pos < 0), so let's resolve projs.
400          */
401         if(pos < 0)
402                 pos = redir_proj((const ir_node **) &irn, pos);
403
404         /* look if the node is one of ours. */
405         bo = pmap_get(factory->irn_op_map, get_irn_op(irn));
406
407         if(bo) {
408                 int i;
409
410                 for(i = 0; i < bo->n_pos; ++i) {
411                         if(pos == bo->pos[i]) {
412
413                                 /* be nodes have no input constraints.
414                                    so return normal register requirements. */
415                                 if(pos >= 0) {
416                                         req->cls = bo->cls;
417                                         req->type = arch_register_req_type_normal;
418                                 }
419
420                                 /*
421                                  * if an output requirement is requested,
422                                  * return the one stored in the node.
423                                  */
424                                 else {
425                                         be_node_attr_t *attr = (be_node_attr_t *) &irn->attr;
426                                         *req = attr->reg_data[pos].req;
427                                 }
428
429                                 return req;
430                         }
431                 }
432         }
433
434         return NULL;
435 }
436
437 void be_set_Perm_out_req(ir_node *irn, int pos, const arch_register_req_t *req)
438 {
439         be_node_attr_t *a = get_attr_and_check(irn, node_kind_perm);
440
441         assert(pos >= 0 && pos < get_irn_arity(irn) && "position out of range");
442         assert(a->op->kind == node_kind_perm && "node must be a perm node");
443
444         a->reg_data[pos].req = *req;
445 }
446
447 void
448 be_node_set_irn_reg(const arch_irn_ops_t *_self, ir_node *irn,
449                 const arch_register_t *reg)
450 {
451         int pos;
452         be_op_t *bo;
453         be_node_attr_t *attr;
454         const be_node_factory_t *factory =
455                 container_of(_self, const be_node_factory_t, irn_ops);
456
457         if(get_irn_mode(irn) == mode_T)
458                 return;
459
460         pos = redir_proj((const ir_node **) &irn, -1);
461         bo = pmap_get(factory->irn_op_map, get_irn_op(irn));
462
463         if(!bo)
464                 return;
465
466         attr = (be_node_attr_t *) &irn->attr;
467         attr->reg_data[-pos - 1].reg = reg;
468 }
469
470 const arch_register_t *
471 be_node_get_irn_reg(const arch_irn_ops_t *_self, const ir_node *irn)
472 {
473         int i, pos;
474         be_op_t *bo;
475         const be_node_factory_t *factory =
476                 container_of(_self, const be_node_factory_t, irn_ops);
477
478         if(get_irn_mode(irn) == mode_T)
479                 return NULL;
480
481         pos = redir_proj((const ir_node **) &irn, -1);
482         bo = pmap_get(factory->irn_op_map, get_irn_op(irn));
483
484         if(!bo)
485                 return NULL;
486
487         for(i = 0; i < bo->n_pos; ++i) {
488                 if(bo->pos[i] == pos) {
489                         be_node_attr_t *attr = (be_node_attr_t *) &irn->attr;
490                         return attr->reg_data[-pos - 1].reg;
491                 }
492         }
493
494         return NULL;
495 }
496
497 arch_irn_class_t be_node_classify(const arch_irn_ops_t *_self, const ir_node *irn)
498 {
499         const be_node_factory_t *factory = container_of(_self, const be_node_factory_t, irn_ops);
500
501         be_op_t *bo;
502         int idx;
503
504         idx = redir_proj(&irn, 0);
505         bo = pmap_get(factory->irn_op_map, get_irn_op(irn));
506
507         switch(bo->kind) {
508 #define XXX(a) case node_kind_ ## a: return arch_irn_class_ ## a;
509                 XXX(spill)
510                 XXX(reload)
511                 XXX(perm)
512                 XXX(copy)
513 #undef XXX
514                 default:
515                 return 0;
516         }
517
518         return 0;
519 }
520
521 arch_irn_class_t be_node_get_flags(const arch_irn_ops_t *_self, const ir_node *irn)
522 {
523         return 0;
524 }
525
526 static const arch_irn_ops_t *
527 be_node_get_irn_ops(const arch_irn_handler_t *_self, const ir_node *irn)
528 {
529         be_op_t *bo;
530         const be_node_factory_t *factory =
531                 container_of(_self, const be_node_factory_t, handler);
532
533         redir_proj(&irn, 0);
534         bo = pmap_get(factory->irn_op_map, get_irn_op(irn));
535
536         return bo ? &factory->irn_ops : NULL;
537 }
538
539 const arch_irn_handler_t *be_node_get_irn_handler(const be_node_factory_t *f)
540 {
541         return &f->handler;
542 }
543
544 int is_Spill(const ir_node *irn)
545 {
546         return is_be_kind(irn, node_kind_spill);
547 }
548
549 int is_Perm(const ir_node *irn)
550 {
551         return is_be_kind(irn, node_kind_perm);
552 }
553
554 be_node_factory_t *be_node_factory_init(be_node_factory_t *factory, const arch_isa_t *isa)
555 {
556         int i, j, n;
557
558         factory->ops = new_set(cmp_op_map, 64);
559         factory->irn_op_map = pmap_create();
560         obstack_init(&factory->obst);
561
562         factory->handler.get_irn_ops = be_node_get_irn_ops;
563
564         factory->irn_ops.get_irn_reg_req = be_node_get_irn_reg_req;
565         factory->irn_ops.set_irn_reg     = be_node_set_irn_reg;
566         factory->irn_ops.get_irn_reg     = be_node_get_irn_reg;
567         factory->irn_ops.classify        = be_node_classify;
568         factory->irn_ops.get_flags       = be_node_get_flags;
569
570         for(i = 0, n = arch_isa_get_n_reg_class(isa); i < n; ++i) {
571                 const arch_register_class_t *cls = arch_isa_get_reg_class(isa, i);
572                 be_op_t *ent;
573
574                 ent = get_op(factory, cls, node_kind_spill);
575                 ent->op = new_ir_op(get_next_ir_opcode(), "Spill", op_pin_state_pinned,
576                                 0, oparity_unary, 0, sizeof(be_spill_attr_t), &be_node_ops);
577                 ent->n_pos = ARRSIZE(templ_pos_Spill);
578                 ent->pos = templ_pos_Spill;
579                 pmap_insert(factory->irn_op_map, ent->op, ent);
580
581                 ent = get_op(factory, cls, node_kind_reload);
582                 ent->op = new_ir_op(get_next_ir_opcode(), "Reload", op_pin_state_pinned, 0,
583                                 oparity_unary, 0, sizeof(be_node_attr_t), &be_node_ops);
584                 ent->n_pos = ARRSIZE(templ_pos_Reload);
585                 ent->pos = templ_pos_Reload;
586                 pmap_insert(factory->irn_op_map, ent->op, ent);
587
588                 ent = get_op(factory, cls, node_kind_copy);
589                 ent->op = new_ir_op(get_next_ir_opcode(), "Copy", op_pin_state_pinned, 0,
590                                 oparity_unary, 0, sizeof(be_node_attr_t), &be_node_ops);
591                 ent->n_pos = ARRSIZE(templ_pos_Copy);
592                 ent->pos = templ_pos_Copy;
593                 pmap_insert(factory->irn_op_map, ent->op, ent);
594
595                 ent = get_op(factory, cls, node_kind_perm);
596                 ent->op = new_ir_op(get_next_ir_opcode(), "Perm", op_pin_state_pinned, 0,
597                                 oparity_variable, 0,
598                                 sizeof(be_node_attr_t)
599                                 + sizeof(be_reg_data_t) * cls->n_regs, &be_node_ops);
600                 ent->n_pos = 2 * cls->n_regs;
601                 ent->pos = obstack_alloc(&factory->obst, sizeof(ent->pos[0]) * ent->n_pos);
602                 for(j = 0; j < ent->n_pos; j += 2) {
603                         int k = j / 2;
604                         ent->pos[j] = k;
605                         ent->pos[j + 1] = -(k + 1);
606                 }
607                 pmap_insert(factory->irn_op_map, ent->op, ent);
608
609         }
610
611         return factory;
612 }
613
614 static int dump_node(ir_node *irn, FILE *f, dump_reason_t reason)
615 {
616         be_node_attr_t *at = (be_node_attr_t *) &irn->attr;
617         const be_op_t *bo;
618         int i;
619
620         assert(is_be_node(irn));
621         bo = at->op;
622
623         switch(reason) {
624                 case dump_node_opcode_txt:
625                         fprintf(f, get_op_name(bo->op));
626                         break;
627                 case dump_node_mode_txt:
628                         fprintf(f, get_mode_name(get_irn_mode(irn)));
629                         break;
630                 case dump_node_nodeattr_txt:
631                         fprintf(f, "%s ", bo->cls->name);
632                         break;
633                 case dump_node_info_txt:
634                         for(i = 0; i < at->n_regs; ++i) {
635                                 const arch_register_t *reg = at->reg_data[i].reg;
636                                 fprintf(f, "reg #%d: %s\n", i, reg ? reg->name : "n/a");
637                         }
638
639                         if(bo->kind == node_kind_spill) {
640                                 be_spill_attr_t *a = (be_spill_attr_t *) at;
641                                 ir_fprintf(f, "spill context: %+F\n", a->spill_ctx);
642                         }
643                         break;
644         }
645
646         return 0;
647 }
648
649 ir_node *insert_Perm_after(const be_main_env_t *env,
650                                                          const arch_register_class_t *cls,
651                                                          dom_front_info_t *dom_front,
652                                                          ir_node *pos)
653 {
654         const arch_env_t *arch_env  = env->arch_env;
655         ir_node *bl                 = is_Block(pos) ? pos : get_nodes_block(pos);
656         ir_graph *irg               = get_irn_irg(bl);
657         pset *live                  = pset_new_ptr_default();
658         firm_dbg_module_t *dbg      = firm_dbg_register("firm.be.node");
659
660         irn_live_t *li;
661         ir_node *curr, *irn, *perm, **nodes;
662         int i, n;
663
664         firm_dbg_set_mask(dbg, DBG_LEVEL);
665         DBG((dbg, LEVEL_1, "Insert Perm after: %+F\n", pos));
666
667
668         live_foreach(bl, li) {
669                 ir_node *irn = (ir_node *) li->irn;
670                 if(live_is_end(li) && arch_irn_has_reg_class(arch_env, irn, -1, cls))
671                         pset_insert_ptr(live, irn);
672         }
673
674         sched_foreach_reverse(bl, irn) {
675                 ir_node *x;
676
677         /*
678          * If we encounter the node we want to insert the Perm after,
679          * exit immediately, so that this node is still live
680          */
681                 if(irn == pos)
682                         break;
683
684                 DBG((dbg, LEVEL_1, "%+F\n", irn));
685                 for(x = pset_first(live); x; x = pset_next(live))
686                         DBG((dbg, LEVEL_1, "\tlive: %+F\n", x));
687
688                 if(arch_irn_has_reg_class(arch_env, irn, -1, cls))
689                         pset_remove_ptr(live, irn);
690
691                 for(i = 0, n = get_irn_arity(irn); i < n; ++i) {
692                         ir_node *op = get_irn_n(irn, i);
693
694                         if(arch_irn_has_reg_class(arch_env, op, -1, cls))
695                                 pset_insert_ptr(live, op);
696                 }
697         }
698
699         n = pset_count(live);
700         nodes = malloc(n * sizeof(nodes[0]));
701
702         DBG((dbg, LEVEL_1, "live:\n"));
703         for(irn = pset_first(live), i = 0; irn; irn = pset_next(live), i++) {
704                 DBG((dbg, LEVEL_1, "\t%+F\n", irn));
705                 nodes[i] = irn;
706         }
707
708         perm = new_Perm(env->node_factory, cls, irg, bl, n, nodes);
709         sched_add_after(pos, perm);
710         free(nodes);
711
712         curr = perm;
713         for(i = 0; i < n; ++i) {
714                 ir_node *copies[1];
715                 ir_node *perm_op = get_irn_n(perm, i);
716                 const arch_register_t *reg = arch_get_irn_register(arch_env, perm_op);
717
718                 ir_mode *mode = get_irn_mode(perm_op);
719                 ir_node *proj = new_r_Proj(irg, bl, perm, mode, i);
720                 arch_set_irn_register(arch_env, proj, reg);
721
722                 sched_add_after(curr, proj);
723                 curr = proj;
724
725                 copies[0] = proj;
726                 be_introduce_copies(dom_front, perm_op, array_size(copies), copies);
727         }
728         return perm;
729 }