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
163
164
|
/* _nir_foreach_dest() needs to be ALWAYS_INLINE so that it can inline the
* callback if it was declared with ALWAYS_INLINE.
*/
static ALWAYS_INLINE bool
_nir_foreach_dest(nir_instr *instr, nir_foreach_dest_cb cb, void *state)
{
switch (instr->type) {
case nir_instr_type_alu:
return cb(&nir_instr_as_alu(instr)->dest.dest, state);
case nir_instr_type_deref:
return cb(&nir_instr_as_deref(instr)->dest, state);
case nir_instr_type_intrinsic: {
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
if (nir_intrinsic_infos[intrin->intrinsic].has_dest)
return cb(&intrin->dest, state);
return true;
}
case nir_instr_type_tex:
return cb(&nir_instr_as_tex(instr)->dest, state);
case nir_instr_type_phi:
return cb(&nir_instr_as_phi(instr)->dest, state);
case nir_instr_type_parallel_copy: {
nir_foreach_parallel_copy_entry(entry, nir_instr_as_parallel_copy(instr)) {
if (!cb(&entry->dest, state))
return false;
}
return true;
}
case nir_instr_type_load_const:
case nir_instr_type_ssa_undef:
case nir_instr_type_call:
case nir_instr_type_jump:
break;
default:
unreachable("Invalid instruction type");
break;
}
return true;
}
static ALWAYS_INLINE bool
_nir_visit_src(nir_src *src, nir_foreach_src_cb cb, void *state)
{
if (!cb(src, state))
return false;
if (!src->is_ssa && src->reg.indirect)
return cb(src->reg.indirect, state);
return true;
}
typedef struct {
void *state;
nir_foreach_src_cb cb;
} _nir_visit_dest_indirect_state;
static ALWAYS_INLINE bool
_nir_visit_dest_indirect(nir_dest *dest, void *_state)
{
_nir_visit_dest_indirect_state *state = (_nir_visit_dest_indirect_state *) _state;
if (!dest->is_ssa && dest->reg.indirect)
return state->cb(dest->reg.indirect, state->state);
return true;
}
static inline bool
nir_foreach_dest(nir_instr *instr, nir_foreach_dest_cb cb, void *state)
{
return _nir_foreach_dest(instr, cb, state);
}
static inline bool
nir_foreach_src(nir_instr *instr, nir_foreach_src_cb cb, void *state)
{
switch (instr->type) {
case nir_instr_type_alu: {
nir_alu_instr *alu = nir_instr_as_alu(instr);
for (unsigned i = 0; i < nir_op_infos[alu->op].num_inputs; i++)
if (!_nir_visit_src(&alu->src[i].src, cb, state))
return false;
break;
}
case nir_instr_type_deref: {
nir_deref_instr *deref = nir_instr_as_deref(instr);
if (deref->deref_type != nir_deref_type_var) {
if (!_nir_visit_src(&deref->parent, cb, state))
return false;
}
if (deref->deref_type == nir_deref_type_array ||
deref->deref_type == nir_deref_type_ptr_as_array) {
if (!_nir_visit_src(&deref->arr.index, cb, state))
return false;
}
break;
}
case nir_instr_type_intrinsic: {
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
unsigned num_srcs = nir_intrinsic_infos[intrin->intrinsic].num_srcs;
for (unsigned i = 0; i < num_srcs; i++) {
if (!_nir_visit_src(&intrin->src[i], cb, state))
return false;
}
break;
}
case nir_instr_type_tex: {
nir_tex_instr *tex = nir_instr_as_tex(instr);
for (unsigned i = 0; i < tex->num_srcs; i++) {
if (!_nir_visit_src(&tex->src[i].src, cb, state))
return false;
}
break;
}
case nir_instr_type_call: {
nir_call_instr *call = nir_instr_as_call(instr);
for (unsigned i = 0; i < call->num_params; i++) {
if (!_nir_visit_src(&call->params[i], cb, state))
return false;
}
break;
}
case nir_instr_type_phi: {
nir_phi_instr *phi = nir_instr_as_phi(instr);
nir_foreach_phi_src(src, phi) {
if (!_nir_visit_src(&src->src, cb, state))
return false;
}
break;
}
case nir_instr_type_parallel_copy: {
nir_parallel_copy_instr *pc = nir_instr_as_parallel_copy(instr);
nir_foreach_parallel_copy_entry(entry, pc) {
if (!_nir_visit_src(&entry->src, cb, state))
return false;
}
break;
}
case nir_instr_type_jump: {
nir_jump_instr *jump = nir_instr_as_jump(instr);
if (jump->type == nir_jump_goto_if && !_nir_visit_src(&jump->condition, cb, state))
return false;
return true;
}
case nir_instr_type_load_const:
case nir_instr_type_ssa_undef:
return true;
default:
unreachable("Invalid instruction type");
break;
}
_nir_visit_dest_indirect_state dest_state;
dest_state.state = state;
dest_state.cb = cb;
return _nir_foreach_dest(instr, _nir_visit_dest_indirect, &dest_state);
}
|