summaryrefslogtreecommitdiffstats
path: root/third_party/rust/naga/src/compact/statements.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/naga/src/compact/statements.rs')
-rw-r--r--third_party/rust/naga/src/compact/statements.rs300
1 files changed, 300 insertions, 0 deletions
diff --git a/third_party/rust/naga/src/compact/statements.rs b/third_party/rust/naga/src/compact/statements.rs
new file mode 100644
index 0000000000..0698b57258
--- /dev/null
+++ b/third_party/rust/naga/src/compact/statements.rs
@@ -0,0 +1,300 @@
+use super::functions::FunctionTracer;
+use super::FunctionMap;
+use crate::arena::Handle;
+
+impl FunctionTracer<'_> {
+ pub fn trace_block(&mut self, block: &[crate::Statement]) {
+ let mut worklist: Vec<&[crate::Statement]> = vec![block];
+ while let Some(last) = worklist.pop() {
+ for stmt in last {
+ use crate::Statement as St;
+ match *stmt {
+ St::Emit(ref _range) => {
+ // If we come across a statement that actually uses an
+ // expression in this range, it'll get traced from
+ // there. But since evaluating expressions has no
+ // effect, we don't need to assume that everything
+ // emitted is live.
+ }
+ St::Block(ref block) => worklist.push(block),
+ St::If {
+ condition,
+ ref accept,
+ ref reject,
+ } => {
+ self.expressions_used.insert(condition);
+ worklist.push(accept);
+ worklist.push(reject);
+ }
+ St::Switch {
+ selector,
+ ref cases,
+ } => {
+ self.expressions_used.insert(selector);
+ for case in cases {
+ worklist.push(&case.body);
+ }
+ }
+ St::Loop {
+ ref body,
+ ref continuing,
+ break_if,
+ } => {
+ if let Some(break_if) = break_if {
+ self.expressions_used.insert(break_if);
+ }
+ worklist.push(body);
+ worklist.push(continuing);
+ }
+ St::Return { value: Some(value) } => {
+ self.expressions_used.insert(value);
+ }
+ St::Store { pointer, value } => {
+ self.expressions_used.insert(pointer);
+ self.expressions_used.insert(value);
+ }
+ St::ImageStore {
+ image,
+ coordinate,
+ array_index,
+ value,
+ } => {
+ self.expressions_used.insert(image);
+ self.expressions_used.insert(coordinate);
+ if let Some(array_index) = array_index {
+ self.expressions_used.insert(array_index);
+ }
+ self.expressions_used.insert(value);
+ }
+ St::Atomic {
+ pointer,
+ ref fun,
+ value,
+ result,
+ } => {
+ self.expressions_used.insert(pointer);
+ self.trace_atomic_function(fun);
+ self.expressions_used.insert(value);
+ self.expressions_used.insert(result);
+ }
+ St::WorkGroupUniformLoad { pointer, result } => {
+ self.expressions_used.insert(pointer);
+ self.expressions_used.insert(result);
+ }
+ St::Call {
+ function: _,
+ ref arguments,
+ result,
+ } => {
+ for expr in arguments {
+ self.expressions_used.insert(*expr);
+ }
+ if let Some(result) = result {
+ self.expressions_used.insert(result);
+ }
+ }
+ St::RayQuery { query, ref fun } => {
+ self.expressions_used.insert(query);
+ self.trace_ray_query_function(fun);
+ }
+
+ // Trivial statements.
+ St::Break
+ | St::Continue
+ | St::Kill
+ | St::Barrier(_)
+ | St::Return { value: None } => {}
+ }
+ }
+ }
+ }
+
+ fn trace_atomic_function(&mut self, fun: &crate::AtomicFunction) {
+ use crate::AtomicFunction as Af;
+ match *fun {
+ Af::Exchange {
+ compare: Some(expr),
+ } => {
+ self.expressions_used.insert(expr);
+ }
+ Af::Exchange { compare: None }
+ | Af::Add
+ | Af::Subtract
+ | Af::And
+ | Af::ExclusiveOr
+ | Af::InclusiveOr
+ | Af::Min
+ | Af::Max => {}
+ }
+ }
+
+ fn trace_ray_query_function(&mut self, fun: &crate::RayQueryFunction) {
+ use crate::RayQueryFunction as Qf;
+ match *fun {
+ Qf::Initialize {
+ acceleration_structure,
+ descriptor,
+ } => {
+ self.expressions_used.insert(acceleration_structure);
+ self.expressions_used.insert(descriptor);
+ }
+ Qf::Proceed { result } => {
+ self.expressions_used.insert(result);
+ }
+ Qf::Terminate => {}
+ }
+ }
+}
+
+impl FunctionMap {
+ pub fn adjust_body(&self, function: &mut crate::Function) {
+ let block = &mut function.body;
+ let mut worklist: Vec<&mut [crate::Statement]> = vec![block];
+ let adjust = |handle: &mut Handle<crate::Expression>| {
+ self.expressions.adjust(handle);
+ };
+ while let Some(last) = worklist.pop() {
+ for stmt in last {
+ use crate::Statement as St;
+ match *stmt {
+ St::Emit(ref mut range) => {
+ self.expressions.adjust_range(range, &function.expressions);
+ }
+ St::Block(ref mut block) => worklist.push(block),
+ St::If {
+ ref mut condition,
+ ref mut accept,
+ ref mut reject,
+ } => {
+ adjust(condition);
+ worklist.push(accept);
+ worklist.push(reject);
+ }
+ St::Switch {
+ ref mut selector,
+ ref mut cases,
+ } => {
+ adjust(selector);
+ for case in cases {
+ worklist.push(&mut case.body);
+ }
+ }
+ St::Loop {
+ ref mut body,
+ ref mut continuing,
+ ref mut break_if,
+ } => {
+ if let Some(ref mut break_if) = *break_if {
+ adjust(break_if);
+ }
+ worklist.push(body);
+ worklist.push(continuing);
+ }
+ St::Return {
+ value: Some(ref mut value),
+ } => adjust(value),
+ St::Store {
+ ref mut pointer,
+ ref mut value,
+ } => {
+ adjust(pointer);
+ adjust(value);
+ }
+ St::ImageStore {
+ ref mut image,
+ ref mut coordinate,
+ ref mut array_index,
+ ref mut value,
+ } => {
+ adjust(image);
+ adjust(coordinate);
+ if let Some(ref mut array_index) = *array_index {
+ adjust(array_index);
+ }
+ adjust(value);
+ }
+ St::Atomic {
+ ref mut pointer,
+ ref mut fun,
+ ref mut value,
+ ref mut result,
+ } => {
+ adjust(pointer);
+ self.adjust_atomic_function(fun);
+ adjust(value);
+ adjust(result);
+ }
+ St::WorkGroupUniformLoad {
+ ref mut pointer,
+ ref mut result,
+ } => {
+ adjust(pointer);
+ adjust(result);
+ }
+ St::Call {
+ function: _,
+ ref mut arguments,
+ ref mut result,
+ } => {
+ for expr in arguments {
+ adjust(expr);
+ }
+ if let Some(ref mut result) = *result {
+ adjust(result);
+ }
+ }
+ St::RayQuery {
+ ref mut query,
+ ref mut fun,
+ } => {
+ adjust(query);
+ self.adjust_ray_query_function(fun);
+ }
+
+ // Trivial statements.
+ St::Break
+ | St::Continue
+ | St::Kill
+ | St::Barrier(_)
+ | St::Return { value: None } => {}
+ }
+ }
+ }
+ }
+
+ fn adjust_atomic_function(&self, fun: &mut crate::AtomicFunction) {
+ use crate::AtomicFunction as Af;
+ match *fun {
+ Af::Exchange {
+ compare: Some(ref mut expr),
+ } => {
+ self.expressions.adjust(expr);
+ }
+ Af::Exchange { compare: None }
+ | Af::Add
+ | Af::Subtract
+ | Af::And
+ | Af::ExclusiveOr
+ | Af::InclusiveOr
+ | Af::Min
+ | Af::Max => {}
+ }
+ }
+
+ fn adjust_ray_query_function(&self, fun: &mut crate::RayQueryFunction) {
+ use crate::RayQueryFunction as Qf;
+ match *fun {
+ Qf::Initialize {
+ ref mut acceleration_structure,
+ ref mut descriptor,
+ } => {
+ self.expressions.adjust(acceleration_structure);
+ self.expressions.adjust(descriptor);
+ }
+ Qf::Proceed { ref mut result } => {
+ self.expressions.adjust(result);
+ }
+ Qf::Terminate => {}
+ }
+ }
+}