mirror of
https://github.com/irmen/prog8.git
synced 2025-01-26 03:32:22 +00:00
better not(x) replacement by x==0
This commit is contained in:
parent
435d6f6f3f
commit
dc82a0fc16
@ -115,15 +115,9 @@ class AstPreprocessor(val program: Program, val errors: IErrorReporter, val comp
|
|||||||
|
|
||||||
override fun before(expr: PrefixExpression, parent: Node): Iterable<IAstModification> {
|
override fun before(expr: PrefixExpression, parent: Node): Iterable<IAstModification> {
|
||||||
if(expr.operator == "not") {
|
if(expr.operator == "not") {
|
||||||
// To enable simple bitwise and/or/xor/not instructions in the codegen for the logical and/or/xor/not,
|
// not(x) --> x==0
|
||||||
// we wrap the operands in a call to boolean() if required so that they are 0 or 1 as needed.
|
val dt = expr.expression.inferType(program).getOr(DataType.UNDEFINED)
|
||||||
// Making the codegen more generic to do this by itself all the time will generate much larger
|
val replacement = BinaryExpression(expr.expression, "==", NumericLiteral(dt,0.0, expr.position), expr.position)
|
||||||
// code because it is hard to decide there if the value conversion to 0 or 1 is needed or not,
|
|
||||||
// so a lot of useless checks and conversions are added. Here we can be smarter so the codegen
|
|
||||||
// can just rely on the correct value of the operands (0 or 1) if they're boolean, and just use bitwise instructions.
|
|
||||||
|
|
||||||
// not(x) --> boolean(x)==0
|
|
||||||
val replacement = BinaryExpression(wrapWithBooleanConversion(expr.expression), "==", NumericLiteral.optimalInteger(0, expr.position), expr.position)
|
|
||||||
return listOf(IAstModification.ReplaceNodeSafe(expr, replacement, parent))
|
return listOf(IAstModification.ReplaceNodeSafe(expr, replacement, parent))
|
||||||
}
|
}
|
||||||
return noModifications
|
return noModifications
|
||||||
|
@ -462,8 +462,7 @@ class TestOptimization: FunSpec({
|
|||||||
ubyte z2
|
ubyte z2
|
||||||
z2 = 255
|
z2 = 255
|
||||||
ubyte z3
|
ubyte z3
|
||||||
z3 = 0
|
z3 = 1
|
||||||
z3 = (boolean(z3)==0)
|
|
||||||
uword z4
|
uword z4
|
||||||
z4 = 0
|
z4 = 0
|
||||||
ubyte z5
|
ubyte z5
|
||||||
@ -474,30 +473,28 @@ class TestOptimization: FunSpec({
|
|||||||
z6 -= 5
|
z6 -= 5
|
||||||
*/
|
*/
|
||||||
val statements = result.program.entrypoint.statements
|
val statements = result.program.entrypoint.statements
|
||||||
statements.size shouldBe 15
|
statements.size shouldBe 14
|
||||||
val z1decl = statements[0] as VarDecl
|
val z1decl = statements[0] as VarDecl
|
||||||
val z1init = statements[1] as Assignment
|
val z1init = statements[1] as Assignment
|
||||||
val z2decl = statements[2] as VarDecl
|
val z2decl = statements[2] as VarDecl
|
||||||
val z2init = statements[3] as Assignment
|
val z2init = statements[3] as Assignment
|
||||||
val z3decl = statements[4] as VarDecl
|
val z3decl = statements[4] as VarDecl
|
||||||
val z3init = statements[5] as Assignment
|
val z3init = statements[5] as Assignment
|
||||||
val z3not = statements[6] as Assignment
|
val z4decl = statements[6] as VarDecl
|
||||||
val z4decl = statements[7] as VarDecl
|
val z4init = statements[7] as Assignment
|
||||||
val z4init = statements[8] as Assignment
|
val z5decl = statements[8] as VarDecl
|
||||||
val z5decl = statements[9] as VarDecl
|
val z5init = statements[9] as Assignment
|
||||||
val z5init = statements[10] as Assignment
|
val z5plus = statements[10] as Assignment
|
||||||
val z5plus = statements[11] as Assignment
|
val z6decl = statements[11] as VarDecl
|
||||||
val z6decl = statements[12] as VarDecl
|
val z6init = statements[12] as Assignment
|
||||||
val z6init = statements[13] as Assignment
|
val z6plus = statements[13] as Assignment
|
||||||
val z6plus = statements[14] as Assignment
|
|
||||||
|
|
||||||
z1decl.name shouldBe "z1"
|
z1decl.name shouldBe "z1"
|
||||||
z1init.value shouldBe NumericLiteral(DataType.UBYTE, 10.0, Position.DUMMY)
|
z1init.value shouldBe NumericLiteral(DataType.UBYTE, 10.0, Position.DUMMY)
|
||||||
z2decl.name shouldBe "z2"
|
z2decl.name shouldBe "z2"
|
||||||
z2init.value shouldBe NumericLiteral(DataType.UBYTE, 255.0, Position.DUMMY)
|
z2init.value shouldBe NumericLiteral(DataType.UBYTE, 255.0, Position.DUMMY)
|
||||||
z3decl.name shouldBe "z3"
|
z3decl.name shouldBe "z3"
|
||||||
z3init.value shouldBe NumericLiteral(DataType.UBYTE, 0.0, Position.DUMMY)
|
z3init.value shouldBe NumericLiteral(DataType.UBYTE, 1.0, Position.DUMMY)
|
||||||
z3not.value shouldBe instanceOf<BinaryExpression>()
|
|
||||||
z4decl.name shouldBe "z4"
|
z4decl.name shouldBe "z4"
|
||||||
z4init.value shouldBe NumericLiteral(DataType.UBYTE, 0.0, Position.DUMMY)
|
z4init.value shouldBe NumericLiteral(DataType.UBYTE, 0.0, Position.DUMMY)
|
||||||
z5decl.name shouldBe "z5"
|
z5decl.name shouldBe "z5"
|
||||||
|
@ -20,155 +20,181 @@ main {
|
|||||||
ubyte ub4 = 0
|
ubyte ub4 = 0
|
||||||
ubyte bvalue
|
ubyte bvalue
|
||||||
|
|
||||||
txt.print("bitwise or 14: ")
|
txt.print("const not 126: ")
|
||||||
txt.print_ub(ub1 | ub2 | ub3 | ub4)
|
txt.print_ub(not 129)
|
||||||
txt.nl()
|
txt.nl()
|
||||||
txt.print("bitwise or 142: ")
|
txt.print("const not 255: ")
|
||||||
txt.print_ub(ub1 | ub2 | ub3 | ub4 | 128)
|
txt.print_ub(not 0)
|
||||||
txt.nl()
|
txt.nl()
|
||||||
txt.print("bitwise and 0: ")
|
bvalue = 129
|
||||||
txt.print_ub(ub1 & ub2 & ub3 & ub4)
|
txt.print("bitwise not 126: ")
|
||||||
txt.nl()
|
bvalue = not bvalue
|
||||||
txt.print("bitwise and 8: ")
|
txt.print_ub(bvalue)
|
||||||
txt.print_ub(ub3 & ub3 & 127)
|
|
||||||
txt.nl()
|
|
||||||
txt.print("bitwise xor 14: ")
|
|
||||||
txt.print_ub(ub1 ^ ub2 ^ ub3 ^ ub4)
|
|
||||||
txt.nl()
|
|
||||||
txt.print("bitwise xor 6: ")
|
|
||||||
txt.print_ub(ub1 ^ ub2 ^ ub3 ^ 8)
|
|
||||||
txt.nl()
|
|
||||||
txt.print("bitwise not 247: ")
|
|
||||||
txt.print_ub(~ub3)
|
|
||||||
txt.nl()
|
txt.nl()
|
||||||
|
bvalue = 0
|
||||||
txt.print("bitwise not 255: ")
|
txt.print("bitwise not 255: ")
|
||||||
txt.print_ub(~ub4)
|
bvalue = not bvalue
|
||||||
|
txt.print_ub(bvalue)
|
||||||
txt.nl()
|
txt.nl()
|
||||||
|
|
||||||
txt.print("not 0: ")
|
; txt.print("bitwise or 14: ")
|
||||||
bvalue = not ub3
|
; txt.print_ub(ub1 | ub2 | ub3 | ub4)
|
||||||
txt.print_ub(bvalue)
|
; txt.nl()
|
||||||
if not ub1
|
; txt.print("bitwise or 142: ")
|
||||||
txt.print(" / fail")
|
; txt.print_ub(ub1 | ub2 | ub3 | ub4 | 128)
|
||||||
else
|
; txt.nl()
|
||||||
txt.print(" / ok")
|
; txt.print("bitwise and 0: ")
|
||||||
txt.nl()
|
; txt.print_ub(ub1 & ub2 & ub3 & ub4)
|
||||||
|
; txt.nl()
|
||||||
txt.print("not 1: ")
|
; txt.print("bitwise and 8: ")
|
||||||
bvalue = not ub4
|
; txt.print_ub(ub3 & ub3 & 127)
|
||||||
txt.print_ub(bvalue)
|
; txt.nl()
|
||||||
if not ub4
|
; txt.print("bitwise xor 14: ")
|
||||||
txt.print(" / ok")
|
; txt.print_ub(ub1 ^ ub2 ^ ub3 ^ ub4)
|
||||||
else
|
; txt.nl()
|
||||||
txt.print(" / fail")
|
; txt.print("bitwise xor 6: ")
|
||||||
txt.nl()
|
; txt.print_ub(ub1 ^ ub2 ^ ub3 ^ 8)
|
||||||
|
; txt.nl()
|
||||||
bvalue = bvalue and 128
|
; txt.print("bitwise not 247: ")
|
||||||
txt.print("bvl 1: ")
|
; txt.print_ub(~ub3)
|
||||||
txt.print_ub(bvalue)
|
; txt.nl()
|
||||||
if bvalue and 128
|
; txt.print("bitwise not 255: ")
|
||||||
txt.print(" / ok")
|
; txt.print_ub(~ub4)
|
||||||
else
|
; txt.nl()
|
||||||
txt.print(" / fail")
|
;
|
||||||
txt.nl()
|
; txt.print("not 0: ")
|
||||||
|
; bvalue = 3 * (ub4 | not (ub3 | ub3 | ub3))
|
||||||
txt.print("and 1: ")
|
; txt.print_ub(bvalue)
|
||||||
bvalue = ub1 and ub2 and ub3
|
; if 3*(ub4 | not (ub1 | ub1 | ub1))
|
||||||
txt.print_ub(bvalue)
|
; txt.print(" / fail")
|
||||||
if ub1 and ub2 and ub3
|
; else
|
||||||
txt.print(" / ok")
|
; txt.print(" / ok")
|
||||||
else
|
; txt.nl()
|
||||||
txt.print(" / fail")
|
;
|
||||||
txt.nl()
|
; txt.print("not 0: ")
|
||||||
txt.print("and 1: ")
|
; bvalue = not ub3
|
||||||
bvalue = ub1 and ub2 and ub3 and 64
|
; txt.print_ub(bvalue)
|
||||||
txt.print_ub(bvalue)
|
; if not ub1
|
||||||
if ub1 and ub2 and ub3 and 64
|
; txt.print(" / fail")
|
||||||
txt.print(" / ok")
|
; else
|
||||||
else
|
; txt.print(" / ok")
|
||||||
txt.print(" / fail")
|
; txt.nl()
|
||||||
txt.nl()
|
;
|
||||||
txt.print("and 1: ")
|
; txt.print("not 1: ")
|
||||||
bvalue = ub1 and ub2 and ub3 and ftrue(99)
|
; bvalue = not ub4
|
||||||
txt.print_ub(bvalue)
|
; txt.print_ub(bvalue)
|
||||||
if ub1 and ub2 and ub3 and ftrue(99)
|
; if not ub4
|
||||||
txt.print(" / ok")
|
; txt.print(" / ok")
|
||||||
else
|
; else
|
||||||
txt.print(" / fail")
|
; txt.print(" / fail")
|
||||||
txt.nl()
|
; txt.nl()
|
||||||
txt.print("and 0: ")
|
;
|
||||||
bvalue = ub1 and ub2 and ub3 and ub4
|
; bvalue = bvalue and 128
|
||||||
txt.print_ub(bvalue)
|
; txt.print("bvl 1: ")
|
||||||
if ub1 and ub2 and ub3 and ub4
|
; txt.print_ub(bvalue)
|
||||||
txt.print(" / fail")
|
; if bvalue and 128
|
||||||
else
|
; txt.print(" / ok")
|
||||||
txt.print(" / ok")
|
; else
|
||||||
txt.nl()
|
; txt.print(" / fail")
|
||||||
txt.print("and 0: ")
|
; txt.nl()
|
||||||
bvalue = ub1 and ub2 and ub3 and ffalse(99)
|
;
|
||||||
txt.print_ub(bvalue)
|
; txt.print("and 1: ")
|
||||||
if ub1 and ub2 and ub3 and ffalse(99)
|
; bvalue = ub1 and ub2 and ub3
|
||||||
txt.print(" / fail")
|
; txt.print_ub(bvalue)
|
||||||
else
|
; if ub1 and ub2 and ub3
|
||||||
txt.print(" / ok")
|
; txt.print(" / ok")
|
||||||
txt.nl()
|
; else
|
||||||
|
; txt.print(" / fail")
|
||||||
txt.print(" or 1: ")
|
; txt.nl()
|
||||||
bvalue = ub1 or ub2 or ub3 or ub4
|
; txt.print("and 1: ")
|
||||||
txt.print_ub(bvalue)
|
; bvalue = ub1 and ub2 and ub3 and 64
|
||||||
if ub1 or ub2 or ub3 or ub4
|
; txt.print_ub(bvalue)
|
||||||
txt.print(" / ok")
|
; if ub1 and ub2 and ub3 and 64
|
||||||
else
|
; txt.print(" / ok")
|
||||||
txt.print(" / fail")
|
; else
|
||||||
txt.nl()
|
; txt.print(" / fail")
|
||||||
txt.print(" or 1: ")
|
; txt.nl()
|
||||||
bvalue = ub4 or ub4 or ub1
|
; txt.print("and 1: ")
|
||||||
txt.print_ub(bvalue)
|
; bvalue = ub1 and ub2 and ub3 and ftrue(99)
|
||||||
if ub4 or ub4 or ub1
|
; txt.print_ub(bvalue)
|
||||||
txt.print(" / ok")
|
; if ub1 and ub2 and ub3 and ftrue(99)
|
||||||
else
|
; txt.print(" / ok")
|
||||||
txt.print(" / fail")
|
; else
|
||||||
txt.nl()
|
; txt.print(" / fail")
|
||||||
txt.print(" or 1: ")
|
; txt.nl()
|
||||||
bvalue = ub1 or ub2 or ub3 or ftrue(99)
|
; txt.print("and 0: ")
|
||||||
txt.print_ub(bvalue)
|
; bvalue = ub1 and ub2 and ub3 and ub4
|
||||||
if ub1 or ub2 or ub3 or ftrue(99)
|
; txt.print_ub(bvalue)
|
||||||
txt.print(" / ok")
|
; if ub1 and ub2 and ub3 and ub4
|
||||||
else
|
; txt.print(" / fail")
|
||||||
txt.print(" / fail")
|
; else
|
||||||
txt.nl()
|
; txt.print(" / ok")
|
||||||
|
; txt.nl()
|
||||||
txt.print("xor 1: ")
|
; txt.print("and 0: ")
|
||||||
bvalue = ub1 xor ub2 xor ub3 xor ub4
|
; bvalue = ub1 and ub2 and ub3 and ffalse(99)
|
||||||
txt.print_ub(bvalue)
|
; txt.print_ub(bvalue)
|
||||||
if ub1 xor ub2 xor ub3 xor ub4
|
; if ub1 and ub2 and ub3 and ffalse(99)
|
||||||
txt.print(" / ok")
|
; txt.print(" / fail")
|
||||||
else
|
; else
|
||||||
txt.print(" / fail")
|
; txt.print(" / ok")
|
||||||
txt.nl()
|
; txt.nl()
|
||||||
txt.print("xor 1: ")
|
;
|
||||||
bvalue = ub1 xor ub2 xor ub3 xor ffalse(99)
|
; txt.print(" or 1: ")
|
||||||
txt.print_ub(bvalue)
|
; bvalue = ub1 or ub2 or ub3 or ub4
|
||||||
if ub1 xor ub2 xor ub3 xor ffalse(99)
|
; txt.print_ub(bvalue)
|
||||||
txt.print(" / ok")
|
; if ub1 or ub2 or ub3 or ub4
|
||||||
else
|
; txt.print(" / ok")
|
||||||
txt.print(" / fail")
|
; else
|
||||||
txt.nl()
|
; txt.print(" / fail")
|
||||||
|
; txt.nl()
|
||||||
txt.print("xor 0: ")
|
; txt.print(" or 1: ")
|
||||||
bvalue = ub1 xor ub2 xor ub3 xor ub4 xor true
|
; bvalue = ub4 or ub4 or ub1
|
||||||
txt.print_ub(bvalue)
|
; txt.print_ub(bvalue)
|
||||||
if ub1 xor ub2 xor ub3 xor ub4 xor true
|
; if ub4 or ub4 or ub1
|
||||||
txt.print(" / fail")
|
; txt.print(" / ok")
|
||||||
else
|
; else
|
||||||
txt.print(" / ok")
|
; txt.print(" / fail")
|
||||||
txt.nl()
|
; txt.nl()
|
||||||
txt.print("xor 0: ")
|
; txt.print(" or 1: ")
|
||||||
bvalue = ub1 xor ub2 xor ub3 xor ftrue(99)
|
; bvalue = ub1 or ub2 or ub3 or ftrue(99)
|
||||||
txt.print_ub(bvalue)
|
; txt.print_ub(bvalue)
|
||||||
if ub1 xor ub2 xor ub3 xor ftrue(99)
|
; if ub1 or ub2 or ub3 or ftrue(99)
|
||||||
txt.print(" / fail")
|
; txt.print(" / ok")
|
||||||
else
|
; else
|
||||||
txt.print(" / ok")
|
; txt.print(" / fail")
|
||||||
|
; txt.nl()
|
||||||
|
;
|
||||||
|
; txt.print("xor 1: ")
|
||||||
|
; bvalue = ub1 xor ub2 xor ub3 xor ub4
|
||||||
|
; txt.print_ub(bvalue)
|
||||||
|
; if ub1 xor ub2 xor ub3 xor ub4
|
||||||
|
; txt.print(" / ok")
|
||||||
|
; else
|
||||||
|
; txt.print(" / fail")
|
||||||
|
; txt.nl()
|
||||||
|
; txt.print("xor 1: ")
|
||||||
|
; bvalue = ub1 xor ub2 xor ub3 xor ffalse(99)
|
||||||
|
; txt.print_ub(bvalue)
|
||||||
|
; if ub1 xor ub2 xor ub3 xor ffalse(99)
|
||||||
|
; txt.print(" / ok")
|
||||||
|
; else
|
||||||
|
; txt.print(" / fail")
|
||||||
|
; txt.nl()
|
||||||
|
;
|
||||||
|
; txt.print("xor 0: ")
|
||||||
|
; bvalue = ub1 xor ub2 xor ub3 xor ub4 xor true
|
||||||
|
; txt.print_ub(bvalue)
|
||||||
|
; if ub1 xor ub2 xor ub3 xor ub4 xor true
|
||||||
|
; txt.print(" / fail")
|
||||||
|
; else
|
||||||
|
; txt.print(" / ok")
|
||||||
|
; txt.nl()
|
||||||
|
; txt.print("xor 0: ")
|
||||||
|
; bvalue = ub1 xor ub2 xor ub3 xor ftrue(99)
|
||||||
|
; txt.print_ub(bvalue)
|
||||||
|
; if ub1 xor ub2 xor ub3 xor ftrue(99)
|
||||||
|
; txt.print(" / fail")
|
||||||
|
; else
|
||||||
|
; txt.print(" / ok")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -486,6 +486,7 @@ logical: ``not`` ``and`` ``or`` ``xor``
|
|||||||
These operators are the usual logical operations that are part of a logical expression to reason
|
These operators are the usual logical operations that are part of a logical expression to reason
|
||||||
about truths (boolean values). The result of such an expression is a 'boolean' value 'true' or 'false'
|
about truths (boolean values). The result of such an expression is a 'boolean' value 'true' or 'false'
|
||||||
(which in reality is just a byte value of 1 or 0).
|
(which in reality is just a byte value of 1 or 0).
|
||||||
|
Notice that the expression ``not x`` is equivalent to ``x==0``, and the compiler will treat it as such.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
Unlike most other programming languages, there is no short-cirquit or McCarthy-evaluation
|
Unlike most other programming languages, there is no short-cirquit or McCarthy-evaluation
|
||||||
|
Loading…
x
Reference in New Issue
Block a user