From db4f37709f0e94b667cd14a4e8fac30d4cce8180 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Mon, 29 Apr 2024 21:53:50 +0300 Subject: [PATCH] Optimize consecutive mov/add/sub instructions to single instruction --- 04_semantics_and_running/main.py | 92 +++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 2 deletions(-) diff --git a/04_semantics_and_running/main.py b/04_semantics_and_running/main.py index 2b41778..e218a0e 100644 --- a/04_semantics_and_running/main.py +++ b/04_semantics_and_running/main.py @@ -335,6 +335,7 @@ class CompileData: i = 0 # Remove redundant movq instructions + # movq %rax, %rax while i < len(instructions): if instructions[i].opcode != 'movq' or instructions[i].operands[0] != instructions[i].operands[1]: i += 1 @@ -345,7 +346,11 @@ class CompileData: i = 0 # Optimize movq to register followed by pushq register - while i < len(instructions): + # movq $1, %rax + # pushq %rax + # becomes + # pushq $1 + while i < len(instructions) - 1: if instructions[i].opcode != 'movq' or instructions[i + 1].opcode != 'pushq': i += 1 continue @@ -360,7 +365,11 @@ class CompileData: i = 0 # Optimize movq to rax followed by movq from rax - while i < len(instructions): + # movq $1, %rax + # movq %rax, %rcx + # becomes + # movq $1, %rcx + while i < len(instructions) - 1: if instructions[i].opcode != 'movq' or instructions[i + 1].opcode != 'movq': i += 1 continue @@ -379,8 +388,84 @@ class CompileData: changed = True if changed: continue + i = 0 + # Replace negative immediate in addq/subq with positive immediate + # This is not a real optimization, but it makes the code easier to optimize + # subq $-1, %rax + # becomes + # addq $1, %rax + while i < len(instructions): + if instructions[i].opcode not in ['addq', 'subq']: + i += 1 + continue + if instructions[i].operands[1][0] != '$': + i += 1 + continue + value = int(instructions[i].operands[1][1:]) + if value >= 0: + i += 1 + continue + new_opcode = 'subq' if instructions[i].opcode == 'addq' else 'addq' + instructions[i] = Instruction(new_opcode, [instructions[i].operands[0], f'${-value}']) + changed = True + if changed: continue + + i = 0 + # Optimize repeated addq/subq instructions + # addq $1, %rax + # addq $2, %rax + # becomes + # addq $3, %rax + while i < len(instructions) - 1: + if instructions[i].opcode not in ['addq', 'subq']: + i += 1 + continue + if instructions[i].operands[1] != instructions[i + 1].operands[1]: + i += 1 + continue + lhs = int(instructions[i].operands[0][1:]) + if instructions[i].opcode == 'subq': lhs = -lhs + rhs = int(instructions[i + 1].operands[0][1:]) + if instructions[i + 1].opcode == 'subq': rhs = -rhs + new_value = lhs + rhs + new_opcode = 'addq' if new_value >= 0 else 'subq' + instructions[i] = Instruction(new_opcode, [f'${abs(new_value)}', instructions[i].operands[1]]) + instructions.pop(i + 1) + i -= 1 + changed = True + if changed: continue + + i = 0 + # Optimize movq immediate to register followed addq/subq with immediate + # movq $1, %rax + # addq $2, %rax + # becomes + # movq $3, %rax + while i < len(instructions) - 1: + if instructions[i].opcode != 'movq' or instructions[i + 1].opcode not in ['addq', 'subq']: + i += 1 + continue + if instructions[i].operands[1] != instructions[i + 1].operands[1]: + i += 1 + continue + if instructions[i].operands[0][0] != '$' or instructions[i + 1].operands[0][0] != '$': + i += 1 + continue + lhs = int(instructions[i].operands[0][1:]) + rhs = int(instructions[i + 1].operands[0][1:]) + if instructions[i + 1].opcode == 'subq': rhs = -rhs + new_value = lhs + rhs + instructions[i] = Instruction('movq', [f'${new_value}', instructions[i].operands[1]]) + instructions.pop(i + 1) + i -= 1 + changed = True + if changed: continue + i = 0 # Optimize addq/subq for immediate 1 + # addq $1, %rax + # becomes + # incq %rax while i < len(instructions): if instructions[i].opcode not in ['addq', 'subq']: i += 1 @@ -395,6 +480,9 @@ class CompileData: i = 0 # Optimize zeroing of register + # movq $0, %rax + # becomes + # xorq %rax, %rax while i < len(instructions): if instructions[i].opcode != 'movq': i += 1