* @author Martin Trapp, Christian Schaefer, Goetz Lindenmaier, Michael Beck
* @version $Id$
*/
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "config.h"
-#ifdef HAVE_STRING_H
-# include <string.h>
-#endif
+#include <string.h>
+#include "pset_new.h"
#include "ident.h"
#include "irnode_t.h"
#include "irgraph_t.h"
#include "irhooks.h"
#include "irtools.h"
+#include "beinfo.h"
+
/* some constants fixing the positions of nodes predecessors
in the in array */
#define CALL_PARAM_OFFSET 2
char *p;
int i;
- assert(irg && op && mode);
+ assert(irg);
+ assert(op);
+ assert(mode);
p = obstack_alloc(irg->obst, node_size);
memset(p, 0, node_size);
res = (ir_node *)(p + firm_add_node_size);
edges_notify_edge(res, i - 1, res->in[i], NULL, irg);
hook_new_node(irg, res);
+ if (get_irg_phase_state(irg) == phase_backend) {
+ be_info_new_node(res);
+ }
return res;
}
int add_irn_dep(ir_node *node, ir_node *dep) {
int res = 0;
+ /* DEP edges are only allowed in backend phase */
+ assert(get_irg_phase_state(get_irn_irg(node)) == phase_backend);
if (node->deps == NULL) {
node->deps = NEW_ARR_F(ir_node *, 1);
node->deps[0] = dep;
return node->op->name;
}
-unsigned long (get_irn_visited)(const ir_node *node) {
+ir_visited_t (get_irn_visited)(const ir_node *node) {
return _get_irn_visited(node);
}
-void (set_irn_visited)(ir_node *node, unsigned long visited) {
+void (set_irn_visited)(ir_node *node, ir_visited_t visited) {
_set_irn_visited(node, visited);
}
_mark_irn_visited(node);
}
-int (irn_not_visited)(const ir_node *node) {
- return _irn_not_visited(node);
-}
-
int (irn_visited)(const ir_node *node) {
return _irn_visited(node);
}
+int (irn_visited_else_mark)(ir_node *node) {
+ return _irn_visited_else_mark(node);
+}
+
void (set_irn_link)(ir_node *node, void *link) {
_set_irn_link(node, link);
}
void set_irn_pinned(ir_node *node, op_pin_state state) {
/* due to optimization an opt may be turned into a Tuple */
- if (get_irn_op(node) == op_Tuple)
+ if (is_Tuple(node))
return;
assert(node && get_op_pinned(get_irn_op(node)) >= op_pin_state_exc_pinned);
node->attr.except.pin_state = state;
}
-#ifdef DO_HEAPANALYSIS
-/* Access the abstract interpretation information of a node.
- Returns NULL if no such information is available. */
-struct abstval *get_irn_abst_value(ir_node *n) {
- return n->av;
-}
-/* Set the abstract interpretation information of a node. */
-void set_irn_abst_value(ir_node *n, struct abstval *os) {
- n->av = os;
-}
-struct section *firm_get_irn_section(ir_node *n) {
- return n->sec;
-}
-void firm_set_irn_section(ir_node *n, struct section *s) {
- n->sec = s;
-}
-#else
-/* Dummies needed for firmjni. */
-struct abstval *get_irn_abst_value(ir_node *n) {
- (void) n;
- return NULL;
-}
-void set_irn_abst_value(ir_node *n, struct abstval *os) {
- (void) n;
- (void) os;
-}
-struct section *firm_get_irn_section(ir_node *n) {
- (void) n;
- return NULL;
-}
-void firm_set_irn_section(ir_node *n, struct section *s) {
- (void) n;
- (void) s;
-}
-#endif /* DO_HEAPANALYSIS */
-
-
/* Outputs a unique number for this node */
long get_irn_node_nr(const ir_node *node) {
assert(node);
node->attr.block.is_matured = matured;
}
-unsigned long (get_Block_block_visited)(const ir_node *node) {
+ir_visited_t (get_Block_block_visited)(const ir_node *node) {
return _get_Block_block_visited(node);
}
-void (set_Block_block_visited)(ir_node *node, unsigned long visit) {
+void (set_Block_block_visited)(ir_node *node, ir_visited_t visit) {
_set_Block_block_visited(node, visit);
}
_mark_Block_block_visited(node);
}
-int (Block_not_block_visited)(const ir_node *node) {
- return _Block_not_block_visited(node);
-}
-
int (Block_block_visited)(const ir_node *node) {
return _Block_block_visited(node);
}
void add_End_keepalive(ir_node *end, ir_node *ka) {
assert(is_End(end));
- assert((is_Phi(ka) || is_Proj(ka) || is_Block(ka) || is_irn_keep(ka)) && "Only Phi, Block or Keep nodes can be kept alive!");
add_irn_n(end, ka);
}
end->in[1 + END_KEEPALIVE_OFFSET + idx] = old;
edges_notify_edge(end, idx, old, NULL, irg);
}
+ /* now n - 1 keeps, 1 block input */
ARR_RESIZE(ir_node *, end->in, (n - 1) + 1 + END_KEEPALIVE_OFFSET);
}
-void
-free_End(ir_node *end) {
+/* remove Bads, NoMems and doublets from the keep-alive set */
+void remove_End_Bads_and_doublets(ir_node *end) {
+ pset_new_t keeps;
+ int idx, n = get_End_n_keepalives(end);
+ ir_graph *irg;
+
+ if (n <= 0)
+ return;
+
+ irg = get_irn_irg(end);
+ pset_new_init(&keeps);
+
+ for (idx = n - 1; idx >= 0; --idx) {
+ ir_node *ka = get_End_keepalive(end, idx);
+
+ if (is_Bad(ka) || is_NoMem(ka) || pset_new_contains(&keeps, ka)) {
+ /* remove the edge */
+ edges_notify_edge(end, idx, NULL, ka, irg);
+
+ if (idx != n - 1) {
+ /* exchange with the last one */
+ ir_node *old = end->in[1 + END_KEEPALIVE_OFFSET + n - 1];
+ edges_notify_edge(end, n - 1, NULL, old, irg);
+ end->in[1 + END_KEEPALIVE_OFFSET + idx] = old;
+ edges_notify_edge(end, idx, old, NULL, irg);
+ }
+ --n;
+ } else {
+ pset_new_insert(&keeps, ka);
+ }
+ }
+ /* n keeps, 1 block input */
+ ARR_RESIZE(ir_node *, end->in, n + 1 + END_KEEPALIVE_OFFSET);
+
+ pset_new_destroy(&keeps);
+}
+
+void free_End(ir_node *end) {
assert(is_End(end));
end->kind = k_BAD;
DEL_ARR_F(end->in);
}
ir_type *
-get_SymConst_type(ir_node *node) {
+get_SymConst_type(const ir_node *node) {
+ /* the cast here is annoying, but we have to compensate for
+ the skip_tip() */
+ ir_node *irn = (ir_node *)node;
assert(is_SymConst(node) &&
(SYMCONST_HAS_TYPE(get_SymConst_kind(node))));
- return node->attr.symc.sym.type_p = skip_tid(node->attr.symc.sym.type_p);
+ return irn->attr.symc.sym.type_p = skip_tid(irn->attr.symc.sym.type_p);
}
void
ir_node **
get_Call_param_arr(ir_node *node) {
assert(is_Call(node));
- return (ir_node **)&get_irn_in(node)[CALL_PARAM_OFFSET + 1];
+ return &get_irn_in(node)[CALL_PARAM_OFFSET + 1];
}
int
BINOP(Add)
+BINOP(Carry)
BINOP(Sub)
UNOP(Minus)
BINOP(Mul)
#endif /* INTERPROCEDURAL_VIEW */
}
+/* Returns non-zero if a node is a routine parameter. */
+int (is_arg_Proj)(const ir_node *node) {
+ return _is_arg_Proj(node);
+}
+
ir_node **
get_Tuple_preds_arr(ir_node *node) {
assert(is_Tuple(node));
/* Mux support */
ir_node *get_Mux_sel(const ir_node *node) {
- if (is_Psi(node)) {
- assert(get_irn_arity(node) == 3);
- return get_Psi_cond(node, 0);
- }
assert(is_Mux(node));
return node->in[1];
}
void set_Mux_sel(ir_node *node, ir_node *sel) {
- if (is_Psi(node)) {
- assert(get_irn_arity(node) == 3);
- set_Psi_cond(node, 0, sel);
- } else {
- assert(is_Mux(node));
- node->in[1] = sel;
- }
+ assert(is_Mux(node));
+ node->in[1] = sel;
}
ir_node *get_Mux_false(const ir_node *node) {
- if (is_Psi(node)) {
- assert(get_irn_arity(node) == 3);
- return get_Psi_default(node);
- }
assert(is_Mux(node));
return node->in[2];
}
void set_Mux_false(ir_node *node, ir_node *ir_false) {
- if (is_Psi(node)) {
- assert(get_irn_arity(node) == 3);
- set_Psi_default(node, ir_false);
- } else {
- assert(is_Mux(node));
- node->in[2] = ir_false;
- }
+ assert(is_Mux(node));
+ node->in[2] = ir_false;
}
ir_node *get_Mux_true(const ir_node *node) {
- if (is_Psi(node)) {
- assert(get_irn_arity(node) == 3);
- return get_Psi_val(node, 0);
- }
assert(is_Mux(node));
return node->in[3];
}
void set_Mux_true(ir_node *node, ir_node *ir_true) {
- if (is_Psi(node)) {
- assert(get_irn_arity(node) == 3);
- set_Psi_val(node, 0, ir_true);
- } else {
- assert(is_Mux(node));
- node->in[3] = ir_true;
- }
-}
-
-/* Psi support */
-ir_node *get_Psi_cond(const ir_node *node, int pos) {
- assert(is_Psi(node));
- assert(pos < get_Psi_n_conds(node));
- return get_irn_n(node, 2 * pos);
-}
-
-void set_Psi_cond(ir_node *node, int pos, ir_node *cond) {
- assert(is_Psi(node));
- assert(pos < get_Psi_n_conds(node));
- set_irn_n(node, 2 * pos, cond);
-}
-
-ir_node *get_Psi_val(const ir_node *node, int pos) {
- assert(is_Psi(node));
- assert(pos < get_Psi_n_conds(node));
- return get_irn_n(node, 2 * pos + 1);
-}
-
-void set_Psi_val(ir_node *node, int pos, ir_node *val) {
- assert(is_Psi(node));
- assert(pos < get_Psi_n_conds(node));
- set_irn_n(node, 2 * pos + 1, val);
-}
-
-ir_node *get_Psi_default(const ir_node *node) {
- int def_pos = get_irn_arity(node) - 1;
- assert(is_Psi(node));
- return get_irn_n(node, def_pos);
-}
-
-void set_Psi_default(ir_node *node, ir_node *val) {
- int def_pos = get_irn_arity(node);
- assert(is_Psi(node));
- set_irn_n(node, def_pos, val);
-}
-
-int (get_Psi_n_conds)(const ir_node *node) {
- return _get_Psi_n_conds(node);
+ assert(is_Mux(node));
+ node->in[3] = ir_true;
}
/* CopyB support */
node = get_irn_n(node, -1);
if (is_Bad(node)) /* sometimes bad is predecessor of nodes instead of block: in case of optimization */
node = get_irn_n(node, -1);
- assert(get_irn_op(node) == op_Block);
+ assert(is_Block(node));
return node->attr.block.irg;
}
/* returns operand of node if node is a Cast */
ir_node *skip_Cast(ir_node *node) {
- if (get_irn_op(node) == op_Cast)
+ if (is_Cast(node))
+ return get_Cast_op(node);
+ return node;
+}
+
+/* returns operand of node if node is a Cast */
+const ir_node *skip_Cast_const(const ir_node *node) {
+ if (is_Cast(node))
return get_Cast_op(node);
return node;
}
+/* returns operand of node if node is a Pin */
+ir_node *skip_Pin(ir_node *node) {
+ if (is_Pin(node))
+ return get_Pin_op(node);
+ return node;
+}
+
/* returns operand of node if node is a Confirm */
ir_node *skip_Confirm(ir_node *node) {
- if (get_irn_op(node) == op_Confirm)
+ if (is_Confirm(node))
return get_Confirm_value(node);
return node;
}
return _is_Add(node);
}
+int
+(is_Carry)(const ir_node *node) {
+ return _is_Carry(node);
+}
+
int
(is_And)(const ir_node *node) {
return _is_And(node);
return _is_Not(node);
}
-int
-(is_Psi)(const ir_node *node) {
- return _is_Psi(node);
-}
-
int
(is_Id)(const ir_node *node) {
return _is_Id(node);
return _is_Sel(node);
}
-/* returns true if node is a Mux node or a Psi with only one condition. */
+/* returns true if node is a Mux node. */
int
(is_Mux)(const ir_node *node) {
return _is_Mux(node);
}
#endif
-#ifdef DEBUG_libfirm
-void dump_irn(const ir_node *n) {
- int i, arity = get_irn_arity(n);
- printf("%s%s: %ld (%p)\n", get_irn_opname(n), get_mode_name(get_irn_mode(n)), get_irn_node_nr(n), (void *)n);
- if (!is_Block(n)) {
- ir_node *pred = get_irn_n(n, -1);
- printf(" block: %s%s: %ld (%p)\n", get_irn_opname(pred), get_mode_name(get_irn_mode(pred)),
- get_irn_node_nr(pred), (void *)pred);
- }
- printf(" preds: \n");
- for (i = 0; i < arity; ++i) {
- ir_node *pred = get_irn_n(n, i);
- printf(" %d: %s%s: %ld (%p)\n", i, get_irn_opname(pred), get_mode_name(get_irn_mode(pred)),
- get_irn_node_nr(pred), (void *)pred);
+/*
+ * Calculate a hash value of a node.
+ */
+unsigned firm_default_hash(const ir_node *node) {
+ unsigned h;
+ int i, irn_arity;
+
+ /* hash table value = 9*(9*(9*(9*(9*arity+in[0])+in[1])+ ...)+mode)+code */
+ h = irn_arity = get_irn_intra_arity(node);
+
+ /* consider all in nodes... except the block if not a control flow. */
+ for (i = is_cfop(node) ? -1 : 0; i < irn_arity; ++i) {
+ h = 9*h + HASH_PTR(get_irn_intra_n(node, i));
}
-}
-#else /* DEBUG_libfirm */
-void dump_irn(const ir_node *n) { (void) n; }
-#endif /* DEBUG_libfirm */
+ /* ...mode,... */
+ h = 9*h + HASH_PTR(get_irn_mode(node));
+ /* ...and code */
+ h = 9*h + HASH_PTR(get_irn_op(node));
+
+ return h;
+} /* firm_default_hash */