summaryrefslogtreecommitdiffhomepage
path: root/ir/ana/irbackedge.c
blob: 86ac780a6f5e1c263327dccc5292d90c3d515713 (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
/*
 * This file is part of libFirm.
 * Copyright (C) 2012 University of Karlsruhe.
 */

/**
 * @file
 * @brief     Access function for backedges.
 * @author    Goetz Lindenmaier
 * @date      7.2002
 */
#include "irbackedge_t.h"

#include "array.h"
#include "irgraph_t.h"
#include "irnode_t.h"

/*--------------------------------------------------------------------*/
/* Backedge information.                                              */
/*--------------------------------------------------------------------*/


/**
 * Returns backarray if the node can have backedges, else returns
 * NULL.
 *
 * Does not assert whether the backarray is correct -- use
 * very careful!
 */
static bitset_t *mere_get_backarray(const ir_node *n)
{
	switch (get_irn_opcode(n)) {
	case iro_Block:
		if (!get_Block_matured(n))
			return NULL;

		assert(n->attr.block.backedge != NULL);
		return n->attr.block.backedge;
	case iro_Phi:
		assert(n->attr.phi.u.backedge != NULL);
		return n->attr.phi.u.backedge;
	default:
		break;
	}
	return NULL;
}

/**
 * Returns backarray if the node can have backedges, else returns
 * NULL.
 */
static bitset_t *get_backarray(const ir_node *n)
{
	bitset_t *ba = mere_get_backarray(n);
#ifndef NDEBUG
	if (ba != NULL) {
		size_t bal = bitset_size(ba);  /* avoid macro expansion in assertion. */
		size_t inl = get_irn_arity(n);
		assert(bal == inl);
	}
#endif

	return ba;
}

#ifndef NDEBUG
/**
 * Returns non-zero if node has no backarray, or
 *                  if size of backarray == size of in array.
 */
static int legal_backarray(const ir_node *n)
{
	bitset_t *ba = mere_get_backarray(n);
	if (ba && (bitset_size(ba) != (unsigned) get_irn_arity(n)))
		return 0;
	return 1;
}
#endif

void fix_backedges(struct obstack *obst, ir_node *n)
{
	bitset_t *arr = mere_get_backarray(n);
	if (arr == NULL)
		return;

	int arity = get_irn_arity(n);
	if (bitset_size(arr) != (unsigned) arity) {
		arr = new_backedge_arr(obst, arity);

		unsigned opc = get_irn_opcode(n);
		if (opc == iro_Phi) {
			n->attr.phi.u.backedge = arr;
		} else if (opc == iro_Block) {
			n->attr.block.backedge = arr;
		}
	}

	assert(legal_backarray(n));
}

int is_backedge(const ir_node *n, int pos)
{
	bitset_t *ba = get_backarray(n);
	if (ba != NULL)
		return bitset_is_set(ba, pos);
	return 0;
}

void set_backedge(ir_node *n, int pos)
{
	bitset_t *ba = get_backarray(n);
	assert(ba != NULL);
	bitset_set(ba, pos);
}

int has_backedges(const ir_node *n)
{
	bitset_t *ba = get_backarray(n);
	if (ba != NULL) {
		return !bitset_is_empty(ba);
	}
	return 0;
}

void clear_backedges(ir_node *n)
{
	bitset_t *ba = get_backarray(n);
	if (ba != NULL) {
		bitset_clear_all(ba);
	}
}

bitset_t *new_backedge_arr(struct obstack *obst, size_t size)
{
	return bitset_obstack_alloc(obst, size);
}