Optimize consecutive mov/add/sub instructions to single instruction
This commit is contained in:
parent
1e8bdf6cd2
commit
db4f37709f
|
@ -335,6 +335,7 @@ class CompileData:
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
# Remove redundant movq instructions
|
# Remove redundant movq instructions
|
||||||
|
# movq %rax, %rax
|
||||||
while i < len(instructions):
|
while i < len(instructions):
|
||||||
if instructions[i].opcode != 'movq' or instructions[i].operands[0] != instructions[i].operands[1]:
|
if instructions[i].opcode != 'movq' or instructions[i].operands[0] != instructions[i].operands[1]:
|
||||||
i += 1
|
i += 1
|
||||||
|
@ -345,7 +346,11 @@ class CompileData:
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
# Optimize movq to register followed by pushq register
|
# 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':
|
if instructions[i].opcode != 'movq' or instructions[i + 1].opcode != 'pushq':
|
||||||
i += 1
|
i += 1
|
||||||
continue
|
continue
|
||||||
|
@ -360,7 +365,11 @@ class CompileData:
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
# Optimize movq to rax followed by movq from rax
|
# 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':
|
if instructions[i].opcode != 'movq' or instructions[i + 1].opcode != 'movq':
|
||||||
i += 1
|
i += 1
|
||||||
continue
|
continue
|
||||||
|
@ -379,8 +388,84 @@ class CompileData:
|
||||||
changed = True
|
changed = True
|
||||||
if changed: continue
|
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
|
i = 0
|
||||||
# Optimize addq/subq for immediate 1
|
# Optimize addq/subq for immediate 1
|
||||||
|
# addq $1, %rax
|
||||||
|
# becomes
|
||||||
|
# incq %rax
|
||||||
while i < len(instructions):
|
while i < len(instructions):
|
||||||
if instructions[i].opcode not in ['addq', 'subq']:
|
if instructions[i].opcode not in ['addq', 'subq']:
|
||||||
i += 1
|
i += 1
|
||||||
|
@ -395,6 +480,9 @@ class CompileData:
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
# Optimize zeroing of register
|
# Optimize zeroing of register
|
||||||
|
# movq $0, %rax
|
||||||
|
# becomes
|
||||||
|
# xorq %rax, %rax
|
||||||
while i < len(instructions):
|
while i < len(instructions):
|
||||||
if instructions[i].opcode != 'movq':
|
if instructions[i].opcode != 'movq':
|
||||||
i += 1
|
i += 1
|
||||||
|
|
Loading…
Reference in New Issue