pub mod const_buffer_fold;
pub mod dead_buffer_elim;
pub mod dead_store_elim;
pub mod decode_scan_fuse;
pub mod read_only_load_hoist;
pub mod store_to_load_forward;
pub mod vectorization;
fn expr_touches_buffer(
expr: &crate::ir::Expr,
buffer: &crate::ir::Ident,
foreign_compare_exchange_touches: bool,
) -> bool {
use crate::ir::{AtomicOp, Expr};
let recurse = |child| expr_touches_buffer(child, buffer, foreign_compare_exchange_touches);
match expr {
Expr::Load {
buffer: other,
index,
} => other == buffer || recurse(index),
Expr::BufLen { buffer: other } | Expr::BufferRef { buffer: other } => other == buffer,
Expr::Atomic {
buffer: other,
index,
expected,
value,
op,
..
} => {
other == buffer
|| recurse(index)
|| (foreign_compare_exchange_touches
&& matches!(
op,
AtomicOp::CompareExchange | AtomicOp::CompareExchangeWeak
))
|| expected.as_deref().is_some_and(recurse)
|| recurse(value)
}
Expr::BinOp { left, right, .. } => recurse(left) || recurse(right),
Expr::UnOp { operand, .. } | Expr::Cast { value: operand, .. } => recurse(operand),
Expr::Fma { a, b, c } => recurse(a) || recurse(b) || recurse(c),
Expr::Select {
cond,
true_val,
false_val,
} => recurse(cond) || recurse(true_val) || recurse(false_val),
Expr::Call { args, .. } => args.iter().any(recurse),
Expr::SubgroupReduce { value, .. } => recurse(value),
Expr::SubgroupShuffle { value, lane } => recurse(value) || recurse(lane),
Expr::SubgroupBallot { cond } => recurse(cond),
Expr::Opaque(_) => true,
Expr::LitU32(_)
| Expr::LitI32(_)
| Expr::LitF32(_)
| Expr::LitBool(_)
| Expr::Var(_)
| Expr::InvocationId { .. }
| Expr::WorkgroupId { .. }
| Expr::LocalId { .. }
| Expr::SubgroupLocalId
| Expr::SubgroupSize => false,
}
}