optimized string compares

This commit is contained in:
Irmen de Jong 2024-08-24 14:34:23 +02:00
parent 48d0185ea4
commit e439720c9d
5 changed files with 68 additions and 53 deletions

View File

@ -248,31 +248,25 @@ _arg_s2 .word 0
strcmp_mem .proc
; -- compares strings in s1 (AY) and s2 (P8ZP_SCRATCH_W2).
; Returns -1,0,1 in A, depeding on the ordering. Clobbers Y.
; Returns -1,0,1 in A, depending on the ordering. Clobbers Y.
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
ldy #0
_loop lda (P8ZP_SCRATCH_W1),y
bne +
lda (P8ZP_SCRATCH_W2),y
bne _return_minusone
beq _return
+ cmp (P8ZP_SCRATCH_W2),y
bcc _return_minusone
bne _return_one
inc P8ZP_SCRATCH_W1
bne +
inc P8ZP_SCRATCH_W1+1
+ inc P8ZP_SCRATCH_W2
bne _loop
inc P8ZP_SCRATCH_W2+1
bne _loop
_return_one
_loop lda (P8ZP_SCRATCH_W1),y
beq _c1_zero
cmp (P8ZP_SCRATCH_W2),y
beq _equal
bmi _less
lda #1
_return rts
_return_minusone
lda #-1
rts
_less lda #-1
rts
_equal iny
bne _loop
_c1_zero lda (P8ZP_SCRATCH_W2),y
beq +
lda #-1
+ rts
.pend

View File

@ -230,9 +230,9 @@ _str .word 0
asmsub compare(uword string1 @R0, uword string2 @AY) clobbers(Y) -> byte @A {
; Compares two strings for sorting.
; Returns -1 (255), 0 or 1 depending on wether string1 sorts before, equal or after string2.
; Returns -1 (255), 0 or 1, meaning: string1 sorts before, equal or after string2.
; Note that you can also directly compare strings and string values with eachother using
; comparison operators ==, < etcetera (it will use strcmp for you under water automatically).
; comparison operators ==, < etcetera (this will use strcmp automatically).
%asm {{
sta P8ZP_SCRATCH_W2
sty P8ZP_SCRATCH_W2+1

View File

@ -112,9 +112,9 @@ string {
sub compare(str st1, str st2) -> byte {
; Compares two strings for sorting.
; Returns -1 (255), 0 or 1 depending on wether string1 sorts before, equal or after string2.
; Returns -1 (255), 0 or 1, meaning: string1 sorts before, equal or after string2.
; Note that you can also directly compare strings and string values with eachother using
; comparison operators ==, < etcetera (it will use strcmp for you under water automatically).
; comparison operators ==, < etcetera (this will use strcmp automatically).
%ir {{
loadm.w r65534,string.compare.st1
loadm.w r65535,string.compare.st2

View File

@ -1,6 +1,8 @@
TODO
====
Move vectors such as USRADD in cx16 to cbm block?
See open issues on github.
Re-generate the skeletons doc files.
@ -38,6 +40,7 @@ Compiler:
- do we need (array)variable alignment tag instead of block alignment tag? You want to align the data, not the code in the block?
- ir: related to the one above: block alignment doesn't translate well to variables in the block (the actual stuff that needs to be aligned in memory) but: need variable alignment tag instead of block alignment tag, really
- ir: fix call() return value handling
- ir: add specialized bit test instructions to support "prog8_ifelse_bittest_xxx" see the check in IRCodeGen
- ir: proper code gen for the CALLI instruction and that it (optionally) returns a word value that needs to be assigned to a reg
- ir: idea: (but LLVM IR simply keeps the variables, so not a good idea then?...): replace all scalar variables by an allocated register. Keep a table of the variable to register mapping (including the datatype)
global initialization values are simply a list of LOAD instructions.

View File

@ -5,42 +5,60 @@
main {
str large1 = "the quick brown fox jumps over the lazy dog. the quick brown fox jumps over the lazy dog. the quick brown fox jumps over the lazy dog. the quick brown fox jumps over the lazy dog."
str large2 = "the quick brown fox jumps over the lazy dog. the quick brown fox jumps over the lazy dog. the quick brown fox jumps over the lazy dog. the quick brown fox jumps over the laxx doggo doggo."
sub start() {
str name = "zn.iff.jpg"
txt.nl()
check("", "", 0)
check("", "a", -1)
check("a", "", 1)
check("a", "a", 0)
check("a", "z", -1)
check("z", "a", 1)
check("irmen", "irmen", 0)
check("irmen", "irmen2", -1)
check("irmen2", "irmen", 1)
check("irmen", "irxen", -1)
check("irmen", "irman", 1)
txt.nl()
ubyte index
bool found
bench() ; orig: 88 (pet: 713) optimized: 56 451
bench2() ; orig: 131 (pet: 1066) optimized: 83 674
}
index, found = string.find(name, '.')
if found {
txt.print_ub(index)
txt.nl()
} else {
txt.print(". not found\n")
sub bench2() {
cbm.SETTIM(0,0,0)
repeat 1000 {
bool compare = large1 != large2
cx16.r0L++
compare = large1 > large2
cx16.r0L++
compare = large1 <= large2
}
txt.print_uw(cbm.RDTIM16())
txt.nl()
}
index, found = string.find(name, '@')
if found {
txt.print_ub(index)
txt.nl()
} else {
txt.print("@ not found\n")
sub bench() {
cbm.SETTIM(0,0,0)
repeat 2000 {
void string.compare(large1,large2)
}
txt.print_uw(cbm.RDTIM16())
txt.nl()
}
index, found = string.rfind(name, '.')
if found {
txt.print_ub(index)
sub check(str s1, str s2, byte expected) {
byte result = string.compare(s1, s2)
txt.print(s1)
txt.print(" & ")
txt.print(s2)
txt.print(": ")
txt.print_b(result)
if result!=expected
txt.print(" !wrong!\n")
else
txt.nl()
} else {
txt.print(". not r found\n")
}
index, found = string.rfind(name, '@')
if found {
txt.print_ub(index)
txt.nl()
} else {
txt.print("@ not r found\n")
}
}
}