mirror of
https://github.com/irmen/prog8.git
synced 2024-12-23 09:32:43 +00:00
apply De Morgan's laws for logical not, results in smaller code
This commit is contained in:
parent
8ba5a0d90c
commit
8a0e650511
@ -48,6 +48,34 @@ internal class NotExpressionAndIfComparisonExprChanger(val program: Program, val
|
||||
return listOf(IAstModification.ReplaceNode(expr, notExpr, parent))
|
||||
}
|
||||
|
||||
|
||||
// applying De Morgan's laws proved beneficial for the code generator,
|
||||
// when the code has one outer 'not' instead of two inner ones.
|
||||
if(expr.operator=="or" || expr.operator=="and") {
|
||||
val newOper = if(expr.operator=="or") "and" else "or"
|
||||
val leftP = expr.left as? PrefixExpression
|
||||
val rightP = expr.right as? PrefixExpression
|
||||
if(leftP!=null && leftP.operator=="not" && rightP!=null && rightP.operator=="not") {
|
||||
// (not a) or (not b) --> not(a and b)
|
||||
// (not a) and (not b) --> not(a or b)
|
||||
val inner = BinaryExpression(leftP.expression, newOper, rightP.expression, expr.position)
|
||||
val notExpr = PrefixExpression("not", inner, expr.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr, notExpr, parent))
|
||||
}
|
||||
val leftB = expr.left as? BinaryExpression
|
||||
val rightB = expr.right as? BinaryExpression
|
||||
if(leftB!=null && leftB.operator=="==" && (leftB.right as? NumericLiteral)?.number==0.0
|
||||
&& rightB!=null && rightB.operator=="==" && (rightB.right as? NumericLiteral)?.number==0.0) {
|
||||
// a==0 or b==0 --> (a!=0 and b!=0)==0
|
||||
// a==0 and b==0 --> (a!=0 or b!=0)==0
|
||||
leftB.operator = "!="
|
||||
rightB.operator = "!="
|
||||
val inner = BinaryExpression(leftB, newOper, rightB, expr.position)
|
||||
val notExpr = BinaryExpression(inner, "==", NumericLiteral.optimalInteger(0, expr.position), expr.position)
|
||||
return listOf(IAstModification.ReplaceNode(expr, notExpr, parent))
|
||||
}
|
||||
}
|
||||
|
||||
return noModifications
|
||||
}
|
||||
|
||||
|
@ -307,8 +307,8 @@ class TestOptimization: FunSpec({
|
||||
a1 = not a1 ; a1 = a1==0
|
||||
a1 = not not a1 ; a1 = a1, so removed totally
|
||||
a1 = not not not a1 ; a1 = a1==0
|
||||
a1 = not a1 or not a2 ; a1 = a1==0 or a2==0
|
||||
a1 = not a1 and not a2 ; a1 = a1==0 and a2==0
|
||||
a1 = not a1 or not a2 ; a1 = (a1 and a2)==0
|
||||
a1 = not a1 and not a2 ; a1 = (a1 or a2)==0
|
||||
}
|
||||
}
|
||||
"""
|
||||
@ -324,8 +324,12 @@ class TestOptimization: FunSpec({
|
||||
value1.right shouldBe NumericLiteral(DataType.UBYTE, 0.0, Position.DUMMY)
|
||||
value2.operator shouldBe "=="
|
||||
value2.right shouldBe NumericLiteral(DataType.UBYTE, 0.0, Position.DUMMY)
|
||||
value3.operator shouldBe "or"
|
||||
value4.operator shouldBe "and"
|
||||
value3.operator shouldBe "=="
|
||||
value3.right shouldBe NumericLiteral(DataType.UBYTE, 0.0, Position.DUMMY)
|
||||
(value3.left as BinaryExpression).operator shouldBe "and"
|
||||
value4.operator shouldBe "=="
|
||||
value4.right shouldBe NumericLiteral(DataType.UBYTE, 0.0, Position.DUMMY)
|
||||
(value4.left as BinaryExpression).operator shouldBe "or"
|
||||
}
|
||||
|
||||
test("various 'not' operator rewrites with optimizations") {
|
||||
@ -337,8 +341,8 @@ class TestOptimization: FunSpec({
|
||||
a1 = not a1 ; a1 = a1==0
|
||||
a1 = not not a1 ; a1 = a1, so removed totally
|
||||
a1 = not not not a1 ; a1 = a1==0
|
||||
a1 = not a1 or not a2 ; a1 = a1==0 or a2==0
|
||||
a1 = not a1 and not a2 ; a1 = a1==0 and a2==0
|
||||
a1 = not a1 or not a2 ; a1 = (a1 and a2)==0
|
||||
a1 = not a1 and not a2 ; a1 = (a1 or a2)==0
|
||||
}
|
||||
}
|
||||
"""
|
||||
@ -354,8 +358,12 @@ class TestOptimization: FunSpec({
|
||||
value1.right shouldBe NumericLiteral(DataType.UBYTE, 0.0, Position.DUMMY)
|
||||
value2.operator shouldBe "=="
|
||||
value2.right shouldBe NumericLiteral(DataType.UBYTE, 0.0, Position.DUMMY)
|
||||
value3.operator shouldBe "or"
|
||||
value4.operator shouldBe "and"
|
||||
value3.operator shouldBe "=="
|
||||
value3.right shouldBe NumericLiteral(DataType.UBYTE, 0.0, Position.DUMMY)
|
||||
(value3.left as BinaryExpression).operator shouldBe "and"
|
||||
value4.operator shouldBe "=="
|
||||
value4.right shouldBe NumericLiteral(DataType.UBYTE, 0.0, Position.DUMMY)
|
||||
(value4.left as BinaryExpression).operator shouldBe "or"
|
||||
}
|
||||
|
||||
test("asmgen correctly deals with float typecasting in augmented assignment") {
|
||||
|
@ -4,18 +4,31 @@
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
ubyte @shared rnr = $a0
|
||||
txt.print_ub(rnr>=$33)
|
||||
txt.print_ub(rnr>=$66)
|
||||
txt.print_ub(rnr>=$99)
|
||||
txt.print_ub(rnr>=$cc)
|
||||
txt.nl()
|
||||
; 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
|
||||
|
||||
ubyte wordNr = (rnr >= $33) as ubyte + (rnr >= $66) as ubyte + (rnr >= $99) as ubyte + (rnr >= $CC) as ubyte
|
||||
txt.print_uw(wordNr)
|
||||
txt.nl()
|
||||
wordNr = 100 - (rnr >= $33) - (rnr >= $66) - (rnr >= $99) - (rnr >= $CC)
|
||||
txt.print_uw(wordNr)
|
||||
txt.nl()
|
||||
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
|
||||
; cx16.r0++
|
||||
; if not (a1 and a2)
|
||||
; cx16.r0++
|
||||
; if not a1 and not a2
|
||||
; cx16.r0++
|
||||
; if not (a1 or a2)
|
||||
; cx16.r0++
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user