forked from Archive/PX4-Autopilot
240 lines
11 KiB
Plaintext
240 lines
11 KiB
Plaintext
P-Code optimizations:
|
|
Let <push-ops> be oPUSH|oPUSHB
|
|
Let <load-ops> be oLOD|oLODB|PUSH|oLADR|oLCADR
|
|
|
|
pcopt.c:unaryOptimize
|
|
STEP 1:
|
|
Remove unary operators on constants:
|
|
<push-op> arg + oNEG -> <push-op> arg
|
|
<push-op> arg + oABS -> <push-op> |arg|
|
|
<push-op> arg + oINC -> <push-op> arg+1
|
|
<push-op> arg + oDEC -> <push-op> arg-1
|
|
<push-op> arg + oNOT -> <push-op> ~arg
|
|
|
|
Simplify binary operations on constants
|
|
<push-op> arg + oADD
|
|
if arg == 0 -> delete both
|
|
else if arg == 1 -> oINC
|
|
else if arg == -1 -> oDEC
|
|
<push-op> arg + oSUB
|
|
if arg == 0 -> delete both
|
|
else if arg == 1 -> oDEC
|
|
else if arg == -1 -> oINC
|
|
<push-op> arg + oMUL
|
|
if arg is power of 2 -> oSLL power
|
|
<push-op> arg + oDIV
|
|
if arg is power of 2 -> oSRA power
|
|
<push-op> arg + oSLL
|
|
if arg is 0 -> <push-op> arg
|
|
<push-op> arg + oSRL
|
|
if arg is 0 -> <push-op> arg
|
|
<push-op> arg + oSRA
|
|
if arg is 0 -> <push-op> arg
|
|
<push-op> arg + oOR
|
|
if arg is 0 -> <push-op> arg
|
|
<push-op> arg + oAND
|
|
if arg is 0xffff -> <push-op> arg
|
|
|
|
Delete comparisons with zero
|
|
<push-op> arg + oEQUZ
|
|
if arg == 0 -> <push-op> true
|
|
else -> <push-op> false
|
|
<push-op> arg + oNEQZ
|
|
if arg != 0 -> <push-op> true
|
|
else -> <push-op> false
|
|
<push-op> arg + oLTZ
|
|
if arg < 0 -> <push-op> true
|
|
else -> <push-op> false
|
|
<push-op> arg + oGTEZ
|
|
if arg >= 0 -> <push-op> true
|
|
else -> <push-op> false
|
|
<push-op> arg + oGTZ
|
|
if arg > 0 -> <push-op> true
|
|
else -> <push-op> false
|
|
<push-op> arg + oLTEZ
|
|
if arg <= 0 -> <push-op> true
|
|
else -> <push-op> false
|
|
|
|
Simplify comparisons with certain constants
|
|
<push-op> arg + oEQU
|
|
if arg == 0 -> oEQUZ
|
|
else if arg == 1 -> oDEC + oEQUZ
|
|
else if arg == -1 -> oINC + oEQUZ
|
|
<push-op> arg + oNEQ
|
|
if arg == 0 -> oNEQZ
|
|
else if arg == 1 -> oDEC + oNEQZ
|
|
else if arg == -1 -> oINC + oNEQZ
|
|
<push-op> arg + oLT
|
|
if arg == 0 -> oLTZ
|
|
else if arg == 1 -> oDEC + oLTZ
|
|
else if arg == -1 -> oINC + oLTZ
|
|
<push-op> arg + oGTE
|
|
if arg == 0 -> oGTEZ
|
|
else if arg == 1 -> oDEC + oGTEZ
|
|
else if arg == -1 -> oINC + oGTEZ
|
|
<push-op> arg + oGT
|
|
if arg == 0 -> oGTZ
|
|
else if arg == 1 -> oDEC + oGTZ
|
|
else if arg == -1 -> oINC + oGTZ
|
|
<push-op> arg + oLTE
|
|
if arg == 0 -> oLTEZ
|
|
else if arg == 1 -> oDEC + oLTEZ
|
|
else if arg == -1 -> oINC + oLTEZ
|
|
|
|
Simplify or delete condition branches on constants
|
|
<push-op> arg + oJEQUZ
|
|
if arg == 0 -> oJMP
|
|
else -> delete both
|
|
<push-op> arg + oJNEQZ
|
|
if arg != 0 -> oJMP
|
|
else -> delete both
|
|
<push-op> arg + oJLTZ
|
|
if arg < 0 -> oJMP
|
|
else -> delete both
|
|
<push-op> arg + oJGTEZ
|
|
if arg >= 0 -> oJMP
|
|
else -> delete both
|
|
<push-op> arg + oJGTZ
|
|
if arg > 0 -> oJMP
|
|
else -> delete both
|
|
<push-op> arg + oJLTEZ
|
|
if arg <= 0 -> oJMP
|
|
else -> delete both
|
|
STEP 1a:
|
|
<push-op> arg
|
|
if arg < 256 -> oPUSHB arg
|
|
else -> oPUSH arg
|
|
|
|
STEP 2:
|
|
Delete multiple modifications of DSEG pointer
|
|
INDS arg1 + INDS arg2 -> INDS arg1+arg2
|
|
|
|
pcopt.c:binaryOptimize
|
|
STEP 1:
|
|
<push-op> arg1 + <push-op> arg2 + oADD -> oPUSH arg1 + arg2 + STEP 1a
|
|
<push-op> arg1 + <push-op> arg2 + oSUB -> oPUSH arg1 - arg2 + STEP 1a
|
|
<push-op> arg1 + <push-op> arg2 + oMUL -> oPUSH arg1 * arg2 + STEP 1a
|
|
<push-op> arg1 + <push-op> arg2 + oDIV -> oPUSH arg1 / arg2 + STEP 1a
|
|
<push-op> arg1 + <push-op> arg2 + oMOD -> oPUSH arg1 % arg2 + STEP 1a
|
|
<push-op> arg1 + <push-op> arg2 + oSLL -> oPUSH arg1 << arg2 + STEP 1a
|
|
<push-op> arg1 + <push-op> arg2 + oSRL -> oPUSH arg1 >> arg2 + STEP 1a
|
|
<push-op> arg1 + <push-op> arg2 + oSRA -> oPUSH arg1 >> arg2 + STEP 1a
|
|
<push-op> arg1 + <push-op> arg2 + oOR -> oPUSH arg1 | arg2 + STEP 1a
|
|
<push-op> arg1 + <push-op> arg2 + oAND -> oPUSH arg1 & arg2 + STEP 1a
|
|
<push-op> arg1 + <push-op> arg2 + oEQU -> oPUSH arg1 == arg2 + STEP 1a
|
|
<push-op> arg1 + <push-op> arg2 + oNEQ -> oPUSH arg1 != arg2 + STEP 1a
|
|
<push-op> arg1 + <push-op> arg2 + oLT -> oPUSH arg1 < arg2 + STEP 1a
|
|
<push-op> arg1 + <push-op> arg2 + oGTE -> oPUSH arg1 >= arg2 + STEP 1a
|
|
<push-op> arg1 + <push-op> arg2 + oGT -> oPUSH arg1 > arg2 + STEP 1a
|
|
<push-op> arg1 + <push-op> arg2 + oLTE -> oPUSH arg1 <= arg2 + STEP 1a
|
|
STEP 1a:
|
|
<push-op> arg
|
|
if arg < 256 -> oPUSHB arg
|
|
else -> oPUSH arg
|
|
|
|
STEP 2:
|
|
<push-op> arg1 + <load-ops> arg2 + oADD
|
|
if arg1 == 0 -> <load-ops> arg
|
|
else if arg1 == 1 -> <load-ops> arg + oINC
|
|
else if arg1 == -1 -> <load-ops> arg + oDEC
|
|
<push-op> arg1 + <load-ops> arg2 + oSUB
|
|
if arg1 == 0 -> <load-ops> arg + oNEG
|
|
<push-op> arg1 + <load-ops> arg2 + oMUL -> <load-ops> arg + oSLL log
|
|
if arg is a power of 2
|
|
<push-op> arg1 + <load-ops> arg2 + oOR
|
|
if arg1 == 0 -> <load-ops> arg
|
|
<push-op> arg1 + <load-ops> arg2 + oAND
|
|
if arg1 == 0xffff -> <load-ops> arg
|
|
<push-op> arg1 + <load-ops> arg2 + oEQU
|
|
if arg1 == 0 -> <load-ops> arg + oEQUZ
|
|
<push-op> arg1 + <load-ops> arg2 + oNEQ
|
|
if arg1 == 0 -> <load-ops> arg + oNEQZ
|
|
<push-op> arg1 + <load-ops> arg2 + oLT
|
|
if arg1 == 0 -> <load-ops> arg + oLTZ
|
|
<push-op> arg1 + <load-ops> arg2 + oGTE
|
|
if arg1 == 0 -> <load-ops> arg + oGTEZ
|
|
<push-op> arg1 + <load-ops> arg2 + oGT
|
|
if arg1 == 0 -> <load-ops> arg + oGTZ
|
|
<push-op> arg1 + <load-ops> arg2 + oLTE
|
|
if arg1 == 0 -> <load-ops> arg + oLTEZ
|
|
|
|
STEP 2a:
|
|
if the <push-op> op is still there
|
|
<push-op> arg
|
|
if arg < 256 -> oPUSHB arg
|
|
else -> oPUSH arg
|
|
|
|
STEP 3
|
|
oNEG + oADD -> oSUB
|
|
oNEG + oSUB -> oADD
|
|
|
|
pjopt.c: BranchOptimize
|
|
oNOT + oJEQUZ -> oJNEQZ
|
|
oNOT + oJNEQZ -> oJEQUZ
|
|
oNEG + oJLTZ -> oJGTZ
|
|
oNEG + oJGTEZ -> oJLTEZ
|
|
oNEG + oJGTZ -> oJLTZ
|
|
oNEG + oJLTEZ -> oJGTEZ
|
|
oEQU + oNOT -> oNEQ
|
|
oEQU + oJEQUZ -> oJNEQ
|
|
oEQU + oJNEQZ -> oJEQU
|
|
oNEQ + oNOT -> oEQU
|
|
oNEQ + oJEQUZ -> oJEQU
|
|
oNEQ + oJNEQZ -> oJNEQ
|
|
oLT + oNOT -> oGTE
|
|
oLT + oJEQUZ -> oJGTE
|
|
oLT + oJNEQZ -> oJLT
|
|
oGTE + oNOT -> oLT
|
|
oGTE + oJEQUZ -> oJLT
|
|
oGTE + oJNEQZ -> oJGTE
|
|
oGT + oNOT -> oLTE
|
|
oGT + oJEQUZ -> oJLTE
|
|
oGT + oJNEQZ -> oJGT
|
|
oLTE + oJNOT -> oGT
|
|
oLTE + oJEQUZ -> oJGT
|
|
oLTE + oJNEQZ -> oJLTE
|
|
oEQUZ + oNOT -> oNEQZ
|
|
oEQUZ + oJEQUZ -> oJNEQZ
|
|
oEQUZ + oJNEQZ -> oJEQUZ
|
|
oNEQZ + oNOT -> oEQUZ
|
|
oNEQZ + oJEQUZ -> oJEQUZ
|
|
oNEQZ + oJNEQZ -> oJNEQZ
|
|
oLTZ + oNOT -> oGTEZ
|
|
oLTZ + oJEQUZ -> oJGTEZ
|
|
oLTZ + oJNEQZ -> oJLTZ
|
|
oGTEZ + oNOT -> oLTZ
|
|
oGTEZ + oJEQUZ -> oJLTZ
|
|
oGTEZ + oJNEQZ -> oJGTEZ
|
|
oGTZ + oNOT -> oLTEZ
|
|
oGTZ + oJEQUZ -> oJLTEZ
|
|
oGTZ + oJNEQZ -> oJGTZ
|
|
oLTEZ + oNOT -> oGTZ
|
|
oLTEZ + oJEQUZ -> oJGTZ
|
|
oLTEZ + oJNEQZ -> oJLTEZ
|
|
|
|
plopt.c:LoadOptimize()
|
|
Eliminate duplicate loads
|
|
oLOD arg1 + oLOAD arg1 -> oLOD arg1 + oDUP
|
|
|
|
Convert loads indexed by a constant to unindexed loads
|
|
!!! DISABLED !!! Does not work because arg2 is a label, not an address !!!
|
|
<push-op> arg1 + oLODX arg2 -> oLOD arg1 + arg2
|
|
<push-op> arg1 + oLADRX arg2 -> oLADR arg1 + arg2
|
|
<push-op> arg1 + oLODBX arg2 -> oLODB arg1 + arg2
|
|
<push-op> arg1 + oLODMX arg2 -> oLODM arg1 + arg2
|
|
<push-op> arg
|
|
if arg < 256 -> oPUSHB arg
|
|
|
|
plopt.c:StoreOptimize()
|
|
Eliminate store followed by load
|
|
oSTO arg + oLOAD arg -> oSTO arg + oDUP
|
|
|
|
Convert stores indexed by a constant to unindexed stores
|
|
<push-op> arg1 + ? + oSTOX arg2 -> ? + oSTO arg1 + arg2
|
|
<push-op> arg1 + ? + oSTOBX arg2 -> ? + oSTOB arg1 + arg2
|
|
|
|
Missing local optimization:
|
|
|
|
Need to check for branches (conditional or unconditional) to the
|
|
next instruction.
|