mirror of
https://github.com/irmen/prog8.git
synced 2024-12-23 09:32:43 +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> {
|
||||
val newExpr = applyAbsorptionLaws(expr)
|
||||
if(newExpr!=null)
|
||||
return listOf(IAstModification.ReplaceNode(expr, newExpr, parent))
|
||||
|
||||
val leftVal = expr.left.constValue(program)
|
||||
val rightVal = expr.right.constValue(program)
|
||||
|
||||
@ -158,8 +162,8 @@ class ExpressionSimplifier(private val program: Program,
|
||||
val y = determineY(x, leftBinExpr)
|
||||
if (y != null) {
|
||||
val yPlus1 = BinaryExpression(y, "+", NumericLiteral(leftDt, 1.0, y.position), y.position)
|
||||
val newExpr = BinaryExpression(x, "*", yPlus1, x.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr, newExpr, parent))
|
||||
val replacement = BinaryExpression(x, "*", yPlus1, x.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr, replacement, parent))
|
||||
}
|
||||
} else {
|
||||
// Y*X - X -> X*(Y - 1)
|
||||
@ -168,8 +172,8 @@ class ExpressionSimplifier(private val program: Program,
|
||||
val y = determineY(x, leftBinExpr)
|
||||
if (y != null) {
|
||||
val yMinus1 = BinaryExpression(y, "-", NumericLiteral(leftDt, 1.0, y.position), y.position)
|
||||
val newExpr = BinaryExpression(x, "*", yMinus1, x.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr, newExpr, parent))
|
||||
val replacement = BinaryExpression(x, "*", yMinus1, x.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr, replacement, parent))
|
||||
}
|
||||
}
|
||||
} else if (rightBinExpr?.operator == "*") {
|
||||
@ -180,8 +184,8 @@ class ExpressionSimplifier(private val program: Program,
|
||||
val y = determineY(x, rightBinExpr)
|
||||
if (y != null) {
|
||||
val yPlus1 = BinaryExpression(y, "+", NumericLiteral.optimalInteger(1, y.position), y.position)
|
||||
val newExpr = BinaryExpression(x, "*", yPlus1, x.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr, newExpr, parent))
|
||||
val replacement = BinaryExpression(x, "*", yPlus1, x.position)
|
||||
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
|
||||
val constFalse = NumericLiteral.fromBoolean(false, expr.position)
|
||||
val newExpr: Expression? = when (expr.operator) {
|
||||
val newExpr2 = when (expr.operator) {
|
||||
"|" -> {
|
||||
when {
|
||||
leftVal?.number==0.0 -> expr.right
|
||||
@ -336,12 +340,44 @@ class ExpressionSimplifier(private val program: Program,
|
||||
}
|
||||
}
|
||||
|
||||
if(newExpr != null)
|
||||
return listOf(IAstModification.ReplaceNode(expr, newExpr, parent))
|
||||
if(newExpr2 != null)
|
||||
return listOf(IAstModification.ReplaceNode(expr, newExpr2, parent))
|
||||
|
||||
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> {
|
||||
if(functionCallExpr.target.nameInSource == listOf("lsb")) {
|
||||
if(functionCallExpr.args.isEmpty())
|
||||
|
@ -965,4 +965,83 @@ main {
|
||||
(assignv1 as NumericLiteral).number shouldBe 1.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.
|
||||
bool @shared a1 = true
|
||||
bool @shared a2
|
||||
bool @shared a4
|
||||
bool @shared a
|
||||
bool @shared b
|
||||
|
||||
if a1==0 and a2==0
|
||||
cx16.r0++
|
||||
; absorbption opt:
|
||||
; 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
|
||||
cx16.r0++
|
||||
bool @shared iteration_in_progress = false
|
||||
ubyte @shared num_bytes = 99
|
||||
|
||||
if a1==0 or a2==0
|
||||
cx16.r0++
|
||||
if not iteration_in_progress or not num_bytes
|
||||
txt.print("yep1")
|
||||
else
|
||||
txt.print("nope1")
|
||||
|
||||
if (a1!=0 and a2!=0)==0
|
||||
cx16.r0++
|
||||
iteration_in_progress = true
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user