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 */
4static ALWAYS_INLINE bool
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
44static ALWAYS_INLINE bool
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
54typedef struct {
55   void *state;
56   nir_foreach_src_cb cb;
57} _nir_visit_dest_indirect_state;
58
59static ALWAYS_INLINE bool
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
70static inline bool
71nir_foreach_dest(nir_instr *instr, nir_foreach_dest_cb cb, void *state)
72{
73   return _nir_foreach_dest(instr, cb, state);
74}
75
76static inline bool
77nir_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