summaryrefslogtreecommitdiffhomepage
path: root/ir/opt
diff options
context:
space:
mode:
authorElias Aebi <elias.aebi@student.kit.edu>2018-02-06 11:02:03 +0100
committerJohannes Bucher <johannes.bucher2@student.kit.edu>2019-01-24 17:42:00 +0100
commitb7079aeef61af00d9e29c8721fc48e9c8ea719ec (patch)
tree677b07589943e04d7626e65aaf8af30644d1dca9 /ir/opt
parent03a6b4c91fe8f68264c59012c49068462afe994a (diff)
WIP loop unrolling
Diffstat (limited to 'ir/opt')
-rw-r--r--ir/opt/loop2.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/ir/opt/loop2.c b/ir/opt/loop2.c
index 98f0663..0bbb8ca 100644
--- a/ir/opt/loop2.c
+++ b/ir/opt/loop2.c
@@ -1,6 +1,103 @@
#include "lcssa_t.h"
+#include "irtools.h"
+#include <assert.h>
+
+static void duplicate_node(ir_node *const node, ir_node *const new_block)
+{
+ ir_printf("duplicate node %n (%d)\n", node, get_irn_node_nr(node));
+ //int const opt = get_optimize();
+ //set_optimize(0);
+ ir_node *const new_node = exact_copy(node);
+ //set_optimize(opt);
+ set_nodes_block(new_node, new_block);
+ set_irn_link(node, new_node);
+ printf("new node %ld\n", get_irn_node_nr(new_node));
+}
+
+static void rewire_node(ir_node *const node)
+{
+ ir_node *const new_node = get_irn_link(node);
+ assert(get_irn_arity(node) == get_irn_arity(new_node));
+ // TODO: use foreach_irn_in
+ int const arity = get_irn_arity(new_node);
+ for (int i = 0; i < arity; ++i) {
+ ir_node *const pred = get_irn_n(new_node, i);
+ ir_node *const new_pred = get_irn_link(pred);
+ if (is_backedge(node, i)) {
+ assert(new_pred != NULL);
+ set_irn_n(node, i, new_pred);
+ }
+ else if (new_pred != NULL) {
+ set_irn_n(new_node, i, new_pred);
+ }
+ }
+}
+
+static void duplicate_block(ir_node *const block)
+{
+ ir_node *const new_block = exact_copy(block);
+ unsigned int const n_outs = get_irn_n_outs(block);
+ for (unsigned int i = 0; i < n_outs; ++i) {
+ ir_node *const node = get_irn_out(block, i);
+ assert(!is_Block(node));
+ duplicate_node(node, new_block);
+ }
+}
+
+static void rewire_block(ir_node *const block)
+{
+ rewire_node(block);
+ unsigned int const n_outs = get_irn_n_outs(block);
+ for (unsigned int i = 0; i < n_outs; ++i) {
+ ir_node *const node = get_irn_out(block, i);
+ assert(!is_Block(node));
+ rewire_node(node);
+ }
+}
+
+static void duplicate_loop(ir_loop *const loop)
+{
+ printf("duplicating loop\n");
+ size_t const n_elements = get_loop_n_elements(loop);
+ // step 1: duplicate blocks
+ for (size_t i = 0; i < n_elements; ++i) {
+ loop_element const element = get_loop_element(loop, i);
+ if (*element.kind == k_ir_node) {
+ assert(is_Block(element.node));
+ duplicate_block(element.node);
+ }
+ }
+ // step 2: rewire the edges
+ for (size_t i = 0; i < n_elements; ++i) {
+ loop_element const element = get_loop_element(loop, i);
+ if (*element.kind == k_ir_node) {
+ assert(is_Block(element.node));
+ rewire_block(element.node);
+ }
+ }
+}
+
+// duplicate one innermost loop, for testing purposes
+static void duplicate_one_loop(ir_loop *const loop)
+{
+ size_t const n_elements = get_loop_n_elements(loop);
+ for (size_t i = 0; i < n_elements; ++i) {
+ loop_element const element = get_loop_element(loop, i);
+ if (*element.kind == k_ir_loop) {
+ duplicate_one_loop(element.son);
+ return;
+ }
+ }
+ duplicate_loop(loop);
+}
void do_loop_unrolling2(ir_graph *const irg)
{
assure_lcssa(irg);
+ assure_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_LOOPINFO | IR_GRAPH_PROPERTY_CONSISTENT_OUTS);
+ ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK);
+ irg_walk_graph(irg, firm_clear_link, NULL, NULL);
+ duplicate_one_loop(get_irg_loop(irg));
+ ir_free_resources(irg, IR_RESOURCE_IRN_LINK);
+ dump_ir_graph(irg, "loop-unrolling");
}