#include <string.h>
#endif
-# include "irnode_t.h"
-# include "irgraph_t.h"
-# include "iredges_t.h"
-# include "irmode_t.h"
-# include "iropt_t.h"
-# include "ircons_t.h"
-# include "irgmod.h"
-# include "irvrfy.h"
-# include "tv_t.h"
-# include "dbginfo_t.h"
-# include "iropt_dbg.h"
-# include "irflag_t.h"
-# include "irhooks.h"
-# include "irarch.h"
-# include "hashptr.h"
-# include "archop.h"
-# include "opt_polymorphy.h"
-# include "opt_confirms.h"
+#include "irnode_t.h"
+#include "irgraph_t.h"
+#include "iredges_t.h"
+#include "irmode_t.h"
+#include "iropt_t.h"
+#include "ircons_t.h"
+#include "irgmod.h"
+#include "irvrfy.h"
+#include "tv_t.h"
+#include "dbginfo_t.h"
+#include "iropt_dbg.h"
+#include "irflag_t.h"
+#include "irhooks.h"
+#include "irarch.h"
+#include "hashptr.h"
+#include "archop.h"
+#include "opt_polymorphy.h"
+#include "opt_confirms.h"
/* Make types visible to allow most efficient access */
# include "entity_t.h"
*/
tarval *computed_value(ir_node *n)
{
- if (n->op->computed_value)
- return n->op->computed_value(n);
+ if (n->op->ops.computed_value)
+ return n->op->ops.computed_value(n);
return tarval_bad;
}
/**
- * set the default computed_value evaluator
+ * set the default computed_value evaluator in an ir_op_ops.
+ *
+ * @param code the opcode for the default operation
+ * @param ops the operations initialized
+ *
+ * @return
+ * The operations.
*/
-static ir_op *firm_set_default_computed_value(ir_op *op)
+static ir_op_ops *firm_set_default_computed_value(opcode code, ir_op_ops *ops)
{
#define CASE(a) \
case iro_##a: \
- op->computed_value = computed_value_##a; \
+ ops->computed_value = computed_value_##a; \
break
- switch (op->code) {
+ switch (code) {
CASE(Const);
CASE(SymConst);
CASE(Add);
CASE(Mux);
CASE(Confirm);
default:
- op->computed_value = NULL;
+ /* leave NULL */;
}
- return op;
+ return ops;
#undef CASE
}
(get_irn_mode(get_Cond_selector(get_Proj_pred(a))) == mode_b)) {
/* Also a single entry Block following a single exit Block. Phis have
twice the same operand and will be optimized away. */
- n = get_nodes_block(a);
+ n = get_nodes_block(get_Proj_pred(a));
DBG_OPT_IFSIM1(oldn, a, b, n);
}
}
else if (get_opt_unreachable_code() &&
(n != current_ir_graph->start_block) &&
(n != current_ir_graph->end_block) ) {
- int i, n_cfg = get_Block_n_cfgpreds(n);
+ int i;
/* If all inputs are dead, this block is dead too, except if it is
- the start or end block. This is a step of unreachable code
+ the start or end block. This is one step of unreachable code
elimination */
- for (i = 0; i < n_cfg; i++) {
+ for (i = get_Block_n_cfgpreds(n) - 1; i >= 0; --i) {
ir_node *pred = get_Block_cfgpred(n, i);
ir_node *pred_blk;
break;
}
}
- if (i == n_cfg)
+ if (i < 0) {
n = set_Block_dead(n);
+ DBG_OPT_DEAD_BLOCK(oldn, n);
+ }
}
return n;
*/
static ir_node *equivalent_node_Jmp(ir_node *n)
{
- /* GL: Why not same for op_Raise?? */
/* unreachable code elimination */
if (is_Block_dead(get_nodes_block(n)))
n = new_Bad();
return n;
}
+/* Same for op_Raise */
+#define equivalent_node_Raise equivalent_node_Jmp
+
+
/* We do not evaluate Cond here as we replace it by a new node, a Jmp.
See transform_node_Proj_Cond(). */
/**
* Optimize an "idempotent unary op", ie op(op(n)) = n.
*
- * @fixme -(-a) == a, but might overflow two times.
- * We handle it anyway here but the better way would be a
- * flag. This would be needed for Pascal for instance.
+ * @todo
+ * -(-a) == a, but might overflow two times.
+ * We handle it anyway here but the better way would be a
+ * flag. This would be needed for Pascal for instance.
*/
static ir_node *equivalent_node_idempotent_unop(ir_node *n)
{
assert(0); /* This should not happen! */
n = new_Bad();
}
- } else if (get_irn_mode(n) == mode_X) {
+ }
+ else if (get_irn_mode(n) == mode_X) {
if (is_Block_dead(get_nodes_block(skip_Proj(n)))) {
/* Remove dead control flow -- early gigo(). */
n = new_Bad();
}
}
+
return n;
}
/**
* Remove Confirm nodes if setting is on.
+ * Replace Confirms(x, '=', Constlike) by Constlike.
*/
static ir_node *equivalent_node_Confirm(ir_node *n)
{
- if (get_Confirm_cmp(n) == pn_Cmp_Eq) {
+ ir_node *pred = get_Confirm_value(n);
+ pn_Cmp pnc = get_Confirm_cmp(n);
+
+ if (get_irn_op(pred) == op_Confirm && pnc == get_Confirm_cmp(pred)) {
+ /*
+ * rare case: two identical Confirms one after another,
+ * replace the second one with the first.
+ */
+ return pred;
+ }
+ if (pnc == pn_Cmp_Eq) {
ir_node *bound = get_Confirm_bound(n);
- ir_op *op = get_irn_op(bound);
/*
* Optimize a rare case:
- * Confirm(x, '=', Const) ==> Const
+ * Confirm(x, '=', Constlike) ==> Constlike
*/
- if (op == op_Const || op == op_SymConst)
+ if (is_irn_constlike(bound)) {
+ DBG_OPT_CONFIRM(n, bound);
return bound;
+ }
}
- return get_opt_remove_Confirm() ? get_Confirm_value(n) : n;
+ return get_opt_remove_confirm() ? get_Confirm_value(n) : n;
+}
+
+/**
+ * Optimize CopyB(mem, x, x) into a Nop
+ */
+static ir_node *equivalent_node_CopyB(ir_node *n)
+{
+ ir_node *a = get_CopyB_dst(n);
+ ir_node *b = get_CopyB_src(n);
+
+ if (a == b) {
+ /* Turn CopyB into a tuple (mem, bad, bad) */
+ ir_node *mem = get_CopyB_mem(n);
+ turn_into_tuple(n, pn_CopyB_max);
+ set_Tuple_pred(n, pn_CopyB_M, mem);
+ set_Tuple_pred(n, pn_CopyB_X_except, new_Bad()); /* no exception */
+ set_Tuple_pred(n, pn_Call_M_except, new_Bad());
+ }
+ return n;
}
/**
ir_node *
equivalent_node(ir_node *n)
{
- if (n->op->equivalent_node)
- return n->op->equivalent_node(n);
+ if (n->op->ops.equivalent_node)
+ return n->op->ops.equivalent_node(n);
return n;
}
/**
- * set the default equivalent node operation
+ * sets the default equivalent node operation for an ir_op_ops.
+ *
+ * @param code the opcode for the default operation
+ * @param ops the operations initialized
+ *
+ * @return
+ * The operations.
*/
-static ir_op *firm_set_default_equivalent_node(ir_op *op)
+static ir_op_ops *firm_set_default_equivalent_node(opcode code, ir_op_ops *ops)
{
#define CASE(a) \
case iro_##a: \
- op->equivalent_node = equivalent_node_##a; \
+ ops->equivalent_node = equivalent_node_##a; \
break
- switch (op->code) {
+ switch (code) {
CASE(Block);
CASE(Jmp);
+ CASE(Raise);
CASE(Or);
CASE(Add);
CASE(Eor);
CASE(Mux);
CASE(Cmp);
CASE(Confirm);
+ CASE(CopyB);
default:
- op->equivalent_node = NULL;
+ /* leave NULL */;
}
- return op;
+ return ops;
#undef CASE
}
/* Turn Div into a tuple (mem, bad, value) */
ir_node *mem = get_Div_mem(n);
- turn_into_tuple(n, 3);
+ turn_into_tuple(n, pn_Div_max);
set_Tuple_pred(n, pn_Div_M, mem);
set_Tuple_pred(n, pn_Div_X_except, new_Bad());
set_Tuple_pred(n, pn_Div_res, value);
}
/* We might generate an endless loop, so keep it alive. */
add_End_keepalive(get_irg_end(current_ir_graph), get_nodes_block(n));
- } else if ((ta != tarval_bad) &&
- (get_irn_mode(a) == mode_Iu) &&
- (get_Cond_kind(n) == dense) &&
- (get_opt_unreachable_code())) {
- /* I don't want to allow Tuples smaller than the biggest Proj.
- Also this tuple might get really big...
- I generate the Jmp here, and remember it in link. Link is used
- when optimizing Proj. */
- set_irn_link(n, new_r_Jmp(current_ir_graph, get_nodes_block(n)));
- /* We might generate an endless loop, so keep it alive. */
- add_End_keepalive(get_irg_end(current_ir_graph), get_nodes_block(n));
- } else if ((get_irn_op(a) == op_Eor)
- && (get_irn_mode(a) == mode_b)
- && (classify_tarval(value_of(get_Eor_right(a))) == TV_CLASSIFY_ONE)) {
- /* The Eor is a negate. Generate a new Cond without the negate,
- simulate the negate by exchanging the results. */
- set_irn_link(n, new_r_Cond(current_ir_graph, get_nodes_block(n),
- get_Eor_left(a)));
- } else if ((get_irn_op(a) == op_Not)
- && (get_irn_mode(a) == mode_b)) {
- /* A Not before the Cond. Generate a new Cond without the Not,
- simulate the Not by exchanging the results. */
- set_irn_link(n, new_r_Cond(current_ir_graph, get_nodes_block(n),
- get_Not_op(a)));
}
return n;
}
static ir_node *transform_node_Cast(ir_node *n) {
ir_node *oldn = n;
ir_node *pred = get_Cast_op(n);
- type *tp = get_irn_type(n);
+ ir_type *tp = get_irn_type(n);
if (get_irn_op(pred) == op_Const && get_Const_type(pred) != tp) {
n = new_rd_Const_type(NULL, current_ir_graph, get_irn_n(pred, -1), get_irn_mode(pred),
if (get_opt_unreachable_code()) {
ir_node *n = get_Proj_pred(proj);
ir_node *b = get_Cond_selector(n);
- tarval *tb = value_of(b);
- if (tb != tarval_bad && mode_is_int(get_tarval_mode(tb))) {
- /* we have a constant switch */
- long num = get_Proj_proj(proj);
+ if (mode_is_int(get_irn_mode(b))) {
+ tarval *tb = value_of(b);
- if (num != get_Cond_defaultProj(n)) { /* we cannot optimize default Proj's yet */
- if (get_tarval_long(tb) == num) {
- /* Do NOT create a jump here, or we will have 2 control flow ops
- * in a block. This case is optimized away in optimize_cf(). */
- return proj;
- }
- else {
- /* this case will NEVER be taken, kill it */
- return new_Bad();
+ if (tb != tarval_bad) {
+ /* we have a constant switch */
+ long num = get_Proj_proj(proj);
+
+ if (num != get_Cond_defaultProj(n)) { /* we cannot optimize default Proj's yet */
+ if (get_tarval_long(tb) == num) {
+ /* Do NOT create a jump here, or we will have 2 control flow ops
+ * in a block. This case is optimized away in optimize_cf(). */
+ return proj;
+ }
+ else {
+ /* this case will NEVER be taken, kill it */
+ return new_Bad();
+ }
}
}
}
*/
static ir_node *transform_node(ir_node *n)
{
- if (n->op->transform_node)
- n = n->op->transform_node(n);
+ if (n->op->ops.transform_node)
+ n = n->op->ops.transform_node(n);
return n;
}
/**
- * set the default transform node operation
+ * sSets the default transform node operation for an ir_op_ops.
+ *
+ * @param code the opcode for the default operation
+ * @param ops the operations initialized
+ *
+ * @return
+ * The operations.
*/
-static ir_op *firm_set_default_transform_node(ir_op *op)
+static ir_op_ops *firm_set_default_transform_node(opcode code, ir_op_ops *ops)
{
#define CASE(a) \
case iro_##a: \
- op->transform_node = transform_node_##a; \
+ ops->transform_node = transform_node_##a; \
break
- switch (op->code) {
+ switch (code) {
CASE(Add);
CASE(Sub);
CASE(Mul);
CASE(End);
CASE(Mux);
default:
- op->transform_node = NULL;
+ /* leave NULL */;
}
- return op;
+ return ops;
#undef CASE
}
}
/**
- * set the default node attribute compare operation
+ * Set the default node attribute compare operation for an ir_op_ops.
+ *
+ * @param code the opcode for the default operation
+ * @param ops the operations initialized
+ *
+ * @return
+ * The operations.
*/
-static ir_op *firm_set_default_node_cmp_attr(ir_op *op)
+static ir_op_ops *firm_set_default_node_cmp_attr(opcode code, ir_op_ops *ops)
{
-#define CASE(a) \
- case iro_##a: \
- op->node_cmp_attr = node_cmp_attr_##a; \
+#define CASE(a) \
+ case iro_##a: \
+ ops->node_cmp_attr = node_cmp_attr_##a; \
break
- switch (op->code) {
+ switch (code) {
CASE(Const);
CASE(Proj);
CASE(Filter);
CASE(Store);
CASE(Confirm);
default:
- op->node_cmp_attr = NULL;
+ /* leave NULL */;
}
- return op;
+ return ops;
#undef CASE
}
* here, we already now that the nodes are identical except their
* attributes
*/
- if (a->op->node_cmp_attr)
- return a->op->node_cmp_attr(a, b);
+ if (a->op->ops.node_cmp_attr)
+ return a->op->ops.node_cmp_attr(a, b);
return 0;
}
if (is_Block(block)) {
irn_arity = get_irn_arity(block);
for (i = 0; i < irn_arity; i++) {
- if (!is_Bad(get_irn_n(block, i))) break;
+ if (!is_Bad(get_irn_n(block, i)))
+ break;
}
if (i == irn_arity) return new_Bad();
}
return new_Bad();
for (i = 0; i < irn_arity; i++) {
- if (is_Bad(get_irn_n(node, i))) {
+ ir_node *pred = get_irn_n(node, i);
+
+ if (is_Bad(pred))
return new_Bad();
- }
+ if (is_Unknown(pred) && mode_is_data(get_irn_mode(node)))
+ return new_Unknown(get_irn_mode(node));
}
}
#if 0
* These optimizations deallocate nodes from the obstack.
* It can only be called if it is guaranteed that no other nodes
* reference this one, i.e., right after construction of a node.
+ *
+ * current_ir_graph must be set to the graph of the node!
*/
ir_node *
optimize_node(ir_node *n)
tv = computed_value(n);
if (tv != tarval_bad) {
ir_node *nw;
- type *old_tp = get_irn_type(n);
+ ir_type *old_tp = get_irn_type(n);
int i, arity = get_irn_arity(n);
int node_size;
tv = computed_value(n);
if (tv != tarval_bad) {
/* evaluation was successful -- replace the node. */
- type *old_tp = get_irn_type(n);
+ ir_type *old_tp = get_irn_type(n);
int i, arity = get_irn_arity(n);
/*
return optimize_in_place_2 (n);
}
-/**
- * set the default ir op operations
+/*
+ * Sets the default operation for an ir_ops.
*/
-ir_op *firm_set_default_operations(ir_op *op)
+ir_op_ops *firm_set_default_operations(opcode code, ir_op_ops *ops)
{
- op = firm_set_default_computed_value(op);
- op = firm_set_default_equivalent_node(op);
- op = firm_set_default_transform_node(op);
- op = firm_set_default_node_cmp_attr(op);
- op = firm_set_default_get_type(op);
+ ops = firm_set_default_computed_value(code, ops);
+ ops = firm_set_default_equivalent_node(code, ops);
+ ops = firm_set_default_transform_node(code, ops);
+ ops = firm_set_default_node_cmp_attr(code, ops);
+ ops = firm_set_default_get_type(code, ops);
+ ops = firm_set_default_get_type_attr(code, ops);
+ ops = firm_set_default_get_entity_attr(code, ops);
- return op;
+ return ops;
}