1use alloc::{vec, vec::Vec};
2
3use super::functions::FunctionTracer;
4use super::FunctionMap;
5use crate::arena::Handle;
6use crate::compact::handle_set_map::HandleMap;
7
8impl FunctionTracer<'_> {
9 pub fn trace_block(&mut self, block: &[crate::Statement]) {
10 self.trace_block_impl(block, false)
11 }
12
13 #[cfg(msl_out)]
26 pub fn trace_block_including_emits(&mut self, block: &[crate::Statement]) {
27 self.trace_block_impl(block, true)
28 }
29
30 fn trace_block_impl(&mut self, block: &[crate::Statement], emits_are_used: bool) {
31 let mut worklist: Vec<&[crate::Statement]> = vec![block];
32 while let Some(last) = worklist.pop() {
33 for stmt in last {
34 use crate::Statement as St;
35 match *stmt {
36 St::Emit(ref range) => {
37 if emits_are_used {
43 self.expressions_used.insert_iter(range.clone());
44 }
45 }
46 St::Block(ref block) => worklist.push(block),
47 St::If {
48 condition,
49 ref accept,
50 ref reject,
51 } => {
52 self.expressions_used.insert(condition);
53 worklist.push(accept);
54 worklist.push(reject);
55 }
56 St::Switch {
57 selector,
58 ref cases,
59 } => {
60 self.expressions_used.insert(selector);
61 for case in cases {
62 worklist.push(&case.body);
63 }
64 }
65 St::Loop {
66 ref body,
67 ref continuing,
68 break_if,
69 } => {
70 if let Some(break_if) = break_if {
71 self.expressions_used.insert(break_if);
72 }
73 worklist.push(body);
74 worklist.push(continuing);
75 }
76 St::Return { value: Some(value) } => {
77 self.expressions_used.insert(value);
78 }
79 St::Store { pointer, value } => {
80 self.expressions_used.insert(pointer);
81 self.expressions_used.insert(value);
82 }
83 St::ImageStore {
84 image,
85 coordinate,
86 array_index,
87 value,
88 } => {
89 self.expressions_used.insert(image);
90 self.expressions_used.insert(coordinate);
91 if let Some(array_index) = array_index {
92 self.expressions_used.insert(array_index);
93 }
94 self.expressions_used.insert(value);
95 }
96 St::Atomic {
97 pointer,
98 ref fun,
99 value,
100 result,
101 } => {
102 self.expressions_used.insert(pointer);
103 self.trace_atomic_function(fun);
104 self.expressions_used.insert(value);
105 if let Some(result) = result {
106 self.expressions_used.insert(result);
107 }
108 }
109 St::ImageAtomic {
110 image,
111 coordinate,
112 array_index,
113 fun: _,
114 value,
115 } => {
116 self.expressions_used.insert(image);
117 self.expressions_used.insert(coordinate);
118 if let Some(array_index) = array_index {
119 self.expressions_used.insert(array_index);
120 }
121 self.expressions_used.insert(value);
122 }
123 St::WorkGroupUniformLoad { pointer, result } => {
124 self.expressions_used.insert(pointer);
125 self.expressions_used.insert(result);
126 }
127 St::Call {
128 function,
129 ref arguments,
130 result,
131 } => {
132 self.trace_call(function);
133 for expr in arguments {
134 self.expressions_used.insert(*expr);
135 }
136 if let Some(result) = result {
137 self.expressions_used.insert(result);
138 }
139 }
140 St::RayQuery { query, ref fun } => {
141 self.expressions_used.insert(query);
142 self.trace_ray_query_function(fun);
143 }
144 St::SubgroupBallot { result, predicate } => {
145 if let Some(predicate) = predicate {
146 self.expressions_used.insert(predicate);
147 }
148 self.expressions_used.insert(result);
149 }
150 St::SubgroupCollectiveOperation {
151 op: _,
152 collective_op: _,
153 argument,
154 result,
155 } => {
156 self.expressions_used.insert(argument);
157 self.expressions_used.insert(result);
158 }
159 St::SubgroupGather {
160 mode,
161 argument,
162 result,
163 } => {
164 match mode {
165 crate::GatherMode::BroadcastFirst => {}
166 crate::GatherMode::Broadcast(index)
167 | crate::GatherMode::Shuffle(index)
168 | crate::GatherMode::ShuffleDown(index)
169 | crate::GatherMode::ShuffleUp(index)
170 | crate::GatherMode::ShuffleXor(index)
171 | crate::GatherMode::QuadBroadcast(index) => {
172 self.expressions_used.insert(index);
173 }
174 crate::GatherMode::QuadSwap(_) => {}
175 }
176 self.expressions_used.insert(argument);
177 self.expressions_used.insert(result);
178 }
179 St::CooperativeStore { target, ref data } => {
180 self.expressions_used.insert(target);
181 self.expressions_used.insert(data.pointer);
182 self.expressions_used.insert(data.stride);
183 }
184 St::RayPipelineFunction(func) => match func {
185 crate::RayPipelineFunction::TraceRay {
186 acceleration_structure,
187 descriptor,
188 payload,
189 } => {
190 self.expressions_used.insert(acceleration_structure);
191 self.expressions_used.insert(descriptor);
192 self.expressions_used.insert(payload);
193 }
194 },
195 St::DebugPrintf {
196 format: _,
197 ref arguments,
198 } => {
199 for &expr in arguments {
200 self.expressions_used.insert(expr);
201 }
202 }
203
204 St::Break
206 | St::Continue
207 | St::Kill
208 | St::ControlBarrier(_)
209 | St::MemoryBarrier(_)
210 | St::Return { value: None } => {}
211 }
212 }
213 }
214 }
215
216 fn trace_atomic_function(&mut self, fun: &crate::AtomicFunction) {
217 use crate::AtomicFunction as Af;
218 match *fun {
219 Af::Exchange {
220 compare: Some(expr),
221 } => {
222 self.expressions_used.insert(expr);
223 }
224 Af::Exchange { compare: None }
225 | Af::Add
226 | Af::Subtract
227 | Af::And
228 | Af::ExclusiveOr
229 | Af::InclusiveOr
230 | Af::Min
231 | Af::Max => {}
232 }
233 }
234
235 fn trace_ray_query_function(&mut self, fun: &crate::RayQueryFunction) {
236 use crate::RayQueryFunction as Qf;
237 match *fun {
238 Qf::Initialize {
239 acceleration_structure,
240 descriptor,
241 } => {
242 self.expressions_used.insert(acceleration_structure);
243 self.expressions_used.insert(descriptor);
244 }
245 Qf::Proceed { result } => {
246 self.expressions_used.insert(result);
247 }
248 Qf::GenerateIntersection { hit_t } => {
249 self.expressions_used.insert(hit_t);
250 }
251 Qf::ConfirmIntersection => {}
252 Qf::Terminate => {}
253 Qf::Begin => {}
254 }
255 }
256}
257
258impl FunctionMap {
259 pub fn adjust_body(
264 &self,
265 function: &mut crate::Function,
266 function_map: &HandleMap<crate::Function>,
267 ) {
268 let block = &mut function.body;
269 let mut worklist: Vec<&mut [crate::Statement]> = vec![block];
270 let adjust = |handle: &mut Handle<crate::Expression>| {
271 self.expressions.adjust(handle);
272 };
273 while let Some(last) = worklist.pop() {
274 for stmt in last {
275 use crate::Statement as St;
276 match *stmt {
277 St::Emit(ref mut range) => {
278 self.expressions.adjust_range(range, &function.expressions);
279 }
280 St::Block(ref mut block) => worklist.push(block),
281 St::If {
282 ref mut condition,
283 ref mut accept,
284 ref mut reject,
285 } => {
286 adjust(condition);
287 worklist.push(accept);
288 worklist.push(reject);
289 }
290 St::Switch {
291 ref mut selector,
292 ref mut cases,
293 } => {
294 adjust(selector);
295 for case in cases {
296 worklist.push(&mut case.body);
297 }
298 }
299 St::Loop {
300 ref mut body,
301 ref mut continuing,
302 ref mut break_if,
303 } => {
304 if let Some(ref mut break_if) = *break_if {
305 adjust(break_if);
306 }
307 worklist.push(body);
308 worklist.push(continuing);
309 }
310 St::Return {
311 value: Some(ref mut value),
312 } => adjust(value),
313 St::Store {
314 ref mut pointer,
315 ref mut value,
316 } => {
317 adjust(pointer);
318 adjust(value);
319 }
320 St::ImageStore {
321 ref mut image,
322 ref mut coordinate,
323 ref mut array_index,
324 ref mut value,
325 } => {
326 adjust(image);
327 adjust(coordinate);
328 if let Some(ref mut array_index) = *array_index {
329 adjust(array_index);
330 }
331 adjust(value);
332 }
333 St::Atomic {
334 ref mut pointer,
335 ref mut fun,
336 ref mut value,
337 ref mut result,
338 } => {
339 adjust(pointer);
340 self.adjust_atomic_function(fun);
341 adjust(value);
342 if let Some(ref mut result) = *result {
343 adjust(result);
344 }
345 }
346 St::ImageAtomic {
347 ref mut image,
348 ref mut coordinate,
349 ref mut array_index,
350 fun: _,
351 ref mut value,
352 } => {
353 adjust(image);
354 adjust(coordinate);
355 if let Some(ref mut array_index) = *array_index {
356 adjust(array_index);
357 }
358 adjust(value);
359 }
360 St::WorkGroupUniformLoad {
361 ref mut pointer,
362 ref mut result,
363 } => {
364 adjust(pointer);
365 adjust(result);
366 }
367 St::Call {
368 ref mut function,
369 ref mut arguments,
370 ref mut result,
371 } => {
372 function_map.adjust(function);
373 for expr in arguments {
374 adjust(expr);
375 }
376 if let Some(ref mut result) = *result {
377 adjust(result);
378 }
379 }
380 St::RayQuery {
381 ref mut query,
382 ref mut fun,
383 } => {
384 adjust(query);
385 self.adjust_ray_query_function(fun);
386 }
387 St::SubgroupBallot {
388 ref mut result,
389 ref mut predicate,
390 } => {
391 if let Some(ref mut predicate) = *predicate {
392 adjust(predicate);
393 }
394 adjust(result);
395 }
396 St::SubgroupCollectiveOperation {
397 op: _,
398 collective_op: _,
399 ref mut argument,
400 ref mut result,
401 } => {
402 adjust(argument);
403 adjust(result);
404 }
405 St::SubgroupGather {
406 ref mut mode,
407 ref mut argument,
408 ref mut result,
409 } => {
410 match *mode {
411 crate::GatherMode::BroadcastFirst => {}
412 crate::GatherMode::Broadcast(ref mut index)
413 | crate::GatherMode::Shuffle(ref mut index)
414 | crate::GatherMode::ShuffleDown(ref mut index)
415 | crate::GatherMode::ShuffleUp(ref mut index)
416 | crate::GatherMode::ShuffleXor(ref mut index)
417 | crate::GatherMode::QuadBroadcast(ref mut index) => adjust(index),
418 crate::GatherMode::QuadSwap(_) => {}
419 }
420 adjust(argument);
421 adjust(result);
422 }
423 St::CooperativeStore {
424 ref mut target,
425 ref mut data,
426 } => {
427 adjust(target);
428 adjust(&mut data.pointer);
429 adjust(&mut data.stride);
430 }
431 St::RayPipelineFunction(ref mut func) => match *func {
432 crate::RayPipelineFunction::TraceRay {
433 ref mut acceleration_structure,
434 ref mut descriptor,
435 ref mut payload,
436 } => {
437 adjust(acceleration_structure);
438 adjust(descriptor);
439 adjust(payload);
440 }
441 },
442 St::DebugPrintf {
443 format: _,
444 ref mut arguments,
445 } => {
446 for expr in arguments {
447 adjust(expr);
448 }
449 }
450
451 St::Break
453 | St::Continue
454 | St::Kill
455 | St::ControlBarrier(_)
456 | St::MemoryBarrier(_)
457 | St::Return { value: None } => {}
458 }
459 }
460 }
461 }
462
463 fn adjust_atomic_function(&self, fun: &mut crate::AtomicFunction) {
464 use crate::AtomicFunction as Af;
465 match *fun {
466 Af::Exchange {
467 compare: Some(ref mut expr),
468 } => {
469 self.expressions.adjust(expr);
470 }
471 Af::Exchange { compare: None }
472 | Af::Add
473 | Af::Subtract
474 | Af::And
475 | Af::ExclusiveOr
476 | Af::InclusiveOr
477 | Af::Min
478 | Af::Max => {}
479 }
480 }
481
482 fn adjust_ray_query_function(&self, fun: &mut crate::RayQueryFunction) {
483 use crate::RayQueryFunction as Qf;
484 match *fun {
485 Qf::Initialize {
486 ref mut acceleration_structure,
487 ref mut descriptor,
488 } => {
489 self.expressions.adjust(acceleration_structure);
490 self.expressions.adjust(descriptor);
491 }
492 Qf::Proceed { ref mut result } => {
493 self.expressions.adjust(result);
494 }
495 Qf::GenerateIntersection { ref mut hit_t } => {
496 self.expressions.adjust(hit_t);
497 }
498 Qf::ConfirmIntersection => {}
499 Qf::Terminate => {}
500 Qf::Begin => {}
501 }
502 }
503}