mirror of
https://github.com/irmen/prog8.git
synced 2024-11-18 19:12:44 +00:00
added some more constant foldings
This commit is contained in:
parent
6681787288
commit
5e729e21ff
@ -14,8 +14,8 @@
|
|||||||
float yy
|
float yy
|
||||||
float x
|
float x
|
||||||
float y
|
float y
|
||||||
float xsq
|
float xsquared
|
||||||
float ysq
|
float ysquared
|
||||||
byte iter
|
byte iter
|
||||||
word plotx
|
word plotx
|
||||||
byte ploty
|
byte ploty
|
||||||
@ -24,21 +24,21 @@
|
|||||||
_vm_gfx_text(5, 5, 7, "Calculating Mandelbrot Fractal...")
|
_vm_gfx_text(5, 5, 7, "Calculating Mandelbrot Fractal...")
|
||||||
|
|
||||||
for pixely in yoffset to yoffset+height-1 {
|
for pixely in yoffset to yoffset+height-1 {
|
||||||
yy = flt((pixely-yoffset))/height/3.6+0.4 ; @todo why is /height/3.6 not const-folded???
|
yy = flt((pixely-yoffset))/height/3.6+0.4
|
||||||
|
|
||||||
for pixelx in xoffset to xoffset+width-1 {
|
for pixelx in xoffset to xoffset+width-1 {
|
||||||
xx = flt((pixelx-xoffset))/width/3+0.2 ; @todo why is /width/3 not const-folded???
|
xx = flt((pixelx-xoffset))/width/3+0.2
|
||||||
|
|
||||||
x = 0.0
|
x = 0.0
|
||||||
y = 0.0
|
y = 0.0
|
||||||
xsq = 0
|
xsquared = 0
|
||||||
ysq = 0
|
ysquared = 0
|
||||||
iter = 0
|
iter = 0
|
||||||
while (iter<32 and xsq+ysq<4) {
|
while (iter<32 and xsquared+ysquared<4) {
|
||||||
y = x*y*2 + yy
|
y = x*y*2 + yy
|
||||||
x = xsq - ysq + xx
|
x = xsquared - ysquared + xx
|
||||||
xsq = x*x
|
xsquared = x*x
|
||||||
ysq = y*y
|
ysquared = y*y
|
||||||
iter++
|
iter++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,15 +4,21 @@
|
|||||||
|
|
||||||
sub start() -> () {
|
sub start() -> () {
|
||||||
|
|
||||||
|
const word yoffset=100
|
||||||
|
const float height=20.2
|
||||||
word pixely
|
word pixely
|
||||||
|
float yy
|
||||||
|
float v
|
||||||
|
|
||||||
pixely = A % 0 ; @todo divide 0
|
yy = 11.0-(v-22.0)
|
||||||
pixely = A / 0 ; @todo divide 0
|
yy = 11.0-(22.0-v)
|
||||||
pixely = A // 0 ; @todo divide 0
|
yy = (v-22.0)-11.0
|
||||||
|
yy = (22.0-v)-11.0
|
||||||
|
|
||||||
pixely |= 1 ; pixely = pixely | 1
|
yy = 11.0/(v/22.0)
|
||||||
pixely &= 1 ; pixely = pixely & 1
|
yy = 11.0/(22.0/v)
|
||||||
pixely ^= 1 ; pixely = pixely ^ 1
|
yy = (v/22.0)/11.0
|
||||||
|
yy = (22.0/v)/11.0
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -709,7 +709,7 @@ class PrefixExpression(val operator: String, var expression: IExpression, overri
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class BinaryExpression(var left: IExpression, val operator: String, var right: IExpression, override val position: Position) : IExpression {
|
class BinaryExpression(var left: IExpression, var operator: String, var right: IExpression, override val position: Position) : IExpression {
|
||||||
override lateinit var parent: Node
|
override lateinit var parent: Node
|
||||||
|
|
||||||
override fun linkParents(parent: Node) {
|
override fun linkParents(parent: Node) {
|
||||||
|
@ -3,6 +3,10 @@ package prog8.optimizing
|
|||||||
import prog8.ast.*
|
import prog8.ast.*
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
|
|
||||||
|
|
||||||
|
val associativeOperators = setOf("+", "*", "&", "|", "^", "or", "and", "xor", "==", "!=")
|
||||||
|
|
||||||
|
|
||||||
class ConstExprEvaluator {
|
class ConstExprEvaluator {
|
||||||
|
|
||||||
fun evaluate(left: LiteralValue, operator: String, right: LiteralValue): IExpression {
|
fun evaluate(left: LiteralValue, operator: String, right: LiteralValue): IExpression {
|
||||||
|
@ -171,14 +171,49 @@ class ConstantFolding(private val namespace: INameScope) : IAstProcessor {
|
|||||||
* Try to process a binary expression.
|
* Try to process a binary expression.
|
||||||
* Compile-time constant sub expressions will be evaluated on the spot.
|
* Compile-time constant sub expressions will be evaluated on the spot.
|
||||||
* For instance, "9 * (4 + 2)" will be optimized into the integer literal 54.
|
* For instance, "9 * (4 + 2)" will be optimized into the integer literal 54.
|
||||||
|
*
|
||||||
|
* More complex: dealing with associative operators:
|
||||||
|
* if our operator is +,-,*,/ THEN:
|
||||||
|
* if one of our operands is a const, THEN:
|
||||||
|
* if the other operand is also a binary expression THEN:
|
||||||
|
* if its operator is in the same group as our operator (+ and -, * and /) THEN:
|
||||||
|
* if one of its operands is a const THEN:
|
||||||
|
* reorder the expression by lifting out the calculation on the 2 consts. (so that it can be const-folded later)
|
||||||
*/
|
*/
|
||||||
override fun process(expr: BinaryExpression): IExpression {
|
override fun process(expr: BinaryExpression): IExpression {
|
||||||
return try {
|
return try {
|
||||||
super.process(expr)
|
super.process(expr)
|
||||||
|
|
||||||
val evaluator = ConstExprEvaluator()
|
|
||||||
val leftconst = expr.left.constValue(namespace)
|
val leftconst = expr.left.constValue(namespace)
|
||||||
val rightconst = expr.right.constValue(namespace)
|
val rightconst = expr.right.constValue(namespace)
|
||||||
|
|
||||||
|
// check associative operators and const operands
|
||||||
|
if(setOf("+", "-", "*", "/").contains(expr.operator)) {
|
||||||
|
val subExpr: BinaryExpression? = when {
|
||||||
|
leftconst!=null -> expr.right as? BinaryExpression
|
||||||
|
rightconst!=null -> expr.left as? BinaryExpression
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
if(subExpr!=null) {
|
||||||
|
val sameGroupOperator =
|
||||||
|
when (expr.operator) {
|
||||||
|
"+", "-" -> subExpr.operator == "+" || subExpr.operator == "-"
|
||||||
|
"*", "/" -> subExpr.operator == "*" || subExpr.operator == "/"
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
if (sameGroupOperator) {
|
||||||
|
val subleftconst = subExpr.left.constValue(namespace)
|
||||||
|
val subrightconst = subExpr.right.constValue(namespace)
|
||||||
|
if (subleftconst != null || subrightconst != null) {
|
||||||
|
// reorder!
|
||||||
|
return reorderAssociativeConst(expr, subExpr, leftconst!=null, rightconst!=null, subleftconst!=null, subrightconst!=null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// const fold when both operands are a const
|
||||||
|
val evaluator = ConstExprEvaluator()
|
||||||
return when {
|
return when {
|
||||||
leftconst != null && rightconst != null -> {
|
leftconst != null && rightconst != null -> {
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
@ -192,6 +227,66 @@ class ConstantFolding(private val namespace: INameScope) : IAstProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun reorderAssociativeConst(expr: BinaryExpression,
|
||||||
|
subExpr: BinaryExpression,
|
||||||
|
leftIsConst: Boolean,
|
||||||
|
rightIsConst: Boolean,
|
||||||
|
subleftIsConst: Boolean,
|
||||||
|
subrightIsConst: Boolean): IExpression {
|
||||||
|
|
||||||
|
if(expr.operator==subExpr.operator) {
|
||||||
|
// both operators are the same.
|
||||||
|
|
||||||
|
// If + or *, we can simply swap the const of expr and Var in subexpr.
|
||||||
|
if(expr.operator=="+" || expr.operator=="*") {
|
||||||
|
if(leftIsConst) {
|
||||||
|
if(subleftIsConst)
|
||||||
|
expr.left = subExpr.right.also { subExpr.right = expr.left }
|
||||||
|
else
|
||||||
|
expr.left = subExpr.left.also { subExpr.left = expr.left }
|
||||||
|
} else {
|
||||||
|
if(subleftIsConst)
|
||||||
|
expr.right = subExpr.right.also {subExpr.right = expr.right }
|
||||||
|
else
|
||||||
|
expr.right = subExpr.left.also { subExpr.left = expr.right }
|
||||||
|
}
|
||||||
|
optimizationsDone++
|
||||||
|
return expr
|
||||||
|
}
|
||||||
|
|
||||||
|
// If - or /, we simetimes must reorder more, and flip operators (- -> +, / -> *)
|
||||||
|
if(expr.operator=="-" || expr.operator=="/") {
|
||||||
|
optimizationsDone++
|
||||||
|
if(leftIsConst) {
|
||||||
|
if(subleftIsConst) {
|
||||||
|
val tmp = subExpr.right
|
||||||
|
subExpr.right = subExpr.left
|
||||||
|
subExpr.left = expr.left
|
||||||
|
expr.left = tmp
|
||||||
|
expr.operator = if(expr.operator=="-") "+" else "*"
|
||||||
|
} else
|
||||||
|
return BinaryExpression(
|
||||||
|
BinaryExpression(expr.left, if(expr.operator=="-") "+" else "*", subExpr.right, subExpr.position),
|
||||||
|
expr.operator, subExpr.left, expr.position)
|
||||||
|
} else {
|
||||||
|
if(subleftIsConst)
|
||||||
|
expr.right = subExpr.right.also {subExpr.right = expr.right}
|
||||||
|
else
|
||||||
|
return BinaryExpression(
|
||||||
|
subExpr.left, expr.operator,
|
||||||
|
BinaryExpression(expr.right, if(expr.operator=="-") "+" else "*", subExpr.right, subExpr.position),
|
||||||
|
expr.position)
|
||||||
|
}
|
||||||
|
return expr
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: other combinations of operators and constants
|
||||||
|
return expr
|
||||||
|
} else {
|
||||||
|
return expr // TODO reorder when operators are not identical
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun process(range: RangeExpr): IExpression {
|
override fun process(range: RangeExpr): IExpression {
|
||||||
range.from = range.from.process(this)
|
range.from = range.from.process(this)
|
||||||
range.to = range.to.process(this)
|
range.to = range.to.process(this)
|
||||||
|
@ -115,7 +115,6 @@ class SimplifyExpressions(private val namespace: INameScope) : IAstProcessor {
|
|||||||
private data class ReorderedAssociativeBinaryExpr(val expr: BinaryExpression, val leftVal: LiteralValue?, val rightVal: LiteralValue?)
|
private data class ReorderedAssociativeBinaryExpr(val expr: BinaryExpression, val leftVal: LiteralValue?, val rightVal: LiteralValue?)
|
||||||
|
|
||||||
private fun reorderAssociative(expr: BinaryExpression, leftVal: LiteralValue?): ReorderedAssociativeBinaryExpr {
|
private fun reorderAssociative(expr: BinaryExpression, leftVal: LiteralValue?): ReorderedAssociativeBinaryExpr {
|
||||||
val associativeOperators = setOf("+", "*", "&", "|", "^", "or", "and", "xor", "==", "!=")
|
|
||||||
if(associativeOperators.contains(expr.operator) && leftVal!=null) {
|
if(associativeOperators.contains(expr.operator) && leftVal!=null) {
|
||||||
// swap left and right so that right is always the constant
|
// swap left and right so that right is always the constant
|
||||||
val tmp = expr.left
|
val tmp = expr.left
|
||||||
|
Loading…
Reference in New Issue
Block a user