diff --git a/codeOptimizers/src/prog8/optimizer/ExpressionSimplifier.kt b/codeOptimizers/src/prog8/optimizer/ExpressionSimplifier.kt index 0f3433304..3244ffac5 100644 --- a/codeOptimizers/src/prog8/optimizer/ExpressionSimplifier.kt +++ b/codeOptimizers/src/prog8/optimizer/ExpressionSimplifier.kt @@ -402,12 +402,24 @@ class ExpressionSimplifier(private val program: Program, return expr.left } } + else if(expr.operator=="or" && rightB.operator=="or") { + if(expr.left isSameAs rightB.left || expr.left isSameAs rightB.right) { + // a or (a or b) -> a or b + return expr.right + } + } + else if(expr.operator=="and" && rightB.operator=="and") { + if(expr.left isSameAs rightB.left || expr.left isSameAs rightB.right) { + // a and (a and b) -> a and b + return expr.right + } + } } 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) { + if(expr.right isSameAs leftB.left || expr.right isSameAs leftB.right) { return expr.right } } @@ -416,6 +428,18 @@ class ExpressionSimplifier(private val program: Program, return expr.right } } + else if(expr.operator=="or" && leftB.operator=="or") { + if(expr.right isSameAs leftB.left || expr.right isSameAs leftB.right) { + // (a or b) or a -> a or b + return expr.left + } + } + else if(expr.operator=="and" && leftB.operator=="and") { + if(expr.right isSameAs leftB.left || expr.right isSameAs leftB.right) { + // (a and b) or a -> a and b + return expr.left + } + } } return null } diff --git a/compiler/test/TestOptimization.kt b/compiler/test/TestOptimization.kt index 0eee90082..e83173f0d 100644 --- a/compiler/test/TestOptimization.kt +++ b/compiler/test/TestOptimization.kt @@ -825,16 +825,19 @@ main { 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 (b and a) and b + cx16.r0 ++ + if (b or a) or b + cx16.r0 ++ } }""" val result = compileText(Cx16Target(), true, src, writeAssembly = false)!! val st = result.compilerAst.entrypoint.statements - st.size shouldBe 10 + st.size shouldBe 12 val if1 = st[4] as IfElse val if2 = st[5] as IfElse val if3 = st[6] as IfElse @@ -845,8 +848,20 @@ main { (if4.condition as IdentifierReference).nameInSource shouldBe listOf("a") val if5 = st[8] as IfElse val if6 = st[9] as IfElse - if5.condition shouldBe instanceOf() - if6.condition shouldBe instanceOf() + val if7 = st[10] as IfElse + val if8 = st[11] as IfElse + val if5bc = if5.condition as BinaryExpression + val if6bc = if6.condition as BinaryExpression + val if7bc = if7.condition as BinaryExpression + val if8bc = if8.condition as BinaryExpression + if5bc.left shouldBe instanceOf() + if5bc.right shouldBe instanceOf() + if6bc.left shouldBe instanceOf() + if6bc.right shouldBe instanceOf() + if7bc.left shouldBe instanceOf() + if7bc.right shouldBe instanceOf() + if8bc.left shouldBe instanceOf() + if8bc.right shouldBe instanceOf() } test("funky bitshifts") {