mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 01:29:28 +00:00
added Absorption laws optimization
This commit is contained in:
parent
8a0e650511
commit
37638e7ed0
@ -97,6 +97,10 @@ class ExpressionSimplifier(private val program: Program,
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun after(expr: BinaryExpression, parent: Node): Iterable<IAstModification> {
|
override fun after(expr: BinaryExpression, parent: Node): Iterable<IAstModification> {
|
||||||
|
val newExpr = applyAbsorptionLaws(expr)
|
||||||
|
if(newExpr!=null)
|
||||||
|
return listOf(IAstModification.ReplaceNode(expr, newExpr, parent))
|
||||||
|
|
||||||
val leftVal = expr.left.constValue(program)
|
val leftVal = expr.left.constValue(program)
|
||||||
val rightVal = expr.right.constValue(program)
|
val rightVal = expr.right.constValue(program)
|
||||||
|
|
||||||
@ -158,8 +162,8 @@ class ExpressionSimplifier(private val program: Program,
|
|||||||
val y = determineY(x, leftBinExpr)
|
val y = determineY(x, leftBinExpr)
|
||||||
if (y != null) {
|
if (y != null) {
|
||||||
val yPlus1 = BinaryExpression(y, "+", NumericLiteral(leftDt, 1.0, y.position), y.position)
|
val yPlus1 = BinaryExpression(y, "+", NumericLiteral(leftDt, 1.0, y.position), y.position)
|
||||||
val newExpr = BinaryExpression(x, "*", yPlus1, x.position)
|
val replacement = BinaryExpression(x, "*", yPlus1, x.position)
|
||||||
return listOf(IAstModification.ReplaceNode(expr, newExpr, parent))
|
return listOf(IAstModification.ReplaceNode(expr, replacement, parent))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Y*X - X -> X*(Y - 1)
|
// Y*X - X -> X*(Y - 1)
|
||||||
@ -168,8 +172,8 @@ class ExpressionSimplifier(private val program: Program,
|
|||||||
val y = determineY(x, leftBinExpr)
|
val y = determineY(x, leftBinExpr)
|
||||||
if (y != null) {
|
if (y != null) {
|
||||||
val yMinus1 = BinaryExpression(y, "-", NumericLiteral(leftDt, 1.0, y.position), y.position)
|
val yMinus1 = BinaryExpression(y, "-", NumericLiteral(leftDt, 1.0, y.position), y.position)
|
||||||
val newExpr = BinaryExpression(x, "*", yMinus1, x.position)
|
val replacement = BinaryExpression(x, "*", yMinus1, x.position)
|
||||||
return listOf(IAstModification.ReplaceNode(expr, newExpr, parent))
|
return listOf(IAstModification.ReplaceNode(expr, replacement, parent))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (rightBinExpr?.operator == "*") {
|
} else if (rightBinExpr?.operator == "*") {
|
||||||
@ -180,8 +184,8 @@ class ExpressionSimplifier(private val program: Program,
|
|||||||
val y = determineY(x, rightBinExpr)
|
val y = determineY(x, rightBinExpr)
|
||||||
if (y != null) {
|
if (y != null) {
|
||||||
val yPlus1 = BinaryExpression(y, "+", NumericLiteral.optimalInteger(1, y.position), y.position)
|
val yPlus1 = BinaryExpression(y, "+", NumericLiteral.optimalInteger(1, y.position), y.position)
|
||||||
val newExpr = BinaryExpression(x, "*", yPlus1, x.position)
|
val replacement = BinaryExpression(x, "*", yPlus1, x.position)
|
||||||
return listOf(IAstModification.ReplaceNode(expr, newExpr, parent))
|
return listOf(IAstModification.ReplaceNode(expr, replacement, parent))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -270,7 +274,7 @@ class ExpressionSimplifier(private val program: Program,
|
|||||||
|
|
||||||
// simplify when a term is constant and directly determines the outcome
|
// simplify when a term is constant and directly determines the outcome
|
||||||
val constFalse = NumericLiteral.fromBoolean(false, expr.position)
|
val constFalse = NumericLiteral.fromBoolean(false, expr.position)
|
||||||
val newExpr: Expression? = when (expr.operator) {
|
val newExpr2 = when (expr.operator) {
|
||||||
"|" -> {
|
"|" -> {
|
||||||
when {
|
when {
|
||||||
leftVal?.number==0.0 -> expr.right
|
leftVal?.number==0.0 -> expr.right
|
||||||
@ -336,12 +340,44 @@ class ExpressionSimplifier(private val program: Program,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(newExpr != null)
|
if(newExpr2 != null)
|
||||||
return listOf(IAstModification.ReplaceNode(expr, newExpr, parent))
|
return listOf(IAstModification.ReplaceNode(expr, newExpr2, parent))
|
||||||
|
|
||||||
return noModifications
|
return noModifications
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun applyAbsorptionLaws(expr: BinaryExpression): Expression? {
|
||||||
|
val rightB = expr.right as? BinaryExpression
|
||||||
|
if(rightB!=null) {
|
||||||
|
// absorption laws: a or (a and b) --> a, a and (a or b) --> a
|
||||||
|
if(expr.operator=="or" && rightB.operator=="and") {
|
||||||
|
if(expr.left isSameAs rightB.left || expr.left isSameAs rightB.right) {
|
||||||
|
return expr.left
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(expr.operator=="and" && rightB.operator=="or") {
|
||||||
|
if(expr.left isSameAs rightB.left || expr.left isSameAs rightB.right) {
|
||||||
|
return expr.left
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val leftB = expr.left as? BinaryExpression
|
||||||
|
if(leftB!=null) {
|
||||||
|
// absorption laws: (a and b) or a --> a, (a or b) and a --> a
|
||||||
|
if(expr.operator=="or" && leftB.operator=="and") {
|
||||||
|
if(expr.right isSameAs leftB.left || expr.left isSameAs leftB.right) {
|
||||||
|
return expr.right
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(expr.operator=="and" && leftB.operator=="or") {
|
||||||
|
if(expr.right isSameAs leftB.left || expr.right isSameAs leftB.right) {
|
||||||
|
return expr.right
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
override fun after(functionCallExpr: FunctionCallExpression, parent: Node): Iterable<IAstModification> {
|
override fun after(functionCallExpr: FunctionCallExpression, parent: Node): Iterable<IAstModification> {
|
||||||
if(functionCallExpr.target.nameInSource == listOf("lsb")) {
|
if(functionCallExpr.target.nameInSource == listOf("lsb")) {
|
||||||
if(functionCallExpr.args.isEmpty())
|
if(functionCallExpr.args.isEmpty())
|
||||||
|
@ -965,4 +965,83 @@ main {
|
|||||||
(assignv1 as NumericLiteral).number shouldBe 1.0
|
(assignv1 as NumericLiteral).number shouldBe 1.0
|
||||||
(assignv2 as NumericLiteral).number shouldBe 0.0
|
(assignv2 as NumericLiteral).number shouldBe 0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test("De Morgan's laws") {
|
||||||
|
val src="""
|
||||||
|
main {
|
||||||
|
sub start() {
|
||||||
|
bool @shared a1
|
||||||
|
bool @shared a2
|
||||||
|
|
||||||
|
if a1==0 and a2==0
|
||||||
|
cx16.r0++
|
||||||
|
if a1==0 or a2==0
|
||||||
|
cx16.r0++
|
||||||
|
|
||||||
|
if not a1 or not a2
|
||||||
|
cx16.r0++
|
||||||
|
if not a1 and not a2
|
||||||
|
cx16.r0++
|
||||||
|
}
|
||||||
|
}"""
|
||||||
|
val result = compileText(Cx16Target(), true, src, writeAssembly = false)!!
|
||||||
|
val st = result.compilerAst.entrypoint.statements
|
||||||
|
st.size shouldBe 8
|
||||||
|
val if1c = (st[4] as IfElse).condition as BinaryExpression
|
||||||
|
val if2c = (st[5] as IfElse).condition as BinaryExpression
|
||||||
|
val if3c = (st[6] as IfElse).condition as BinaryExpression
|
||||||
|
val if4c = (st[7] as IfElse).condition as BinaryExpression
|
||||||
|
if1c.operator shouldBe "=="
|
||||||
|
(if1c.right as NumericLiteral).number shouldBe 0.0
|
||||||
|
(if1c.left as BinaryExpression).operator shouldBe "or"
|
||||||
|
if2c.operator shouldBe "=="
|
||||||
|
(if2c.right as NumericLiteral).number shouldBe 0.0
|
||||||
|
(if2c.left as BinaryExpression).operator shouldBe "and"
|
||||||
|
if3c.operator shouldBe "=="
|
||||||
|
(if3c.right as NumericLiteral).number shouldBe 0.0
|
||||||
|
(if3c.left as BinaryExpression).operator shouldBe "and"
|
||||||
|
if4c.operator shouldBe "=="
|
||||||
|
(if4c.right as NumericLiteral).number shouldBe 0.0
|
||||||
|
(if4c.left as BinaryExpression).operator shouldBe "or"
|
||||||
|
}
|
||||||
|
|
||||||
|
test("absorption laws") {
|
||||||
|
val src="""
|
||||||
|
main {
|
||||||
|
sub start() {
|
||||||
|
bool @shared a
|
||||||
|
bool @shared b
|
||||||
|
|
||||||
|
if a or (a and b)
|
||||||
|
cx16.r0 ++
|
||||||
|
if a or (b and a)
|
||||||
|
cx16.r0 ++
|
||||||
|
if a and (a or b)
|
||||||
|
cx16.r0 ++
|
||||||
|
if a and (b or a)
|
||||||
|
cx16.r0 ++
|
||||||
|
|
||||||
|
; no opt:
|
||||||
|
if a and (b and a)
|
||||||
|
cx16.r0 ++
|
||||||
|
if a or (b or a)
|
||||||
|
cx16.r0 ++
|
||||||
|
}
|
||||||
|
}"""
|
||||||
|
val result = compileText(Cx16Target(), true, src, writeAssembly = false)!!
|
||||||
|
val st = result.compilerAst.entrypoint.statements
|
||||||
|
st.size shouldBe 10
|
||||||
|
val if1 = st[4] as IfElse
|
||||||
|
val if2 = st[5] as IfElse
|
||||||
|
val if3 = st[6] as IfElse
|
||||||
|
val if4 = st[7] as IfElse
|
||||||
|
(if1.condition as IdentifierReference).nameInSource shouldBe listOf("a")
|
||||||
|
(if2.condition as IdentifierReference).nameInSource shouldBe listOf("a")
|
||||||
|
(if3.condition as IdentifierReference).nameInSource shouldBe listOf("a")
|
||||||
|
(if4.condition as IdentifierReference).nameInSource shouldBe listOf("a")
|
||||||
|
val if5 = st[8] as IfElse
|
||||||
|
val if6 = st[9] as IfElse
|
||||||
|
if5.condition shouldBe instanceOf<BinaryExpression>()
|
||||||
|
if6.condition shouldBe instanceOf<BinaryExpression>()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
@ -7,19 +7,51 @@ main {
|
|||||||
; is optimizing this useful? : not a1 or not a2 -> not(a1 and a2) likewise for and.
|
; is optimizing this useful? : not a1 or not a2 -> not(a1 and a2) likewise for and.
|
||||||
bool @shared a1 = true
|
bool @shared a1 = true
|
||||||
bool @shared a2
|
bool @shared a2
|
||||||
bool @shared a4
|
bool @shared a
|
||||||
|
bool @shared b
|
||||||
|
|
||||||
if a1==0 and a2==0
|
; absorbption opt:
|
||||||
cx16.r0++
|
; if a or (a and b)
|
||||||
|
; cx16.r0 ++
|
||||||
|
; if a or (b and a)
|
||||||
|
; cx16.r0 ++
|
||||||
|
; if a and (a or b)
|
||||||
|
; cx16.r0 ++
|
||||||
|
; if a and (b or a)
|
||||||
|
; cx16.r0 ++
|
||||||
|
;
|
||||||
|
; ; no opt:
|
||||||
|
; if a and (b and a)
|
||||||
|
; cx16.r0 ++
|
||||||
|
; if a or (b or a)
|
||||||
|
; cx16.r0 ++
|
||||||
|
|
||||||
if (a1!=0 or a2!=0)==0
|
bool @shared iteration_in_progress = false
|
||||||
cx16.r0++
|
ubyte @shared num_bytes = 99
|
||||||
|
|
||||||
if a1==0 or a2==0
|
if not iteration_in_progress or not num_bytes
|
||||||
cx16.r0++
|
txt.print("yep1")
|
||||||
|
else
|
||||||
|
txt.print("nope1")
|
||||||
|
|
||||||
if (a1!=0 and a2!=0)==0
|
iteration_in_progress = true
|
||||||
cx16.r0++
|
if not iteration_in_progress or not num_bytes
|
||||||
|
txt.print("yep2")
|
||||||
|
else
|
||||||
|
txt.print("nope2")
|
||||||
|
|
||||||
|
;
|
||||||
|
; if a1==0 and a2==0
|
||||||
|
; cx16.r0++
|
||||||
|
;
|
||||||
|
; if (a1!=0 or a2!=0)==0
|
||||||
|
; cx16.r0++
|
||||||
|
;
|
||||||
|
; if a1==0 or a2==0
|
||||||
|
; cx16.r0++
|
||||||
|
;
|
||||||
|
; if (a1!=0 and a2!=0)==0
|
||||||
|
; cx16.r0++
|
||||||
|
|
||||||
|
|
||||||
; if not a1 or not a2
|
; if not a1 or not a2
|
||||||
|
Loading…
Reference in New Issue
Block a user