Skip to content

Commit f1b13a4

Browse files
MaxGraeydcodeIO
authored andcommitted
Improve memcmp and compareImpl implementations (AssemblyScript#870)
1 parent 41fd648 commit f1b13a4

36 files changed

+2493
-725
lines changed

std/assembly/util/memory.ts

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -263,10 +263,30 @@ export function memset(dest: usize, c: u8, n: usize): void { // see: musl/src/st
263263

264264
// @ts-ignore: decorator
265265
@inline
266-
export function memcmp(vl: usize, vr: usize, n: usize): i32 { // see: musl/src/string/memcmp.c
266+
export function memcmp(vl: usize, vr: usize, n: usize): i32 {
267267
if (vl == vr) return 0;
268-
while (n != 0 && load<u8>(vl) == load<u8>(vr)) {
269-
n--; vl++; vr++;
268+
if (ASC_SHRINK_LEVEL < 2) {
269+
if ((vl & 7) == (vr & 7)) {
270+
while (vl & 7) {
271+
if (!n) return 0;
272+
let a = <i32>load<u8>(vl);
273+
let b = <i32>load<u8>(vr);
274+
if (a != b) return a - b;
275+
n--; vl++; vr++;
276+
}
277+
while (n >= 8) {
278+
if (load<u64>(vl) != load<u64>(vr)) break;
279+
vl += 8;
280+
vr += 8;
281+
n -= 8;
282+
}
283+
}
284+
}
285+
while (n--) {
286+
let a = <i32>load<u8>(vl);
287+
let b = <i32>load<u8>(vr);
288+
if (a != b) return a - b;
289+
vl++; vr++;
270290
}
271-
return n ? <i32>load<u8>(vl) - <i32>load<u8>(vr) : 0;
291+
return 0;
272292
}

std/assembly/util/string.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,26 @@ const Powers10Lo: f64[] = [
4949
];
5050

5151
export function compareImpl(str1: string, index1: usize, str2: string, index2: usize, len: usize): i32 {
52-
var result = 0;
5352
var ptr1 = changetype<usize>(str1) + (index1 << 1);
5453
var ptr2 = changetype<usize>(str2) + (index2 << 1);
55-
while (len && !(result = <i32>load<u16>(ptr1) - <i32>load<u16>(ptr2))) {
56-
--len, ptr1 += 2, ptr2 += 2;
54+
if (ASC_SHRINK_LEVEL < 2) {
55+
if (len >= 4 && !((ptr1 & 7) | (ptr2 & 7))) {
56+
do {
57+
if (load<u64>(ptr1) != load<u64>(ptr2)) break;
58+
ptr1 += 8;
59+
ptr2 += 8;
60+
len -= 4;
61+
} while (len >= 4);
62+
}
5763
}
58-
return result;
64+
while (len--) {
65+
let a = <i32>load<u16>(ptr1);
66+
let b = <i32>load<u16>(ptr2);
67+
if (a != b) return a - b;
68+
ptr1 += 2;
69+
ptr2 += 2;
70+
}
71+
return 0;
5972
}
6073

6174
export function isSpace(c: i32): bool {

tests/compiler/builtins.optimized.wat

Lines changed: 66 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -84,36 +84,83 @@
8484
)
8585
(func $~lib/util/string/compareImpl (; 8 ;) (type $FUNCSIG$iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
8686
(local $3 i32)
87-
loop $continue|0
88-
local.get $2
89-
if (result i32)
87+
(local $4 i32)
88+
local.get $0
89+
i32.const 7
90+
i32.and
91+
local.get $1
92+
i32.const 7
93+
i32.and
94+
i32.or
95+
i32.eqz
96+
i32.const 0
97+
local.get $2
98+
i32.const 4
99+
i32.ge_u
100+
select
101+
if
102+
loop $continue|0
90103
local.get $0
91-
i32.load16_u
104+
i64.load
92105
local.get $1
93-
i32.load16_u
94-
i32.sub
95-
local.tee $3
96-
i32.eqz
97-
else
98-
i32.const 0
106+
i64.load
107+
i64.eq
108+
if
109+
local.get $0
110+
i32.const 8
111+
i32.add
112+
local.set $0
113+
local.get $1
114+
i32.const 8
115+
i32.add
116+
local.set $1
117+
local.get $2
118+
i32.const 4
119+
i32.sub
120+
local.tee $2
121+
i32.const 4
122+
i32.ge_u
123+
br_if $continue|0
124+
end
99125
end
100-
if
126+
end
127+
loop $continue|1
128+
block $break|1
101129
local.get $2
130+
local.tee $3
102131
i32.const 1
103132
i32.sub
104133
local.set $2
134+
local.get $3
135+
i32.eqz
136+
br_if $break|1
105137
local.get $0
106-
i32.const 2
107-
i32.add
108-
local.set $0
138+
i32.load16_u
139+
local.tee $3
109140
local.get $1
110-
i32.const 2
111-
i32.add
112-
local.set $1
113-
br $continue|0
141+
i32.load16_u
142+
local.tee $4
143+
i32.ne
144+
if
145+
local.get $3
146+
local.get $4
147+
i32.sub
148+
return
149+
else
150+
local.get $0
151+
i32.const 2
152+
i32.add
153+
local.set $0
154+
local.get $1
155+
i32.const 2
156+
i32.add
157+
local.set $1
158+
br $continue|1
159+
end
160+
unreachable
114161
end
115162
end
116-
local.get $3
163+
i32.const 0
117164
)
118165
(func $~lib/string/String.__eq (; 9 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
119166
(local $2 i32)

tests/compiler/builtins.untouched.wat

Lines changed: 78 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
(global $~lib/builtins/f64.MIN_SAFE_INTEGER f64 (f64.const -9007199254740991))
7878
(global $~lib/builtins/f64.MAX_SAFE_INTEGER f64 (f64.const 9007199254740991))
7979
(global $~lib/builtins/f64.EPSILON f64 (f64.const 2.220446049250313e-16))
80+
(global $~lib/ASC_SHRINK_LEVEL i32 (i32.const 0))
8081
(export "memory" (memory $0))
8182
(export "test" (func $builtins/test))
8283
(start $start)
@@ -126,59 +127,114 @@
126127
(local $6 i32)
127128
(local $7 i32)
128129
(local $8 i32)
130+
(local $9 i32)
129131
local.get $0
130132
call $~lib/rt/stub/__retain
131133
drop
132134
local.get $2
133135
call $~lib/rt/stub/__retain
134136
drop
135-
i32.const 0
136-
local.set $5
137137
local.get $0
138138
local.get $1
139139
i32.const 1
140140
i32.shl
141141
i32.add
142-
local.set $6
142+
local.set $5
143143
local.get $2
144144
local.get $3
145145
i32.const 1
146146
i32.shl
147147
i32.add
148-
local.set $7
149-
block $break|0
150-
loop $continue|0
151-
local.get $4
152-
if (result i32)
148+
local.set $6
149+
local.get $4
150+
i32.const 4
151+
i32.ge_u
152+
if (result i32)
153+
local.get $5
154+
i32.const 7
155+
i32.and
156+
local.get $6
157+
i32.const 7
158+
i32.and
159+
i32.or
160+
i32.eqz
161+
else
162+
i32.const 0
163+
end
164+
if
165+
block $break|0
166+
loop $continue|0
167+
local.get $5
168+
i64.load
153169
local.get $6
154-
i32.load16_u
155-
local.get $7
156-
i32.load16_u
170+
i64.load
171+
i64.ne
172+
if
173+
br $break|0
174+
end
175+
local.get $5
176+
i32.const 8
177+
i32.add
178+
local.set $5
179+
local.get $6
180+
i32.const 8
181+
i32.add
182+
local.set $6
183+
local.get $4
184+
i32.const 4
157185
i32.sub
158-
local.tee $5
159-
i32.eqz
160-
else
161-
i32.const 0
186+
local.set $4
187+
local.get $4
188+
i32.const 4
189+
i32.ge_u
190+
br_if $continue|0
162191
end
163-
i32.eqz
164-
br_if $break|0
192+
end
193+
end
194+
block $break|1
195+
loop $continue|1
165196
local.get $4
197+
local.tee $7
166198
i32.const 1
167199
i32.sub
168200
local.set $4
201+
local.get $7
202+
i32.eqz
203+
br_if $break|1
204+
local.get $5
205+
i32.load16_u
206+
local.set $7
169207
local.get $6
208+
i32.load16_u
209+
local.set $8
210+
local.get $7
211+
local.get $8
212+
i32.ne
213+
if
214+
local.get $7
215+
local.get $8
216+
i32.sub
217+
local.set $9
218+
local.get $0
219+
call $~lib/rt/stub/__release
220+
local.get $2
221+
call $~lib/rt/stub/__release
222+
local.get $9
223+
return
224+
end
225+
local.get $5
170226
i32.const 2
171227
i32.add
172-
local.set $6
173-
local.get $7
228+
local.set $5
229+
local.get $6
174230
i32.const 2
175231
i32.add
176-
local.set $7
177-
br $continue|0
232+
local.set $6
233+
br $continue|1
178234
end
179235
unreachable
180236
end
181-
local.get $5
237+
i32.const 0
182238
local.set $8
183239
local.get $0
184240
call $~lib/rt/stub/__release

0 commit comments

Comments
 (0)