#include "debug.h"
#include "beirg.h"
+#include "beabi.h"
#include "betranshlp.h"
#include "belive.h"
#include "benode.h"
void be_set_transformed_node(ir_node *old_node, ir_node *new_node)
{
+ ir_graph *irg = get_irn_irg(old_node);
+
set_irn_link(old_node, new_node);
mark_irn_visited(old_node);
+ hook_dead_node_elim_subst(irg, old_node, new_node);
}
int be_is_transformed(const ir_node *node)
}
}
-void be_dep_on_frame(ir_node* node)
-{
- ir_graph *const irg = current_ir_graph;
-
- if (get_irg_start_block(irg) == get_nodes_block(node))
- add_irn_dep(node, get_irg_frame(irg));
-}
-
void be_set_transform_function(ir_op *op, be_transform_func func)
{
/* shouldn't be assigned twice (except for exchanging the default
op->ops.generic = (op_func) func;
}
+/**
+ * Transform helper for blocks.
+ */
+static ir_node *transform_block(ir_node *node)
+{
+ ir_graph *irg = get_irn_irg(node);
+ dbg_info *dbgi = get_irn_dbg_info(node);
+ ir_node *block;
+
+ block = new_ir_node(dbgi, irg, NULL, get_irn_op(node), get_irn_mode(node),
+ get_irn_arity(node), get_irn_in(node) + 1);
+ copy_node_attr(irg, node, block);
+ block->node_nr = node->node_nr;
+
+ /* put the preds in the worklist */
+ be_enqueue_preds(node);
+
+ return block;
+}
+
+static ir_node *transform_end(ir_node *node)
+{
+ /* end has to be duplicated manually because we need a dynamic in array */
+ ir_graph *irg = get_irn_irg(node);
+ dbg_info *dbgi = get_irn_dbg_info(node);
+ ir_node *block = be_transform_node(get_nodes_block(node));
+ int i, arity;
+ ir_node *new_end;
+
+ new_end = new_ir_node(dbgi, irg, block, op_End, mode_X, -1, NULL);
+ copy_node_attr(irg, node, new_end);
+ be_duplicate_deps(node, new_end);
+
+ set_irg_end(irg, new_end);
+
+ /* do not transform predecessors yet to keep the pre-transform
+ * phase from visiting all the graph */
+ arity = get_irn_arity(node);
+ for (i = 0; i < arity; ++i) {
+ ir_node *in = get_irn_n(node, i);
+ add_End_keepalive(new_end, in);
+ }
+ be_enqueue_preds(node);
+
+ return new_end;
+}
+
void be_start_transform_setup(void)
{
clear_irp_opcodes_generic_func();
be_set_transform_function(op_Bad, be_duplicate_node);
- be_set_transform_function(op_be_Barrier, be_duplicate_node);
be_set_transform_function(op_be_Copy, be_duplicate_node);
be_set_transform_function(op_be_CopyKeep, be_duplicate_node);
be_set_transform_function(op_be_IncSP, be_duplicate_node);
be_set_transform_function(op_be_Keep, be_duplicate_node);
be_set_transform_function(op_be_Return, be_duplicate_node);
be_set_transform_function(op_be_Start, be_duplicate_node);
+ be_set_transform_function(op_Block, transform_block);
+ be_set_transform_function(op_End, transform_end);
be_set_transform_function(op_NoMem, be_duplicate_node);
be_set_transform_function(op_Pin, be_duplicate_node);
be_set_transform_function(op_Start, be_duplicate_node);
assert(new_node != NULL);
be_set_transformed_node(node, new_node);
- hook_dead_node_elim_subst(current_ir_graph, node, new_node);
return new_node;
}
return be_transform_node(place);
}
-static void pre_transform_anchor(int anchor)
+static void pre_transform_anchor(ir_graph *irg, int anchor)
{
ir_node *old_anchor_node = get_irn_n(env.old_anchor, anchor);
ir_node *transformed = be_transform_node(old_anchor_node);
- set_irg_anchor(current_ir_graph, anchor, transformed);
-}
-
-static void kill_unused_anchor(int anchor)
-{
- ir_node *old_anchor_node = get_irn_n(env.old_anchor, anchor);
- ir_node *old_bad = get_irn_n(env.old_anchor, anchor_bad);
- if (old_anchor_node != NULL && get_irn_n_edges(old_anchor_node) <= 1) {
- set_irn_n(env.old_anchor, anchor, old_bad);
- }
-}
-
-static ir_node *new_be_Anchor(ir_graph *irg)
-{
- struct obstack *obst = be_get_be_obst(irg);
- backend_info_t *info;
- ir_node *new_anchor;
-
- /* Hack: some places in the code ask the Anchor for its register
- requirements */
- new_anchor = new_r_Anchor(irg);
- info = be_get_info(new_anchor);
- info->out_infos = NEW_ARR_D(reg_out_info_t, obst, 1);
- memset(info->out_infos, 0, 1 * sizeof(info->out_infos[0]));
- info->out_infos[0].req = arch_no_register_req;
-
- return new_anchor;
+ set_irg_anchor(irg, anchor, transformed);
}
/**
inc_irg_visited(irg);
- env.irg = irg;
- env.worklist = new_waitq();
- env.old_anchor = irg->anchor;
+ env.irg = irg;
+ env.worklist = new_waitq();
+ env.old_anchor = irg->anchor;
old_end = get_irg_end(irg);
waitq_put(env.worklist, anchor);
}
- new_anchor = new_be_Anchor(irg);
+ new_anchor = new_r_Anchor(irg);
irg->anchor = new_anchor;
/* pre transform some anchors (so they are available in the other transform
* functions) */
- pre_transform_anchor(anchor_bad);
- pre_transform_anchor(anchor_no_mem);
- pre_transform_anchor(anchor_start_block);
- pre_transform_anchor(anchor_start);
- pre_transform_anchor(anchor_frame);
- kill_unused_anchor(anchor_tls);
+ pre_transform_anchor(irg, anchor_no_mem);
+ pre_transform_anchor(irg, anchor_end_block);
+ pre_transform_anchor(irg, anchor_end);
+ pre_transform_anchor(irg, anchor_start_block);
+ pre_transform_anchor(irg, anchor_start);
+ pre_transform_anchor(irg, anchor_frame);
if (pre_transform)
pre_transform();
hook_dead_node_elim(irg, 0);
}
-/**
- * Transform helper for blocks.
- */
-static ir_node *gen_Block(ir_node *node)
-{
- ir_graph *irg = current_ir_graph;
- dbg_info *dbgi = get_irn_dbg_info(node);
- ir_node *block;
-
- block = new_ir_node(dbgi, irg, NULL, get_irn_op(node), get_irn_mode(node),
- get_irn_arity(node), get_irn_in(node) + 1);
- copy_node_attr(irg, node, block);
- block->node_nr = node->node_nr;
-
- /* put the preds in the worklist */
- be_enqueue_preds(node);
-
- return block;
-}
-
-static ir_node *gen_End(ir_node *node)
-{
- /* end has to be duplicated manually because we need a dynamic in array */
- ir_graph *irg = current_ir_graph;
- dbg_info *dbgi = get_irn_dbg_info(node);
- ir_node *block = be_transform_node(get_nodes_block(node));
- int i, arity;
- ir_node *new_end;
-
- new_end = new_ir_node(dbgi, irg, block, op_End, mode_X, -1, NULL);
- copy_node_attr(irg, node, new_end);
- be_duplicate_deps(node, new_end);
-
- set_irg_end(irg, new_end);
-
- /* transform preds */
- arity = get_irn_arity(node);
- for (i = 0; i < arity; ++i) {
- ir_node *in = get_irn_n(node, i);
- ir_node *new_in = be_transform_node(in);
-
- add_End_keepalive(new_end, new_in);
- }
-
- return new_end;
-}
-
void be_transform_graph(ir_graph *irg, arch_pretrans_nodes *func)
{
ir_graph *old_current_ir_graph = current_ir_graph;
/* create new value table for CSE */
new_identities(irg);
- /* enter special helper */
- op_Block->ops.generic = (op_func)gen_Block;
- op_End->ops.generic = (op_func)gen_End;
-
/* do the main transformation */
transform_nodes(irg, func);
edges_deactivate(irg);
edges_activate(irg);
}
-
-int be_mux_is_abs(ir_node *sel, ir_node *mux_true, ir_node *mux_false)
-{
- ir_node *cmp_left;
- ir_node *cmp_right;
- ir_mode *mode;
- ir_relation relation;
-
- if (!is_Cmp(sel))
- return 0;
-
- /**
- * Note further that these optimization work even for floating point
- * with NaN's because -NaN == NaN.
- * However, if +0 and -0 is handled differently, we cannot use the Abs/-Abs
- * transformations.
- */
- mode = get_irn_mode(mux_true);
- if (mode_honor_signed_zeros(mode))
- return 0;
-
- /* must be <, <=, >=, > */
- relation = get_Cmp_relation(sel);
- if ((relation & ir_relation_less_greater) == 0)
- return 0;
-
- if (!ir_is_negated_value(mux_true, mux_false))
- return 0;
-
- /* must be x cmp 0 */
- cmp_right = get_Cmp_right(sel);
- if (!is_Const(cmp_right) || !is_Const_null(cmp_right))
- return 0;
-
- cmp_left = get_Cmp_left(sel);
- if (cmp_left == mux_false) {
- if (relation & ir_relation_less) {
- return 1;
- } else {
- assert(relation & ir_relation_greater);
- return -1;
- }
- } else if (cmp_left == mux_true) {
- if (relation & ir_relation_less) {
- return -1;
- } else {
- assert(relation & ir_relation_greater);
- return 1;
- }
- }
-
- return 0;
-}
-
-ir_node *be_get_abs_op(ir_node *sel)
-{
- ir_node *cmp_left = get_Cmp_left(sel);
- return cmp_left;
-}