5e58666b02be6181e91168ba7a837dc00d5883dc
[libfirm] / ir / be / bessadestr.c
1 /**
2  * Author:      Daniel Grund
3  * Date:                25.05.2005
4  * Copyright:   (c) Universitaet Karlsruhe
5  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
6  *
7  * Performs SSA-Destruction.
8  */
9
10 #include "debug.h"
11 #include "set.h"
12 #include "pmap.h"
13 #include "irnode.h"
14 #include "iredges_t.h"
15 #include "bechordal_t.h"
16 #include "bearch.h"
17
18 #define get_reg(irn) arch_get_irn_register(chordal_env->arch_env, irn, arch_pos_make_out(0))
19 #define set_reg(irn, reg) arch_set_irn_register(chordal_env->arch_env, irn, arch_pos_make_out(0), reg)
20
21 /**
22  * Maps blocks to perm nodes inserted during phi destruction.
23  */
24 typedef struct _block2perm_t {
25         ir_node *block, *perm;
26 } block2perm_t;
27
28 static int set_cmp_b2p(const void *x, const void *y, size_t size) {
29         const block2perm_t *b1 = x;
30         const block2perm_t *b2 = y;
31         return b1->block != b2->block;
32 }
33
34 /**
35  * Adjusts the register allocation for the phi-operands
36  * by inserting perm nodes, if necessary.
37  * @param phi The phi node to adjust operands for
38  */
39 static void adjust_arguments(be_chordal_env_t *chordal_env, const ir_node *phi) {
40         int i, max;
41         ir_node *arg, *perm, *proj;
42         const arch_register_t *phi_reg, *arg_reg, *proj_reg;
43         const ir_edge_t *edge;
44         set *b2p;
45         block2perm_t find, *found;
46
47         assert(is_Phi(phi) && "Can only handle phi-destruction :)");
48
49         b2p = chordal_env->data;
50         phi_reg = get_reg(phi);
51         /* all arguments of the phi */
52         for(i=0, max=get_irn_arity(phi); i<max; ++i) {
53                 arg = get_irn_n(phi, i);
54                 arg_reg = get_reg(arg);
55                 /* if registers don't match ...*/
56                 if (phi_reg != arg_reg) {
57                         /* iff needed insert perm node */
58                         find.block = get_nodes_block(arg);
59                         find.perm = NULL;
60                         found = set_insert(b2p, &find, sizeof(find), HASH_PTR(find.block));
61                         if (!found->perm)
62                                 found->perm = insert_perm(TODO);
63
64                         /* now we have the perm in the predecessor block */
65                         perm = found->perm;
66                         /* adjust assigned registers for the projs */
67                         foreach_out_edge(perm, edge) {
68                                 proj = get_edge_src_irn(edge);
69                                 proj_reg = get_reg(proj);
70                                 if (proj_reg == arg_reg)
71                                         set_reg(proj, phi_reg);
72                                 else if (proj_reg == phi_reg)
73                                         set_reg(proj, arg_reg);
74                         }
75                 }
76         }
77 }
78
79 static void checker(be_chordal_env_t *chordal_env) {
80         pmap_entry *pme;
81         int i, max;
82
83         /* iterate over all blocks */
84         pmap_foreach(chordal_env->border_heads, pme) {
85                 border_t *curr;
86                 struct list_head *head = pme->value;
87
88                 /* iterate over all ops in the block */
89                 list_for_each_entry_reverse(border_t, curr, head, list)
90                         if (curr->is_def && curr->is_real && is_Phi(curr->irn)) {
91                                 const arch_register_t *phi_reg, *arg_reg;
92                                 phi_reg = get_reg(curr->irn);
93                                 /* iterate over all args of phi */
94                                 for(i=0, max=get_irn_arity(phi); i<max; ++i) {
95                                         arg_reg = get_reg(get_irn_n(curr->irn, i));
96                                         assert(phi_reg == arg_reg && "WTF? You can do it better!?");
97                                 }
98                         }
99         }
100 }
101
102 void be_ssa_destruction(be_chordal_env_t *chordal_env) {
103         pmap_entry *pme;
104         set *b2p;
105
106         b2p = new_set(set_cmp_b2p, 32);
107         chordal_env->data = b2p;
108         /* iterate over all blocks */
109         pmap_foreach(chordal_env->border_heads, pme) {
110                 border_t *curr;
111                 struct list_head *head = pme->value;
112
113                 /* iterate over all ops in the block
114                  * BETTER: phis are the first ops, so stop iteration on first non-phi-op */
115                 list_for_each_entry_reverse(border_t, curr, head, list)
116                         if (curr->is_def && curr->is_real && is_Phi(curr->irn))
117                                 adjust_arguments(chordal_env, curr->irn);
118         }
119         del_set(b2p);
120         checker(chordal_env);
121 }