4 * Copyright: (c) Universitaet Karlsruhe
5 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
7 * Performs SSA-Destruction.
17 #include "iredges_t.h"
21 #include "bechordal_t.h"
24 #include "besched_t.h"
26 #define get_reg(irn) arch_get_irn_register(chordal_env->arch_env, irn, 0)
27 #define set_reg(irn, reg) arch_set_irn_register(chordal_env->arch_env, irn, 0, reg)
30 * Maps blocks to perm nodes inserted during phi destruction.
32 typedef struct _block2perm_t {
33 ir_node *block, *perm;
36 static int set_cmp_b2p(const void *x, const void *y, size_t size) {
37 const block2perm_t *b1 = x;
38 const block2perm_t *b2 = y;
39 return b1->block != b2->block;
42 #define is_Branch(irn) (arch_irn_classify(arch_env, irn) == arch_irn_class_branch)
43 #define is_Perm(irn) (arch_irn_classify(arch_env, irn) == arch_irn_class_perm)
44 #define get_reg_cls(irn) (arch_get_irn_reg_class(arch_env, irn, arch_pos_make_out(0)))
45 #define is_curr_reg_class(irn) (get_reg_cls(p) == chordal_env->cls)
47 static ir_node *get_perm(be_main_session_env_t *session, be_chordal_env_t *chordal_env, ir_node *block) {
48 block2perm_t find, *found;
50 set *b2p = chordal_env->data;
51 const arch_env_t *arch_env = chordal_env->arch_env;
53 /* iff needed insert perm node */
55 /* .if the perm is in the pset return it */
58 found = set_insert(b2p, &find, sizeof(find), HASH_PTR(find.block));
62 /* .else look for a perm of right register class in the schedule */
63 p = sched_last(find.block);
64 while (!is_Block(p) && (is_Branch(p) || (is_Perm(p) && !is_curr_reg_class(p))))
67 /* if we haven't found a perm of the right register class create a new one */
68 if (! (is_Perm(p) && is_curr_reg_class(p)))
69 p = insert_Perm_after(session, chordal_env->cls, p);
71 /* insert perm into pset */
77 * Adjusts the register allocation for the phi-operands
78 * by inserting perm nodes, if necessary.
79 * @param phi The phi node to adjust operands for
81 static void adjust_arguments(be_main_session_env_t *session, be_chordal_env_t *chordal_env, const ir_node *phi) {
83 ir_node *arg, *perm, *proj;
84 const arch_register_t *phi_reg, *arg_reg, *proj_reg;
85 const ir_edge_t *edge;
86 ir_node *phi_block = get_nodes_block(phi);
88 assert(is_Phi(phi) && "Can only handle phi-destruction :)");
90 phi_reg = get_reg(phi);
91 /* all arguments of the phi */
92 for(i=0, max=get_irn_arity(phi); i<max; ++i) {
93 arg = get_irn_n(phi, i);
94 arg_reg = get_reg(arg);
95 /* if registers don't match ...*/
96 if (phi_reg != arg_reg) {
97 perm = get_perm(session, chordal_env, get_nodes_block(get_irn_n(phi_block, i)));
98 /* adjust assigned registers for the projs */
99 foreach_out_edge(perm, edge) {
100 proj = get_edge_src_irn(edge);
101 proj_reg = get_reg(proj);
102 if (proj_reg == arg_reg)
103 set_reg(proj, phi_reg);
104 else if (proj_reg == phi_reg)
105 set_reg(proj, arg_reg);
111 static void checker(be_chordal_env_t *chordal_env) {
115 /* iterate over all blocks */
116 pmap_foreach(chordal_env->border_heads, pme) {
118 struct list_head *head = pme->value;
120 /* iterate over the first ops in the block */
121 list_for_each_entry_reverse(border_t, curr, head, list)
122 if (curr->is_def && curr->is_real && is_Phi(curr->irn)) {
123 const arch_register_t *phi_reg, *arg_reg;
124 if (!is_Phi(curr->irn))
127 phi_reg = get_reg(curr->irn);
128 /* iterate over all args of phi */
129 for(i=0, max=get_irn_arity(curr->irn); i<max; ++i) {
130 arg_reg = get_reg(get_irn_n(curr->irn, i));
131 assert(phi_reg == arg_reg && "WTF? You can do it better!?");
137 void be_ssa_destruction(be_main_session_env_t *session, be_chordal_env_t *chordal_env) {
141 b2p = new_set(set_cmp_b2p, 32);
142 chordal_env->data = b2p;
143 /* iterate over all blocks */
144 pmap_foreach(chordal_env->border_heads, pme) {
146 struct list_head *head = pme->value;
148 /* iterate over the first ops in the block until a non-phi is reached */
149 list_for_each_entry_reverse(border_t, curr, head, list)
150 if (curr->is_def && curr->is_real) {
151 if (!is_Phi(curr->irn))
153 adjust_arguments(session, chordal_env, curr->irn);
156 dump_ir_block_graph_sched(session->irg, "-ssa-destr");
158 checker(chordal_env);