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 x
|
||||
float y
|
||||
float xsq
|
||||
float ysq
|
||||
float xsquared
|
||||
float ysquared
|
||||
byte iter
|
||||
word plotx
|
||||
byte ploty
|
||||
@ -24,21 +24,21 @@
|
||||
_vm_gfx_text(5, 5, 7, "Calculating Mandelbrot Fractal...")
|
||||
|
||||
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 {
|
||||
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
|
||||
y = 0.0
|
||||
xsq = 0
|
||||
ysq = 0
|
||||
xsquared = 0
|
||||
ysquared = 0
|
||||
iter = 0
|
||||
while (iter<32 and xsq+ysq<4) {
|
||||
while (iter<32 and xsquared+ysquared<4) {
|
||||
y = x*y*2 + yy
|
||||
x = xsq - ysq + xx
|
||||
xsq = x*x
|
||||
ysq = y*y
|
||||
x = xsquared - ysquared + xx
|
||||
xsquared = x*x
|
||||
ysquared = y*y
|
||||
iter++
|
||||
}
|
||||
|
||||
|
@ -4,15 +4,21 @@
|
||||
|
||||
sub start() -> () {
|
||||
|
||||
const word yoffset=100
|
||||
const float height=20.2
|
||||
word pixely
|
||||
float yy
|
||||
float v
|
||||
|
||||
pixely = A % 0 ; @todo divide 0
|
||||
pixely = A / 0 ; @todo divide 0
|
||||
pixely = A // 0 ; @todo divide 0
|
||||
yy = 11.0-(v-22.0)
|
||||
yy = 11.0-(22.0-v)
|
||||
yy = (v-22.0)-11.0
|
||||
yy = (22.0-v)-11.0
|
||||
|
||||
pixely |= 1 ; pixely = pixely | 1
|
||||
pixely &= 1 ; pixely = pixely & 1
|
||||
pixely ^= 1 ; pixely = pixely ^ 1
|
||||
yy = 11.0/(v/22.0)
|
||||
yy = 11.0/(22.0/v)
|
||||
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 fun linkParents(parent: Node) {
|
||||
|
@ -3,6 +3,10 @@ package prog8.optimizing
|
||||
import prog8.ast.*
|
||||
import kotlin.math.pow
|
||||
|
||||
|
||||
val associativeOperators = setOf("+", "*", "&", "|", "^", "or", "and", "xor", "==", "!=")
|
||||
|
||||
|
||||
class ConstExprEvaluator {
|
||||
|
||||
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.
|
||||
* Compile-time constant sub expressions will be evaluated on the spot.
|
||||
* 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 {
|
||||
return try {
|
||||
super.process(expr)
|
||||
|
||||
val evaluator = ConstExprEvaluator()
|
||||
val leftconst = expr.left.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 {
|
||||
leftconst != null && rightconst != null -> {
|
||||
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 {
|
||||
range.from = range.from.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 fun reorderAssociative(expr: BinaryExpression, leftVal: LiteralValue?): ReorderedAssociativeBinaryExpr {
|
||||
val associativeOperators = setOf("+", "*", "&", "|", "^", "or", "and", "xor", "==", "!=")
|
||||
if(associativeOperators.contains(expr.operator) && leftVal!=null) {
|
||||
// swap left and right so that right is always the constant
|
||||
val tmp = expr.left
|
||||
|
Loading…
Reference in New Issue
Block a user