У меня есть функция с сигнатурой void aggregate(const char *string, int64_t length, void *dest)
, цель которой - сопоставить каждый символ в string
с соответствующим битом в dest
, где бит равен 1, если этот символ равен '\"'
, и 0 в противном случае.Так что если строка "\"aaaaaa\"...
, то 0b10000001...
записывается в dest
.Эта функция обрабатывает 32 байта из string
за один раз, поэтому length
должен быть кратным этому.
В любом случае, у меня есть рабочая функция, но согласно моему профилированию она тратит более 80% времени по инструкции subs
.Я знаю, что вы должны быть осторожны при обработке обычных регистров наряду с SIMD, но я не могу понять, почему это такое узкое место.Я также попытался сделать cmp
с указателем текущей строки и концом строки, и зацикливался, только если текущий указатель меньше конца.Однако это не помогло.Я также попытался развернуться, чтобы выполнить половину или четверть инструкций subs
, но это тоже не помогло.Есть идеи?
#define vadds_raw v0
#define vadds vadds_raw##.16b
#define vrepquote v1.16b
#define vchrs0_raw v2
#define vchrs0 vchrs0_raw##.16b
#define stepmask_raw v7
#define stepmask stepmask_raw##.16b
#define halfmask_raw v8
#define adder_scratch v9
#define string x0
#define length x1
#define out x2
#define scratch_reg x3
.section __TEXT,__text,regular,pure_instructions
.build_version ios, 12, 0
.globl _aggregate
.p2align 2
_aggregate:
// load masks
movi vrepquote, #0x22
mov scratch_reg, 0x4080
movk scratch_reg, 0x1020, lsl 16
movk scratch_reg, 0x0408, lsl 32
movk scratch_reg, 0x0201, lsl 48
dup stepmask_raw.2d, scratch_reg
mov scratch_reg, 0xffff
movk scratch_reg, 0xffff, lsl 16
movk scratch_reg, 0xffff, lsl 32
movk scratch_reg, 0xffff, lsl 48
ins halfmask_raw.d[0], x31 // zero it out
ins halfmask_raw.d[1], scratch_reg
iter:
subs length, length, #16
ldur q2, [string]
cmeq vchrs0, vchrs0, vrepquote
and vchrs0, vchrs0, stepmask
movi.16b vadds_raw, #0
addv b0, vchrs0_raw.8b
and vchrs0, vchrs0, halfmask_raw.16b
addv b9, vchrs0
ins vadds_raw.b[1], adder_scratch.b[0]
str h0, [out]
add out, out, #2
add string, string, #16
b.hi iter
ret