#include "config.h"
#endif
+#ifdef HAVE_STRING_H
#include <string.h>
+#endif
+
+#include <stdlib.h>
#include "irloop_t.h"
This reduces the depth of the loop tree. */
#define NO_LOOPS_WITHOUT_HEAD 1
-
-INLINE void add_loop_son(ir_loop *loop, ir_loop *son);
-
-INLINE void add_loop_node(ir_loop *loop, ir_node *n);
-
static ir_graph *outermost_ir_graph; /* The outermost graph the scc is computed
for */
static ir_loop *current_loop; /* Current loop construction is working
static INLINE void
mark_irn_in_stack (ir_node *n) {
- assert(get_irn_link(n));
- /* to slow */
- /* ((scc_info *)get_irn_link(n))->in_stack = true; */
- ((scc_info *)n->link)->in_stack = true;
+ scc_info *scc = get_irn_link(n);
+ assert(scc);
+ scc->in_stack = true;
}
static INLINE void
mark_irn_not_in_stack (ir_node *n) {
- assert(get_irn_link(n));
- /* to slow */
- /* ((scc_info *)get_irn_link(n))->in_stack = false; */
- ((scc_info *)n->link)->in_stack = false;
+ scc_info *scc = get_irn_link(n);
+ assert(scc);
+ scc->in_stack = false;
}
static INLINE bool
irn_is_in_stack (ir_node *n) {
- assert(get_irn_link(n));
- /* to slow */
- /* return ((scc_info *)get_irn_link(n))->in_stack; */
- return ((scc_info *)n->link)->in_stack;
+ scc_info *scc = get_irn_link(n);
+ assert(scc);
+ return scc->in_stack;
}
static INLINE void
set_irn_uplink (ir_node *n, int uplink) {
- assert(get_irn_link(n));
- /* to slow */
- /* ((scc_info *)get_irn_link(n))->uplink = uplink; */
- ((scc_info *)n->link)->uplink = uplink;
+ scc_info *scc = get_irn_link(n);
+ assert(scc);
+ scc->uplink = uplink;
}
-INLINE int
+int
get_irn_uplink (ir_node *n) {
- assert(get_irn_link(n));
- /* from fast to slow */
- /* return ((scc_info *)get_irn_link(n))->uplink; */
- return ((scc_info *)n->link)->uplink;
+ scc_info *scc = get_irn_link(n);
+ assert(scc);
+ return scc->uplink;
}
static INLINE void
set_irn_dfn (ir_node *n, int dfn) {
- assert(get_irn_link(n));
- /* to slow */
- /* ((scc_info *)get_irn_link(n))->dfn = dfn; */
- ((scc_info *)n->link)->dfn = dfn;
+ scc_info *scc = get_irn_link(n);
+ assert(scc);
+ scc->dfn = dfn;
}
-INLINE int
+int
get_irn_dfn (ir_node *n) {
- assert(get_irn_link(n));
- /* to slow */
- /* return ((scc_info *)get_irn_link(n))->dfn; */
- return ((scc_info *)n->link)->dfn;
+ scc_info *scc = get_irn_link(n);
+ assert(scc);
+ return scc->dfn;
}
-INLINE void
-set_irn_loop (ir_node *n, ir_loop* loop) {
+void
+set_irn_loop (ir_node *n, ir_loop *loop) {
n->loop = loop;
}
/* Uses temporary information to get the loop */
-INLINE ir_loop *
+ir_loop *
get_irn_loop (ir_node *n) {
return n->loop;
}
static ir_node **stack = NULL;
static int tos = 0; /* top of stack */
+/**
+ * initializes the stack
+ */
static INLINE void init_stack(void) {
if (stack) {
ARR_RESIZE (ir_node *, stack, 1000);
}
#endif
+/**
+ * push a node onto the stack
+ *
+ * @param n The node to push
+ */
static INLINE void
push (ir_node *n)
{
mark_irn_in_stack(n);
}
+/**
+ * pop a node from the stack
+ *
+ * @return The topmost node
+ */
static INLINE ir_node *
pop (void)
{
return n;
}
-/* The nodes up to n belong to the current loop.
- Removes them from the stack and adds them to the current loop. */
+/**
+ * The nodes up to n belong to the current loop.
+ * Removes them from the stack and adds them to the current loop.
+ */
static INLINE void
pop_scc_to_loop (ir_node *n)
{
add_loop_node(current_loop, m);
set_irn_loop(m, current_loop);
i++;
+
/* if (m==n) break;*/
} while(m != n);
ir_loop *last_son = lelement.son;
if (get_kind(last_son) == k_ir_loop &&
- get_loop_n_elements(last_son) == 1)
- {
- ir_loop *gson;
+ get_loop_n_elements(last_son) == 1) {
+ ir_loop *gson;
- lelement = get_loop_element(last_son, 0);
- gson = lelement.son;
- if(get_kind(gson) == k_ir_loop)
- {
- loop_element new_last_son;
+ lelement = get_loop_element(last_son, 0);
+ gson = lelement.son;
- gson -> outer_loop = l;
- new_last_son.son = gson;
- l -> children[last] = new_last_son;
- }
+ if (get_kind(gson) == k_ir_loop) {
+ loop_element new_last_son;
+
+ gson->outer_loop = l;
+ new_last_son.son = gson;
+ l->children[last] = new_last_son;
}
+ }
current_loop = l;
}
/* Use EXCLUSIVELY this function to add sons, otherwise the loop->n_sons
is invalid! */
-INLINE void
+void
add_loop_son(ir_loop *loop, ir_loop *son) {
loop_element lson;
lson.son = son;
/* Use EXCLUSIVELY this function to add nodes, otherwise the loop->n_nodes
is invalid! */
-INLINE void
+void
add_loop_node(ir_loop *loop, ir_node *n) {
loop_element ln;
ln.node = n;
#endif
/* Test for legal loop header: Block, Phi, ... */
-INLINE static bool is_possible_loop_head(ir_node *n) {
+static INLINE bool is_possible_loop_head(ir_node *n) {
ir_op *op = get_irn_op(n);
return ((op == op_Block) ||
(op == op_Phi) ||
#endif
-INLINE static int
+static INLINE int
is_outermost_loop(ir_loop *l) {
return l == get_loop_outer_loop(l);
}
dump_loop(l, "-ha");
}
- if (get_loop_loop_nr(l) == 11819)
- dump_loop(l, "-ha-debug");
-
return found_problem;
}
if (found_problem) exit(0);
}
+
+/* ------------------------------------------------------------------- */
+/* Simple analyses based on the loop information */
+/* ------------------------------------------------------------------- */
+
+int is_loop_variant(ir_loop *l, ir_loop *b) {
+ int i, n_elems;
+
+ if (l == b) return true;
+
+ n_elems = get_loop_n_elements(l);
+ for (i = 0; i < n_elems; ++i) {
+ loop_element e = get_loop_element(l, i);
+ if (is_ir_loop(e.kind))
+ if (is_loop_variant(e.son, b))
+ return true;
+ }
+
+ return false;
+}
+
+/* Test whether a value is loop invariant.
+ *
+ * @param n The node to be tested.
+ * @param block A block node. We pass the block, not the loop as we must
+ * start off with a block loop to find all proper uses.
+ *
+ * Returns true, if the node n is not changed in the loop block
+ * belongs to or in inner loops of this blocks loop. */
+int is_loop_invariant(ir_node *n, ir_node *block) {
+ ir_loop *l = get_irn_loop(block);
+ ir_node *b = (is_Block(n)) ? n : get_nodes_block(n);
+ return !is_loop_variant(l, get_irn_loop(b));
+}