mirror of
https://github.com/irmen/prog8.git
synced 2024-10-17 10:24:55 +00:00
optimize % and logical operations on words
This commit is contained in:
parent
6fe0959fdc
commit
c0920a43a3
@ -3052,6 +3052,82 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
|||||||
" lda ${segment[0].callLabel} | eor #${hexVal(segment[1])} | sta ${ESTACK_LO.toHex()},x | dex "
|
" lda ${segment[0].callLabel} | eor #${hexVal(segment[1])} | sta ${ESTACK_LO.toHex()},x | dex "
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// push memory word | wordvalue
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_MEM_W, Opcode.PUSH_WORD, Opcode.BITOR_WORD),
|
||||||
|
listOf(Opcode.PUSH_MEM_UW, Opcode.PUSH_WORD, Opcode.BITOR_WORD)) { segment ->
|
||||||
|
"""
|
||||||
|
lda ${hexVal(segment[0])}
|
||||||
|
ora #<${hexVal(segment[1])}
|
||||||
|
sta ${ESTACK_LO.toHex()},x
|
||||||
|
lda ${hexValPlusOne(segment[0])}
|
||||||
|
ora #>${hexVal(segment[1])}
|
||||||
|
sta ${ESTACK_HI.toHex()},x
|
||||||
|
dex
|
||||||
|
"""
|
||||||
|
},
|
||||||
|
// push memory word & wordvalue
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_MEM_W, Opcode.PUSH_WORD, Opcode.BITAND_WORD),
|
||||||
|
listOf(Opcode.PUSH_MEM_UW, Opcode.PUSH_WORD, Opcode.BITAND_WORD)) { segment ->
|
||||||
|
"""
|
||||||
|
lda ${hexVal(segment[0])}
|
||||||
|
and #<${hexVal(segment[1])}
|
||||||
|
sta ${ESTACK_LO.toHex()},x
|
||||||
|
lda ${hexValPlusOne(segment[0])}
|
||||||
|
and #>${hexVal(segment[1])}
|
||||||
|
sta ${ESTACK_HI.toHex()},x
|
||||||
|
dex
|
||||||
|
"""
|
||||||
|
},
|
||||||
|
// push memory word ^ wordvalue
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_MEM_W, Opcode.PUSH_WORD, Opcode.BITXOR_WORD),
|
||||||
|
listOf(Opcode.PUSH_MEM_UW, Opcode.PUSH_WORD, Opcode.BITXOR_WORD)) { segment ->
|
||||||
|
"""
|
||||||
|
lda ${hexVal(segment[0])}
|
||||||
|
eor #<${hexVal(segment[1])}
|
||||||
|
sta ${ESTACK_LO.toHex()},x
|
||||||
|
lda ${hexValPlusOne(segment[0])}
|
||||||
|
eor #>${hexVal(segment[1])}
|
||||||
|
sta ${ESTACK_HI.toHex()},x
|
||||||
|
dex
|
||||||
|
"""
|
||||||
|
},
|
||||||
|
// push var word | wordvalue
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.PUSH_WORD, Opcode.BITOR_WORD)) { segment ->
|
||||||
|
"""
|
||||||
|
lda ${segment[0].callLabel}
|
||||||
|
ora #<${hexVal(segment[1])}
|
||||||
|
sta ${ESTACK_LO.toHex()},x
|
||||||
|
lda ${segment[0].callLabel}+1
|
||||||
|
ora #>${hexVal(segment[1])}
|
||||||
|
sta ${ESTACK_HI.toHex()},x
|
||||||
|
dex
|
||||||
|
"""
|
||||||
|
},
|
||||||
|
// push var word & wordvalue
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.PUSH_WORD, Opcode.BITAND_WORD)) { segment ->
|
||||||
|
"""
|
||||||
|
lda ${segment[0].callLabel}
|
||||||
|
and #<${hexVal(segment[1])}
|
||||||
|
sta ${ESTACK_LO.toHex()},x
|
||||||
|
lda ${segment[0].callLabel}+1
|
||||||
|
and #>${hexVal(segment[1])}
|
||||||
|
sta ${ESTACK_HI.toHex()},x
|
||||||
|
dex
|
||||||
|
"""
|
||||||
|
},
|
||||||
|
// push var word ^ wordvalue
|
||||||
|
AsmPattern(listOf(Opcode.PUSH_VAR_WORD, Opcode.PUSH_WORD, Opcode.BITXOR_WORD)) { segment ->
|
||||||
|
"""
|
||||||
|
lda ${segment[0].callLabel}
|
||||||
|
eor #<${hexVal(segment[1])}
|
||||||
|
sta ${ESTACK_LO.toHex()},x
|
||||||
|
lda ${segment[0].callLabel}+1
|
||||||
|
eor #>${hexVal(segment[1])}
|
||||||
|
sta ${ESTACK_HI.toHex()},x
|
||||||
|
dex
|
||||||
|
"""
|
||||||
|
},
|
||||||
|
|
||||||
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.MKWORD)) { segment ->
|
AsmPattern(listOf(Opcode.PUSH_VAR_BYTE, Opcode.PUSH_VAR_BYTE, Opcode.MKWORD)) { segment ->
|
||||||
"""
|
"""
|
||||||
lda ${segment[0].callLabel}
|
lda ${segment[0].callLabel}
|
||||||
|
@ -13,8 +13,6 @@ import kotlin.math.log2
|
|||||||
-X + A -> A - X
|
-X + A -> A - X
|
||||||
X+ (-A) -> X - A
|
X+ (-A) -> X - A
|
||||||
X- (-A) -> X + A
|
X- (-A) -> X + A
|
||||||
X % 1 -> constant 0 (if X is byte/word)
|
|
||||||
X % 2 -> X and 1 (if X is byte/word)
|
|
||||||
|
|
||||||
|
|
||||||
todo expression optimization: common (sub) expression elimination (turn common expressions into single subroutine call + introduce variable to hold it)
|
todo expression optimization: common (sub) expression elimination (turn common expressions into single subroutine call + introduce variable to hold it)
|
||||||
@ -120,6 +118,7 @@ class SimplifyExpressions(private val namespace: INameScope, private val heap: H
|
|||||||
"+" -> return optimizeAdd(expr, leftVal, rightVal)
|
"+" -> return optimizeAdd(expr, leftVal, rightVal)
|
||||||
"-" -> return optimizeSub(expr, leftVal, rightVal)
|
"-" -> return optimizeSub(expr, leftVal, rightVal)
|
||||||
"**" -> return optimizePower(expr, leftVal, rightVal)
|
"**" -> return optimizePower(expr, leftVal, rightVal)
|
||||||
|
"%" -> return optimizeRemainder(expr, leftVal, rightVal)
|
||||||
}
|
}
|
||||||
return expr
|
return expr
|
||||||
}
|
}
|
||||||
@ -349,6 +348,30 @@ class SimplifyExpressions(private val namespace: INameScope, private val heap: H
|
|||||||
return expr
|
return expr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun optimizeRemainder(expr: BinaryExpression, leftVal: LiteralValue?, rightVal: LiteralValue?): IExpression {
|
||||||
|
if(leftVal==null && rightVal==null)
|
||||||
|
return expr
|
||||||
|
|
||||||
|
// simplify assignments A = B <operator> C
|
||||||
|
|
||||||
|
val cv = rightVal?.asIntegerValue?.toDouble()
|
||||||
|
when(expr.operator) {
|
||||||
|
"%" -> {
|
||||||
|
if (cv == 1.0) {
|
||||||
|
optimizationsDone++
|
||||||
|
return LiteralValue.fromNumber(0, expr.resultingDatatype(namespace, heap)!!, expr.position)
|
||||||
|
} else if (cv == 2.0) {
|
||||||
|
optimizationsDone++
|
||||||
|
expr.operator = "&"
|
||||||
|
expr.right = LiteralValue.optimalInteger(1, expr.position)
|
||||||
|
return expr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return expr
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private fun optimizeDivision(expr: BinaryExpression, leftVal: LiteralValue?, rightVal: LiteralValue?): IExpression {
|
private fun optimizeDivision(expr: BinaryExpression, leftVal: LiteralValue?, rightVal: LiteralValue?): IExpression {
|
||||||
if(leftVal==null && rightVal==null)
|
if(leftVal==null && rightVal==null)
|
||||||
return expr
|
return expr
|
||||||
@ -379,8 +402,7 @@ class SimplifyExpressions(private val namespace: INameScope, private val heap: H
|
|||||||
if(leftDt in IntegerDatatypes) {
|
if(leftDt in IntegerDatatypes) {
|
||||||
// divided by a power of two => shift right
|
// divided by a power of two => shift right
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
val numshifts = log2(cv)
|
val numshifts = log2(cv).toInt()
|
||||||
println("DIV: SHIFT RIGHT $cv -> $numshifts") // TODO
|
|
||||||
return BinaryExpression(expr.left, ">>", LiteralValue.optimalInteger(numshifts, expr.position), expr.position)
|
return BinaryExpression(expr.left, ">>", LiteralValue.optimalInteger(numshifts, expr.position), expr.position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -388,8 +410,7 @@ class SimplifyExpressions(private val namespace: INameScope, private val heap: H
|
|||||||
if(leftDt in IntegerDatatypes) {
|
if(leftDt in IntegerDatatypes) {
|
||||||
// divided by a negative power of two => negate, then shift right
|
// divided by a negative power of two => negate, then shift right
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
val numshifts = log2(-cv)
|
val numshifts = log2(-cv).toInt()
|
||||||
println("DIV: SHIFT RIGHT $cv -> $numshifts") // TODO
|
|
||||||
return BinaryExpression(PrefixExpression("-", expr.left, expr.position), ">>", LiteralValue.optimalInteger(numshifts, expr.position), expr.position)
|
return BinaryExpression(PrefixExpression("-", expr.left, expr.position), ">>", LiteralValue.optimalInteger(numshifts, expr.position), expr.position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,18 +168,22 @@ class StatementOptimizer(private val namespace: INameScope, private val heap: He
|
|||||||
if(assignment.aug_op!=null)
|
if(assignment.aug_op!=null)
|
||||||
throw AstException("augmented assignments should have been converted to normal assignments before this optimizer")
|
throw AstException("augmented assignments should have been converted to normal assignments before this optimizer")
|
||||||
|
|
||||||
// remove assignments that have no effect X=X , X+=0, X-=0, X*=1, X/=1, X//=1, A |= 0, A ^= 0, A<<=0, etc etc
|
|
||||||
if(assignment.targets.size==1) {
|
if(assignment.targets.size==1) {
|
||||||
val target=assignment.targets[0]
|
val target=assignment.targets[0]
|
||||||
if(same(target, assignment.value)) {
|
if(same(target, assignment.value)) {
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
return NopStatement(assignment.position)
|
return NopStatement(assignment.position)
|
||||||
}
|
}
|
||||||
val targetDt = target.determineDatatype(namespace, heap, assignment)
|
val targetDt = target.determineDatatype(namespace, heap, assignment)!!
|
||||||
val bexpr=assignment.value as? BinaryExpression
|
val bexpr=assignment.value as? BinaryExpression
|
||||||
if(bexpr!=null && same(target, bexpr.left)) {
|
if(bexpr!=null) {
|
||||||
val cv = bexpr.right.constValue(namespace, heap)?.asNumericValue?.toDouble()
|
val cv = bexpr.right.constValue(namespace, heap)?.asNumericValue?.toDouble()
|
||||||
if(cv!=null) {
|
if(cv!=null) {
|
||||||
|
if (same(target, bexpr.left)) {
|
||||||
|
|
||||||
|
// remove assignments that have no effect X=X , X+=0, X-=0, X*=1, X/=1, X//=1, A |= 0, A ^= 0, A<<=0, etc etc
|
||||||
|
// A = A <operator> B
|
||||||
|
|
||||||
when (bexpr.operator) {
|
when (bexpr.operator) {
|
||||||
"+" -> {
|
"+" -> {
|
||||||
if (cv == 0.0) {
|
if (cv == 0.0) {
|
||||||
@ -211,10 +215,6 @@ class StatementOptimizer(private val namespace: INameScope, private val heap: He
|
|||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
return NopStatement(assignment.position)
|
return NopStatement(assignment.position)
|
||||||
}
|
}
|
||||||
"%" -> if (cv==1.0) {
|
|
||||||
optimizationsDone++
|
|
||||||
return NopStatement(assignment.position)
|
|
||||||
}
|
|
||||||
"/" -> if (cv == 1.0) {
|
"/" -> if (cv == 1.0) {
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
return NopStatement(assignment.position)
|
return NopStatement(assignment.position)
|
||||||
@ -241,8 +241,7 @@ class StatementOptimizer(private val namespace: INameScope, private val heap: He
|
|||||||
assignment.value = LiteralValue.optimalInteger(0, assignment.value.position)
|
assignment.value = LiteralValue.optimalInteger(0, assignment.value.position)
|
||||||
assignment.value.linkParents(assignment)
|
assignment.value.linkParents(assignment)
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// replace by in-place lsl(...) call
|
// replace by in-place lsl(...) call
|
||||||
val scope = AnonymousScope(mutableListOf(), assignment.position)
|
val scope = AnonymousScope(mutableListOf(), assignment.position)
|
||||||
var numshifts = cv.toInt()
|
var numshifts = cv.toInt()
|
||||||
@ -264,8 +263,7 @@ class StatementOptimizer(private val namespace: INameScope, private val heap: He
|
|||||||
assignment.value = LiteralValue.optimalInteger(0, assignment.value.position)
|
assignment.value = LiteralValue.optimalInteger(0, assignment.value.position)
|
||||||
assignment.value.linkParents(assignment)
|
assignment.value.linkParents(assignment)
|
||||||
optimizationsDone++
|
optimizationsDone++
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// replace by in-place lsr(...) call
|
// replace by in-place lsr(...) call
|
||||||
val scope = AnonymousScope(mutableListOf(), assignment.position)
|
val scope = AnonymousScope(mutableListOf(), assignment.position)
|
||||||
var numshifts = cv.toInt()
|
var numshifts = cv.toInt()
|
||||||
@ -281,6 +279,7 @@ class StatementOptimizer(private val namespace: INameScope, private val heap: He
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return super.process(assignment)
|
return super.process(assignment)
|
||||||
}
|
}
|
||||||
|
182
examples/test.p8
182
examples/test.p8
@ -1,4 +1,5 @@
|
|||||||
%import c64utils
|
%import c64utils
|
||||||
|
%import c64flt
|
||||||
|
|
||||||
~ main {
|
~ main {
|
||||||
|
|
||||||
@ -12,178 +13,17 @@
|
|||||||
uword uw2
|
uword uw2
|
||||||
word w = 1000
|
word w = 1000
|
||||||
word w2
|
word w2
|
||||||
|
float f1 = 1.1
|
||||||
|
float f2 = 2.2
|
||||||
|
|
||||||
ub2=i*1
|
i %= 1
|
||||||
c64scr.print_ub(ub2)
|
i %= 2
|
||||||
c64.CHROUT('\n')
|
ub2 = i % 1
|
||||||
ub2=i*2
|
ub2 = i % 2
|
||||||
c64scr.print_ub(ub2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
ub2=i*3
|
|
||||||
c64scr.print_ub(ub2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
ub2=i*4
|
|
||||||
c64scr.print_ub(ub2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
ub2=i*5
|
|
||||||
c64scr.print_ub(ub2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
ub2=i*6
|
|
||||||
c64scr.print_ub(ub2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
ub2=i*7
|
|
||||||
c64scr.print_ub(ub2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
ub2=i*8
|
|
||||||
c64scr.print_ub(ub2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
ub2=i*9
|
|
||||||
c64scr.print_ub(ub2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
ub2=i*10
|
|
||||||
c64scr.print_ub(ub2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
ub2=i*11
|
|
||||||
c64scr.print_ub(ub2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
ub2=i*12
|
|
||||||
c64scr.print_ub(ub2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
ub2=i*13
|
|
||||||
c64scr.print_ub(ub2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
ub2=i*14
|
|
||||||
c64scr.print_ub(ub2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
ub2=i*15
|
|
||||||
c64scr.print_ub(ub2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
ub2=i*16
|
|
||||||
c64scr.print_ub(ub2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
ub2=i*17
|
|
||||||
c64scr.print_ub(ub2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
ub2=i*18
|
|
||||||
c64scr.print_ub(ub2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
ub2=i*19
|
|
||||||
c64scr.print_ub(ub2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
ub2=i*20
|
|
||||||
c64scr.print_ub(ub2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
ub2=i*21
|
|
||||||
c64scr.print_ub(ub2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
ub2=i*22
|
|
||||||
c64scr.print_ub(ub2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
ub2=i*23
|
|
||||||
c64scr.print_ub(ub2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
ub2=i*24
|
|
||||||
c64scr.print_ub(ub2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
ub2=i*25
|
|
||||||
c64scr.print_ub(ub2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
|
|
||||||
i=5
|
|
||||||
ub2=i*40
|
|
||||||
c64scr.print_ub(ub2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
|
|
||||||
|
|
||||||
b2=j*1
|
|
||||||
c64scr.print_b(b2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
b2=j*2
|
|
||||||
c64scr.print_b(b2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
b2=j*3
|
|
||||||
c64scr.print_b(b2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
b2=j*4
|
|
||||||
c64scr.print_b(b2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
b2=j*5
|
|
||||||
c64scr.print_b(b2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
b2=j*6
|
|
||||||
c64scr.print_b(b2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
b2=j*7
|
|
||||||
c64scr.print_b(b2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
b2=j*8
|
|
||||||
c64scr.print_b(b2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
b2=j*9
|
|
||||||
c64scr.print_b(b2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
b2=j*10
|
|
||||||
c64scr.print_b(b2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
b2=j*11
|
|
||||||
c64scr.print_b(b2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
b2=j*12
|
|
||||||
c64scr.print_b(b2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
b2=j*13
|
|
||||||
c64scr.print_b(b2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
b2=j*14
|
|
||||||
c64scr.print_b(b2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
b2=j*15
|
|
||||||
c64scr.print_b(b2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
b2=j*16
|
|
||||||
c64scr.print_b(b2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
b2=j*17
|
|
||||||
c64scr.print_b(b2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
b2=j*18
|
|
||||||
c64scr.print_b(b2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
b2=j*19
|
|
||||||
c64scr.print_b(b2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
b2=j*20
|
|
||||||
c64scr.print_b(b2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
b2=j*21
|
|
||||||
c64scr.print_b(b2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
b2=j*22
|
|
||||||
c64scr.print_b(b2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
b2=j*23
|
|
||||||
c64scr.print_b(b2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
b2=j*24
|
|
||||||
c64scr.print_b(b2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
b2=j*25
|
|
||||||
c64scr.print_b(b2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
|
|
||||||
j=3
|
|
||||||
b2=j*40
|
|
||||||
c64scr.print_b(b2)
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
|
|
||||||
c64.CHROUT('\n')
|
|
||||||
|
|
||||||
|
|
||||||
;@todo multiplication by negative values
|
|
||||||
|
|
||||||
;@todo the same, for uword and word
|
|
||||||
|
|
||||||
|
uw %= 1
|
||||||
|
uw %= 2
|
||||||
|
uw2 = uw % 1
|
||||||
|
uw2 = uw % 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user