2 * This file is part of libFirm.
3 * Copyright (C) 2012 University of Karlsruhe.
8 * @brief be transform helper extracted from the ia32 backend.
9 * @author Matthias Braun, Michael Beck
18 #include "irgraph_t.h"
26 #include "execfreq_t.h"
30 #include "betranshlp.h"
34 typedef struct be_transform_env_t {
35 ir_graph *irg; /**< The irg, the node should be created in */
36 waitq *worklist; /**< worklist of nodes that still need to be
38 ir_node *old_anchor; /**< the old anchor node in the old irg */
42 static be_transform_env_t env;
44 void be_set_transformed_node(ir_node *old_node, ir_node *new_node)
46 set_irn_link(old_node, new_node);
47 mark_irn_visited(old_node);
50 int be_is_transformed(const ir_node *node)
52 return irn_visited(node);
55 static inline ir_node *be_get_transformed_node(ir_node *old_node)
57 if (irn_visited(old_node)) {
58 ir_node *new_node = (ir_node*)get_irn_link(old_node);
59 assert(new_node != NULL);
65 void be_duplicate_deps(ir_node *old_node, ir_node *new_node)
67 int deps = get_irn_deps(old_node);
68 for (int i = 0; i < deps; ++i) {
69 ir_node *dep = get_irn_dep(old_node, i);
70 ir_node *new_dep = be_transform_node(dep);
72 add_irn_dep(new_node, new_dep);
76 ir_node *be_transform_phi(ir_node *node, const arch_register_req_t *req)
78 ir_node *block = be_transform_node(get_nodes_block(node));
79 ir_graph *irg = get_Block_irg(block);
80 dbg_info *dbgi = get_irn_dbg_info(node);
82 /* phi nodes allow loops, so we use the old arguments for now
83 * and fix this later */
84 ir_node **ins = get_irn_in(node)+1;
85 int arity = get_irn_arity(node);
86 ir_mode *mode = req->cls != NULL ? req->cls->mode : get_irn_mode(node);
87 ir_node *phi = new_ir_node(dbgi, irg, block, op_Phi, mode, arity, ins);
88 copy_node_attr(irg, node, phi);
89 be_duplicate_deps(node, phi);
91 backend_info_t *info = be_get_info(phi);
92 struct obstack *obst = be_get_be_obst(irg);
93 info->in_reqs = OALLOCN(obst, const arch_register_req_t*, arity);
94 for (int i = 0; i < arity; ++i) {
95 info->in_reqs[i] = req;
98 arch_set_irn_register_req_out(phi, 0, req);
99 be_enqueue_preds(node);
104 void be_set_transform_function(ir_op *op, be_transform_func func)
106 /* shouldn't be assigned twice (except for exchanging the default
107 * be_duplicate_node entries) */
108 assert(op->ops.generic == NULL
109 || op->ops.generic == (op_func) be_duplicate_node);
110 op->ops.generic = (op_func) func;
114 * Transform helper for blocks.
116 static ir_node *transform_block(ir_node *node)
118 ir_graph *irg = get_irn_irg(node);
119 dbg_info *dbgi = get_irn_dbg_info(node);
120 ir_mode *mode = get_irn_mode(node);
121 ir_node *block = new_ir_node(dbgi, irg, NULL, get_irn_op(node), mode,
122 get_irn_arity(node), get_irn_in(node) + 1);
123 copy_node_attr(irg, node, block);
124 block->node_nr = node->node_nr;
126 /* transfer execfreq value */
127 double execfreq = get_block_execfreq(node);
128 set_block_execfreq(block, execfreq);
130 /* put the preds in the worklist */
131 be_enqueue_preds(node);
136 static ir_node *transform_end(ir_node *node)
138 /* end has to be duplicated manually because we need a dynamic in array */
139 ir_graph *irg = get_irn_irg(node);
140 dbg_info *dbgi = get_irn_dbg_info(node);
141 ir_node *block = be_transform_node(get_nodes_block(node));
142 ir_node *new_end = new_ir_node(dbgi, irg, block, op_End, mode_X, -1, NULL);
143 copy_node_attr(irg, node, new_end);
144 be_duplicate_deps(node, new_end);
146 set_irg_end(irg, new_end);
148 /* do not transform predecessors yet to keep the pre-transform
149 * phase from visiting all the graph */
150 int arity = get_irn_arity(node);
151 for (int i = 0; i < arity; ++i) {
152 ir_node *in = get_irn_n(node, i);
153 add_End_keepalive(new_end, in);
155 be_enqueue_preds(node);
160 ir_node *be_duplicate_node(ir_node *node)
162 ir_node *block = be_transform_node(get_nodes_block(node));
163 ir_graph *irg = env.irg;
164 dbg_info *dbgi = get_irn_dbg_info(node);
165 ir_mode *mode = get_irn_mode(node);
166 ir_op *op = get_irn_op(node);
169 int arity = get_irn_arity(node);
170 if (op->opar == oparity_dynamic) {
171 new_node = new_ir_node(dbgi, irg, block, op, mode, -1, NULL);
172 for (int i = 0; i < arity; ++i) {
173 ir_node *in = get_irn_n(node, i);
174 in = be_transform_node(in);
175 add_irn_n(new_node, in);
178 ir_node **ins = ALLOCAN(ir_node*, arity);
179 for (int i = 0; i < arity; ++i) {
180 ir_node *in = get_irn_n(node, i);
181 ins[i] = be_transform_node(in);
184 new_node = new_ir_node(dbgi, irg, block, op, mode, arity, ins);
187 copy_node_attr(irg, node, new_node);
188 be_duplicate_deps(node, new_node);
190 new_node->node_nr = node->node_nr;
194 ir_node *be_transform_node(ir_node *node)
196 ir_node *new_node = be_get_transformed_node(node);
197 if (new_node != NULL)
200 DEBUG_ONLY(be_set_transformed_node(node, NULL);)
202 ir_op *op = get_irn_op(node);
203 be_transform_func *transform = (be_transform_func *)op->ops.generic;
205 new_node = transform(node);
206 assert(new_node != NULL);
208 be_set_transformed_node(node, new_node);
212 void be_enqueue_preds(ir_node *node)
214 /* put the preds in the worklist */
215 int arity = get_irn_arity(node);
216 for (int i = 0; i < arity; ++i) {
217 ir_node *pred = get_irn_n(node, i);
218 pdeq_putr(env.worklist, pred);
223 * Rewire nodes which are potential loops (like Phis) to avoid endless loops.
225 static void fix_loops(ir_node *node)
227 assert(node_is_in_irgs_storage(env.irg, node));
229 if (irn_visited_else_mark(node))
232 bool changed = false;
233 if (! is_Block(node)) {
234 ir_node *block = get_nodes_block(node);
235 ir_node *new_block = (ir_node*)get_irn_link(block);
237 if (new_block != NULL) {
238 set_nodes_block(node, new_block);
246 int arity = get_irn_arity(node);
247 for (int i = 0; i < arity; ++i) {
248 ir_node *in = get_irn_n(node, i);
249 ir_node *nw = (ir_node*)get_irn_link(in);
251 if (nw != NULL && nw != in) {
252 set_irn_n(node, i, nw);
261 set_nodes_block(node, get_nodes_block(get_Proj_pred(node)));
265 arity = get_irn_deps(node);
266 for (int i = 0; i < arity; ++i) {
267 ir_node *in = get_irn_dep(node, i);
268 ir_node *nw = (ir_node*)get_irn_link(in);
270 if (nw != NULL && nw != in) {
271 set_irn_dep(node, i, nw);
280 identify_remember(node);
284 ir_node *be_pre_transform_node(ir_node *place)
289 return be_transform_node(place);
292 static void pre_transform_anchor(ir_graph *irg, int anchor)
294 ir_node *old_anchor_node = get_irn_n(env.old_anchor, anchor);
295 ir_node *transformed = be_transform_node(old_anchor_node);
296 set_irg_anchor(irg, anchor, transformed);
300 * Transforms all nodes. Deletes the old obstack and creates a new one.
302 static void transform_nodes(ir_graph *irg, arch_pretrans_nodes *pre_transform)
304 hook_dead_node_elim(irg, 1);
306 inc_irg_visited(irg);
309 env.worklist = new_waitq();
310 env.old_anchor = irg->anchor;
312 ir_node *old_end = get_irg_end(irg);
314 /* put all anchor nodes in the worklist */
315 for (int i = get_irg_n_anchors(irg) - 1; i >= 0; --i) {
316 ir_node *anchor = get_irg_anchor(irg, i);
320 waitq_put(env.worklist, anchor);
323 ir_node *new_anchor = new_r_Anchor(irg);
324 irg->anchor = new_anchor;
326 /* pre transform some anchors (so they are available in the other transform
328 pre_transform_anchor(irg, anchor_no_mem);
329 pre_transform_anchor(irg, anchor_end_block);
330 pre_transform_anchor(irg, anchor_end);
331 pre_transform_anchor(irg, anchor_start_block);
332 pre_transform_anchor(irg, anchor_start);
333 pre_transform_anchor(irg, anchor_frame);
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);
344 /* fix loops and set new anchors*/
345 inc_irg_visited(irg);
346 for (int i = get_irg_n_anchors(irg) - 1; i >= 0; --i) {
347 ir_node *anchor = get_irn_n(env.old_anchor, i);
352 anchor = (ir_node*)get_irn_link(anchor);
354 set_irn_n(new_anchor, i, anchor);
357 del_waitq(env.worklist);
359 hook_dead_node_elim(irg, 0);
362 void be_transform_graph(ir_graph *irg, arch_pretrans_nodes *func)
364 ir_graph *old_current_ir_graph = current_ir_graph;
365 current_ir_graph = irg;
367 /* create a new obstack */
368 struct obstack old_obst = irg->obst;
369 obstack_init(&irg->obst);
370 irg->last_node_idx = 0;
374 /* create new value table for CSE */
377 /* do the main transformation */
378 transform_nodes(irg, func);
380 /* free the old obstack */
381 obstack_free(&old_obst, 0);
384 current_ir_graph = old_current_ir_graph;
386 /* most analysis info is wrong after transformation */
387 be_invalidate_live_chk(irg);
388 confirm_irg_properties(irg, IR_GRAPH_PROPERTIES_NONE);
390 /* recalculate edges */
394 bool be_upper_bits_clean(const ir_node *node, ir_mode *mode)
396 ir_op *op = get_irn_op(node);
397 if (op->ops.generic1 == NULL)
399 upper_bits_clean_func func = (upper_bits_clean_func)op->ops.generic1;
400 return func(node, mode);
403 static bool bit_binop_upper_bits_clean(const ir_node *node, ir_mode *mode)
405 return be_upper_bits_clean(get_binop_left(node), mode)
406 && be_upper_bits_clean(get_binop_right(node), mode);
409 static bool mux_upper_bits_clean(const ir_node *node, ir_mode *mode)
411 return be_upper_bits_clean(get_Mux_true(node), mode)
412 && be_upper_bits_clean(get_Mux_false(node), mode);
415 static bool and_upper_bits_clean(const ir_node *node, ir_mode *mode)
417 if (!mode_is_signed(mode)) {
418 return be_upper_bits_clean(get_And_left(node), mode)
419 || be_upper_bits_clean(get_And_right(node), mode);
421 return bit_binop_upper_bits_clean(node, mode);
425 static bool shr_upper_bits_clean(const ir_node *node, ir_mode *mode)
427 if (mode_is_signed(mode)) {
430 const ir_node *right = get_Shr_right(node);
431 if (is_Const(right)) {
432 ir_tarval *tv = get_Const_tarval(right);
433 long val = get_tarval_long(tv);
434 if (val >= 32 - (long)get_mode_size_bits(mode))
437 return be_upper_bits_clean(get_Shr_left(node), mode);
441 static bool shrs_upper_bits_clean(const ir_node *node, ir_mode *mode)
443 return be_upper_bits_clean(get_Shrs_left(node), mode);
446 static bool const_upper_bits_clean(const ir_node *node, ir_mode *mode)
448 ir_tarval *tv = get_Const_tarval(node);
449 long val = get_tarval_long(tv);
450 if (mode_is_signed(mode)) {
451 long shifted = val >> (get_mode_size_bits(mode)-1);
452 return shifted == 0 || shifted == -1;
454 unsigned long shifted = (unsigned long)val;
455 shifted >>= get_mode_size_bits(mode)-1;
461 static bool conv_upper_bits_clean(const ir_node *node, ir_mode *mode)
463 ir_mode *dest_mode = get_irn_mode(node);
464 const ir_node *op = get_Conv_op(node);
465 ir_mode *src_mode = get_irn_mode(op);
466 if (mode_is_float(src_mode))
469 unsigned src_bits = get_mode_size_bits(src_mode);
470 unsigned dest_bits = get_mode_size_bits(dest_mode);
471 /* downconvs are a nop */
472 if (src_bits >= dest_bits)
473 return be_upper_bits_clean(op, mode);
474 /* upconvs are fine if src is big enough or if sign matches */
475 if (src_bits <= get_mode_size_bits(mode)
476 && mode_is_signed(src_mode) == mode_is_signed(mode))
481 static bool proj_upper_bits_clean(const ir_node *node, ir_mode *mode)
483 const ir_node *pred = get_Proj_pred(node);
484 switch (get_irn_opcode(pred)) {
486 ir_mode *load_mode = get_Load_mode(pred);
487 unsigned load_bits = get_mode_size_bits(load_mode);
488 if (load_bits > get_mode_size_bits(mode))
490 if (mode_is_signed(load_mode) != mode_is_signed(mode))
500 void be_set_upper_bits_clean_function(ir_op *op, upper_bits_clean_func func)
502 op->ops.generic1 = (op_func)func;
505 void be_start_transform_setup(void)
507 ir_clear_opcodes_generic_func();
509 be_set_transform_function(op_Bad, be_duplicate_node);
510 be_set_transform_function(op_be_Copy, be_duplicate_node);
511 be_set_transform_function(op_be_CopyKeep, be_duplicate_node);
512 be_set_transform_function(op_be_IncSP, be_duplicate_node);
513 be_set_transform_function(op_be_Keep, be_duplicate_node);
514 be_set_transform_function(op_be_Return, be_duplicate_node);
515 be_set_transform_function(op_be_Start, be_duplicate_node);
516 be_set_transform_function(op_Block, transform_block);
517 be_set_transform_function(op_End, transform_end);
518 be_set_transform_function(op_NoMem, be_duplicate_node);
519 be_set_transform_function(op_Pin, be_duplicate_node);
520 be_set_transform_function(op_Start, be_duplicate_node);
521 be_set_transform_function(op_Sync, be_duplicate_node);
523 be_set_upper_bits_clean_function(op_And, and_upper_bits_clean);
524 be_set_upper_bits_clean_function(op_Const, const_upper_bits_clean);
525 be_set_upper_bits_clean_function(op_Conv, conv_upper_bits_clean);
526 be_set_upper_bits_clean_function(op_Eor, bit_binop_upper_bits_clean);
527 be_set_upper_bits_clean_function(op_Mux, mux_upper_bits_clean);
528 be_set_upper_bits_clean_function(op_Or, bit_binop_upper_bits_clean);
529 be_set_upper_bits_clean_function(op_Proj, proj_upper_bits_clean);
530 be_set_upper_bits_clean_function(op_Shr, shr_upper_bits_clean);
531 be_set_upper_bits_clean_function(op_Shrs, shrs_upper_bits_clean);