mirror of
https://github.com/irmen/prog8.git
synced 2025-02-16 22:30:46 +00:00
optimize certain boolean comparisons more
This commit is contained in:
parent
c6bf57b390
commit
9826d7c494
@ -282,7 +282,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
}
|
||||
is PtPrefix -> {
|
||||
if(assign.target.array==null) {
|
||||
if(assign.source.datatype==assign.target.datatype) {
|
||||
if(assign.source.datatype isAssignableTo assign.target.datatype || (assign.source.datatype==DataType.BOOL && assign.target.datatype in ByteDatatypes)) {
|
||||
if(assign.source.datatype in IntegerDatatypesWithBoolean) {
|
||||
val signed = assign.source.datatype in SignedDatatypes
|
||||
if(assign.source.datatype in ByteDatatypesWithBoolean) {
|
||||
|
@ -19,7 +19,7 @@ import kotlin.math.pow
|
||||
|
||||
// TODO add more peephole expression optimizations? Investigate what optimizations binaryen has?
|
||||
|
||||
class ExpressionSimplifier(private val program: Program, private val errors: IErrorReporter) : AstWalker() {
|
||||
class ExpressionSimplifier(private val program: Program, private val options: CompilationOptions, private val errors: IErrorReporter) : AstWalker() {
|
||||
private val powersOfTwo = (1..16).map { (2.0).pow(it) }.toSet()
|
||||
private val negativePowersOfTwo = powersOfTwo.map { -it }.toSet()
|
||||
|
||||
@ -249,50 +249,94 @@ class ExpressionSimplifier(private val program: Program, private val errors: IEr
|
||||
}
|
||||
}
|
||||
|
||||
if(leftDt==DataType.BOOL) {
|
||||
// optimize boolean constant comparisons
|
||||
if(expr.operator=="==" && rightVal?.number==1.0)
|
||||
return listOf(IAstModification.ReplaceNode(expr, expr.left, parent))
|
||||
if(expr.operator=="!=" && rightVal?.number==0.0)
|
||||
return listOf(IAstModification.ReplaceNode(expr, expr.left, parent))
|
||||
// optimize boolean constant comparisons
|
||||
if(expr.operator=="==") {
|
||||
if(rightDt==DataType.BOOL && leftDt==DataType.BOOL) {
|
||||
if(rightVal?.asBooleanValue==true)
|
||||
return listOf(IAstModification.ReplaceNode(expr, expr.left, parent))
|
||||
else
|
||||
return listOf(IAstModification.ReplaceNode(expr, PrefixExpression("not", expr.left, expr.position), parent))
|
||||
}
|
||||
if (rightVal?.number == 1.0) {
|
||||
if (options.strictBool) {
|
||||
if (rightDt != leftDt) {
|
||||
val right = NumericLiteral(leftDt, rightVal.number, rightVal.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr.right, right, expr))
|
||||
}
|
||||
} else
|
||||
return listOf(IAstModification.ReplaceNode(expr, expr.left, parent))
|
||||
}
|
||||
else if (rightVal?.number == 0.0) {
|
||||
if (options.strictBool) {
|
||||
if (rightDt != leftDt) {
|
||||
val right = NumericLiteral(leftDt, rightVal.number, rightVal.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr.right, right, expr))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (expr.operator=="!=") {
|
||||
if(rightDt==DataType.BOOL && leftDt==DataType.BOOL) {
|
||||
if(rightVal?.asBooleanValue==false)
|
||||
return listOf(IAstModification.ReplaceNode(expr, expr.left, parent))
|
||||
else
|
||||
return listOf(IAstModification.ReplaceNode(expr, PrefixExpression("not", expr.left, expr.position), parent))
|
||||
}
|
||||
if (rightVal?.number == 1.0) {
|
||||
if(options.strictBool) {
|
||||
if(rightDt!=leftDt) {
|
||||
val right = NumericLiteral(leftDt, rightVal.number, rightVal.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr.right, right, expr))
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (rightVal?.number == 0.0) {
|
||||
if(options.strictBool) {
|
||||
if(rightDt!=leftDt) {
|
||||
val right = NumericLiteral(leftDt, rightVal.number, rightVal.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr.right, right, expr))
|
||||
}
|
||||
} else
|
||||
return listOf(IAstModification.ReplaceNode(expr, expr.left, parent))
|
||||
}
|
||||
}
|
||||
|
||||
if(rightDt==DataType.BOOL && expr.operator in arrayOf("and", "or", "xor")) {
|
||||
if(leftVal!=null) {
|
||||
val result = if(leftVal.asBooleanValue) {
|
||||
when(expr.operator) {
|
||||
"and" -> expr.right
|
||||
"or" -> NumericLiteral.fromBoolean(true, expr.position)
|
||||
"xor" -> PrefixExpression("not", expr.right, expr.position)
|
||||
else -> throw FatalAstException("weird op")
|
||||
}
|
||||
} else {
|
||||
when(expr.operator) {
|
||||
"and" -> NumericLiteral.fromBoolean(false, expr.position)
|
||||
"or" -> expr.right
|
||||
"xor" -> expr.right
|
||||
else -> throw FatalAstException("weird op")
|
||||
}
|
||||
if(expr.operator in arrayOf("and", "or", "xor")) {
|
||||
if(leftVal!=null) {
|
||||
val result = if(leftVal.asBooleanValue) {
|
||||
when(expr.operator) {
|
||||
"and" -> expr.right
|
||||
"or" -> NumericLiteral.fromBoolean(true, expr.position)
|
||||
"xor" -> PrefixExpression("not", expr.right, expr.position)
|
||||
else -> throw FatalAstException("weird op")
|
||||
}
|
||||
return listOf(IAstModification.ReplaceNode(expr, result, parent))
|
||||
}
|
||||
else if(rightVal!=null) {
|
||||
val result = if(rightVal.asBooleanValue) {
|
||||
when(expr.operator) {
|
||||
"and" -> expr.left
|
||||
"or" -> NumericLiteral.fromBoolean(true, expr.position)
|
||||
"xor" -> PrefixExpression("not", expr.left, expr.position)
|
||||
else -> throw FatalAstException("weird op")
|
||||
}
|
||||
} else {
|
||||
when(expr.operator) {
|
||||
"and" -> NumericLiteral.fromBoolean(false, expr.position)
|
||||
"or" -> expr.left
|
||||
"xor" -> expr.left
|
||||
else -> throw FatalAstException("weird op")
|
||||
}
|
||||
} else {
|
||||
when(expr.operator) {
|
||||
"and" -> NumericLiteral.fromBoolean(false, expr.position)
|
||||
"or" -> expr.right
|
||||
"xor" -> expr.right
|
||||
else -> throw FatalAstException("weird op")
|
||||
}
|
||||
return listOf(IAstModification.ReplaceNode(expr, result, parent))
|
||||
}
|
||||
return listOf(IAstModification.ReplaceNode(expr, result, parent))
|
||||
}
|
||||
else if(rightVal!=null) {
|
||||
val result = if(rightVal.asBooleanValue) {
|
||||
when(expr.operator) {
|
||||
"and" -> expr.left
|
||||
"or" -> NumericLiteral.fromBoolean(true, expr.position)
|
||||
"xor" -> PrefixExpression("not", expr.left, expr.position)
|
||||
else -> throw FatalAstException("weird op")
|
||||
}
|
||||
} else {
|
||||
when(expr.operator) {
|
||||
"and" -> NumericLiteral.fromBoolean(false, expr.position)
|
||||
"or" -> expr.left
|
||||
"xor" -> expr.left
|
||||
else -> throw FatalAstException("weird op")
|
||||
}
|
||||
}
|
||||
return listOf(IAstModification.ReplaceNode(expr, result, parent))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,8 +59,8 @@ fun Program.inlineSubroutines(options: CompilationOptions): Int {
|
||||
return inliner.applyModifications()
|
||||
}
|
||||
|
||||
fun Program.simplifyExpressions(errors: IErrorReporter) : Int {
|
||||
val opti = ExpressionSimplifier(this, errors)
|
||||
fun Program.simplifyExpressions(errors: IErrorReporter, options: CompilationOptions) : Int {
|
||||
val opti = ExpressionSimplifier(this, options, errors)
|
||||
opti.visit(this)
|
||||
return opti.applyModifications()
|
||||
}
|
||||
|
@ -432,7 +432,7 @@ private fun optimizeAst(program: Program, compilerOptions: CompilationOptions, e
|
||||
removeUnusedCode(program, errors,compilerOptions)
|
||||
while (true) {
|
||||
// keep optimizing expressions and statements until no more steps remain
|
||||
val optsDone1 = program.simplifyExpressions(errors)
|
||||
val optsDone1 = program.simplifyExpressions(errors, compilerOptions)
|
||||
val optsDone2 = program.optimizeStatements(errors, functions, compilerOptions)
|
||||
val optsDone3 = program.inlineSubroutines(compilerOptions)
|
||||
program.constantFold(errors, compilerOptions) // because simplified statements and expressions can result in more constants that can be folded away
|
||||
|
@ -2,7 +2,19 @@ TODO
|
||||
====
|
||||
|
||||
the not changed (master branch) Petaxian compiled with -nostrictbool is a lot smaller than the updated (boolean branch) compiled without.
|
||||
What is the difference!
|
||||
What is the difference! ...:
|
||||
|
||||
beq +
|
||||
lda #1
|
||||
[possibly another label here]
|
||||
+ beq label_xxxx_shortcut / bne label_xxxx_shortcut
|
||||
or *_afterif labels.
|
||||
|
||||
if x>=GUN_MAX_RIGHT and not leftmost ; uses many Scratch vars ...
|
||||
...
|
||||
|
||||
--> add more special cases for PrefixExpression "not" to IfElseAsmgen? AssignmentAsmgen?
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -5,59 +5,14 @@
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
; cx16.r0L = true
|
||||
; cx16.r1L = false
|
||||
;
|
||||
; bool @shared bzz = 1
|
||||
; ubyte @shared ubb = true
|
||||
;
|
||||
; bool @shared bb1, bb2
|
||||
; bb1 = 0
|
||||
; bb2 = 44
|
||||
; bb1 = cx16.r0L
|
||||
;
|
||||
; bb2 = bb1 and cx16.r0L
|
||||
; cx16.r0L = bb1 ^ cx16.r0L
|
||||
;
|
||||
; ; bool[3] barr1 = 42
|
||||
; byte[3] @shared sbarr1 = true
|
||||
; ubyte[3] @shared ubarr1 = true
|
||||
; ubyte[3] @shared ubarr2 = bb2
|
||||
;
|
||||
; bool[] @shared boolarray = [1,0]
|
||||
; bool[] @shared boolarray2 = [42,0,false]
|
||||
; byte[] @shared sba = [true, false]
|
||||
; byte[] @shared sba2 = [true, false, 42]
|
||||
; ubyte[] @shared uba = [true, false]
|
||||
; ubyte[] @shared uba2 = [true, false, 42]
|
||||
;
|
||||
; if cx16.r0L >= 44 and not cx16.r0L
|
||||
; cx16.r0L++
|
||||
;
|
||||
; txt.print_ubhex(bb1, 1)
|
||||
; txt.print_ubhex(bb2, 42)
|
||||
; txt.print_ubhex(bb2, cx16.r0L)
|
||||
;
|
||||
; if cx16.r0L {
|
||||
; cx16.r0L++
|
||||
; }
|
||||
;
|
||||
; if cx16.r0 {
|
||||
; cx16.r0L++
|
||||
; }
|
||||
;
|
||||
; kapoof()
|
||||
; kapoof2()
|
||||
}
|
||||
ubyte @shared x
|
||||
bool @shared leftmost
|
||||
|
||||
; sub kapoof() -> bool {
|
||||
; cx16.r0L++
|
||||
; return cx16.r0L
|
||||
; }
|
||||
;
|
||||
; sub kapoof2() -> ubyte {
|
||||
; cx16.r0L++
|
||||
; return cx16.r0L==0
|
||||
; }
|
||||
if x>=10 and leftmost
|
||||
cx16.r0L++
|
||||
|
||||
if x>=10 and not leftmost
|
||||
cx16.r0L++
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user