perf(llvmlite): 窥孔 alloca 判定加首字符短路并消除逐行 strlen
_peep_is_alloc_of 增加首字符预筛、两个调用点同步加守卫,避免逐行乘逐槽的 strncmp 与函数调用(该点实测约 439 万次 strncmp)。 _peep_replace_token 预扫改为以 NUL 为界单趟扫描,strlen(line_buf) 后移到命中之后,无命中调用不再求长(该点实测约 134 万次 strlen)。均保持逐输入等价。
This commit is contained in:
1 parent
c4c6eafd70
commit
c4fe8bd496
1 file changed
+14
-5
+14
-5
@@ -694,15 +694,18 @@ def _peep_replace_token(pool: rowptr[memhub.MemBuddy],
|
||||
return line_buf
|
||||
if tlen == 0:
|
||||
return line_buf
|
||||
ln: t.CSizeT = string.strlen(line_buf)
|
||||
# 预扫是否命中
|
||||
# 预扫是否命中:不依赖 strlen,以 NUL 为界单趟扫描(绝大多数调用无命中即返回,
|
||||
# 从而省去逐行 strlen)。逐输入等价:tok 无 NUL(tlen=strlen(tok)),故
|
||||
# strncmp 判等必蕴含记号完整落在串内(i+tlen 处仍非 NUL);凡 i+tlen>ln 的
|
||||
# 位置 strncmp 必先遇到 line_buf 的 NUL 而与 tok 的非 NUL 字节不等,故原
|
||||
# 上界 i+tlen<=ln 从未排除任一可能命中,去掉后命中判定不变。
|
||||
hit: int = 0
|
||||
i: t.CSizeT = 0
|
||||
while i + tlen <= ln:
|
||||
while line_buf[i] != '\0':
|
||||
if line_buf[i] == '%' and line_buf[i + 1] == tok[0] \
|
||||
and string.strncmp(line_buf + i + 1, tok, tlen) == 0:
|
||||
nxt: int = 0
|
||||
if i + 1 + tlen < ln:
|
||||
if line_buf[i + 1 + tlen] != '\0':
|
||||
cc: int = line_buf[i + 1 + tlen]
|
||||
if (cc >= 48 and cc <= 57) or (cc >= 65 and cc <= 90) or (cc >= 97 and cc <= 122) or cc == 95:
|
||||
nxt = 1
|
||||
@@ -712,6 +715,7 @@ def _peep_replace_token(pool: rowptr[memhub.MemBuddy],
|
||||
i += 1
|
||||
if hit == 0:
|
||||
return line_buf
|
||||
ln: t.CSizeT = string.strlen(line_buf)
|
||||
# 缓冲大小上界:单行最多 ⌊ln/2⌋ 次替换,每次去掉 ≥2 字节(%+名)换入 rlen 字节;
|
||||
# 最坏输出 ≤ ln + (ln/2)·rlen + NUL。ln + 1 + rlen·(ln+1) 恒覆盖该上界,
|
||||
# 避免 K≥2 且替换串更长时把新缓冲写穿(随机内存破坏)。
|
||||
@@ -801,6 +805,11 @@ def _peep_is_alloc_of(eb: str, a_name: str, nl: t.CSizeT) -> int:
|
||||
"""
|
||||
if eb is None or a_name is None or nl == 0 or eb[0] != '%':
|
||||
return 0
|
||||
# 首字符预筛:nl>=1,strncmp 判等必然蕴含首字符相等;首字符不同即可廉价拒绝,
|
||||
# 避免绝大多数行进入 strncmp 调用。逐输入等价:本分支拒绝当且仅当原 strncmp
|
||||
# 也必返回非 0(首字节不同)。eb[0]=='%' 非 NUL ⇒ eb[1] 读在串内(最多为 NUL)。
|
||||
if eb[1] != a_name[0]:
|
||||
return 0
|
||||
if string.strncmp(eb + 1, a_name, nl) != 0:
|
||||
return 0
|
||||
eqpos: str = string.strstr(eb, " = alloca ")
|
||||
@@ -997,7 +1006,7 @@ def _peephole_opt(func: rowptr[Function], pool: rowptr[memhub.MemBuddy]):
|
||||
db: str = ld.Buf
|
||||
if db is not None:
|
||||
kill: int = 0
|
||||
if db[0] == '%':
|
||||
if db[0] == '%' and db[1] == a_name[0]:
|
||||
if _peep_is_alloc_of(db, a_name, a_name_len) != 0:
|
||||
kill = 1
|
||||
if kill == 0 and _peep_last_ref_eq(db, a_name, a_name_len) != 0:
|
||||
|
||||
Reference in new issue
Block a user