use std::fmt::{Debug};
use super::{code, target};
use code::{Switch, EBB, Convention};
#[allow(unused)]
mod dep;
use dep::{Dep};
mod op;
use op::{Op};
mod resources;
use resources::{Resources};
mod cost;
use cost::{Cost, op_cost};
mod dataflow;
use dataflow::{Dataflow, Node};
mod cft;
use cft::{Cold, Exit, CFT};
mod simulation;
use simulation::{simulate};
mod builder;
use builder::{build};
pub trait LookupLeaf {
type Leaf: Debug + Clone;
fn after(&self, leaf: &Self::Leaf) -> &Convention;
fn weight(&self, leaf: &Self::Leaf) -> usize;
}
pub fn optimize<L: LookupLeaf>(before: &Convention, input: &EBB<L::Leaf>, lookup_leaf: &L)
-> EBB<L::Leaf> {
let (dataflow, cft) = simulate(before, input, lookup_leaf);
build(before, &dataflow, &cft, lookup_leaf)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::code::{REGISTERS as R, BinaryOp, builder as cb};
use BinaryOp::*;
use crate::code::tests::{EmulatorResult, random_ebb, random_ebb_convention};
impl LookupLeaf for Convention {
type Leaf = usize;
fn after(&self, _leaf: &usize) -> &Convention {
self
}
fn weight(&self, leaf: &usize) -> usize {
*leaf
}
}
pub fn optimize_and_compare(input_ebb: EBB<usize>, convention: Convention) {
let mut expected = EmulatorResult::new(&input_ebb, &convention);
expected.keep_only(&convention.lives);
let output_ebb = optimize(&convention, &input_ebb, &convention);
let mut observed = EmulatorResult::new(&output_ebb, &convention);
observed.keep_only(&convention.lives);
if expected != observed {
println!("input_ebb: {:#x?}", input_ebb);
println!("expected: {:#x?}", expected);
println!("output_ebb: {:#x?}", output_ebb);
println!("observed: {:#x?}", observed);
panic!("expected != observed");
}
}
#[test]
fn regression_0() {
let ebb = cb::build(|mut b| {
b.binary64(Xor, R[2], R[3], R[4]);
b.binary64(Lt, R[3], R[3], R[4]);
b.guard(R[3], false, cb::build(|b| b.jump(0)));
b.binary64(Lt, R[2], R[2], R[2]);
b.jump(1)
});
optimize_and_compare(ebb, random_ebb_convention());
}
#[test]
fn regression_8() {
let ebb = cb::build(|mut b| {
b.const_binary64(Add, R[2], R[2], 0x3b386b745518224d as i64);
b.binary64(Xor, R[4], R[2], R[4]);
b.binary64(Lt, R[2], R[3], R[2]);
b.guard(R[2], false, cb::build(|b| b.jump(0)));
b.binary64(Lt, R[3], R[2], R[2]);
b.guard(R[3], true, cb::build(|b| b.jump(1)));
b.const_binary64(Add, R[2], R[2], 0xc531fbc2c4c7042 as i64);
b.binary64(Xor, R[4], R[2], R[4]);
b.guard(R[2], false, cb::build(|b| b.jump(2)));
b.jump(3)
});
optimize_and_compare(ebb, random_ebb_convention());
}
#[test]
fn regression_27() {
let ebb = cb::build(|mut b| {
b.const_binary64(Add, R[4], R[4], 0x523e32f31c82fa38 as i64);
b.binary64(Xor, R[2], R[4], R[2]);
b.binary64(Lt, R[4], R[3], R[3]);
b.guard(R[4], true, cb::build(|b| b.jump(0)));
b.const_binary64(Add, R[3], R[3], 0x2854088f4544aaa6 as i64);
b.guard(R[3], false, cb::build(|b| b.jump(1)));
b.jump(2)
});
optimize_and_compare(ebb, random_ebb_convention());
}
#[test]
fn optimize_random_ebbs() {
for seed in 0..1000 {
let input_ebb = random_ebb(seed, 2);
optimize_and_compare(input_ebb, random_ebb_convention());
}
}
}