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