we have a basic optimizer going! lets goo!!!!!

This commit is contained in:
SpookyDervish
2025-09-08 20:21:36 +10:00
parent 9bae73f1e1
commit 24db80b520
6 changed files with 169 additions and 42 deletions

View File

@@ -429,4 +429,4 @@ class X86_64Generator(Generator):
f.write("section .text\n") f.write("section .text\n")
optimizer = X86_64Optimizer(self.lines) optimizer = X86_64Optimizer(self.lines)
f.write(optimizer.peephole()) f.writelines(optimizer.peephole())

View File

@@ -1,11 +1,81 @@
from typing import List, Dict, NamedTuple, Union
import re
class Instruction(NamedTuple):
opcode: str
operands: List[str]
class PeepholeRule(NamedTuple):
match: List[Instruction]
replace: List[Instruction]
class Optimizer: class Optimizer:
def __init__(self, lines: list[str]): def __init__(self, lines: list[str], window_size: int = 5):
self.lines = lines self.lines = lines
self.final_str = "" self.final_str = ""
# sliding window pos # sliding window
self.pos = 0 self.window_size = window_size
self.rules: list[PeepholeRule] = []
def match_instruction(self, pattern: Instruction, instr: Instruction, bindings: Dict[str, str]) -> bool:
if pattern.opcode != instr.opcode:
return False
if len(pattern.operands) != len(instr.operands):
return False
for p_op, i_op in zip(pattern.operands, instr.operands):
if p_op.isidentifier(): # wildcard like 'x'
if p_op in bindings:
if bindings[p_op] != i_op:
return False
else:
bindings[p_op] = i_op
else:
if p_op != i_op:
return False
return True
def match_window(self, patterns: List[Instruction], window: List[Instruction]) -> Union[Dict[str, str], None]:
if len(patterns) != len(window):
return None
bindings = {}
for p, i in zip(patterns, window):
if not self.match_instruction(p, i, bindings):
return None
return bindings
def parse_instruction(self, line: str) -> Instruction:
# Assumes format: OPCODE operand1, operand2
parts = line.strip().split(None, 1)
opcode = parts[0]
operands = re.split(r'\s*,\s*', parts[1]) if len(parts) > 1 else []
return Instruction(opcode, operands)
def apply_replacement(self, replacements: List[Instruction], bindings: dict[str, str]) -> List[Instruction]:
result = []
for pattern in replacements:
operands = [bindings.get(op, op) for op in pattern.operands]
result.append(Instruction(pattern.opcode, operands))
return result
def peephole(self): def peephole(self):
pass self.lines = [self.parse_instruction(line) for line in self.lines]
i = 0
while i < len(self.lines):
matched = False
for rule in self.rules:
window = self.lines[i:i+len(rule.match)]
bindings = self.match_window(rule.match, window)
if bindings is not None:
replacement_instrs = self.apply_replacement(rule.replace, bindings)
self.lines[i:i + len(rule.match)] = replacement_instrs
matched = True
break
if not matched:
i += 1
self.lines = [f"{line.opcode} {', '.join(line.operands)}\n" for line in self.lines]
return self.lines

View File

@@ -1,11 +1,59 @@
from optimizers.optimizer import Optimizer from optimizers.optimizer import Optimizer, PeepholeRule, Instruction
class X86_64Optimizer(Optimizer): class X86_64Optimizer(Optimizer):
def peephole(self): def __init__(self, lines, window_size = 5):
lines = [] super().__init__(lines, window_size)
self.rules = [
for line in self.lines: PeepholeRule(
lines.append(line) match=[
Instruction("setg",["al"]),
self.final_str = ''.join(lines) Instruction("movzx", ["rax", "al"]),
return self.final_str Instruction("push", ["rax"]),
Instruction("mov", ["eax", "x"]),
Instruction("test", ["eax", "eax"]),
Instruction("jnz", ["y"])
],
replace=[
Instruction("jg", ["y"])
]
),
PeepholeRule(
match=[
Instruction("setl",["al"]),
Instruction("movzx", ["rax", "al"]),
Instruction("push", ["rax"]),
Instruction("mov", ["eax", "x"]),
Instruction("test", ["eax", "eax"]),
Instruction("jnz", ["y"])
],
replace=[
Instruction("jl", ["y"])
]
),
PeepholeRule(
match=[
Instruction("sete",["al"]),
Instruction("movzx", ["rax", "al"]),
Instruction("push", ["rax"]),
Instruction("mov", ["eax", "x"]),
Instruction("test", ["eax", "eax"]),
Instruction("jnz", ["y"])
],
replace=[
Instruction("je", ["y"])
]
),
PeepholeRule(
match=[
Instruction("setne",["al"]),
Instruction("movzx", ["rax", "al"]),
Instruction("push", ["rax"]),
Instruction("mov", ["eax", "x"]),
Instruction("test", ["eax", "eax"]),
Instruction("jnz", ["y"])
],
replace=[
Instruction("jne", ["y"])
]
),
]

BIN
out

Binary file not shown.

49
out.asm
View File

@@ -1,27 +1,34 @@
; ~~~ Auto generated by the GroundPY compiler for Linux x86_64 targets. ~~~ ; ~~~ Auto generated by the GroundPY compiler for Linux x86_64 targets. ~~~
section .data section .data
.LC0: db "yes", 10, 0
.LC1: equ $ - .LC0
.LC2: db "no", 10, 0
.LC3: equ $ - .LC2
section .text section .text
global _start global _start
_start: _start:
mov rax, 0 mov rax, 123
push rax push rax
mov rax, 0 mov rax, 100000000
push rax mov rbx, [rsp + 0]
.loop: cmp rax, rbx
mov rax, [rsp + 8] jg .yes
add rax, 1 .yes:
mov QWORD [rsp + 8], rax mov rsi, .LC0
mov rax, 100000000 mov rdx, .LC1
mov rbx, [rsp + 8] mov rax, 1
cmp rax, rbx mov rdi, 1
setg al syscall
movzx rax, al mov rax, 60
mov QWORD [rsp + 0], rax mov rdi, 0
mov eax, [rsp + 0] syscall
test eax, eax .no:
jnz .loop mov rsi, .LC2
mov rax, 60 mov rdx, .LC3
mov rdi, [rsp + 0] mov rax, 1
syscall mov rdi, 1
syscall
mov rax, 60
mov rdi, 0
syscall

View File

@@ -1,7 +1,9 @@
set &x 0 set &x 123
set &cond 0
@loop
add $x 1 &x
greater 100000000 $x &cond greater 100000000 $x &cond
if $cond %loop if $cond %yes
end $cond @yes
stdout "yes\n"
end 0
@no
stdout "no\n"
end 0