Browse Source

1. Move remove_dead_code to its own final stage optiimzation
2. Fix bug with calculate_static_value
3. Disabled move_load_top.rs until a better unique register is added into place

Cesar Rodas 9 months ago
parent
commit
7eb02fad1b

+ 25 - 17
utxo/src/filter_expr/compiler/mod.rs

@@ -137,10 +137,34 @@ impl<'a> Compiler<'a> {
     }
 
     pub fn remove_dead_code(opcodes: Vec<OpCode>) -> Vec<OpCode> {
-        let (new_opcodes, _) = optimizations::remove_dead_code(opcodes);
+        let mut new_opcodes = opcodes;
+        loop {
+            let (new_opcodes_, has_changed) = optimizations::remove_dead_code(new_opcodes);
+            new_opcodes = new_opcodes_;
+            if !has_changed {
+                break;
+            }
+        }
+
         new_opcodes
     }
 
+    pub fn optimize(opcodes: Vec<OpCode>) -> (Vec<OpCode>, bool) {
+        vec![
+            optimizations::assign_unique_register_addresses,
+            optimizations::remove_redundant_load_and_mov,
+            optimizations::remove_unused_values,
+            optimizations::calculate_static_values,
+            optimizations::remove_useless_jumps,
+            //optimizations::move_load_top,
+        ]
+        .into_iter()
+        .fold((opcodes, false), |(opcodes, has_optimized), f| {
+            let (opcodes, optimized) = f(opcodes);
+            (opcodes, has_optimized || optimized)
+        })
+    }
+
     /// Returns a list of Addresses that are labeled in the opcodes list. This function is required
     /// to resolve any jump in the compiler
     pub fn labels_to_addr(opcodes: &[OpCode]) -> HashMap<Addr, Addr> {
@@ -161,22 +185,6 @@ impl<'a> Compiler<'a> {
             .collect::<HashMap<_, _>>()
     }
 
-    pub fn optimize(opcodes: Vec<OpCode>) -> (Vec<OpCode>, bool) {
-        vec![
-            optimizations::assign_unique_register_addresses,
-            optimizations::remove_redundant_load_and_mov,
-            optimizations::remove_unused_values,
-            optimizations::calculate_static_values,
-            optimizations::remove_useless_jumps,
-            optimizations::move_load_top,
-        ]
-        .into_iter()
-        .fold((opcodes, false), |(opcodes, has_optimized), f| {
-            let (opcodes, optimized) = f(opcodes);
-            (opcodes, has_optimized || optimized)
-        })
-    }
-
     pub fn resolve_label_to_addr(opcodes: Vec<OpCode>) -> Result<Vec<OpCode>, Error> {
         let labels_to_addr = Self::labels_to_addr(&opcodes);
 

+ 8 - 6
utxo/src/filter_expr/compiler/optimizations/calculate_static_values.rs

@@ -15,8 +15,10 @@ pub fn calculate_static_values(mut opcodes: Vec<OpCode>) -> (Vec<OpCode>, bool)
             }
             OpCode::JMP(_) | OpCode::HLT(_) | OpCode::LABEL(_) => {}
             OpCode::MOV(dst, src) => {
+                register.remove(dst);
                 if let Some(value) = register.remove(src) {
-                    register.insert(*dst, value.clone());
+                    *opcode = OpCode::LOAD(*dst, value);
+                    has_changed = true;
                 }
             }
             OpCode::LOAD_EXTERNAL(dst, _)
@@ -45,10 +47,11 @@ pub fn calculate_static_values(mut opcodes: Vec<OpCode>) -> (Vec<OpCode>, bool)
             OpCode::JNE(reg, addr) => {
                 if let Some(Value::Bool(false)) = register.get(reg) {
                     *opcode = OpCode::JMP(*addr);
+                    has_changed = true;
                 }
             }
             OpCode::EQ(dst, reg1, reg2) => {
-                let value1 = if let Some(value) = register.get(reg1) {
+                let value1 = if let Some(value) = register.remove(reg1) {
                     value.clone()
                 } else {
                     register.remove(dst);
@@ -61,8 +64,8 @@ pub fn calculate_static_values(mut opcodes: Vec<OpCode>) -> (Vec<OpCode>, bool)
                     return;
                 };
                 let result = value1 == value2;
-                register.insert(*dst, result.into());
                 *opcode = OpCode::LOAD(*dst, result.into());
+                has_changed = true;
             }
             OpCode::MUL(dst, reg1, reg2)
             | OpCode::SUB(dst, reg1, reg2)
@@ -82,6 +85,8 @@ pub fn calculate_static_values(mut opcodes: Vec<OpCode>) -> (Vec<OpCode>, bool)
                         return;
                     }
                 };
+                register.remove(dst);
+
                 if let Some(calculated_value) = match opcode {
                     OpCode::ADD(_, _, _) => number1.checked_add(number2).map(Value::Number),
                     OpCode::MUL(_, _, _) => number1.checked_mul(number2).map(Value::Number),
@@ -89,11 +94,8 @@ pub fn calculate_static_values(mut opcodes: Vec<OpCode>) -> (Vec<OpCode>, bool)
                     OpCode::DIV(_, _, _) => number1.checked_div(number2).map(Value::Number),
                     _ => None,
                 } {
-                    register.insert(*dst, calculated_value.clone());
                     *opcode = OpCode::LOAD(*dst, calculated_value);
                     has_changed = true;
-                } else {
-                    register.remove(dst);
                 }
             }
         };

+ 2 - 13
utxo/src/filter_expr/compiler/optimizations/remove_dead_code.rs

@@ -11,19 +11,7 @@ use std::collections::HashSet;
 pub fn remove_dead_code(mut opcodes: Vec<OpCode>) -> (Vec<OpCode>, bool) {
     let total = opcodes.len();
     // list of opcodes that have been executed
-    let mut executed_opcodes = opcodes
-        .iter()
-        .map(|opcode| {
-            if matches!(
-                opcode,
-                OpCode::LABEL(_) | OpCode::LOAD(_, _) | OpCode::LOAD_EXTERNAL(_, _)
-            ) {
-                1
-            } else {
-                0usize
-            }
-        })
-        .collect::<Vec<_>>();
+    let mut executed_opcodes = opcodes.iter().map(|opcode| 0usize).collect::<Vec<_>>();
 
     // current opcode position
     let mut current = 0;
@@ -36,6 +24,7 @@ pub fn remove_dead_code(mut opcodes: Vec<OpCode>) -> (Vec<OpCode>, bool) {
     let label_to_addr = Compiler::labels_to_addr(&opcodes);
 
     loop {
+        println!("current = {current}");
         match if let Some(opcode) = opcodes.get(current) {
             executed_opcodes[current] += 1;
             opcode

+ 12 - 11
utxo/src/filter_expr/filter.rs

@@ -72,17 +72,18 @@ impl<'a> Filter<'a> {
         self.opcodes = Compiler::remove_dead_code(new_opcodes);
         self.initial_register.clear();
         self.opcodes_to_execute = Compiler::resolve_label_to_addr(
-            self.opcodes
-                .iter()
-                .filter_map(|opcode| match opcode {
-                    OpCode::LOAD(addr, value) => {
-                        self.initial_register
-                            .insert(*addr, ValueOrRef::Value(value.clone()));
-                        None
-                    }
-                    _ => Some(opcode.clone()),
-                })
-                .collect::<Vec<_>>(),
+            self.opcodes.clone(), /*
+                                  self.opcodes
+                                      .iter()
+                                      .filter_map(|opcode| match opcode {
+                                          OpCode::LOAD(addr, value) => {
+                                              self.initial_register
+                                                  .insert(*addr, ValueOrRef::Value(value.clone()));
+                                              None
+                                          }
+                                          _ => Some(opcode.clone()),
+                                      })
+                                      .collect::<Vec<_>>()*/
         )
         .unwrap();
         self

+ 11 - 0
utxo/src/filter_expr/runtime.rs

@@ -77,6 +77,17 @@ pub fn execute<'a>(
                 let new_value = Value::Bool(get!(registers, reg1) == get!(registers, reg2)).into();
                 set!(registers, dst, new_value);
             }
+            OpCode::DIV(dst, reg1, reg2) => {
+                let num1 = get!(registers, reg1).as_number()?;
+                let num2 = get!(registers, reg2).as_number()?;
+                set!(
+                    registers,
+                    dst,
+                    num1.checked_div(num2)
+                        .map(|number| Value::Number(number).into())
+                        .ok_or(Error::Overflow)?
+                );
+            }
             OpCode::MUL(dst, reg1, reg2) => {
                 let num1 = get!(registers, reg1).as_number()?;
                 let num2 = get!(registers, reg2).as_number()?;