peepmatic: Do not use paths in linear IR
Rather than using paths from the root instruction to the instruction we are matching against or checking if it is constant or whatever, use temporary variables. When we successfully match an instruction's opcode, we simultaneously define these temporaries for the instruction's operands. This is similar to how open-coding these matches in Rust would use `match` expressions with pattern matching to bind the operands to variables at the same time. This saves about 1.8% of instructions retired when Peepmatic is enabled.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
//! Traversals over the AST.
|
||||
|
||||
use crate::ast::*;
|
||||
use std::collections::VecDeque;
|
||||
use std::fmt::Debug;
|
||||
use std::hash::Hash;
|
||||
|
||||
@@ -103,6 +104,44 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// A breadth-first traversal of an AST
|
||||
///
|
||||
/// This implementation is not recursive, and exposes an `Iterator` interface
|
||||
/// that yields `DynAstRef` items.
|
||||
///
|
||||
/// The traversal can walk a whole set of `Optimization`s or just a subtree of
|
||||
/// the AST, because the `new` constructor takes anything that can convert into
|
||||
/// a `DynAstRef`.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Bfs<'a, TOperator> {
|
||||
queue: VecDeque<DynAstRef<'a, TOperator>>,
|
||||
}
|
||||
|
||||
impl<'a, TOperator> Bfs<'a, TOperator>
|
||||
where
|
||||
TOperator: Copy + Debug + Eq + Hash,
|
||||
{
|
||||
/// Construct a new `Bfs` traversal starting at the given `start` AST node.
|
||||
pub fn new(start: impl Into<DynAstRef<'a, TOperator>>) -> Self {
|
||||
let mut queue = VecDeque::with_capacity(16);
|
||||
queue.push_back(start.into());
|
||||
Bfs { queue }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, TOperator> Iterator for Bfs<'a, TOperator>
|
||||
where
|
||||
TOperator: Copy + Debug + Eq + Hash,
|
||||
{
|
||||
type Item = DynAstRef<'a, TOperator>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let node = self.queue.pop_front()?;
|
||||
node.child_nodes(&mut self.queue);
|
||||
Some(node)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Reference in New Issue
Block a user