|  | @@ -3,19 +3,82 @@ use std::collections::BTreeMap;
 | 
	
		
			
				|  |  |  use super::ir;
 | 
	
		
			
				|  |  |  use super::ir::Instruction;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +enum CellState {
 | 
	
		
			
				|  |  | +    Value(i64),
 | 
	
		
			
				|  |  | +    Added(i64)
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +struct TapeState {
 | 
	
		
			
				|  |  | +    pub cell_states: BTreeMap<i64, CellState>
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -pub struct LoopLinearizer;
 | 
	
		
			
				|  |  | +pub struct Optimizer {
 | 
	
		
			
				|  |  | +    state: TapeState
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -impl ir::MutVisitor for LoopLinearizer {
 | 
	
		
			
				|  |  | +impl TapeState {
 | 
	
		
			
				|  |  | +    fn add(&mut self, offset: i64, value: i64) {
 | 
	
		
			
				|  |  | +        let cell_state = self.cell_states.get_mut(&offset);
 | 
	
		
			
				|  |  | +        if let Some(cell) = cell_state {
 | 
	
		
			
				|  |  | +            let new_cell = match cell {
 | 
	
		
			
				|  |  | +                CellState::Value(val) => CellState::Value(*val + value),
 | 
	
		
			
				|  |  | +                CellState::Added(val) => CellState::Added(*val + value)
 | 
	
		
			
				|  |  | +            };
 | 
	
		
			
				|  |  | +            std::mem::replace(cell, new_cell);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        else {
 | 
	
		
			
				|  |  | +            self.cell_states.insert(offset, CellState::Added(value));
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    fn set(&mut self, offset: i64, value: i64) {
 | 
	
		
			
				|  |  | +        let cell_state = self.cell_states.get_mut(&offset);
 | 
	
		
			
				|  |  | +        if let Some(cell) = cell_state {
 | 
	
		
			
				|  |  | +            std::mem::replace(cell, CellState::Value(value));
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        else {
 | 
	
		
			
				|  |  | +            self.cell_states.insert(offset, CellState::Value(value));
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    fn get(&self, offset: i64) -> Option<&CellState> {
 | 
	
		
			
				|  |  | +        self.cell_states.get(&offset)
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +impl Optimizer {
 | 
	
		
			
				|  |  | +    pub fn new() -> Self {
 | 
	
		
			
				|  |  | +        Optimizer {
 | 
	
		
			
				|  |  | +            state: TapeState {
 | 
	
		
			
				|  |  | +                cell_states: BTreeMap::new()
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +impl ir::MutVisitor for Optimizer {
 | 
	
		
			
				|  |  |      type Ret = ();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    fn visit_instructions(&mut self, instr: &'_ mut Vec<Instruction>) {
 | 
	
		
			
				|  |  | +    fn visit_instructions(&mut self, instr: &mut Vec<Instruction>) {
 | 
	
		
			
				|  |  |          for inst in instr {
 | 
	
		
			
				|  |  |              self.walk_instruction(inst);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    fn visit_add(&mut self, add: &'_ mut Instruction) {
 | 
	
		
			
				|  |  | +    fn visit_add(&mut self, add: &mut Instruction) {
 | 
	
		
			
				|  |  | +        if let Instruction::Add{ offset, value } = add {
 | 
	
		
			
				|  |  | +            let cell_state = self.state.get(*offset);
 | 
	
		
			
				|  |  | +            if let Some(CellState::Value(v)) = cell_state {
 | 
	
		
			
				|  |  | +                self.state.add(*offset, *value);
 | 
	
		
			
				|  |  | +                //std::mem::replace(add, Instruction::Set{ offset: *offset, value: *value + v });
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            else {
 | 
	
		
			
				|  |  | +                self.state.add(*offset, *value);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    fn visit_set(&mut self, set: &mut Instruction) {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      fn visit_linear_loop(&mut self, lloop: &'_ mut Instruction) {
 | 
	
	
		
			
				|  | @@ -49,6 +112,8 @@ impl ir::MutVisitor for LoopLinearizer {
 | 
	
		
			
				|  |  |              if !dirty && increments.get(&0) == Some(&-1) {
 | 
	
		
			
				|  |  |                  std::mem::replace(l, Instruction::LinearLoop(increments));
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | +            // set cell at offset 0 to 0
 | 
	
		
			
				|  |  | +            self.state.set(0, 0);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 |