we have a basic optimizer going! lets goo!!!!!
This commit is contained in:
@@ -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())
|
@@ -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
|
@@ -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"])
|
||||||
|
]
|
||||||
|
),
|
||||||
|
]
|
41
out.asm
41
out.asm
@@ -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
|
|
||||||
push rax
|
|
||||||
.loop:
|
|
||||||
mov rax, [rsp + 8]
|
|
||||||
add rax, 1
|
|
||||||
mov QWORD [rsp + 8], rax
|
|
||||||
mov rax, 100000000
|
mov rax, 100000000
|
||||||
mov rbx, [rsp + 8]
|
mov rbx, [rsp + 0]
|
||||||
cmp rax, rbx
|
cmp rax, rbx
|
||||||
setg al
|
jg .yes
|
||||||
movzx rax, al
|
.yes:
|
||||||
mov QWORD [rsp + 0], rax
|
mov rsi, .LC0
|
||||||
mov eax, [rsp + 0]
|
mov rdx, .LC1
|
||||||
test eax, eax
|
mov rax, 1
|
||||||
jnz .loop
|
mov rdi, 1
|
||||||
mov rax, 60
|
syscall
|
||||||
mov rdi, [rsp + 0]
|
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
|
||||||
syscall
|
syscall
|
||||||
|
|
14
test2.grnd
14
test2.grnd
@@ -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
|
Reference in New Issue
Block a user