diff --git a/generators/x86_64.py b/generators/x86_64.py index e704b08..de1f285 100644 --- a/generators/x86_64.py +++ b/generators/x86_64.py @@ -429,4 +429,4 @@ class X86_64Generator(Generator): f.write("section .text\n") optimizer = X86_64Optimizer(self.lines) - f.writelines(optimizer.peephole()) \ No newline at end of file + f.writelines(optimizer.optimize_until_stable()) \ No newline at end of file diff --git a/optimizers/optimizer.py b/optimizers/optimizer.py index 05a3c2c..00ee9cf 100644 --- a/optimizers/optimizer.py +++ b/optimizers/optimizer.py @@ -1,5 +1,6 @@ from typing import List, Dict, NamedTuple, Union import re +from console import console class Instruction(NamedTuple): @@ -11,7 +12,7 @@ class PeepholeRule(NamedTuple): replace: List[Instruction] class Optimizer: - def __init__(self, lines: list[str], window_size: int = 5): + def __init__(self, lines: list[str], window_size: int = 6): self.lines = lines self.final_str = "" @@ -20,6 +21,7 @@ class Optimizer: self.rules: list[PeepholeRule] = [] def match_instruction(self, pattern: Instruction, instr: Instruction, bindings: Dict[str, str]) -> bool: + #print(pattern.opcode == instr.opcode, instr.opcode, instr.operands, pattern.opcode) if pattern.opcode != instr.opcode: return False if len(pattern.operands) != len(instr.operands): @@ -59,6 +61,17 @@ class Optimizer: operands = [bindings.get(op, op) for op in pattern.operands] result.append(Instruction(pattern.opcode, operands)) return result + + def optimize_until_stable(self): + while True: + passes = 1 + old_instructions = self.lines + new_instructions = self.peephole() + if old_instructions == new_instructions: + print(f"Optimized in {passes} passes.") + return new_instructions + old_instructions = new_instructions + passes += 1 def peephole(self): self.lines = [self.parse_instruction(line) for line in self.lines] diff --git a/optimizers/x86_64.py b/optimizers/x86_64.py index 709b628..89a5009 100644 --- a/optimizers/x86_64.py +++ b/optimizers/x86_64.py @@ -17,6 +17,20 @@ class X86_64Optimizer(Optimizer): Instruction("jg", ["y"]) ] ), + PeepholeRule( + match=[ + Instruction("setg",["al"]), + Instruction("movzx", ["rax", "al"]), + Instruction("mov", ["z", "rax"]), + Instruction("mov", ["eax", "x"]), + Instruction("test", ["eax", "eax"]), + Instruction("jnz", ["y"]) + ], + replace=[ + Instruction("jg", ["y"]) + ] + ), + PeepholeRule( match=[ Instruction("setl",["al"]), @@ -30,6 +44,20 @@ class X86_64Optimizer(Optimizer): Instruction("jl", ["y"]) ] ), + PeepholeRule( + match=[ + Instruction("setl",["al"]), + Instruction("movzx", ["rax", "al"]), + Instruction("mov", ["z", "rax"]), + Instruction("mov", ["eax", "x"]), + Instruction("test", ["eax", "eax"]), + Instruction("jnz", ["y"]) + ], + replace=[ + Instruction("jl", ["y"]) + ] + ), + PeepholeRule( match=[ Instruction("sete",["al"]), @@ -43,6 +71,20 @@ class X86_64Optimizer(Optimizer): Instruction("je", ["y"]) ] ), + PeepholeRule( + match=[ + Instruction("sete",["al"]), + Instruction("movzx", ["rax", "al"]), + Instruction("mov", ["z", "rax"]), + Instruction("mov", ["eax", "x"]), + Instruction("test", ["eax", "eax"]), + Instruction("jnz", ["y"]) + ], + replace=[ + Instruction("je", ["y"]) + ] + ), + PeepholeRule( match=[ Instruction("setne",["al"]), @@ -56,4 +98,27 @@ class X86_64Optimizer(Optimizer): Instruction("jne", ["y"]) ] ), + PeepholeRule( + match=[ + Instruction("setne",["al"]), + Instruction("movzx", ["rax", "al"]), + Instruction("mov", ["z", "rax"]), + Instruction("mov", ["eax", "x"]), + Instruction("test", ["eax", "eax"]), + Instruction("jnz", ["y"]) + ], + replace=[ + Instruction("jne", ["y"]) + ] + ), + + PeepholeRule( + match=[ + Instruction("mov", ["rax", "x"]), + Instruction("push", ["rax"]) + ], + replace=[ + Instruction("push", ["x"]) + ] + ) ] \ No newline at end of file diff --git a/out b/out index a9a5b34..b0bed4d 100644 Binary files a/out and b/out differ diff --git a/out.asm b/out.asm index e8f9ea2..012f102 100644 --- a/out.asm +++ b/out.asm @@ -1,34 +1,19 @@ ; ~~~ Auto generated by the GroundPY compiler for Linux x86_64 targets. ~~~ section .data -.LC0: db "yes", 10, 0 -.LC1: equ $ - .LC0 -.LC2: db "no", 10, 0 -.LC3: equ $ - .LC2 section .text global _start _start: -mov rax, 123 -push rax +push 0 +push 1 +.loop: +mov rax, [rsp + 8] +add rax, 1 +mov QWORD [rsp + 8], rax mov rax, 100000000 -mov rbx, [rsp + 0] +mov rbx, [rsp + 8] cmp rax, rbx -jg .yes -.yes: -mov rsi, .LC0 -mov rdx, .LC1 -mov rax, 1 -mov rdi, 1 -syscall +jg .loop mov rax, 60 -mov rdi, 0 -syscall -.no: -mov rsi, .LC2 -mov rdx, .LC3 -mov rax, 1 -mov rdi, 1 -syscall -mov rax, 60 -mov rdi, 0 +mov rdi, [rsp + 8] syscall diff --git a/test2.grnd b/test2.grnd index 4966a87..573e90f 100644 --- a/test2.grnd +++ b/test2.grnd @@ -1,9 +1,7 @@ -set &x 123 -greater 100000000 $x &cond -if $cond %yes -@yes -stdout "yes\n" -end 0 -@no -stdout "no\n" -end 0 \ No newline at end of file +set &var 0 +set &cond true +@loop +add $var 1 &var +greater 100000000 $var &cond +if $cond %loop +end $var \ No newline at end of file