replace and kill survive_dce stuff
[libfirm] / ir / be / betranshlp.c
1 /*
2  * Copyright (C) 1995-2010 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       be transform helper extracted from the ia32 backend.
23  * @author      Matthias Braun, Michael Beck
24  * @date        14.06.2007
25  * @version     $Id$
26  */
27 #include "config.h"
28
29 #include "pdeq.h"
30 #include "irop_t.h"
31 #include "iropt_t.h"
32 #include "irnode_t.h"
33 #include "irgraph_t.h"
34 #include "ircons_t.h"
35 #include "irhooks.h"
36 #include "iredges.h"
37 #include "irouts.h"
38 #include "trouts.h"
39 #include "cgana.h"
40 #include "debug.h"
41
42 #include "beirg.h"
43 #include "beabi.h"
44 #include "betranshlp.h"
45 #include "belive.h"
46 #include "benode.h"
47
48 typedef struct be_transform_env_t {
49         ir_graph *irg;         /**< The irg, the node should be created in */
50         waitq    *worklist;    /**< worklist of nodes that still need to be
51                                     transformed */
52         ir_node  *old_anchor;  /**< the old anchor node in the old irg */
53 } be_transform_env_t;
54
55
56 static be_transform_env_t env;
57
58 void be_set_transformed_node(ir_node *old_node, ir_node *new_node)
59 {
60         set_irn_link(old_node, new_node);
61         mark_irn_visited(old_node);
62 }
63
64 int be_is_transformed(const ir_node *node)
65 {
66         return irn_visited(node);
67 }
68
69 static inline ir_node *be_get_transformed_node(ir_node *old_node)
70 {
71         if (irn_visited(old_node)) {
72                 ir_node *new_node = (ir_node*)get_irn_link(old_node);
73                 assert(new_node != NULL);
74                 return new_node;
75         }
76         return NULL;
77 }
78
79 void be_duplicate_deps(ir_node *old_node, ir_node *new_node)
80 {
81         int i;
82         int deps = get_irn_deps(old_node);
83
84         for (i = 0; i < deps; ++i) {
85                 ir_node *dep     = get_irn_dep(old_node, i);
86                 ir_node *new_dep = be_transform_node(dep);
87
88                 add_irn_dep(new_node, new_dep);
89         }
90 }
91
92 void be_set_transform_function(ir_op *op, be_transform_func func)
93 {
94         /* shouldn't be assigned twice (except for exchanging the default
95          * be_duplicate_node entries) */
96         assert(op->ops.generic == NULL
97                         || op->ops.generic == (op_func) be_duplicate_node);
98         op->ops.generic = (op_func) func;
99 }
100
101 void be_start_transform_setup(void)
102 {
103         clear_irp_opcodes_generic_func();
104
105         be_set_transform_function(op_Bad,         be_duplicate_node);
106         be_set_transform_function(op_be_Copy,     be_duplicate_node);
107         be_set_transform_function(op_be_CopyKeep, be_duplicate_node);
108         be_set_transform_function(op_be_IncSP,    be_duplicate_node);
109         be_set_transform_function(op_be_Keep,     be_duplicate_node);
110         be_set_transform_function(op_be_Return,   be_duplicate_node);
111         be_set_transform_function(op_be_Start,    be_duplicate_node);
112         be_set_transform_function(op_NoMem,       be_duplicate_node);
113         be_set_transform_function(op_Pin,         be_duplicate_node);
114         be_set_transform_function(op_Start,       be_duplicate_node);
115         be_set_transform_function(op_Sync,        be_duplicate_node);
116 }
117
118 ir_node *be_duplicate_node(ir_node *node)
119 {
120         ir_node  *block = be_transform_node(get_nodes_block(node));
121         ir_graph *irg   = env.irg;
122         dbg_info *dbgi  = get_irn_dbg_info(node);
123         ir_mode  *mode  = get_irn_mode(node);
124         ir_op    *op    = get_irn_op(node);
125         ir_node  *new_node;
126         int      i, arity;
127
128         arity = get_irn_arity(node);
129         if (op->opar == oparity_dynamic) {
130                 new_node = new_ir_node(dbgi, irg, block, op, mode, -1, NULL);
131                 for (i = 0; i < arity; ++i) {
132                         ir_node *in = get_irn_n(node, i);
133                         in = be_transform_node(in);
134                         add_irn_n(new_node, in);
135                 }
136         } else {
137                 ir_node **ins = ALLOCAN(ir_node*, arity);
138                 for (i = 0; i < arity; ++i) {
139                         ir_node *in = get_irn_n(node, i);
140                         ins[i] = be_transform_node(in);
141                 }
142
143                 new_node = new_ir_node(dbgi, irg, block, op, mode, arity, ins);
144         }
145
146         copy_node_attr(irg, node, new_node);
147         be_duplicate_deps(node, new_node);
148
149         new_node->node_nr = node->node_nr;
150         return new_node;
151 }
152
153 ir_node *be_transform_node(ir_node *node)
154 {
155         ir_op             *op;
156         ir_node           *new_node = be_get_transformed_node(node);
157         be_transform_func *transform;
158
159         if (new_node != NULL)
160                 return new_node;
161
162         DEBUG_ONLY(be_set_transformed_node(node, NULL));
163
164         op = get_irn_op(node);
165         if (op->ops.generic == NULL) {
166                 panic("No transform function registered for node %+F.", node);
167         }
168         transform = (be_transform_func *)op->ops.generic;
169
170         new_node = transform(node);
171         assert(new_node != NULL);
172
173         be_set_transformed_node(node, new_node);
174         hook_dead_node_elim_subst(current_ir_graph, node, new_node);
175         return new_node;
176 }
177
178 void be_enqueue_preds(ir_node *node)
179 {
180         int i, arity;
181
182         /* put the preds in the worklist */
183         arity = get_irn_arity(node);
184         for (i = 0; i < arity; ++i) {
185                 ir_node *pred = get_irn_n(node, i);
186                 pdeq_putr(env.worklist, pred);
187         }
188 }
189
190 /**
191  * Rewire nodes which are potential loops (like Phis) to avoid endless loops.
192  */
193 static void fix_loops(ir_node *node)
194 {
195         int i, arity;
196         int changed;
197
198         assert(node_is_in_irgs_storage(env.irg, node));
199
200         if (irn_visited_else_mark(node))
201                 return;
202
203         changed = 0;
204         if (! is_Block(node)) {
205                 ir_node *block     = get_nodes_block(node);
206                 ir_node *new_block = (ir_node*)get_irn_link(block);
207
208                 if (new_block != NULL) {
209                         set_nodes_block(node, new_block);
210                         block = new_block;
211                         changed = 1;
212                 }
213
214                 fix_loops(block);
215         }
216
217         arity = get_irn_arity(node);
218         for (i = 0; i < arity; ++i) {
219                 ir_node *in = get_irn_n(node, i);
220                 ir_node *nw = (ir_node*)get_irn_link(in);
221
222                 if (nw != NULL && nw != in) {
223                         set_irn_n(node, i, nw);
224                         in = nw;
225                         changed = 1;
226                 }
227
228                 fix_loops(in);
229         }
230         /* fix proj block */
231         if (is_Proj(node)) {
232                 set_nodes_block(node, get_nodes_block(get_Proj_pred(node)));
233                 changed = 1;
234         }
235
236         arity = get_irn_deps(node);
237         for (i = 0; i < arity; ++i) {
238                 ir_node *in = get_irn_dep(node, i);
239                 ir_node *nw = (ir_node*)get_irn_link(in);
240
241                 if (nw != NULL && nw != in) {
242                         set_irn_dep(node, i, nw);
243                         in = nw;
244                         changed = 1;
245                 }
246
247                 fix_loops(in);
248         }
249
250         if (changed) {
251                 identify_remember(node);
252         }
253 }
254
255 ir_node *be_pre_transform_node(ir_node *place)
256 {
257         if (place == NULL)
258                 return NULL;
259
260         return be_transform_node(place);
261 }
262
263 static void pre_transform_anchor(int anchor)
264 {
265         ir_node *old_anchor_node = get_irn_n(env.old_anchor, anchor);
266         ir_node *transformed     = be_transform_node(old_anchor_node);
267         set_irg_anchor(current_ir_graph, anchor, transformed);
268 }
269
270 static void kill_unused_anchor(int anchor)
271 {
272         ir_node *old_anchor_node = get_irn_n(env.old_anchor, anchor);
273         ir_node *old_bad         = get_irn_n(env.old_anchor, anchor_bad);
274         if (old_anchor_node != NULL && get_irn_n_edges(old_anchor_node) <= 1) {
275                 set_irn_n(env.old_anchor, anchor, old_bad);
276         }
277 }
278
279 static ir_node *new_be_Anchor(ir_graph *irg)
280 {
281         struct obstack *obst = be_get_be_obst(irg);
282         backend_info_t *info;
283         ir_node        *new_anchor;
284
285         /* Hack: some places in the code ask the Anchor for its register
286            requirements */
287         new_anchor = new_r_Anchor(irg);
288         info = be_get_info(new_anchor);
289         info->out_infos = NEW_ARR_D(reg_out_info_t, obst, 1);
290         memset(info->out_infos, 0, 1 * sizeof(info->out_infos[0]));
291         info->out_infos[0].req = arch_no_register_req;
292
293         return new_anchor;
294 }
295
296 /**
297  * Transforms all nodes. Deletes the old obstack and creates a new one.
298  */
299 static void transform_nodes(ir_graph *irg, arch_pretrans_nodes *pre_transform)
300 {
301         int       i;
302         ir_node  *old_end, *new_anchor;
303
304         hook_dead_node_elim(irg, 1);
305
306         inc_irg_visited(irg);
307
308         env.irg         = irg;
309         env.worklist    = new_waitq();
310         env.old_anchor  = irg->anchor;
311
312         old_end = get_irg_end(irg);
313
314         /* put all anchor nodes in the worklist */
315         for (i = get_irg_n_anchors(irg) - 1; i >= 0; --i) {
316                 ir_node *anchor = get_irg_anchor(irg, i);
317
318                 if (anchor == NULL)
319                         continue;
320                 waitq_put(env.worklist, anchor);
321         }
322
323         new_anchor  = new_be_Anchor(irg);
324         irg->anchor = new_anchor;
325
326         /* pre transform some anchors (so they are available in the other transform
327          * functions) */
328         pre_transform_anchor(anchor_bad);
329         pre_transform_anchor(anchor_no_mem);
330         pre_transform_anchor(anchor_start_block);
331         pre_transform_anchor(anchor_start);
332         pre_transform_anchor(anchor_frame);
333         kill_unused_anchor(anchor_tls);
334
335         if (pre_transform)
336                 pre_transform();
337
338         /* process worklist (this should transform all nodes in the graph) */
339         while (! waitq_empty(env.worklist)) {
340                 ir_node *node = (ir_node*)waitq_get(env.worklist);
341                 be_transform_node(node);
342         }
343
344         /* let beabi grab new nodes */
345         be_abi_transform_fixup(irg);
346         assert(waitq_empty(env.worklist)); // let's hope this didn't trigger new transforms
347
348         /* fix loops and set new anchors*/
349         inc_irg_visited(irg);
350         for (i = get_irg_n_anchors(irg) - 1; i >= 0; --i) {
351                 ir_node *anchor = get_irn_n(env.old_anchor, i);
352
353                 if (anchor == NULL)
354                         continue;
355
356                 anchor = (ir_node*)get_irn_link(anchor);
357                 fix_loops(anchor);
358                 set_irn_n(new_anchor, i, anchor);
359         }
360
361         del_waitq(env.worklist);
362         free_End(old_end);
363         hook_dead_node_elim(irg, 0);
364 }
365
366 /**
367  * Transform helper for blocks.
368  */
369 static ir_node *gen_Block(ir_node *node)
370 {
371         ir_graph *irg             = current_ir_graph;
372         dbg_info *dbgi            = get_irn_dbg_info(node);
373         ir_node  *block;
374
375         block = new_ir_node(dbgi, irg, NULL, get_irn_op(node), get_irn_mode(node),
376                             get_irn_arity(node), get_irn_in(node) + 1);
377         copy_node_attr(irg, node, block);
378         block->node_nr = node->node_nr;
379
380         /* put the preds in the worklist */
381         be_enqueue_preds(node);
382
383         return block;
384 }
385
386 static ir_node *gen_End(ir_node *node)
387 {
388         /* end has to be duplicated manually because we need a dynamic in array */
389         ir_graph *irg   = current_ir_graph;
390         dbg_info *dbgi  = get_irn_dbg_info(node);
391         ir_node  *block = be_transform_node(get_nodes_block(node));
392         int      i, arity;
393         ir_node  *new_end;
394
395         new_end = new_ir_node(dbgi, irg, block, op_End, mode_X, -1, NULL);
396         copy_node_attr(irg, node, new_end);
397         be_duplicate_deps(node, new_end);
398
399         set_irg_end(irg, new_end);
400
401         /* transform preds */
402         arity = get_irn_arity(node);
403         for (i = 0; i < arity; ++i) {
404                 ir_node *in     = get_irn_n(node, i);
405                 ir_node *new_in = be_transform_node(in);
406
407                 add_End_keepalive(new_end, new_in);
408         }
409
410         return new_end;
411 }
412
413 void be_transform_graph(ir_graph *irg, arch_pretrans_nodes *func)
414 {
415         ir_graph *old_current_ir_graph = current_ir_graph;
416         struct obstack *old_obst = NULL;
417         struct obstack *new_obst = NULL;
418
419         current_ir_graph = irg;
420
421         /* create a new obstack */
422         old_obst = irg->obst;
423         new_obst = XMALLOC(struct obstack);
424         obstack_init(new_obst);
425         irg->obst = new_obst;
426         irg->last_node_idx = 0;
427
428         /* invalidate phase info as (at least vrp info) is used inside the
429          * equivalent/compute_value functions and might replace our newly
430          * created nodes with middleend nodes */
431         irg_invalidate_phases(irg);
432
433         /* create new value table for CSE */
434         new_identities(irg);
435
436         /* enter special helper */
437         op_Block->ops.generic = (op_func)gen_Block;
438         op_End->ops.generic   = (op_func)gen_End;
439
440         /* do the main transformation */
441         transform_nodes(irg, func);
442
443         /* free the old obstack */
444         obstack_free(old_obst, 0);
445         xfree(old_obst);
446
447         /* restore state */
448         current_ir_graph = old_current_ir_graph;
449
450         /* most analysis info is wrong after transformation */
451         free_callee_info(irg);
452         free_irg_outs(irg);
453         free_trouts();
454         free_loop_information(irg);
455         set_irg_doms_inconsistent(irg);
456
457         be_liveness_invalidate(be_get_irg_liveness(irg));
458         /* Hack for now, something is buggy with invalidate liveness... */
459         be_birg_from_irg(irg)->lv = NULL;
460         be_invalidate_dom_front(irg);
461
462         /* recalculate edges */
463         edges_deactivate(irg);
464         edges_activate(irg);
465 }
466
467 int be_mux_is_abs(ir_node *sel, ir_node *mux_true, ir_node *mux_false)
468 {
469         ir_node    *cmp_left;
470         ir_node    *cmp_right;
471         ir_mode    *mode;
472         ir_relation relation;
473
474         if (!is_Cmp(sel))
475                 return 0;
476
477         /**
478          * Note further that these optimization work even for floating point
479          * with NaN's because -NaN == NaN.
480          * However, if +0 and -0 is handled differently, we cannot use the Abs/-Abs
481          * transformations.
482          */
483         mode = get_irn_mode(mux_true);
484         if (mode_honor_signed_zeros(mode))
485                 return 0;
486
487         /* must be <, <=, >=, > */
488         relation = get_Cmp_relation(sel);
489         if ((relation & ir_relation_less_greater) == 0)
490                 return 0;
491
492         if (!ir_is_negated_value(mux_true, mux_false))
493                 return 0;
494
495         /* must be x cmp 0 */
496         cmp_right = get_Cmp_right(sel);
497         if (!is_Const(cmp_right) || !is_Const_null(cmp_right))
498                 return 0;
499
500         cmp_left = get_Cmp_left(sel);
501         if (cmp_left == mux_false) {
502                 if (relation & ir_relation_less) {
503                         return 1;
504                 } else {
505                         assert(relation & ir_relation_greater);
506                         return -1;
507                 }
508         } else if (cmp_left == mux_true) {
509                 if (relation & ir_relation_less) {
510                         return -1;
511                 } else {
512                         assert(relation & ir_relation_greater);
513                         return 1;
514                 }
515         }
516
517         return 0;
518 }
519
520 ir_node *be_get_abs_op(ir_node *sel)
521 {
522         ir_node *cmp_left = get_Cmp_left(sel);
523         return cmp_left;
524 }