Optimize artithmetic with immediate values
This commit is contained in:
parent
351634e512
commit
2141a17d1e
|
@ -574,8 +574,17 @@ def compile_ast(node: ASTnode, compile_data: CompileData) -> None:
|
||||||
|
|
||||||
compile_data.code = old_code
|
compile_data.code = old_code
|
||||||
|
|
||||||
# check if we can use temporary registers instead of stack
|
# If RHS is an 32 bit integer literal, we can use it as an immediate value
|
||||||
|
register = None
|
||||||
|
if node.child_rhs.nodetype == 'int_literal' and node.child_rhs.value <= 0x7FFFFFFF:
|
||||||
|
if node.child_lhs.type != 'date':
|
||||||
|
register = f'${node.child_rhs.value}'
|
||||||
|
elif node.child_rhs.value * 86400 <= 0x7FFFFFFF:
|
||||||
|
register = f'${node.child_rhs.value * 86400}'
|
||||||
|
|
||||||
|
# Otherwise, we need to use a register
|
||||||
usable_registers = ['%r8', '%r9', '%r10', '%r11']
|
usable_registers = ['%r8', '%r9', '%r10', '%r11']
|
||||||
|
if register is None:
|
||||||
register = '%rcx'
|
register = '%rcx'
|
||||||
for reg in usable_registers:
|
for reg in usable_registers:
|
||||||
valid = True
|
valid = True
|
||||||
|
@ -595,6 +604,9 @@ def compile_ast(node: ASTnode, compile_data: CompileData) -> None:
|
||||||
break
|
break
|
||||||
|
|
||||||
# Add code for RHS calculation
|
# Add code for RHS calculation
|
||||||
|
if register[0] == '$':
|
||||||
|
pass
|
||||||
|
else:
|
||||||
compile_data.code += rhs_code
|
compile_data.code += rhs_code
|
||||||
if register != '%rcx':
|
if register != '%rcx':
|
||||||
compile_data.code.append(Instruction('movq', ['%rax', register]))
|
compile_data.code.append(Instruction('movq', ['%rax', register]))
|
||||||
|
@ -606,7 +618,7 @@ def compile_ast(node: ASTnode, compile_data: CompileData) -> None:
|
||||||
|
|
||||||
# Add code for LHS calculation
|
# Add code for LHS calculation
|
||||||
compile_data.code += lhs_code
|
compile_data.code += lhs_code
|
||||||
if register != '%rcx':
|
if register[0] == '$' or register != '%rcx':
|
||||||
pass
|
pass
|
||||||
elif not align_stack:
|
elif not align_stack:
|
||||||
compile_data.code.append(Instruction('popq', [register]))
|
compile_data.code.append(Instruction('popq', [register]))
|
||||||
|
@ -615,10 +627,11 @@ def compile_ast(node: ASTnode, compile_data: CompileData) -> None:
|
||||||
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 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':
|
# If register is immediate, this has already been done
|
||||||
|
if register[0] != '$' and node.child_lhs.type == 'date' and node.child_rhs.type == 'int':
|
||||||
compile_data.code.append(Instruction('imulq', ['$86400', register]))
|
compile_data.code.append(Instruction('imulq', ['$86400', register]))
|
||||||
|
|
||||||
# perform operation
|
# Perform operation
|
||||||
if node.value == '+':
|
if node.value == '+':
|
||||||
compile_data.code.append(Instruction('addq', [register, '%rax']))
|
compile_data.code.append(Instruction('addq', [register, '%rax']))
|
||||||
elif node.value == '-':
|
elif node.value == '-':
|
||||||
|
@ -626,6 +639,10 @@ def compile_ast(node: ASTnode, compile_data: CompileData) -> None:
|
||||||
elif node.value == '*':
|
elif node.value == '*':
|
||||||
compile_data.code.append(Instruction('imulq', [register, '%rax']))
|
compile_data.code.append(Instruction('imulq', [register, '%rax']))
|
||||||
elif node.value == '/':
|
elif node.value == '/':
|
||||||
|
# Division by immediate is not possible
|
||||||
|
if register[0] == '$':
|
||||||
|
compile_data.code.append(Instruction('movq', [register, '%rcx']))
|
||||||
|
register = '%rcx'
|
||||||
compile_data.code.append(Instruction('cqo'))
|
compile_data.code.append(Instruction('cqo'))
|
||||||
compile_data.code.append(Instruction('idivq', [register]))
|
compile_data.code.append(Instruction('idivq', [register]))
|
||||||
elif node.value == '<':
|
elif node.value == '<':
|
||||||
|
@ -638,7 +655,7 @@ def compile_ast(node: ASTnode, compile_data: CompileData) -> None:
|
||||||
compile_data.code.append(Instruction('movzbq', ['%al', '%rax']))
|
compile_data.code.append(Instruction('movzbq', ['%al', '%rax']))
|
||||||
else: assert False
|
else: assert False
|
||||||
|
|
||||||
# if both operands are dates, divide result by number of seconds in a day
|
# If both operands are dates, divide result by number of seconds in a day
|
||||||
if node.child_lhs.type == 'date' and node.child_rhs.type == 'date':
|
if node.child_lhs.type == 'date' and node.child_rhs.type == 'date':
|
||||||
assert node.value == '-'
|
assert node.value == '-'
|
||||||
compile_data.code.append(Instruction('movq', ['$86400', register]))
|
compile_data.code.append(Instruction('movq', ['$86400', register]))
|
||||||
|
|
Loading…
Reference in New Issue