Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions interactive/src/passes/canonical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,33 @@ use crate::shapes::{ItemShapes, ScopeShapes};
/// Compose adjacent maps, remove identity maps, and cancel adjacent negations.
/// Structural fusion has already respected shared edges. No other operator is crossed.
pub(super) fn canonical_linear(scope: &mut Scope, shapes: &ScopeShapes, level: Level) -> usize {
let mut changed = 0;
for (item, shape) in scope.items.iter_mut().zip(&shapes.items) {
if let (Item::Sub(child), ItemShapes::Sub(typed)) = (item, shape) {
changed += canonical_linear(child, typed, level.child());
}
}
changed + canonical_scope(scope, shapes, level).0
}

/// Keep item shapes aligned while identity maps and their aliases disappear.
pub(super) fn canonical_typed(scope: &mut Scope, shapes: &mut ScopeShapes, level: Level) -> usize {
let mut changed = 0;
for (item, shape) in scope.items.iter_mut().zip(&mut shapes.items) {
if let (Item::Sub(child), ItemShapes::Sub(typed)) = (item, shape) {
changed += canonical_typed(child, typed, level.child());
}
}
let (local, dead) = canonical_scope(scope, shapes, level);
let mut keep = dead.iter();
shapes.items.retain(|_| !*keep.next().unwrap());
changed + local
}

fn canonical_scope(scope: &mut Scope, shapes: &ScopeShapes, level: Level) -> (usize, Vec<bool>) {
let mut changed = 0;
for (item, shape) in scope.items.iter_mut().zip(&shapes.items) {
match (item, shape) {
(Item::Sub(child), ItemShapes::Sub(shapes)) => changed += canonical_linear(child, shapes, level.child()),
(Item::Op(Node::Linear { input, ops }), _) => {
let steps = shapes.of(input).and_then(|s| {
crate::shapes::linear_shapes(ops, s.key, s.val, level).ok()
Expand Down Expand Up @@ -90,7 +113,7 @@ pub(super) fn canonical_linear(scope: &mut Scope, shapes: &ScopeShapes, level: L
}
scope.for_each_ref(|r| if let Ref::Local(i) = r { *r = remap[*i].clone(); });
super::structural::compact(scope, &dead);
changed
(changed, dead)
}

fn compose_run(maps: &[&Lambda], input: &Shape) -> Option<Lambda> {
Expand Down
23 changes: 4 additions & 19 deletions interactive/src/passes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,25 +194,10 @@ pub fn run(
changes.clear();
if !config.projection { changes.push(Change::Off("projection")); }
else if valid {
let mut candidate = program.clone();
let mut masked = 0;
let mut converged = false;
for _ in 0..16 {
timings.projection_rounds += 1;
let count = projection::pushdown_timed(&mut candidate, source, root, timings.pass_mut(Pass::ShapeInference)).unwrap_or(0);
if count == 0 { converged = true; break; }
// Masks expose optimizer rewrites. In turn, merging identical masks can
// give a reduce one reader and make its remaining map fusible.
optimize_with(&mut candidate, source, root, config, &mut timings, &mut |_, _, _, _, _, _| {});
if !accept(&candidate, &mut timings) { break; }
masked += count;
}
if converged {
if masked > 0 {
changes.push(Change::Masked(masked));
*program = candidate;
} else { changes.push(Change::NoProjection); }
} else { changes.push(Change::Rejected); }
timings.projection_rounds += 1;
let count = projection::pushdown_timed(program, source, root, &shapes, config, &mut timings).unwrap_or(0);
if count > 0 { changes.push(Change::Masked(count)); }
else { changes.push(Change::NoProjection); }
} else { changes.push(Change::Skipped); }
timings.projection.record(start.elapsed(), changes.iter().map(Change::count).sum());
timings.observe("after projection", program, &changes, observe);
Expand Down
Loading
Loading