【发布时间】:2019-03-17 22:57:15
【问题描述】:
我有一个函数,其签名为void aggregate(const char *string, int64_t length, void *dest),其目标是将string 中的每个字符映射到dest 中的相应位,如果该字符为'\"',则该位为1,否则为0。所以如果字符串是"\"aaaaaa\"...,那么0b10000001...会被写入dest。此函数一次处理来自string 的 32 个字节,因此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
【问题讨论】:
-
subs真的有错还是分析器错误地归咎于它? -
我打赌这是一个分支错误预测
-
你如何衡量这个?哪个分析器,哪个处理器?
标签: assembly optimization simd arm64