mirror of
https://github.com/irmen/prog8.git
synced 2024-10-05 03:56:02 +00:00
optimize conditional expression WORD & $ff00 to just msb(WORD)&$ff
This commit is contained in:
parent
d6b8936376
commit
18790d867c
@ -360,6 +360,12 @@ internal class AssignmentAsmGen(private val program: Program,
|
||||
if(expr.operator in setOf("&", "|", "^", "and", "or", "xor")) {
|
||||
if(expr.left.inferType(program).isBytes && expr.right.inferType(program).isBytes &&
|
||||
expr.left.isSimple && expr.right.isSimple) {
|
||||
// if(expr.right is NumericLiteral || expr.right is IdentifierReference) {
|
||||
// TODO("optimized code for logical with right number/variable arg (byte)")
|
||||
// } else if(expr.left is NumericLiteral || expr.left is IdentifierReference) {
|
||||
// TODO("optimized code for logical with left number/variable arg (byte)")
|
||||
// }
|
||||
|
||||
assignExpressionToRegister(expr.left, RegisterOrPair.A, false)
|
||||
asmgen.saveRegisterStack(CpuRegister.A, false)
|
||||
assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_B1", DataType.UBYTE, expr.definingSubroutine)
|
||||
@ -375,6 +381,11 @@ internal class AssignmentAsmGen(private val program: Program,
|
||||
}
|
||||
if(expr.left.inferType(program).isWords && expr.right.inferType(program).isWords &&
|
||||
expr.left.isSimple && expr.right.isSimple) {
|
||||
// if(expr.right is NumericLiteral || expr.right is IdentifierReference) {
|
||||
// TODO("optimized code for logical with right number/variable arg (word)")
|
||||
// } else if(expr.left is NumericLiteral || expr.left is IdentifierReference) {
|
||||
// TODO("optimized code for logical with left number/variable arg (word)")
|
||||
// }
|
||||
assignExpressionToRegister(expr.left, RegisterOrPair.AY, false)
|
||||
asmgen.saveRegisterStack(CpuRegister.A, false)
|
||||
asmgen.saveRegisterStack(CpuRegister.Y, false)
|
||||
|
@ -10,13 +10,14 @@ import prog8.ast.statements.*
|
||||
import prog8.ast.walk.AstWalker
|
||||
import prog8.ast.walk.IAstModification
|
||||
import prog8.code.core.*
|
||||
import prog8.code.target.VMTarget
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.log2
|
||||
import kotlin.math.pow
|
||||
|
||||
// TODO add more peephole expression optimizations? Investigate what optimizations binaryen has, also see https://egorbo.com/peephole-optimizations.html
|
||||
|
||||
class ExpressionSimplifier(private val program: Program) : AstWalker() {
|
||||
class ExpressionSimplifier(private val program: Program, private val compTarget: ICompilationTarget) : AstWalker() {
|
||||
private val powersOfTwo = (1..16).map { (2.0).pow(it) }.toSet()
|
||||
private val negativePowersOfTwo = powersOfTwo.map { -it }.toSet()
|
||||
|
||||
@ -71,6 +72,22 @@ class ExpressionSimplifier(private val program: Program) : AstWalker() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(compTarget.name!=VMTarget.NAME) {
|
||||
val booleanCondition = ifElse.condition as? BinaryExpression
|
||||
if(booleanCondition!=null && booleanCondition.operator=="&") {
|
||||
// special optimization of WORD & $ff00 -> just and the msb of WORD with $ff
|
||||
val rightNum = booleanCondition.right as? NumericLiteral
|
||||
if(rightNum!=null && rightNum.type==DataType.UWORD && (rightNum.number.toInt() and 0x00ff)==0) {
|
||||
val msb = BuiltinFunctionCall(IdentifierReference(listOf("msb"), booleanCondition.left.position), mutableListOf(booleanCondition.left), booleanCondition.left.position)
|
||||
val bytevalue = NumericLiteral(DataType.UBYTE, (rightNum.number.toInt() shr 8).toDouble(), booleanCondition.right.position)
|
||||
return listOf(
|
||||
IAstModification.ReplaceNode(booleanCondition.left, msb, booleanCondition),
|
||||
IAstModification.ReplaceNode(booleanCondition.right, bytevalue, booleanCondition))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return noModifications
|
||||
}
|
||||
|
||||
|
@ -60,8 +60,8 @@ fun Program.inlineSubroutines(): Int {
|
||||
return inliner.applyModifications()
|
||||
}
|
||||
|
||||
fun Program.simplifyExpressions() : Int {
|
||||
val opti = ExpressionSimplifier(this)
|
||||
fun Program.simplifyExpressions(target: ICompilationTarget) : Int {
|
||||
val opti = ExpressionSimplifier(this, target)
|
||||
opti.visit(this)
|
||||
return opti.applyModifications()
|
||||
}
|
||||
|
@ -358,7 +358,7 @@ private fun optimizeAst(program: Program, compilerOptions: CompilationOptions, e
|
||||
remover.applyModifications()
|
||||
while (true) {
|
||||
// keep optimizing expressions and statements until no more steps remain
|
||||
val optsDone1 = program.simplifyExpressions()
|
||||
val optsDone1 = program.simplifyExpressions(compTarget)
|
||||
val optsDone2 = program.splitBinaryExpressions(compilerOptions)
|
||||
val optsDone3 = program.optimizeStatements(errors, functions, compTarget)
|
||||
val optsDone4 = program.inlineSubroutines()
|
||||
|
@ -3,6 +3,9 @@ TODO
|
||||
|
||||
For next release
|
||||
^^^^^^^^^^^^^^^^
|
||||
- finish the logical expression optimizations set in TODO's in attemptAssignOptimizedBinexpr()
|
||||
- try more benchmarks from https://gglabs.us/node/2293
|
||||
|
||||
...
|
||||
|
||||
|
||||
@ -77,6 +80,7 @@ Optimizations:
|
||||
- VariableAllocator: can we think of a smarter strategy for allocating variables into zeropage, rather than first-come-first-served?
|
||||
- when a loopvariable of a forloop isn't referenced in the body, and the iterations are known, replace the loop by a repeatloop
|
||||
but we have no efficient way right now to see if the body references a variable.
|
||||
- optimize function argument expressions better (use temporary variables to replace non-simple expressions?)
|
||||
|
||||
|
||||
STRUCTS again?
|
||||
|
@ -3,16 +3,17 @@
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
ubyte[] buffer = [$11,$22,$33,$44]
|
||||
uword data = &buffer
|
||||
|
||||
uword crc = $ffff
|
||||
crc ^= mkword(@(data), 0)
|
||||
txt.print_uwhex(crc, true)
|
||||
crc = $ffff
|
||||
ubyte variable = @(data)
|
||||
crc ^= mkword(variable, 0)
|
||||
txt.print_uwhex(crc, true)
|
||||
txt.print_uwhex(crc | (crc & $8000), true)
|
||||
; if crc & $8000 ; msb(crc) & $80
|
||||
; txt.print("yes")
|
||||
; else
|
||||
; txt.print("fail!")
|
||||
;
|
||||
; if msb(crc) & $80
|
||||
; txt.print("yes")
|
||||
; else
|
||||
; txt.print("fail!")
|
||||
}
|
||||
|
||||
; sub start2() {
|
||||
|
Loading…
Reference in New Issue
Block a user