mirror of
https://github.com/irmen/prog8.git
synced 2025-02-18 20:30:43 +00:00
optimize x=min(x,100) and some other simple min() and max() cases
This commit is contained in:
parent
3b3616afda
commit
d187cef6b7
@ -2455,11 +2455,9 @@ $endLabel""")
|
||||
}
|
||||
BaseDataType.UWORD, BaseDataType.WORD -> {
|
||||
if(asmgen.isTargetCpu(CpuType.CPU65c02))
|
||||
asmgen.out(
|
||||
" st${regs.toString().lowercase()} $targetAsmVarName | stz $targetAsmVarName+1")
|
||||
asmgen.out(" st${regs.toString().lowercase()} $targetAsmVarName | stz $targetAsmVarName+1")
|
||||
else
|
||||
asmgen.out(
|
||||
" st${regs.toString().lowercase()} $targetAsmVarName | lda #0 | sta $targetAsmVarName+1")
|
||||
asmgen.out(" st${regs.toString().lowercase()} $targetAsmVarName | lda #0 | sta $targetAsmVarName+1")
|
||||
}
|
||||
BaseDataType.FLOAT -> {
|
||||
when(regs) {
|
||||
@ -2486,15 +2484,9 @@ $endLabel""")
|
||||
}
|
||||
BaseDataType.UWORD -> {
|
||||
if(asmgen.isTargetCpu(CpuType.CPU65c02))
|
||||
asmgen.out(
|
||||
" st${
|
||||
regs.toString().lowercase()
|
||||
} $targetAsmVarName | stz $targetAsmVarName+1")
|
||||
asmgen.out(" st${regs.toString().lowercase()} $targetAsmVarName | stz $targetAsmVarName+1")
|
||||
else
|
||||
asmgen.out(
|
||||
" st${
|
||||
regs.toString().lowercase()
|
||||
} $targetAsmVarName | lda #0 | sta $targetAsmVarName+1")
|
||||
asmgen.out(" st${regs.toString().lowercase()} $targetAsmVarName | lda #0 | sta $targetAsmVarName+1")
|
||||
}
|
||||
BaseDataType.WORD -> {
|
||||
when(regs) {
|
||||
|
@ -9,6 +9,7 @@ import prog8.code.core.AssociativeOperators
|
||||
import prog8.code.core.BaseDataType
|
||||
import prog8.code.core.CompilationOptions
|
||||
import prog8.code.core.IErrorReporter
|
||||
import prog8.code.core.Position
|
||||
|
||||
|
||||
class StatementOptimizer(private val program: Program,
|
||||
@ -400,9 +401,91 @@ class StatementOptimizer(private val program: Program,
|
||||
}
|
||||
}
|
||||
|
||||
val funcName = (assignment.value as? FunctionCallExpression)?.target?.nameInSource
|
||||
if(funcName?.size==1) {
|
||||
if(funcName[0].startsWith("min__")) {
|
||||
val (v1, v2) = (assignment.value as FunctionCallExpression).args
|
||||
if(v1 isSameAs v2)
|
||||
errors.err("identical values given, function is useless", assignment.value.position)
|
||||
if ((v1 is NumericLiteral || v1 is IdentifierReference) && v2 isSameAs assignment.target) {
|
||||
// x = min(100, x) -> if x>100 x=100
|
||||
val ifstmt = makeMinMaxCheckAndAssignRight(v2, ">", v1, assignment.target, assignment.position)
|
||||
return listOf(IAstModification.ReplaceNode(assignment, ifstmt, parent))
|
||||
} else if ((v2 is NumericLiteral || v2 is IdentifierReference) && v1 isSameAs assignment.target) {
|
||||
// x = min(x, 100) -> if x>100 x=100
|
||||
val ifstmt = makeMinMaxCheckAndAssignRight(v1, ">", v2, assignment.target, assignment.position)
|
||||
return listOf(IAstModification.ReplaceNode(assignment, ifstmt, parent))
|
||||
}
|
||||
|
||||
if(v2 is NumericLiteral || v2 is IdentifierReference) {
|
||||
// x = min(expression, 100) -> x=expression, if x>100 x=100
|
||||
val assign = Assignment(assignment.target.copy(), v1, AssignmentOrigin.OPTIMIZER, assignment.position)
|
||||
val ifstmt = makeMinMaxCheckAndAssignRight(assign.target.toExpression(), ">", v2, assignment.target, assignment.position)
|
||||
return listOf(
|
||||
IAstModification.InsertAfter(assignment, ifstmt, parent as IStatementContainer),
|
||||
IAstModification.ReplaceNode(assignment, assign, parent)
|
||||
)
|
||||
} else if(v1 is NumericLiteral || v1 is IdentifierReference) {
|
||||
// x = min(100, expression) -> x=expression, if x>100 x=100
|
||||
val assign = Assignment(assignment.target.copy(), v2, AssignmentOrigin.OPTIMIZER, assignment.position)
|
||||
val ifstmt = makeMinMaxCheckAndAssignRight(assign.target.toExpression(), ">", v1, assignment.target, assignment.position)
|
||||
return listOf(
|
||||
IAstModification.InsertAfter(assignment, ifstmt, parent as IStatementContainer),
|
||||
IAstModification.ReplaceNode(assignment, assign, parent)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
else if(funcName[0].startsWith("max__")) {
|
||||
val (v1, v2) = (assignment.value as FunctionCallExpression).args
|
||||
if(v1 isSameAs v2)
|
||||
errors.err("identical values given, function is useless", assignment.value.position)
|
||||
if ((v1 is NumericLiteral || v1 is IdentifierReference) && v2 isSameAs assignment.target) {
|
||||
// x = max(100, x) -> if x<100 x=100
|
||||
val ifstmt = makeMinMaxCheckAndAssignRight(v2, "<", v1, assignment.target, assignment.position)
|
||||
return listOf(IAstModification.ReplaceNode(assignment, ifstmt, parent))
|
||||
} else if ((v2 is NumericLiteral || v2 is IdentifierReference) && v1 isSameAs assignment.target) {
|
||||
// x = max(x, 100) -> if x<100 x=100
|
||||
val ifstmt = makeMinMaxCheckAndAssignRight(v1, "<", v2, assignment.target, assignment.position)
|
||||
return listOf(IAstModification.ReplaceNode(assignment, ifstmt, parent))
|
||||
}
|
||||
|
||||
if(v2 is NumericLiteral || v2 is IdentifierReference) {
|
||||
// x = max(expression, 100) -> x=expression, if x<100 x=100
|
||||
val assign = Assignment(assignment.target.copy(), v1, AssignmentOrigin.OPTIMIZER, assignment.position)
|
||||
val ifstmt = makeMinMaxCheckAndAssignRight(assign.target.toExpression(), "<", v2, assignment.target, assignment.position)
|
||||
return listOf(
|
||||
IAstModification.InsertAfter(assignment, ifstmt, parent as IStatementContainer),
|
||||
IAstModification.ReplaceNode(assignment, assign, parent)
|
||||
)
|
||||
} else if(v1 is NumericLiteral || v1 is IdentifierReference) {
|
||||
// x = max(100, expression) -> x=expression, if x<100 x=100
|
||||
val assign = Assignment(assignment.target.copy(), v2, AssignmentOrigin.OPTIMIZER, assignment.position)
|
||||
val ifstmt = makeMinMaxCheckAndAssignRight(assign.target.toExpression(), "<", v1, assignment.target, assignment.position)
|
||||
return listOf(
|
||||
IAstModification.InsertAfter(assignment, ifstmt, parent as IStatementContainer),
|
||||
IAstModification.ReplaceNode(assignment, assign, parent)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return noModifications
|
||||
}
|
||||
|
||||
private fun makeMinMaxCheckAndAssignRight(left: Expression, operator: String, right: Expression, target: AssignTarget, position: Position): IfElse {
|
||||
require(right is NumericLiteral || right is IdentifierReference)
|
||||
val compare = BinaryExpression(left, operator, right, position)
|
||||
val assign = Assignment(target, right.copy(), AssignmentOrigin.OPTIMIZER, position)
|
||||
return IfElse(
|
||||
compare,
|
||||
AnonymousScope(mutableListOf(assign), position),
|
||||
AnonymousScope(mutableListOf(), position),
|
||||
position
|
||||
)
|
||||
}
|
||||
|
||||
override fun before(unrollLoop: UnrollLoop, parent: Node): Iterable<IAstModification> {
|
||||
val iterations = unrollLoop.iterations.constValue(program)?.number?.toInt()
|
||||
return if(iterations!=null && iterations<1)
|
||||
|
@ -1,9 +1,6 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
- min/max(x1,x2) lots of code in a temp word, can sometimes just use the existing variables x1 and x2
|
||||
|
||||
|
||||
- add paypal donation button as well?
|
||||
- announce prog8 on the 6502.org site?
|
||||
|
||||
@ -13,6 +10,8 @@ TODO
|
||||
Future Things and Ideas
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- allow when stringvar. Usecase: if sv=="aa" else if sv=="bb" else if sv=="cc" -> needs much code, when(stringvar) would avoid reloading both strings for every case (rockrunner bdcff.p8)
|
||||
|
||||
- Kotlin: can we use inline value classes in certain spots?
|
||||
- Improve the SublimeText syntax file for prog8, you can also install this for 'bat': https://github.com/sharkdp/bat?tab=readme-ov-file#adding-new-syntaxes--language-definitions
|
||||
|
||||
@ -86,9 +85,6 @@ Optimizations
|
||||
- if magicwall_enabled and (jiffy_counter & 3 == 1) sounds.magicwall() -> generates shortcut jump to another jump, why not immediately after the if
|
||||
- explode(x, y+1) pushes x on the stack and pops it, could simply load it in reverse order and not use the stack.normal
|
||||
- return mkword(attrs[cx16.r2L], object[cx16.r2L]) same as the explode() above
|
||||
- return peekw(table+64+pos*2) .... or rather .. return <complex expression> -> can this be optimized by using a temporary variable and chop up the expression?
|
||||
likewise cx16.r0 = (gfx_lores.WIDTH-bmx.width)/2 + (gfx_lores.HEIGHT-bmx.height)/2*gfx_lores.WIDTH a lot of register juggling
|
||||
- if sv=="aa" else if sv=="bb" else if sv=="cc" -> needs much code, allow when(stringvar) too to avoid reloading both strings for every case (rockrunner bdcff.p8)
|
||||
- if cx16.r0L>=97 and cx16.r0L<=122 {...} -> treats the boolean condition as a byte 0/1 result , can't it somehow just act on the carry bit alone?
|
||||
same with if x1!=x2 or y1!=y2..... but it's because of the way boolean expressions are handled... can this be optimized?
|
||||
|
||||
|
@ -1,38 +1,33 @@
|
||||
%import textio
|
||||
%option no_sysinit
|
||||
%zeropage kernalsafe
|
||||
%zeropage basicsafe
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
ubyte @shared bb0, bb1, bb2, bb3, bb4
|
||||
uword @shared ww0, ww1, ww2, ww3, ww4
|
||||
|
||||
bb0 = min(bb1, 100)
|
||||
bb1 = min(bb1, 100)
|
||||
bb0 = min(100, bb1)
|
||||
bb1 = min(100, bb1)
|
||||
bb0 = min(bb1, bb2)
|
||||
bb2 = min(bb1+bb2, bb3+bb4)
|
||||
bb4 = 100
|
||||
ww4 = 100
|
||||
|
||||
bb0 = max(bb1, 100)
|
||||
bb1 = max(bb1, 100)
|
||||
bb0 = max(100, bb1)
|
||||
bb1 = max(100, bb1)
|
||||
bb0 = max(bb1, bb2)
|
||||
bb2 = max(bb1+bb2, bb3+bb4)
|
||||
|
||||
ww0 = min(ww1, 100)
|
||||
ww1 = min(ww1, 100)
|
||||
ww0 = min(100, ww1)
|
||||
ww1 = min(100, ww1)
|
||||
ww0 = min(ww1, ww2)
|
||||
ww2 = min(ww1+ww2, ww3+ww4)
|
||||
|
||||
ww0 = max(ww1, 100)
|
||||
ww1 = max(ww1, 100)
|
||||
ww0 = max(100, ww1)
|
||||
ww1 = max(100, ww1)
|
||||
ww0 = max(ww1, ww2)
|
||||
ww2 = max(ww1+ww2, ww3+ww4)
|
||||
bb0 = min(bb1+10, 100)
|
||||
bb0 = min(100, bb1+10)
|
||||
; bb0 = min(bb1, bb4)
|
||||
; bb2 = min(bb1+bb2, bb3+bb4)
|
||||
;
|
||||
; bb0 = max(bb1, 100)
|
||||
; bb0 = max(100, bb1)
|
||||
; bb0 = max(bb1, bb4)
|
||||
; bb2 = max(bb1+bb2, bb3+bb4)
|
||||
;
|
||||
; ww0 = min(ww1, 100)
|
||||
; ww0 = min(100, ww1)
|
||||
; ww0 = min(ww1, ww4)
|
||||
; ww2 = min(ww1+ww2, ww3+ww4)
|
||||
;
|
||||
; ww0 = max(ww1, 100)
|
||||
; ww0 = max(100, ww1)
|
||||
; ww0 = max(ww1, ww4)
|
||||
; ww2 = max(ww1+ww2, ww3+ww4)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user