4 * Copyright: (c) Universitaet Karlsruhe
5 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
7 * Performs SSA-Destruction.
14 #include "iredges_t.h"
15 #include "bechordal_t.h"
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)
22 * Maps blocks to perm nodes inserted during phi destruction.
24 typedef struct _block2perm_t {
25 ir_node *block, *perm;
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;
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
39 static void adjust_arguments(be_chordal_env_t *chordal_env, const ir_node *phi) {
41 ir_node *arg, *perm, *proj;
42 const arch_register_t *phi_reg, *arg_reg, *proj_reg;
43 const ir_edge_t *edge;
45 block2perm_t find, *found;
47 assert(is_Phi(phi) && "Can only handle phi-destruction :)");
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);
60 found = set_insert(b2p, &find, sizeof(find), HASH_PTR(find.block));
62 found->perm = insert_perm(TODO);
64 /* now we have the perm in the predecessor block */
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);
79 static void checker(be_chordal_env_t *chordal_env) {
83 /* iterate over all blocks */
84 pmap_foreach(chordal_env->border_heads, pme) {
86 struct list_head *head = pme->value;
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!?");
102 void be_ssa_destruction(be_chordal_env_t *chordal_env) {
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) {
111 struct list_head *head = pme->value;
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);
120 checker(chordal_env);