Optimize binary_op generation to use less stack if possible
This commit is contained in:
parent
56bcad6fc1
commit
79ca8e78b3
|
@ -487,24 +487,65 @@ def compile_ast(node: ASTnode, compile_data: CompileData) -> None:
|
||||||
else:
|
else:
|
||||||
assert node.child_rhs.type == 'int'
|
assert node.child_rhs.type == 'int'
|
||||||
|
|
||||||
# calculate LHS and store it on stack
|
|
||||||
|
old_code = compile_data.code
|
||||||
|
|
||||||
|
# compile LHS
|
||||||
|
compile_data.code = []
|
||||||
compile_ast(node.child_lhs, compile_data)
|
compile_ast(node.child_lhs, compile_data)
|
||||||
|
lhs_code = compile_data.code
|
||||||
|
|
||||||
|
# compile RHS
|
||||||
|
compile_data.code = []
|
||||||
|
compile_ast(node.child_rhs, compile_data)
|
||||||
|
rhs_code = compile_data.code
|
||||||
|
|
||||||
|
compile_data.code = old_code
|
||||||
|
|
||||||
|
# check if we can use temporary registers instead of stack
|
||||||
|
temp_registers = ['%rcx', '%r8', '%r9', '%r10', '%r11']
|
||||||
|
temp_reg = None
|
||||||
|
for reg in temp_registers:
|
||||||
|
valid = True
|
||||||
|
for instruction in lhs_code:
|
||||||
|
if reg in instruction.operands:
|
||||||
|
valid = False
|
||||||
|
break
|
||||||
|
if valid:
|
||||||
|
temp_reg = reg
|
||||||
|
break
|
||||||
|
|
||||||
|
# check if lhs uses call, this determines whether we need to align stack
|
||||||
|
lhs_call = False
|
||||||
|
for instruction in lhs_code:
|
||||||
|
if instruction.opcode == 'call':
|
||||||
|
lhs_call = True
|
||||||
|
break
|
||||||
|
|
||||||
|
# Add code for RHS calculation
|
||||||
|
compile_data.code += rhs_code
|
||||||
|
if temp_reg is not None:
|
||||||
|
compile_data.code.append(Instruction('movq', ['%rax', temp_reg]))
|
||||||
|
elif not lhs_call:
|
||||||
|
compile_data.code.append(Instruction('pushq', ['%rax']))
|
||||||
|
else:
|
||||||
compile_data.code.append(Instruction('subq', ['$16', '%rsp']))
|
compile_data.code.append(Instruction('subq', ['$16', '%rsp']))
|
||||||
compile_data.code.append(Instruction('movq', ['%rax', '0(%rsp)']))
|
compile_data.code.append(Instruction('movq', ['%rax', '0(%rsp)']))
|
||||||
|
|
||||||
# calculate RHS and store it in RCX
|
# Add code for LHS calculation
|
||||||
compile_ast(node.child_rhs, compile_data)
|
compile_data.code += lhs_code
|
||||||
if node.child_lhs.type == 'date' and node.child_rhs.type == 'int':
|
if temp_reg is not None:
|
||||||
# multiply RHS by number of seconds in a day so we can perform arithmetic on dates
|
compile_data.code.append(Instruction('movq', [temp_reg, '%rcx']))
|
||||||
compile_data.code.append(Instruction('imulq', ['$86400', '%rax', '%rcx']))
|
elif not lhs_call:
|
||||||
|
compile_data.code.append(Instruction('popq', ['%rcx']))
|
||||||
else:
|
else:
|
||||||
compile_data.code.append(Instruction('movq', ['%rax', '%rcx']))
|
compile_data.code.append(Instruction('movq', ['0(%rsp)', '%rcx']))
|
||||||
|
|
||||||
# prepare registers, RAX contains LHS and RCX contains RHS
|
|
||||||
# and restore restore stack
|
|
||||||
compile_data.code.append(Instruction('movq', ['0(%rsp)', '%rax']))
|
|
||||||
compile_data.code.append(Instruction('addq', ['$16', '%rsp']))
|
compile_data.code.append(Instruction('addq', ['$16', '%rsp']))
|
||||||
|
|
||||||
|
# If we are adding or subtracting dates with integers, multiply the integer by number of seconds in a day
|
||||||
|
if node.child_lhs.type == 'date' and node.child_rhs.type == 'int':
|
||||||
|
compile_data.code.append(Instruction('imulq', ['$86400', '%rcx']))
|
||||||
|
|
||||||
# perform operation
|
# perform operation
|
||||||
if node.value == '+':
|
if node.value == '+':
|
||||||
compile_data.code.append(Instruction('addq', ['%rcx', '%rax']))
|
compile_data.code.append(Instruction('addq', ['%rcx', '%rax']))
|
||||||
|
|
Loading…
Reference in New Issue