return res;
}
+bool only_used_by_keepalive(const ir_node *node)
+{
+ foreach_out_edge(node, edge) {
+ ir_node *succ = get_edge_src_irn(edge);
+ if (is_End(succ))
+ continue;
+ if (is_Proj(succ) && only_used_by_keepalive(succ))
+ return true;
+ /* found a real user */
+ return false;
+ }
+ return true;
+}
+
/* include generated code */
#include "gen_irnode.c.inl"
/** initialize ir_node module */
void init_irnode(void);
+/**
+ * because firm keepalive edges are a broken concept, we have to make sure that
+ * nodes which are only held by a keepalive edges are never moved again.
+ * This function returns true in this case.
+ */
+bool only_used_by_keepalive(const ir_node *node);
+
/* this section MUST contain all inline functions */
#define is_ir_node(thing) is_ir_node_(thing)
#define get_irn_arity(node) get_irn_arity_(node)
if (!block_dominates(block_a, block_b)
&& !block_dominates(block_b, block_a))
return 1;
+ /* respect the workaround rule: do not move nodes which are only
+ * held by keepalive edges */
+ if (only_used_by_keepalive(a) || only_used_by_keepalive(b))
+ return 1;
}
}
return get_Block_dom_depth(block) >= 0;
}
-/**
- * Firm keepalive edges are broken (the user should really be the endless loop
- * and not the End node.) This wrong place of the user will lead to wrong
- * results in place_early()/place_late(). We work around these problems by not
- * moving nodes which just have keepalive edges as their users (or no users at
- * all)
- */
-static bool float_exceptions(const ir_node *node)
-{
- foreach_out_edge(node, edge) {
- ir_node *succ = get_edge_src_irn(edge);
- if (is_End(succ))
- continue;
- /* found a real user */
- return false;
- }
- return true;
-}
-
/**
* Find the earliest correct block for node n. --- Place n into the
* same Block as its dominance-deepest Input.
* This works because in firm each cycle contains a Phi or Block node
* (which are pinned)
*/
- if (get_irn_pinned(n) != op_pin_state_floats || float_exceptions(n)) {
+ if (get_irn_pinned(n) != op_pin_state_floats || only_used_by_keepalive(n)) {
/* we can't move pinned nodes */
arity = get_irn_arity(n);
for (i = 0; i < arity; ++i) {
dca = consumer_dom_dca(dca, succ, node);
}
}
+ /* respect the keepalive rule: if our only user is a keepalive, then we must
+ * not move the node any further */
+ if (dca == NULL) {
+ assert(only_used_by_keepalive(node));
+ return get_nodes_block(node);
+ }
+
foreach_out_edge_kind(node, edge, EDGE_KIND_DEP) {
ir_node *succ = get_edge_src_irn(edge);
assert(is_block_reachable(get_nodes_block(succ)));