ref: 1c61d05cba15d7e93d3207d4f3ab3c6043d63b77
parent: d798a21d16cbd1d866752fbde81871012a789ea8
author: Ori Bernstein <ori@eigenstate.org>
date: Mon Jul 31 18:36:12 EDT 2017
Optimize sleq. Now the comparison is done in assembly, using quads for checking the larger loop, and words for the smaller.
--- a/lib/std/memops-impl+plan9-x64.s
+++ b/lib/std/memops-impl+plan9-x64.s
@@ -42,3 +42,36 @@
ANDQ $7,CX
REP; STOSB
RET
+
+TEXT std$memeq+0(SB),$0
+ MOVQ DX,R8
+ ANDQ $~0x7,R8
+ JZ .dotail
+.nextquad:
+ MOVQ (DI),R9
+ MOVQ (SI),R10
+ XORQ R10,R9
+ JNZ .unequal
+ ADDQ $8,SI
+ ADDQ $8,DI
+ SUBQ $8,R8
+ JNZ .nextquad
+.dotail:
+ ANDQ $0x7,DX
+ TESTQ DX,DX
+ JZ .equal
+.nextbyte:
+ MOVBLZX (DI),R9
+ MOVBLZX (SI),R10
+ XORL R10,R9
+ JNZ .unequal
+ ADDQ $1,SI
+ ADDQ $1,DI
+ SUBQ $1,DX
+ JNZ .nextbyte
+.equal:
+ MOVQ $1,AX
+ RET
+.unequal:
+ MOVQ $0,AX
+ RET
--- a/lib/std/memops-impl+posixy-x64.s
+++ b/lib/std/memops-impl+posixy-x64.s
@@ -1,7 +1,4 @@
-/*
-std.memblit : (dst : byte#, src : byte#, len : std.size -> void)
-std.memfill : (dst : byte#, val : byte, len : std.size -> void)
-*/
+/* std.memblit : (dst : byte#, src : byte#, len : std.size -> void) */
.globl _std$memblit
.globl std$memblit
_std$memblit:
@@ -30,6 +27,7 @@
.done:
ret
+/* std.memfill : (dst : byte#, val : byte, len : std.size -> void) */
.globl _std$memfill
.globl std$memfill
_std$memfill:
@@ -46,4 +44,41 @@
movq %rdx,%rcx
andq $7,%rcx
rep stosb
+ ret
+
+/* std.memeq : (a : byte#, b : byte#, len : std.size -> bool) */
+.globl _std$memeq
+.globl std$memeq
+_std$memeq:
+std$memeq:
+ movq %rdx,%r8
+ andq $~0x7,%r8
+ jz .dotail
+.nextquad:
+ movq (%rdi),%r9
+ movq (%rsi),%r10
+ xorq %r10,%r9
+ jnz .unequal
+ addq $8,%rsi
+ addq $8,%rdi
+ subq $8,%r8
+ jnz .nextquad
+.dotail:
+ andq $0x7,%rdx
+ testq %rdx,%rdx
+ jz .equal
+.nextbyte:
+ movzbl (%rdi),%r9d
+ movzbl (%rsi),%r10d
+ xorl %r10d,%r9d
+ jnz .unequal
+ addq $1,%rsi
+ addq $1,%rdi
+ subq $1,%rdx
+ jnz .nextbyte
+.equal:
+ movq $1,%rax
+ ret
+.unequal:
+ movq $0,%rax
ret
--- a/lib/std/memops-impl.myr
+++ b/lib/std/memops-impl.myr
@@ -3,6 +3,7 @@
pkg std =
pkglocal const memblit : (dst : byte#, src : byte#, len : std.size -> void)
pkglocal const memfill : (dst : byte#, val : byte, len : std.size -> void)
+ pkglocal const memeq : (a : byte#, b : byte#, len : std.size -> bool)
;;
@@ -35,5 +36,18 @@
for var i = 0; i < d.len; i++
d[i] = val
;;
+}
+
+const memeq = {a, b, len
+ var sa, sb
+
+ sa = a[:len]
+ sb = b[:len]
+ for i = 0; i < len; i++
+ if sa[i] != sb[i]
+ -> false
+ ;;
+ ;;
+ -> true
}
--- a/lib/std/memops.myr
+++ b/lib/std/memops.myr
@@ -3,5 +3,6 @@
pkg std =
pkglocal extern const memblit : (dst : byte#, src : byte#, len : std.size -> void)
pkglocal extern const memfill : (dst : byte#, val : byte, len : std.size -> void)
+ pkglocal extern const memeq : (a : byte#, b : byte#, len : std.size -> bool)
;;
--- a/lib/std/sleq.myr
+++ b/lib/std/sleq.myr
@@ -1,18 +1,14 @@
+use "types"
+use "memops"
+
pkg std =
generic sleq : (a : @a[:], b : @a[:] -> bool)
;;
generic sleq = {a, b
- var i
-
- if a.len != b.len
+ if a.len == b.len
+ -> memeq((a : byte#), (b : byte#), a.len)
+ else
-> false
;;
-
- for i = 0; i < a.len; i++
- if a[i] != b[i]
- -> false
- ;;
- ;;
- -> true
}