Checker analysis: change order of block processing for better efficiency. (#29)

After going through the checker with @fitzgen, we discussed the dataflow
analysis and @fitzgen noted that it would likely be more efficient to,
for example, process an inner cycle of blocks in a loop nest and
converge before returning to the outer loop. I had written a BFS-style
workqueue loop to converge the dataflow analysis without much thought,
with a FIFO workqueue. Any workqueue ordering will work and will
converge to the same fixpoint (as long as we are operating on a
lattice), but indeed some orderings will be more efficient, and a
DFS-style (LIFO stack) workqueue will give us this property of
converging inner loops first.

In measurements, there doesn't seem to be much of a difference for small
fuzz testcases, but this will likely matter more if/when we try to run
the checker to validate register allocation on large functions.
This commit is contained in:
Chris Fallin
2022-03-10 10:35:08 -08:00
committed by GitHub
parent fe021ad6d4
commit b1a512dbf6

View File

@@ -102,7 +102,6 @@ use crate::{
};
use fxhash::{FxHashMap, FxHashSet};
use smallvec::{smallvec, SmallVec};
use std::collections::VecDeque;
use std::default::Default;
use std::hash::Hash;
use std::result::Result;
@@ -726,16 +725,14 @@ impl<'a, F: Function> Checker<'a, F> {
/// Perform the dataflow analysis to compute checker state at each BB entry.
fn analyze(&mut self) {
let mut queue = VecDeque::new();
let mut queue = Vec::new();
let mut queue_set = FxHashSet::default();
for block in 0..self.f.num_blocks() {
let block = Block::new(block);
queue.push_back(block);
queue_set.insert(block);
}
queue.push(self.f.entry_block());
queue_set.insert(self.f.entry_block());
while !queue.is_empty() {
let block = queue.pop_front().unwrap();
let block = queue.pop().unwrap();
queue_set.remove(&block);
let mut state = self.bb_in.get(&block).cloned().unwrap();
trace!("analyze: block {} has state {:?}", block.index(), state);
@@ -777,7 +774,7 @@ impl<'a, F: Function> Checker<'a, F> {
);
self.bb_in.insert(succ, new_state);
if !queue_set.contains(&succ) {
queue.push_back(succ);
queue.push(succ);
queue_set.insert(succ);
}
}