User:Cipscis/Assembly Optimisations

From the CreationKit Wiki
Jump to navigation Jump to search

Papyrus assembly, as created by the Creation Kit's Papyrus compiler, can be optimised in numerous ways. Here is a partial list of easy optimisations that can be made systematically.

Currently these optimisations are easy enough to be made by hand, but theoretically they could also be made by an "optimiser" utility that steps into the compilation process between the compiler (which compiles Papyrus to Papyrus assembly) and the assembler (which assembles human-readable Papyrus assembly into a more compressed machine-readable form) and makes these optimisations.

Foo = Bar + 1 ; Remove extraneous ASSIGN instructions
;/
Currently:

IADD ::temp0 Bar 1
ASSIGN Foo ::temp0

Better:

IADD Foo Bar 1
/;
BoolVar = IntVar ; Convert CAST + ASSIGN to CAST alone where appropriate
;/
Currently:

CAST ::temp0 IntVar
ASSIGN BoolVar ::temp0

Better:

CAST BoolVar IntVar
/;
True && !True ; Remove extraneous CAST instructions
;/
Currently:

CAST ::temp0 True
JUMPF ::temp0 label0
NOT ::temp0 True
CAST ::temp0 ::temp0
label0:

Better:

JUMPF True label0
NOT ::temp0 True
label0:
/;
If True ; Remove extra JUMPs (and extra labels)
EndIf
;/
Currently:

JUMPF True label1
JUMP label0
label1:
label0:

Better:

JUMPF True label1
label1:
/;
If !True ; Combine NOT and JUMPF to JUMPT where appropriate (i.e. with ::temp vars)
EndIf
;/
Currently:

NOT ::temp0 True
JUMPF ::temp0 label1
JUMP label0
label1:
label0:

Better:

JUMPT True label1
JUMP label0
label1:
label0:
/;
Int Property Foo = 3 AutoReadOnly
; ...
Foo ; Optimise local AutoReadOnly property access
;/
Currently:

RETURN 3
; ...
PROPGET Foo self ::temp0

Better

ASSIGN ::temp0 3
/;
; Remove any "double jumps", where a label is right before a JUMP instruction
;/
Currently:

JUMP label1
; ...
JUMPF ::temp0 label1
; ...
label1:
JUMP label2

Better:

JUMP label2
; ...
JUMPF ::temp0 label2
; ...
JUMP label2
/;
If A && B ; Remove any "double jumps" where the same condition is checked twice in a row
EndIf
;/
Currently

CAST ::temp0 A
JUMPF ::temp0 label1
CAST ::temp0 B
label1:
JUMPF ::temp0 label2
JUMP label0
label2:
label0:

Better

CAST ::temp0 A
JUMPF ::temp0 label2
CAST ::temp0 B
label1:
JUMPF ::temp0 label2
JUMP label0
label2:
label0:
/;
If True ; Optimise out "If True", which can be used for block scope
EndIf
;/
Currently

JUMPF True label1
; Block scope
JUMP label0
label1:
label0:

Better

; Block scope
/;