Prechádzať zdrojové kódy

With the compiler_expr optimizations the output needs fewer optimizations

Changed `compiler_expr` so it can receive in which register to store their output.

With this change the compiled code needs fewer optimizations.

Remove
	- assign_unique_register_addresses
	- move_load_top

Add:
	- Remove unread registers, that includes a LOAD that is never reader, or a LOAD that is not read because it was updated
Cesar Rodas 9 mesiacov pred
rodič
commit
d67d386b52

+ 71 - 54
utxo/src/filter_expr/compiler/mod.rs

@@ -37,55 +37,52 @@ impl<'a> Compiler<'a> {
         &mut self,
         expr: &'a Expr,
         exit_label: Addr,
-    ) -> Result<(Vec<OpCode>, Register), Error> {
-        let mut return_value = self.next_register();
+        return_to: Register,
+    ) -> Result<Vec<OpCode>, Error> {
         Ok(match expr {
-            Expr::Variable(name) => (
-                vec![OpCode::LOAD_EXTERNAL(return_value, name.clone())],
-                return_value,
-            ),
-            Expr::Bool(value) => (
-                vec![OpCode::LOAD(return_value, Value::Bool(*value))],
-                return_value,
-            ),
-            Expr::String(string) => (
-                vec![OpCode::LOAD(return_value, Value::String(string.clone()))],
-                return_value,
-            ),
-            Expr::Number(number) => (
-                vec![OpCode::LOAD(return_value, Value::Number(*number))],
-                return_value,
-            ),
+            Expr::Variable(name) => vec![OpCode::LOAD_EXTERNAL(return_to, name.clone())],
+            Expr::Bool(value) => vec![OpCode::LOAD(return_to, Value::Bool(*value))],
+            Expr::String(string) => vec![OpCode::LOAD(return_to, Value::String(string.clone()))],
+            Expr::Number(number) => vec![OpCode::LOAD(return_to, Value::Number(*number))],
             Expr::Op { op, terms } => {
                 let mut opcodes = vec![];
                 let current_exit_label = self.next_label();
 
-                let mut compiled_terms = terms
-                    .iter()
-                    .map(|term| self.compile_expr(term, current_exit_label))
-                    .collect::<Result<Vec<_>, _>>()?;
-
                 match op {
                     ExprOp::Not => {
-                        let (mut opcodes, term_return_value) =
-                            compiled_terms.pop().ok_or(Error::UnexpectedExprState)?;
-                        if !compiled_terms.is_empty() {
+                        if terms.len() != 1 {
                             return Err(Error::UnexpectedExprState);
                         }
-                        opcodes.push(OpCode::NOT(return_value, return_value));
-                        return_value = term_return_value;
+                        let mut opcodes = terms
+                            .first()
+                            .map(|expr| self.compile_expr(expr, exit_label, return_to))
+                            .ok_or(Error::UnexpectedExprState)??;
+                        opcodes.push(OpCode::NOT(return_to, return_to));
                     }
                     ExprOp::Eq => {
-                        let mut iter = compiled_terms.into_iter();
-                        let (mut term_opcodes, last_value) =
-                            iter.next().ok_or(Error::MissingNextRule)?;
-
+                        let first = self.next_register();
+                        let other = self.next_register();
+
+                        let terms = terms
+                            .iter()
+                            .enumerate()
+                            .map(|(idx, term)| {
+                                self.compile_expr(
+                                    term,
+                                    current_exit_label,
+                                    if idx == 0 { first } else { other },
+                                )
+                            })
+                            .collect::<Result<Vec<_>, _>>()?;
+                        let mut iter = terms.into_iter();
+                        let mut term_opcodes = iter.next().ok_or(Error::MissingNextRule)?;
                         opcodes.append(&mut term_opcodes);
+
                         if iter
-                            .map(|(mut term_codes, term_return)| {
+                            .map(|mut term_codes| {
                                 opcodes.append(&mut term_codes);
-                                opcodes.push(OpCode::EQ(return_value, last_value, term_return));
-                                opcodes.push(OpCode::JNE(return_value, exit_label));
+                                opcodes.push(OpCode::EQ(return_to, first, other));
+                                opcodes.push(OpCode::JNE(return_to, exit_label));
                                 1
                             })
                             .sum::<usize>()
@@ -97,32 +94,51 @@ impl<'a> Compiler<'a> {
                         let _ = opcodes.pop();
                     }
                     ExprOp::Add | ExprOp::Mul | ExprOp::Div | ExprOp::Sub => {
-                        let mut iter = compiled_terms.into_iter();
-                        let (mut term_opcodes, return_value) =
-                            iter.next().ok_or(Error::MissingNextRule)?;
+                        let term_return = self.next_register();
+                        let terms = terms
+                            .iter()
+                            .enumerate()
+                            .map(|(idx, term)| {
+                                self.compile_expr(term, current_exit_label, term_return)
+                            })
+                            .collect::<Result<Vec<_>, _>>()?;
+
+                        let mut iter = terms.into_iter();
+                        let mut term_opcodes = iter.next().ok_or(Error::MissingNextRule)?;
                         opcodes.append(&mut term_opcodes);
+                        opcodes.push(OpCode::MOV(return_to, term_return));
 
-                        for (mut term_opcodes, term_return) in iter {
+                        for mut term_opcodes in iter {
                             opcodes.append(&mut term_opcodes);
                             opcodes.push(match op {
-                                ExprOp::Add => OpCode::ADD(return_value, return_value, term_return),
-                                ExprOp::Mul => OpCode::MUL(return_value, return_value, term_return),
-                                ExprOp::Div => OpCode::DIV(return_value, return_value, term_return),
-                                ExprOp::Sub => OpCode::SUB(return_value, return_value, term_return),
+                                ExprOp::Add => OpCode::ADD(return_to, return_to, term_return),
+                                ExprOp::Mul => OpCode::MUL(return_to, return_to, term_return),
+                                ExprOp::Div => OpCode::DIV(return_to, return_to, term_return),
+                                ExprOp::Sub => OpCode::SUB(return_to, return_to, term_return),
                                 _ => unreachable!(),
                             });
                         }
 
-                        return Ok((opcodes, return_value));
+                        return Ok(opcodes);
                     }
                     ExprOp::Or | ExprOp::And => {
-                        opcodes = vec![OpCode::LOAD(return_value, Value::Bool(false))];
-                        for (mut term_opcodes, term_return_value) in compiled_terms.into_iter() {
+                        opcodes = vec![OpCode::LOAD(return_to, Value::Bool(false))];
+
+                        let terms = terms
+                            .iter()
+                            .enumerate()
+                            .map(|(idx, term)| {
+                                self.compile_expr(term, current_exit_label, return_to)
+                            })
+                            .collect::<Result<Vec<_>, _>>()?;
+
+                        let mut iter = terms.into_iter();
+
+                        for mut term_opcodes in iter.into_iter() {
                             opcodes.append(&mut term_opcodes);
-                            opcodes.push(OpCode::MOV(return_value, term_return_value));
                             match op {
-                                ExprOp::Or => opcodes.push(OpCode::JEQ(return_value, exit_label)),
-                                ExprOp::And => opcodes.push(OpCode::JNE(return_value, exit_label)),
+                                ExprOp::Or => opcodes.push(OpCode::JEQ(return_to, exit_label)),
+                                ExprOp::And => opcodes.push(OpCode::JNE(return_to, exit_label)),
                                 _ => unreachable!(),
                             };
                         }
@@ -131,20 +147,20 @@ impl<'a> Compiler<'a> {
                 }
 
                 opcodes.push(OpCode::LABEL(current_exit_label));
-                (opcodes, return_value)
+                opcodes
             }
         })
     }
 
     pub fn optimize(opcodes: Vec<OpCode>) -> (Vec<OpCode>, bool) {
         vec![
-            optimizations::assign_unique_register_addresses,
+            //optimizations::assign_unique_register_addresses,
             optimizations::remove_redundant_load_and_mov,
             optimizations::remove_unused_values,
             optimizations::calculate_static_values,
             optimizations::remove_useless_jumps,
             optimizations::remove_dead_code,
-            optimizations::move_load_top,
+            //optimizations::move_load_top,
         ]
         .into_iter()
         .fold((opcodes, false), |(opcodes, has_optimized), f| {
@@ -211,9 +227,10 @@ impl<'a> Compiler<'a> {
 
     pub fn compile(mut self) -> Result<Vec<OpCode>, Error> {
         let program_exit = self.next_label();
-        let (mut opcodes, return_value) = self.compile_expr(self.expr, program_exit)?;
+        let return_to = self.next_register();
+        let mut opcodes = self.compile_expr(self.expr, program_exit, return_to)?;
         opcodes.push(OpCode::LABEL(program_exit));
-        opcodes.push(OpCode::HLT(return_value));
+        opcodes.push(OpCode::HLT(return_to));
         Ok(opcodes)
     }
 }

+ 0 - 1
utxo/src/filter_expr/compiler/optimizations/remove_unused_values.rs

@@ -15,7 +15,6 @@ pub fn remove_unused_values(mut opcodes: Vec<OpCode>) -> (Vec<OpCode>, bool) {
             OpCode::NOT(_, reg1)
             | OpCode::CPY(_, reg1)
             | OpCode::MOV(_, reg1)
-            | OpCode::JEQ(reg1, _)
             | OpCode::SHL(_, reg1, _)
             | OpCode::SHR(_, reg1, _)
             | OpCode::NEG(_, reg1)

+ 1 - 1
utxo/src/filter_expr/expr.pest

@@ -10,7 +10,7 @@ not_expr     = { (^"NOT" | "!") ~ logical_expr }
 comparison   = { sum ~ (comp_op ~ sum)? }
 sum          = { product ~ (add_op ~ product)* }
 product      = { factor ~ (mul_op ~ factor)* }
-factor       = { number | string | variable  | bool | "(" ~ logical_expr ~ ")" }
+factor       = { number | string | bool | variable  |  "(" ~ logical_expr ~ ")" }
 comp_op      = { "=" | "!=" | "<" | "<=" | ">" | ">=" }
 add_op       = { "+" | "-" }
 mul_op       = { "*" | "/" }