|
@@ -70,6 +70,33 @@ impl Filter {
|
|
|
OpCode::LOAD(dst, value) => {
|
|
|
register.insert(*dst, value.clone());
|
|
|
}
|
|
|
+ OpCode::JMP(_)
|
|
|
+ | OpCode::HLT(_)
|
|
|
+ | OpCode::JEQ(_, _)
|
|
|
+ | OpCode::JNE(_, _)
|
|
|
+ | OpCode::LABEL(_) => {}
|
|
|
+ OpCode::MOV(dst, src) => {
|
|
|
+ if let Some(value) = register.remove(src) {
|
|
|
+ register.insert(*dst, value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ OpCode::LOAD_EXTERNAL(dst, _)
|
|
|
+ | OpCode::AND(dst, _, _)
|
|
|
+ | OpCode::OR(dst, _, _)
|
|
|
+ | OpCode::NOT(dst, _)
|
|
|
+ | OpCode::MOD(dst, _, _)
|
|
|
+ | OpCode::NE(dst, _, _)
|
|
|
+ | OpCode::GT(dst, _, _)
|
|
|
+ | OpCode::LT(dst, _, _)
|
|
|
+ | OpCode::NEG(dst, _)
|
|
|
+ | OpCode::SHL(dst, _, _)
|
|
|
+ | OpCode::XOR(dst, _, _)
|
|
|
+ | OpCode::SHR(dst, _, _)
|
|
|
+ | OpCode::GE(dst, _, _)
|
|
|
+ | OpCode::LE(dst, _, _)
|
|
|
+ | OpCode::CPY(dst, _) => {
|
|
|
+ register.remove(dst);
|
|
|
+ }
|
|
|
OpCode::JEQ(reg, addr) => {
|
|
|
if let Some(Value::Bool(true)) = register.get(reg) {
|
|
|
*opcode = OpCode::JMP(*addr);
|
|
@@ -84,14 +111,17 @@ impl Filter {
|
|
|
let value1 = if let Some(value) = register.get(reg1) {
|
|
|
value.clone()
|
|
|
} else {
|
|
|
+ register.remove(dst);
|
|
|
return;
|
|
|
};
|
|
|
let value2 = if let Some(value) = register.get(reg2) {
|
|
|
value.clone()
|
|
|
} else {
|
|
|
+ register.remove(dst);
|
|
|
return;
|
|
|
};
|
|
|
let result = value1 == value2;
|
|
|
+ register.insert(*dst, result.into());
|
|
|
*opcode = OpCode::LOAD(*dst, result.into());
|
|
|
}
|
|
|
OpCode::MUL(dst, reg1, reg2)
|
|
@@ -100,13 +130,18 @@ impl Filter {
|
|
|
| OpCode::ADD(dst, reg1, reg2) => {
|
|
|
let number1 = match register.get(reg1) {
|
|
|
Some(Value::Number(number)) => *number,
|
|
|
- _ => return,
|
|
|
+ _ => {
|
|
|
+ register.remove(dst);
|
|
|
+ return;
|
|
|
+ }
|
|
|
};
|
|
|
let number2 = match register.get(reg2) {
|
|
|
Some(Value::Number(number)) => *number,
|
|
|
- _ => return,
|
|
|
+ _ => {
|
|
|
+ register.remove(dst);
|
|
|
+ return;
|
|
|
+ }
|
|
|
};
|
|
|
-
|
|
|
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),
|
|
@@ -117,9 +152,10 @@ impl Filter {
|
|
|
register.insert(*dst, calculated_value.clone());
|
|
|
*opcode = OpCode::LOAD(*dst, calculated_value);
|
|
|
has_changed = true;
|
|
|
+ } else {
|
|
|
+ register.remove(dst);
|
|
|
}
|
|
|
}
|
|
|
- _ => {}
|
|
|
};
|
|
|
});
|
|
|
has_changed
|
|
@@ -169,6 +205,7 @@ impl Filter {
|
|
|
| OpCode::MUL(set, reg1, reg2)
|
|
|
| OpCode::NE(set, reg1, reg2)
|
|
|
| OpCode::GE(set, reg1, reg2)
|
|
|
+ | OpCode::DIV(set, reg1, reg2)
|
|
|
| OpCode::LE(set, reg1, reg2)
|
|
|
| OpCode::GT(set, reg1, reg2)
|
|
|
| OpCode::LT(set, reg1, reg2)
|
|
@@ -302,6 +339,35 @@ impl Filter {
|
|
|
(self, old_total_opcodes != new_total_opcodes)
|
|
|
}
|
|
|
|
|
|
+ pub fn remove_redundant_load_and_mov(mut self) -> (Self, bool) {
|
|
|
+ let old_total_opcodes = self.opcodes.len();
|
|
|
+ let new_opcodes = self
|
|
|
+ .opcodes
|
|
|
+ .into_iter()
|
|
|
+ .fold(Vec::new(), |mut acc, current| {
|
|
|
+ if let OpCode::MOV(target, from) = ¤t {
|
|
|
+ if let Some(last) = acc.last_mut() {
|
|
|
+ println!("herex: {:?} {:?}", last, current);
|
|
|
+ match last {
|
|
|
+ OpCode::LOAD(reg, _) => {
|
|
|
+ if reg == from {
|
|
|
+ *reg = *target;
|
|
|
+ return acc;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ _ => {}
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ acc.push(current);
|
|
|
+ acc
|
|
|
+ });
|
|
|
+ self.opcodes = new_opcodes;
|
|
|
+ let new_total_opcodes = self.opcodes.len();
|
|
|
+
|
|
|
+ (self, old_total_opcodes != new_total_opcodes)
|
|
|
+ }
|
|
|
+
|
|
|
/// Attempts to optiomize the `raw_opcodes` inside the Filter. Returns a tuple with the new
|
|
|
/// self with the optimized opcodes, and a boolean indicating if the program was optimized.
|
|
|
pub fn optimize_round(mut self) -> (Self, bool) {
|
|
@@ -309,6 +375,8 @@ impl Filter {
|
|
|
let has_changed_register_addresses = self.assign_unique_register_addresses();
|
|
|
let (mut new_self, has_removed_unused_values) = self.remove_unused_values();
|
|
|
let (mut new_self, has_removed_useless_jumps) = new_self.remove_useless_jumps();
|
|
|
+ let (mut new_self, has_removed_redundant_load_and_mov) =
|
|
|
+ new_self.remove_redundant_load_and_mov();
|
|
|
|
|
|
new_self.opcodes_to_execute =
|
|
|
Compiler::resolve_label_to_addr(new_self.opcodes.clone()).unwrap();
|
|
@@ -318,7 +386,8 @@ impl Filter {
|
|
|
has_calculated_static_values
|
|
|
|| has_removed_unused_values
|
|
|
|| has_changed_register_addresses
|
|
|
- || has_removed_useless_jumps,
|
|
|
+ || has_removed_useless_jumps
|
|
|
+ || has_removed_redundant_load_and_mov,
|
|
|
)
|
|
|
}
|
|
|
|
|
@@ -370,7 +439,7 @@ mod test {
|
|
|
r#"
|
|
|
WHERE
|
|
|
$foo = 3 + 2 * 4 / 2 * 298210 + $bar
|
|
|
- AND 25 = 5*5
|
|
|
+ AND 25 = 5*$five
|
|
|
"#,
|
|
|
)
|
|
|
.unwrap();
|
|
@@ -388,6 +457,7 @@ mod test {
|
|
|
let external_variables_1 = vec![
|
|
|
("foo".into(), ValueOrRef::Value(0.into())),
|
|
|
("bar".into(), ValueOrRef::Value(0.into())),
|
|
|
+ ("five".into(), ValueOrRef::Value(5.into())),
|
|
|
]
|
|
|
.into_iter()
|
|
|
.collect();
|
|
@@ -395,6 +465,15 @@ mod test {
|
|
|
let external_variables_2 = vec![
|
|
|
("foo".into(), ValueOrRef::Value(1192844.into())),
|
|
|
("bar".into(), ValueOrRef::Value(1.into())),
|
|
|
+ ("five".into(), ValueOrRef::Value(4.into())),
|
|
|
+ ]
|
|
|
+ .into_iter()
|
|
|
+ .collect();
|
|
|
+
|
|
|
+ let external_variables_3 = vec![
|
|
|
+ ("foo".into(), ValueOrRef::Value(1192844.into())),
|
|
|
+ ("bar".into(), ValueOrRef::Value(1.into())),
|
|
|
+ ("five".into(), ValueOrRef::Value(5.into())),
|
|
|
]
|
|
|
.into_iter()
|
|
|
.collect();
|
|
@@ -403,6 +482,9 @@ mod test {
|
|
|
assert!(matches!(value, Value::Bool(false)));
|
|
|
|
|
|
let value = x.execute(&external_variables_2).expect("valid execution");
|
|
|
+ assert!(matches!(value, Value::Bool(false)));
|
|
|
+
|
|
|
+ let value = x.execute(&external_variables_3).expect("valid execution");
|
|
|
assert!(matches!(value, Value::Bool(true)));
|
|
|
}
|
|
|
}
|