1 /* _nir_foreach_dest() needs to be ALWAYS_INLINE so that it can inline the
2  * callback if it was declared with ALWAYS_INLINE.
3  */
4 static ALWAYS_INLINE bool
_nir_foreach_dest(nir_instr * instr,nir_foreach_dest_cb cb,void * state)5 _nir_foreach_dest(nir_instr *instr, nir_foreach_dest_cb cb, void *state)
6 {
7    switch (instr->type) {
8    case nir_instr_type_alu:
9       return cb(&nir_instr_as_alu(instr)->dest.dest, state);
10    case nir_instr_type_deref:
11       return cb(&nir_instr_as_deref(instr)->dest, state);
12    case nir_instr_type_intrinsic: {
13       nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
14       if (nir_intrinsic_infos[intrin->intrinsic].has_dest)
15          return cb(&intrin->dest, state);
16       return true;
17    }
18    case nir_instr_type_tex:
19       return cb(&nir_instr_as_tex(instr)->dest, state);
20    case nir_instr_type_phi:
21       return cb(&nir_instr_as_phi(instr)->dest, state);
22    case nir_instr_type_parallel_copy: {
23       nir_foreach_parallel_copy_entry(entry, nir_instr_as_parallel_copy(instr)) {
24          if (!cb(&entry->dest, state))
25             return false;
26       }
27       return true;
28    }
29 
30    case nir_instr_type_load_const:
31    case nir_instr_type_ssa_undef:
32    case nir_instr_type_call:
33    case nir_instr_type_jump:
34       break;
35 
36    default:
37       unreachable("Invalid instruction type");
38       break;
39    }
40 
41    return true;
42 }
43 
44 static ALWAYS_INLINE bool
_nir_visit_src(nir_src * src,nir_foreach_src_cb cb,void * state)45 _nir_visit_src(nir_src *src, nir_foreach_src_cb cb, void *state)
46 {
47    if (!cb(src, state))
48       return false;
49    if (!src->is_ssa && src->reg.indirect)
50       return cb(src->reg.indirect, state);
51    return true;
52 }
53 
54 typedef struct {
55    void *state;
56    nir_foreach_src_cb cb;
57 } _nir_visit_dest_indirect_state;
58 
59 static ALWAYS_INLINE bool
_nir_visit_dest_indirect(nir_dest * dest,void * _state)60 _nir_visit_dest_indirect(nir_dest *dest, void *_state)
61 {
62    _nir_visit_dest_indirect_state *state = (_nir_visit_dest_indirect_state *) _state;
63 
64    if (!dest->is_ssa && dest->reg.indirect)
65       return state->cb(dest->reg.indirect, state->state);
66 
67    return true;
68 }
69 
70 static inline bool
nir_foreach_dest(nir_instr * instr,nir_foreach_dest_cb cb,void * state)71 nir_foreach_dest(nir_instr *instr, nir_foreach_dest_cb cb, void *state)
72 {
73    return _nir_foreach_dest(instr, cb, state);
74 }
75 
76 static inline bool
nir_foreach_src(nir_instr * instr,nir_foreach_src_cb cb,void * state)77 nir_foreach_src(nir_instr *instr, nir_foreach_src_cb cb, void *state)
78 {
79    switch (instr->type) {
80    case nir_instr_type_alu: {
81       nir_alu_instr *alu = nir_instr_as_alu(instr);
82       for (unsigned i = 0; i < nir_op_infos[alu->op].num_inputs; i++)
83          if (!_nir_visit_src(&alu->src[i].src, cb, state))
84             return false;
85       break;
86    }
87    case nir_instr_type_deref: {
88       nir_deref_instr *deref = nir_instr_as_deref(instr);
89 
90       if (deref->deref_type != nir_deref_type_var) {
91          if (!_nir_visit_src(&deref->parent, cb, state))
92             return false;
93       }
94 
95       if (deref->deref_type == nir_deref_type_array ||
96           deref->deref_type == nir_deref_type_ptr_as_array) {
97          if (!_nir_visit_src(&deref->arr.index, cb, state))
98             return false;
99       }
100       break;
101    }
102    case nir_instr_type_intrinsic: {
103       nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
104       unsigned num_srcs = nir_intrinsic_infos[intrin->intrinsic].num_srcs;
105       for (unsigned i = 0; i < num_srcs; i++) {
106          if (!_nir_visit_src(&intrin->src[i], cb, state))
107             return false;
108       }
109       break;
110    }
111    case nir_instr_type_tex: {
112       nir_tex_instr *tex = nir_instr_as_tex(instr);
113       for (unsigned i = 0; i < tex->num_srcs; i++) {
114          if (!_nir_visit_src(&tex->src[i].src, cb, state))
115             return false;
116       }
117       break;
118    }
119    case nir_instr_type_call: {
120       nir_call_instr *call = nir_instr_as_call(instr);
121       for (unsigned i = 0; i < call->num_params; i++) {
122          if (!_nir_visit_src(&call->params[i], cb, state))
123             return false;
124       }
125       break;
126    }
127    case nir_instr_type_phi: {
128       nir_phi_instr *phi = nir_instr_as_phi(instr);
129       nir_foreach_phi_src(src, phi) {
130          if (!_nir_visit_src(&src->src, cb, state))
131             return false;
132       }
133       break;
134    }
135    case nir_instr_type_parallel_copy: {
136       nir_parallel_copy_instr *pc = nir_instr_as_parallel_copy(instr);
137       nir_foreach_parallel_copy_entry(entry, pc) {
138          if (!_nir_visit_src(&entry->src, cb, state))
139             return false;
140       }
141       break;
142    }
143    case nir_instr_type_jump: {
144       nir_jump_instr *jump = nir_instr_as_jump(instr);
145 
146       if (jump->type == nir_jump_goto_if && !_nir_visit_src(&jump->condition, cb, state))
147          return false;
148       return true;
149    }
150 
151    case nir_instr_type_load_const:
152    case nir_instr_type_ssa_undef:
153       return true;
154 
155    default:
156       unreachable("Invalid instruction type");
157       break;
158    }
159 
160    _nir_visit_dest_indirect_state dest_state;
161    dest_state.state = state;
162    dest_state.cb = cb;
163    return _nir_foreach_dest(instr, _nir_visit_dest_indirect, &dest_state);
164 }
165