optimize certain boolean comparisons more

This commit is contained in:
Irmen de Jong 2024-03-05 01:31:04 +01:00
parent c6bf57b390
commit 9826d7c494
6 changed files with 110 additions and 99 deletions

View File

@ -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) {

View File

@ -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))
}
}

View File

@ -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()
}

View File

@ -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

View File

@ -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?

View File

@ -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++
}
}