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
|
||||
# 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
|
||||
|
|
Loading…
Reference in New Issue