diff --git a/rust_compiler/libs/integration_tests/src/lib.rs b/rust_compiler/libs/integration_tests/src/lib.rs index e59086a..70d95ef 100644 --- a/rust_compiler/libs/integration_tests/src/lib.rs +++ b/rust_compiler/libs/integration_tests/src/lib.rs @@ -172,4 +172,37 @@ mod tests { let output = compile_with_and_without_optimization(source); insta::assert_snapshot!(output); } + + #[test] + fn test_tuples() { + let source = indoc! {r#" + device self = "db"; + device day = "d0"; + + fn getSomethingElse(input) { + return input + 1; + } + + fn getSensorData() { + return ( + day.Vertical, + day.Horizontal, + getSomethingElse(3) + ); + } + + loop { + yield(); + + let (vertical, horizontal, _) = getSensorData(); + + (horizontal, _, _) = getSensorData(); + + self.Setting = horizontal; + } + "#}; + + let output = compile_with_and_without_optimization(source); + insta::assert_snapshot!(output); + } } diff --git a/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__algebraic_simplification.snap b/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__algebraic_simplification.snap index aa56204..ce3aa70 100644 --- a/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__algebraic_simplification.snap +++ b/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__algebraic_simplification.snap @@ -12,7 +12,6 @@ move r9 r1 ## Optimized Output -j 1 move r8 5 move r1 5 move r9 5 diff --git a/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__complex_arithmetic.snap b/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__complex_arithmetic.snap index 724ef55..2f210a5 100644 --- a/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__complex_arithmetic.snap +++ b/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__complex_arithmetic.snap @@ -43,7 +43,6 @@ move r13 r3 add r4 r11 r12 add r5 r4 r13 move r15 r5 -j 16 pop ra pop sp j ra diff --git a/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__constant_folding.snap b/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__constant_folding.snap index 2f4fcf3..075159a 100644 --- a/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__constant_folding.snap +++ b/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__constant_folding.snap @@ -10,5 +10,4 @@ move r8 15 ## Optimized Output -j 1 move r8 15 diff --git a/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__dead_code_elimination.snap b/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__dead_code_elimination.snap index a54418d..febd0c6 100644 --- a/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__dead_code_elimination.snap +++ b/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__dead_code_elimination.snap @@ -26,7 +26,6 @@ push sp push ra add r1 r8 1 move r15 r1 -j 7 pop ra pop sp j ra diff --git a/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__function_with_call.snap b/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__function_with_call.snap index 456c6c2..1c46e9c 100644 --- a/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__function_with_call.snap +++ b/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__function_with_call.snap @@ -38,7 +38,6 @@ push sp push ra add r1 r9 r8 move r15 r1 -j 8 pop ra pop sp j ra diff --git a/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__leaf_function_no_stack_frame.snap b/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__leaf_function_no_stack_frame.snap index 9483d59..991eafb 100644 --- a/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__leaf_function_no_stack_frame.snap +++ b/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__leaf_function_no_stack_frame.snap @@ -19,4 +19,5 @@ j ra ## Optimized Output j main +pop r8 j ra diff --git a/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__nested_function_calls.snap b/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__nested_function_calls.snap index 6763d25..ec9b376 100644 --- a/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__nested_function_calls.snap +++ b/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__nested_function_calls.snap @@ -68,16 +68,15 @@ push sp push ra add r1 r9 r8 move r15 r1 -j 8 pop ra pop sp j ra +pop r8 pop r9 push sp push ra add r1 r9 r9 move r15 r1 -j 17 pop ra pop sp j ra @@ -99,9 +98,11 @@ push r10 push r10 push 2 jal 11 +pop r10 +pop r9 +pop r8 move r11 r15 move r15 r11 -j 41 pop ra pop sp j ra diff --git a/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__select_optimization.snap b/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__select_optimization.snap index 941527a..f881b54 100644 --- a/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__select_optimization.snap +++ b/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__select_optimization.snap @@ -31,7 +31,6 @@ push sp push ra select r9 r8 10 20 move r15 r9 -j 7 pop ra pop sp j ra diff --git a/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__strength_reduction.snap b/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__strength_reduction.snap index 73093d4..93d5295 100644 --- a/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__strength_reduction.snap +++ b/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__strength_reduction.snap @@ -25,7 +25,6 @@ push sp push ra add r1 r8 r8 move r15 r1 -j 7 pop ra pop sp j ra diff --git a/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__tuples.snap b/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__tuples.snap new file mode 100644 index 0000000..1842e80 --- /dev/null +++ b/rust_compiler/libs/integration_tests/src/snapshots/integration_tests__tests__tuples.snap @@ -0,0 +1,94 @@ +--- +source: libs/integration_tests/src/lib.rs +expression: output +--- +## Unoptimized Output + +j main +getSomethingElse: +pop r8 +push sp +push ra +add r1 r8 1 +move r15 r1 +j __internal_L1 +__internal_L1: +pop ra +pop sp +j ra +getSensorData: +push sp +push ra +l r1 d0 Vertical +push r1 +l r2 d0 Horizontal +push r2 +push 3 +jal getSomethingElse +move r3 r15 +push r3 +sub r0 sp 5 +get r0 db r0 +move r15 r0 +j __internal_L2 +__internal_L2: +sub r0 sp 4 +get ra db r0 +j ra +main: +__internal_L3: +yield +jal getSensorData +pop r0 +pop r9 +pop r8 +move sp r15 +jal getSensorData +pop r0 +pop r0 +pop r9 +move sp r15 +s db Setting r9 +j __internal_L3 +__internal_L4: + +## Optimized Output + +j 27 +pop r8 +push sp +push ra +add r1 r8 1 +move r15 r1 +pop ra +pop sp +j ra +push sp +push ra +l r1 d0 Vertical +push r1 +l r2 d0 Horizontal +push r2 +push 3 +jal 1 +move r3 r15 +push r3 +sub r0 sp 5 +get r0 db r0 +move r15 r0 +sub r0 sp 4 +get ra db r0 +j ra +yield +jal 10 +pop r0 +pop r9 +pop r8 +move sp r15 +jal 10 +pop r0 +pop r0 +pop r9 +move sp r15 +s db Setting r9 +j 27 diff --git a/rust_compiler/libs/optimizer/src/dead_code.rs b/rust_compiler/libs/optimizer/src/dead_code.rs index feb1e73..18687de 100644 --- a/rust_compiler/libs/optimizer/src/dead_code.rs +++ b/rust_compiler/libs/optimizer/src/dead_code.rs @@ -1,4 +1,4 @@ -use il::{Instruction, InstructionNode}; +use il::{Instruction, InstructionNode, Operand}; /// Pass: Redundant Move Elimination /// Removes moves where source and destination are the same: `move rx rx` @@ -43,6 +43,31 @@ pub fn remove_unreachable_code<'a>( (output, changed) } +/// Pass: Remove Redundant Jumps +/// Removes jumps to the next instruction (after label resolution). +/// Must run AFTER label resolution since it needs line numbers. +pub fn remove_redundant_jumps<'a>( + input: Vec>, +) -> (Vec>, bool) { + let mut output = Vec::with_capacity(input.len()); + let mut changed = false; + + for (i, node) in input.iter().enumerate() { + // Check if this is a jump to the next line number + if let Instruction::Jump(Operand::Number(target)) = &node.instruction { + // Current line number is i, next line number is i+1 + // If jump target equals the next line, it's redundant + if target.to_string().parse::().ok() == Some(i + 1) { + changed = true; + continue; // Skip this redundant jump + } + } + output.push(node.clone()); + } + + (output, changed) +} + #[cfg(test)] mod tests { use super::*; diff --git a/rust_compiler/libs/optimizer/src/dead_store_elimination.rs b/rust_compiler/libs/optimizer/src/dead_store_elimination.rs index 12c39e6..f6b5adc 100644 --- a/rust_compiler/libs/optimizer/src/dead_store_elimination.rs +++ b/rust_compiler/libs/optimizer/src/dead_store_elimination.rs @@ -13,13 +13,20 @@ pub fn dead_store_elimination<'a>( // Scan for dead writes for (i, node) in input.iter().enumerate() { + // Never remove Pop instructions - they have critical side effects on the stack pointer + if matches!(node.instruction, Instruction::Pop(_)) { + continue; + } + if let Some(dest_reg) = get_destination_reg(&node.instruction) { // If this register was written before and hasn't been read, previous write is dead if let Some(&prev_idx) = last_write.get(&dest_reg) { // Check if the value was ever used between prev_idx and current let was_used = input[prev_idx + 1..i] .iter() - .any(|n| reg_is_read_or_affects_control(&n.instruction, dest_reg)); + .any(|n| reg_is_read_or_affects_control(&n.instruction, dest_reg)) + // Also check if current instruction reads the register before overwriting it + || reg_is_read_or_affects_control(&node.instruction, dest_reg); if !was_used { // Previous write was dead diff --git a/rust_compiler/libs/optimizer/src/lib.rs b/rust_compiler/libs/optimizer/src/lib.rs index 204e78d..74399b2 100644 --- a/rust_compiler/libs/optimizer/src/lib.rs +++ b/rust_compiler/libs/optimizer/src/lib.rs @@ -17,7 +17,7 @@ mod strength_reduction; use algebraic_simplification::algebraic_simplification; use constant_propagation::constant_propagation; -use dead_code::{remove_redundant_moves, remove_unreachable_code}; +use dead_code::{remove_redundant_jumps, remove_redundant_moves, remove_unreachable_code}; use dead_store_elimination::dead_store_elimination; use function_call_optimization::optimize_function_calls; use label_resolution::resolve_labels; @@ -91,5 +91,10 @@ pub fn optimize<'a>(instructions: Instructions<'a>) -> Instructions<'a> { } // Final Pass: Resolve Labels to Line Numbers - Instructions::new(resolve_labels(instructions)) + let mut instructions = resolve_labels(instructions); + + // Post-resolution Pass: Remove redundant jumps (must run after label resolution) + let (instructions, _) = remove_redundant_jumps(instructions); + + Instructions::new(instructions) }