From c4fe8bd496c6dcd920d2b65a92aefac4efb3dd92 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Mon, 14 Sep 2026 08:21:37 +0800 Subject: [PATCH] =?UTF-8?q?perf(llvmlite):=20=E7=AA=A5=E5=AD=94=20alloca?= =?UTF-8?q?=20=E5=88=A4=E5=AE=9A=E5=8A=A0=E9=A6=96=E5=AD=97=E7=AC=A6?= =?UTF-8?q?=E7=9F=AD=E8=B7=AF=E5=B9=B6=E6=B6=88=E9=99=A4=E9=80=90=E8=A1=8C?= =?UTF-8?q?=20strlen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _peep_is_alloc_of 增加首字符预筛、两个调用点同步加守卫,避免逐行乘逐槽的 strncmp 与函数调用(该点实测约 439 万次 strncmp)。 _peep_replace_token 预扫改为以 NUL 为界单趟扫描,strlen(line_buf) 后移到命中之后,无命中调用不再求长(该点实测约 134 万次 strlen)。均保持逐输入等价。 --- llvmlite/__function.vp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/llvmlite/__function.vp b/llvmlite/__function.vp index 28ed2b5..83f7d17 100644 --- a/llvmlite/__function.vp +++ b/llvmlite/__function.vp @@ -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: