started working on a peephole phase
[libfirm] / ir / be / bepeephole.c
1 /*
2  * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief       modifies schedule so flags dependencies are respected.
23  * @author      Matthias Braun, Christoph Mallon
24  * @version     $Id$
25  */
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include "iredges_t.h"
31 #include "irgwalk.h"
32 #include "irprintf.h"
33 #include "error.h"
34
35 #include "beirg_t.h"
36 #include "belive_t.h"
37 #include "bearch_t.h"
38 #include "besched_t.h"
39
40 static const arch_env_t *arch_env;
41 static const be_lv_t    *lv;
42 ir_node              ***register_values;
43
44 static void clear_value(ir_node *node)
45 {
46         const arch_register_t       *reg;
47         const arch_register_class_t *cls;
48         unsigned                     reg_idx;
49         unsigned                     cls_idx;
50
51         if(!mode_is_data(get_irn_mode(node)))
52                 return;
53
54         reg     = arch_get_irn_register(arch_env, node);
55         if(reg == NULL) {
56                 panic("No register assigned at %+F\n", node);
57         }
58         if(arch_register_type_is(reg, virtual))
59                 return;
60         cls     = arch_register_get_class(reg);
61         reg_idx = arch_register_get_index(reg);
62         cls_idx = arch_register_class_index(cls);
63
64         register_values[cls_idx][reg_idx] = NULL;
65 }
66
67 static void set_value(ir_node *node)
68 {
69         const arch_register_t       *reg;
70         const arch_register_class_t *cls;
71         unsigned                     reg_idx;
72         unsigned                     cls_idx;
73
74         if(!mode_is_data(get_irn_mode(node)))
75                 return;
76
77         reg     = arch_get_irn_register(arch_env, node);
78         if(reg == NULL) {
79                 panic("No register assigned at %+F\n", node);
80         }
81         if(arch_register_type_is(reg, virtual))
82                 return;
83         cls     = arch_register_get_class(reg);
84         reg_idx = arch_register_get_index(reg);
85         cls_idx = arch_register_class_index(cls);
86
87 #ifdef DEBUG_libfirm
88         {
89                 ir_node *old_value = register_values[cls_idx][reg_idx];
90                 assert(old_value == NULL || old_value == node);
91         }
92 #endif
93         register_values[cls_idx][reg_idx] = node;
94 }
95
96 static void advance(ir_node *node)
97 {
98         int i, arity;
99
100         /* clear values defined */
101         if(get_irn_mode(node) == mode_T) {
102                 const ir_edge_t *edge;
103                 foreach_out_edge(node, edge) {
104                         ir_node *proj = get_edge_src_irn(edge);
105                         clear_value(proj);
106                 }
107         } else {
108                 clear_value(node);
109         }
110
111         /* set values used */
112         arity = get_irn_arity(node);
113         for(i = 0; i < arity; ++i) {
114                 ir_node *in = get_irn_n(node, i);
115                 set_value(in);
116         }
117 }
118
119 static void process_block(ir_node *block, void *data)
120 {
121         arch_isa_t *isa = arch_env->isa;
122         unsigned n_classes;
123         unsigned i;
124         int l;
125         ir_node *node;
126         (void) data;
127
128         /* construct initial register assignment */
129         n_classes = arch_isa_get_n_reg_class(isa);
130         for(i = 0; i < n_classes; ++i) {
131                 const arch_register_class_t *cls    = arch_isa_get_reg_class(isa, i);
132                 unsigned                     n_regs = arch_register_class_n_regs(cls);
133                 memset(register_values[i], 0, sizeof(ir_node*) * n_regs);
134         }
135
136         assert(lv->nodes && "live sets must be computed");
137         be_lv_foreach(lv, block, be_lv_state_end, l) {
138                 ir_node *node = be_lv_get_irn(lv, block, l);
139                 set_value(node);
140         }
141
142         /* walk the block */
143         sched_foreach_reverse(block, node) {
144                 if(is_Phi(node))
145                         break;
146
147                 advance(node);
148         }
149 }
150
151 void be_peephole_opt(be_irg_t *birg)
152 {
153         arch_isa_t *isa;
154         ir_graph   *irg = be_get_birg_irg(birg);
155         unsigned n_classes;
156         unsigned i;
157
158         /* we sometimes find BadE nodes in float apps like optest_float.c or
159          * kahansum.c for example... */
160         be_liveness_invalidate(birg->lv);
161         be_liveness_assure_sets(be_assure_liveness(birg));
162
163         arch_env = be_get_birg_arch_env(birg);
164         lv       = be_get_birg_liveness(birg);
165         isa      = arch_env->isa;
166
167         n_classes = arch_isa_get_n_reg_class(isa);
168         register_values = alloca(sizeof(register_values[0]) * n_classes);
169         for(i = 0; i < n_classes; ++i) {
170                 const arch_register_class_t *cls    = arch_isa_get_reg_class(isa, i);
171                 unsigned                     n_regs = arch_register_class_n_regs(cls);
172                 register_values[i] = alloca(sizeof(ir_node*) * n_regs);
173         }
174
175         irg_block_walk_graph(irg, process_block, NULL, NULL);
176 }