got rid of multi-assignments

This commit is contained in:
Irmen de Jong 2018-02-20 01:16:16 +01:00
parent de3bca0763
commit 920b6ca51e
9 changed files with 41 additions and 59 deletions

View File

@ -37,7 +37,6 @@ class PlyParser:
module.scope.define_builtin_functions() module.scope.define_builtin_functions()
self.process_imports(module) self.process_imports(module)
self.check_and_merge_zeropages(module) self.check_and_merge_zeropages(module)
self.create_multiassigns(module)
if not self.imported_module: if not self.imported_module:
# the following shall only be done on the main module after all imports have been done: # the following shall only be done on the main module after all imports have been done:
self.check_all_symbolnames(module) self.check_all_symbolnames(module)
@ -249,24 +248,6 @@ class PlyParser:
for node in module.all_nodes(SymbolName): for node in module.all_nodes(SymbolName):
check_symbol_definition(node.name, node.my_scope(), node.sourceref) # type: ignore check_symbol_definition(node.name, node.my_scope(), node.sourceref) # type: ignore
@no_type_check
def create_multiassigns(self, module: Module) -> None:
# create multi-assign statements from nested assignments (A=B=C=5),
def reduce_right(assign: Assignment) -> Assignment:
if isinstance(assign.right, Assignment):
right = reduce_right(assign.right)
for rn in right.left.nodes:
rn.parent = assign.left
assign.left.nodes.extend(right.left.nodes)
assign.right = right.right
assign.right.parent = assign
return assign
for node in module.all_nodes(Assignment):
if isinstance(node.right, Assignment):
multi = reduce_right(node)
assert multi is node and len(multi.left.nodes) > 1 and not isinstance(multi.right, Assignment)
@no_type_check @no_type_check
def apply_directive_options(self, module: Module) -> None: def apply_directive_options(self, module: Module) -> None:
def set_save_registers(scope: Scope, save_dir: Directive) -> None: def set_save_registers(scope: Scope, save_dir: Directive) -> None:

View File

@ -40,7 +40,6 @@ class Optimizer:
self.optimize_assignments() self.optimize_assignments()
self.remove_superfluous_assignments() self.remove_superfluous_assignments()
self.combine_assignments_into_multi() self.combine_assignments_into_multi()
self.optimize_multiassigns()
# @todo optimize addition with self into shift 1 (A+=A -> A<<=1) # @todo optimize addition with self into shift 1 (A+=A -> A<<=1)
self.optimize_goto_compare_with_zero() self.optimize_goto_compare_with_zero()
self.join_incrdecrs() self.join_incrdecrs()
@ -301,19 +300,6 @@ class Optimizer:
rvalue = None rvalue = None
assignments.clear() assignments.clear()
@no_type_check
def optimize_multiassigns(self) -> None:
# optimize multi-assign statements (remove duplicate targets, optimize order)
for assignment in self.module.all_nodes(Assignment):
if len(assignment.left.nodes) > 1:
# remove duplicates
lvalues = set(assignment.left.nodes)
if len(lvalues) != len(assignment.left.nodes):
print("{}: removed duplicate assignment targets".format(assignment.sourceref))
# @todo change order: first registers, then zp addresses, then non-zp addresses, then the rest (if any)
assignment.left.nodes = list(lvalues)
self.optimizations_performed = True
@no_type_check @no_type_check
def remove_unused_subroutines(self) -> None: def remove_unused_subroutines(self) -> None:
# some symbols are used by the emitted assembly code from the code generator, # some symbols are used by the emitted assembly code from the code generator,

View File

@ -846,10 +846,7 @@ class Return(AstNode):
@attr.s(cmp=False, slots=True, repr=False) @attr.s(cmp=False, slots=True, repr=False)
class Assignment(AstNode): class Assignment(AstNode):
# can be single- or multi-assignment # has two subnodes: left (=Register/SymbolName/Dereference ) and right (=Expression)
# has two subnodes: left (=Register/SymbolName/Dereference ) and right (=Expression,
# or another Assignment but those will be converted into multi assign)
@property @property
def left(self) -> Union[Register, SymbolName, Dereference]: def left(self) -> Union[Register, SymbolName, Dereference]:
return self.nodes[0] # type: ignore return self.nodes[0] # type: ignore
@ -1475,7 +1472,6 @@ def p_symbolname(p):
def p_assignment(p): def p_assignment(p):
""" """
assignment : assignment_target IS expression assignment : assignment_target IS expression
| assignment_target IS assignment
""" """
p[0] = Assignment(sourceref=_token_sref(p, 2)) p[0] = Assignment(sourceref=_token_sref(p, 2))
p[0].nodes.append(p[1]) p[0].nodes.append(p[1])

View File

@ -288,13 +288,9 @@ want to work on later, because the contents of the ignored block are not fully p
### Assignments ### Assignments
Assignment statements assign a single value to one or more variables or memory locations. Assignment statements assign a single value to a target variable or memory location.
If you know that you have to assign the same value to more than one thing at once, it is more
efficient to write it as a multi-assign instead of several separate assignments. The compiler
tries to detect this situation however and optimize it itself if it finds the case.
target = value-expression target = value-expression
target1 = target2 = target3 [,...] = value-expression
### Augmented Assignments ### Augmented Assignments

View File

@ -153,8 +153,6 @@ start:
A = 0 A = 0
A = '@' A = '@'
A = 1.2345 A = 1.2345
A=X=Y= true
A=XY= true
A = false A = false
A = 255 A = 255
A = X A = X
@ -180,8 +178,6 @@ start:
XY = uninitbyte1 XY = uninitbyte1
XY = "text-immediate" XY = "text-immediate"
AY = "text-immediate" AY = "text-immediate"
; AX = &"text-immediate" ; equivalent to simply assigning the string directly
; AX = & "text-immediate" ; equivalent to simply assigning the string directly
AX = ctext3 AX = ctext3
AX = "" AX = ""
AX = XY AX = XY
@ -190,7 +186,7 @@ start:
XY = membyte2 XY = membyte2
XY = memword1 XY = memword1
XY = sin XY = sin
; XY = &sin ; @todo not yet implemented XY = &sin ; @todo not yet implemented
[$c000] = A [$c000] = A
@ -214,7 +210,7 @@ start:
[$c000.word] = "" [$c000.word] = ""
[$c000.word] = uninitbyte1 [$c000.word] = uninitbyte1
[$c000.word] = membyte2 [$c000.word] = membyte2
; [$c000.word] = &membyte2 ; @todo not yet implemented [$c000.word] = &membyte2 ; @todo not yet implemented
[$c000.word] = [cword2] [$c000.word] = [cword2]
[$c000.word] = memword1 [$c000.word] = memword1
[$c000.float] = 65535 [$c000.float] = 65535
@ -228,7 +224,7 @@ start:
[$c112.word] = [$c223.byte] [$c112.word] = [$c223.byte]
[$c222.word] = [$c333.word] [$c222.word] = [$c333.word]
[$c333.word] = sin [$c333.word] = sin
; [$c333.word] = &sin ; @todo not yet implemented [$c333.word] = &sin ; @todo not yet implemented
SC = 0 SC = 0
@ -264,7 +260,7 @@ start:
uninitfloat = 9.8765 uninitfloat = 9.8765
uninitfloat = '@' uninitfloat = '@'
initword1 = sin initword1 = sin
; initword1 = &sin ; @todo not yet implemented initword1 = &sin ; @todo not yet implemented
membyte1 = A membyte1 = A
@ -280,7 +276,7 @@ start:
memword1 = 2233 memword1 = 2233
memfloat = 3.4567 memfloat = 3.4567
memword1 = sin memword1 = sin
; memword1 = &sin ; @todo not yet implemented memword1 = &sin ; @todo not yet implemented
membyte1 = A membyte1 = A
memword1 = A memword1 = A

View File

@ -15,7 +15,7 @@ start:
A = c64.VMCSB A = c64.VMCSB
A |= 2 A |= 2
c64.VMCSB = A c64.VMCSB = A
;c64.VMCSB |= 2 ; @todo when this works it replaces the three lines above c64.VMCSB |= 2 ; @todo when this works it replaces the three lines above
; greeting ; greeting
c64scr.print_string("Enter your name: ") c64scr.print_string("Enter your name: ")

View File

@ -33,7 +33,19 @@ start: ;foo
Y = X Y = X
X = 66 X = 66
screen = 0 screen = 0
screen = border = cursor = X = Y = A = X = Y = A = border = cursor = border = cursor = 66 ; multi-assign! screen = 66
border = 66
cursor = 66
X = 66
Y = 66
A = 66
X = 66
Y = 66
A = 66
border = 66
cursor = 66
border = 66
cursor = 66
border = false border = false
border = true border = true
border = 0 border = 0
@ -58,7 +70,9 @@ start: ;foo
Y = 2 Y = 2
Y = true Y = true
Y = false Y = false
A = Y = X = 0 ; multi assign! A = 0
Y = 0
X = 0
; [646,Y] = [$d020,X] ; [646,Y] = [$d020,X]
@ -130,8 +144,19 @@ somelabel1:
goto somelabel1 goto somelabel1
goto block2.somelabel1222 goto block2.somelabel1222
A=X=Y=A=X=Y=A=X=Y=99 A=99
[$d020]=[$d021]=[$d020]=[$d021]=55 X=99
Y=99
A=99
X=99
Y=99
A=99
X=99
Y=99
[$d020]=55
[$d021]=55
[$d020]=55
[$d021]=55
A=1 A=1
X=1 X=1

View File

@ -67,7 +67,8 @@ start:
~ global2 { ~ global2 {
make_screen_black: make_screen_black:
c64.EXTCOL = c64.BGCOL0 = 0 c64.EXTCOL = 0
c64.BGCOL0 = 0
c64.COLOR = 3 c64.COLOR = 3
Y = true Y = true
return return

View File

@ -53,7 +53,8 @@ start2:
~ global2 { ~ global2 {
make_screen_black: make_screen_black:
c64.EXTCOL = c64.BGCOL0 = 0 c64.EXTCOL = 0
c64.BGCOL0 = 0
c64.COLOR = 3 c64.COLOR = 3
return return