summaryrefslogtreecommitdiffhomepage
path: root/ir/ana/irloop.c
blob: 062d8d915543a7555b7c0ffce68f18673f20b4ed (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/*
 * This file is part of libFirm.
 * Copyright (C) 2012 University of Karlsruhe.
 */

/**
 * @file
 * @brief    Loop data structure and access functions -- private stuff.
 * @author   Goetz Lindenmaier
 * @date     7.2002
 */
#include "irloop_t.h"

#include "irprog_t.h"
#include <stdlib.h>

void add_loop_son(ir_loop *loop, ir_loop *son)
{
	assert(loop->kind == k_ir_loop);
	assert(get_kind(son) == k_ir_loop);
	loop_element lson;
	lson.son = son;
	ARR_APP1(loop_element, loop->children, lson);
}

void add_loop_node(ir_loop *loop, ir_node *n)
{
	assert(loop->kind == k_ir_loop);
	loop_element ln;
	ln.node = n;
	ARR_APP1(loop_element, loop->children, ln);
}

void add_loop_irg(ir_loop *loop, ir_graph *irg)
{
	assert(loop->kind == k_ir_loop);
	loop_element ln;
	ln.irg = irg;
	ARR_APP1(loop_element, loop->children, ln);
}

void mature_loops(ir_loop *loop, struct obstack *obst)
{
	loop_element *new_children = DUP_ARR_D(loop_element, obst, loop->children);
	DEL_ARR_F(loop->children);
	loop->children = new_children;

	/* mature child loops */
	for (size_t i = ARR_LEN(new_children); i-- > 0;) {
		loop_element child = new_children[i];

		if (*child.kind == k_ir_loop) {
			mature_loops(child.son, obst);
		}
	}
}

ir_loop *(get_loop_outer_loop)(const ir_loop *loop)
{
	return _get_loop_outer_loop(loop);
}

unsigned (get_loop_depth)(const ir_loop *loop)
{
	return _get_loop_depth(loop);
}

size_t get_loop_n_elements(const ir_loop *loop)
{
	assert(loop->kind == k_ir_loop);
	return ARR_LEN(loop->children);
}

loop_element get_loop_element(const ir_loop *loop, size_t pos)
{
	assert(loop->kind == k_ir_loop && pos < ARR_LEN(loop->children));
	return loop->children[pos];
}

void set_irn_loop(ir_node *n, ir_loop *loop)
{
	n->loop = loop;
}

ir_loop *(get_irn_loop)(const ir_node *n)
{
	return _get_irn_loop(n);
}

long get_loop_loop_nr(const ir_loop *loop)
{
	assert(loop->kind == k_ir_loop);
#ifdef DEBUG_libfirm
	return loop->loop_nr;
#else
	return (long)loop;
#endif
}

void set_loop_link(ir_loop *loop, void *link)
{
	assert(loop->kind == k_ir_loop);
	loop->link = link;
}

void *get_loop_link(const ir_loop *loop)
{
	assert(loop->kind == k_ir_loop);
	return loop->link;
}

void (set_irg_loop)(ir_graph *irg, ir_loop *loop)
{
	_set_irg_loop(irg, loop);
}

ir_loop *(get_irg_loop)(const ir_graph *irg)
{
	return _get_irg_loop(irg);
}

ir_loop *alloc_loop(ir_loop *father, struct obstack *obst)
{
	ir_loop *son = OALLOCZ(obst, ir_loop);
	son->kind     = k_ir_loop;
	son->children = NEW_ARR_F(loop_element, 0);
	son->link     = NULL;
	if (father) {
		son->outer_loop = father;
		add_loop_son(father, son);
		son->depth = father->depth + 1;
	} else {  /* The root loop */
		son->outer_loop = son;
		son->depth      = 0;
	}

#ifdef DEBUG_libfirm
	son->loop_nr = get_irp_new_node_nr();
#endif
	return son;
}

static bool is_loop_variant(ir_loop *l, ir_loop *b)
{
	if (l == b)
		return true;

	for (size_t i = 0, n_elems = get_loop_n_elements(l); i < n_elems; ++i) {
		loop_element e = get_loop_element(l, i);
		if (is_ir_loop(e.kind) && is_loop_variant(e.son, b))
			return true;
	}

	return false;
}

int is_loop_invariant(const ir_node *n, const ir_node *block)
{
	ir_loop       *const l = get_irn_loop(block);
	ir_node const *const b = get_block_const(n);
	return !is_loop_variant(l, get_irn_loop(b));
}