Ver Fonte

Check there is no jump between the checks

Jumps between loads make the analysis useless, and the LOAD cannot be removed safely
Cesar Rodas há 10 meses atrás
pai
commit
535247fb00

+ 1 - 1
utxo/src/filter_expr/compiler/mod.rs

@@ -154,8 +154,8 @@ impl<'a> Compiler<'a> {
 
     pub fn optimize(opcodes: Vec<OpCode>) -> (Vec<OpCode>, bool) {
         vec![
-            optimizations::remove_redundant_load_and_mov,
             optimizations::remove_unused_load,
+            optimizations::remove_redundant_load_and_mov,
             optimizations::calculate_static_values,
             optimizations::remove_useless_jumps,
             optimizations::remove_dead_code,

+ 18 - 1
utxo/src/filter_expr/compiler/optimizations/remove_unused_load.rs

@@ -81,6 +81,7 @@ pub fn remove_unused_load(mut opcodes: Vec<OpCode>) -> (Vec<OpCode>, bool) {
         });
 
     let old_total_opcodes = opcodes.len();
+    let old_opcodes = opcodes.clone();
 
     // remove unused registers. If the register has not been read by any opcode, then it can be
     // removed.
@@ -104,10 +105,26 @@ pub fn remove_unused_load(mut opcodes: Vec<OpCode>) -> (Vec<OpCode>, bool) {
                         next
                     });
 
+                if let Some(next_load) = next_load {
+                    if old_opcodes[pos..next_load].iter().any(|opcode| {
+                        matches!(
+                            opcode,
+                            OpCode::JEQ(_, _) | OpCode::JMP(_) | OpCode::JNE(_, _)
+                        )
+                    }) {
+                        // Between the current LOAD and the next time is updated, either with
+                        // another LOAD or another OpCode that updates this register there is a
+                        // jump, making it too complex to determine right now if the register is
+                        // used or not, it is safer just to keep it until further analysis is
+                        // implemented
+                        return Some(opcode);
+                    }
+                }
+
                 if let Some(readed_at) = used_registers.get(dst) {
                     if readed_at.iter().any(|readed_at| {
                         if let Some(next_load) = next_load {
-                            *readed_at < next_load && *readed_at > pos
+                            *readed_at <= next_load && *readed_at >= pos
                         } else if *readed_at > pos {
                             true
                         } else {