lzkk
|
f608d852bf
|
基础优化
|
2 days ago |
lzkk
|
eb83ab5cd3
|
基础优化
|
2 days ago |
lzkk
|
32f5dd4f75
|
perf(ir): IfConversion + LoopUnroll增强——if-else→算术select + 多phi追踪 + 单BB展开
两大新优化协同工作:
1. IfConversion: 将循环体内简单 if-else diamond 转为算术 select(fv+(tv-fv)*zext(cond))
- 安全检查:T块单一前驱、纯算术指令(禁Div/Mod/浮点)
- 迭代转换支持短路求值链(_and/_xor 的嵌套 diamond)
- 配合 MergeSinglePredBlocks 将链式块压平为单 BB
2. LoopUnroll: 跨迭代追踪所有 header phi 值,而非仅 len phi
- 修复预存悬空指针 bug(展开后 exit 块引用已释放的 phi)
- 展开块合并到 preheader + 吸收 exit ret → 真正单 BB → 可内联
管线调整:Inline 移至 LoopUnroll 之后,使展开后的单 BB 函数能被内联。
huffman: _and/_xor 完全展开(32→1BB)+内联,_or 因短路求值共享块暂未转换
指令基线:36 个测试集改善
|
2 days ago |
lzkk
|
2c43ea28f9
|
fix(mir): 浮点比较被错误降级为整数比较——95_float 修复
EmitIntValue 中整数比较路径未检查浮点操作数,导致 fcmp olt
被降级为 fcvtzs+fcvtzs+cmp(整数比较),浮点语义损坏。
新增浮点操作数检测,走 FCmpRR+FCSet 路径。
门禁:functional 100/100, h_functional 40/40
|
2 days ago |
lzkk
|
ec8c874829
|
fix(ir): LoopUnroll 限制 i32 函数 + 支持 float cast 克隆
- 跳过非 i32 返回值函数(float 循环体含不支持的浮点二元操作)
- 添加 SIToFP/FPToSI 到 CloneInstruction
- 修复 35_math/38_light2d 编译崩溃
门禁:functional 99/100, h_functional 40/40
|
2 days ago |
lzkk
|
608aa98f4e
|
perf(ir): 简单递减循环全展开——countdown loop unrolling
- 检测 while(len) { body; len=len-1; } 递减循环模式
- TripCount ≤64 且为编译时常量 → 全展开
- 展开后函数变为单BB,可被 Inline 内联
- 配合 ConstFold 将常量 len/power 传播到每次迭代
门禁:functional 99/100(95_float预存),h_functional 40/40
|
2 days ago |
lzkk
|
b3187edbbf
|
perf(mir): MIR 清扫——%2指令精简 + 算术select死代码消除
- %2快速路径:and+cmp+csneg ge(3指令)替代 negs+and+and+csneg mi(4指令)
- 穿透Inline中 icmp ne(zext(cmp),0) 冗余链,消除算术select的mov+cmp+cset冗余
- Madd折叠前移:Mul唯一用户是Add时跳过,由Add的Madd统一处理
- Div/Mod/And/Or常量提前处理,避免emit不消费的死MovImm
门禁:functional 99/100(95_float预存失败),h_functional 40/40
|
2 days ago |
lzkk
|
f9bea1bf85
|
chore: 更新脚本和 sylib——clang 参考支持 + 提交脚本
- score.sh 支持 gcc/clang 双参考编译器
- diff_test.sh/diff_test_llvm.sh 小修复
- sylib.c 添加 _sysy_starttime/_sysy_stoptime 别名
- submit.sh 比赛平台提交辅助脚本
|
2 days ago |
lzkk
|
1b9c8cc40d
|
fix(mir): 修复全局变量 .bss/.data 段反复切换——统一分组输出
之前每个零初始化全局变量都会在 .bss → .data 之间切换一次,
大数组(12MB BSS)的 .data 插入可能导致链接器内存布局异常。
现在先输出全部 .bss 段,再输出 .data 段,消除无用的段切换。
这可能是 many_mat_cal-1/3 在平台 100MB 限制下 WA 的根因。
|
2 days ago |
lzkk
|
d9ebea6668
|
perf(ir): if-else→mul select 转换 + 死BB清理,使多BB函数可内联
- TryConvertIfElseToSelect 将 3-5 BB 的 if-else-return 转为单 BB
- 算术 select: fv + (tv-fv)*zext(cmp),仅支持 i32
- 转换后清理死 BB(const_cast erase),使 IsInlineable 识别
- float 函数安全跳过(IsFloat32 + IsInt32 守卫)
- max()→f()→loop_test() 级联内联成功,热循环零函数调用
- 门禁: functional 2预存失败, h_functional 0失败
|
3 days ago |
lzkk
|
40eb6784d3
|
perf(ir): 添加 And/Or 操作码 + if-else→select 转换框架
- IR 层添加 And/Or BinaryInst 支持(IRPrinter/LoopInfo/Lowering 全覆盖)
- MIR 层已有 AndRR/OrRR,直接映射
- Inline.cpp 添加 TryConvertIfElseToSelect:将 3-BB if-else-return
函数转为单 BB 算术 select(fv + (tv-fv)*zext(cmp)),使其可被内联
- 转换逻辑已实现,与快门禁兼容(functional+h_functional 0 失败)
|
3 days ago |
lzkk
|
4403dc08b8
|
perf(mir): 常量除法魔法数优化——smull+asr 替代 sdiv
实现 Hacker's Delight 有符号除法魔法数算法,将 x/C 替换为乘法逆元序列。
32/60 性能测试受益,sdiv 全部消除(仅剩变量除法无法优化)。
- M 为正(MSB=0):smull + asr #(32+s) + sub 符号修正
- M 为负(MSB=1):smull + lsr #32 + add + asr #s + sub 修正
- ModRR 同样受益:q = magic_div(x,C); r = x - q*C (msub)
- 添加 Umull 操作码(与 Smull 对称,为后续优化预留)
- 性能分 33→55(+65%),几何平均 0.55→0.55(因 gcc ref 更多成功运行)
|
3 days ago |
lzkk
|
ea790dd05d
|
fix(scripts): score.sh 使用 canon_diff 忽略尾部空白——匹配 2026test.sh 行为
performance 60/60 AC, functional 100/100 AC, h_functional 40/40 AC。
|
3 days ago |
lzkk
|
8d4a34aa10
|
fix(scripts): 修复 score.sh 输出对比逻辑——适配 SysY 非零返回值 + .out 格式
- 移除错误的 exit_code==0 检查(SysY 可返回任意值)
- 修复 .out 格式生成:stdout 为空时不插入多余空行
- 修复 ref_time 不记录非零退出码的 bug
- functional: 100/100 AC, performance: 57/60 AC
|
3 days ago |
lzkk
|
5cd5c54764
|
feat(scripts): 添加本地评分脚本 score.sh——按比赛计分公式计算分数
公式: 性能分=geometric_mean(gcc时间/我们时间)×100, 总分=正确分×0.5+性能分×0.5
与比赛平台计分公式完全一致(验证误差 < 0.0001)。
支持并行执行、分类筛选、超时控制。
|
3 days ago |
lzkk
|
635f01bd48
|
perf(mir): 添加 Lsr64RR 支持——64位逻辑右移,为常量除法优化铺路
|
3 days ago |
lzkk
|
422f1848fc
|
perf(mir): Lowering 直接生成 AddShiftRR——x+(x*2^n) → add x,x,lsl#n
在 Lowering 阶段检测 Add 的某个操作数是 Mul by 幂次方常量,
直接发射 AddShiftRR 而非分开发射 ShlRR+AddRR。
配合 Peephole 残余合并,共生成 5 处 add lsl。
|
3 days ago |
lzkk
|
8d0c5ebcd0
|
perf(mir): 添加 AddShiftRR/SubShiftRR 支持——lsl+add 合并为 add lsl
- MIR.h: 新增 AddShiftRR/SubShiftRR 操作码(4 操作数: dst, src1, src2, shift)
- RegAlloc: 更新 def/use 分析
- AsmPrinter: 发射 add/sub dst, src1, src2, lsl #shift
- Peephole: 相邻 ShlRR+AddRR/SubRR → AddShiftRR/SubShiftRR
为后续在 Lowering 阶段直接生成移位操作数铺路。
|
3 days ago |
lzkk
|
e1944acc6b
|
perf(mir): Peephole 增强——StoreGlobal→LoadGlobal 跨指令转发 + 冗余 adrp 消除
全局变量前向替换不再只检查相邻指令,可跨越不冲突的中间指令扫描。
添加冗余 adrp 检测(同一符号+同一寄存器,中间无重定义则删除)。
|
3 days ago |
lzkk
|
00c489f0be
|
perf(mir): 消除 Mul 幂次方优化产生的死 MovImm——先检测后发射 rhs
x*2^n 优化为 lsl 时,先检测常量是否幂次方再决定是否发射 rhs,
避免先发射 MovImm 再被 ShlRR 覆盖的死代码。
crypto 1458→1449,crc 303→297。
|
3 days ago |
lzkk
|
4179f40264
|
perf(mir): leaf 函数省略帧指针——无调用+无栈帧时跳过 stp/ldp x29,x30
crypto 1482→1458(-24 指令),crc 306→303。
|
3 days ago |
lzkk
|
10a59110eb
|
perf: 函数内联 + csneg 取模优化,crypto 1.76x→1.69x
- IR 保守内联:纯算术单 BB leaf 函数自底向上迭代内联
- MIR 取模优化:x%2^n 用 negs+and+and+csneg(6→4 指令)
- 添加 CondCode::MI/PL 支持 csneg 的 mi/pl 条件码
- 修正 NegRR 发射 negs(设标志位)供 csneg 使用
|
3 days ago |
lzkk
|
2f1d7dc856
|
perf(ir): 保守函数内联——纯算术单BB leaf 函数自底向上迭代内联
只内联无副作用(无 Load/Store/GEP)的单基本块 leaf 函数。
InsertBefore 保持 BB 结构不变,支持级联收敛(_and→_xor→_or)。
已验证 140/140 功能测试通过,为后续 MIR 层优化铺路。
|
3 days ago |
lzkk
|
feab5508a8
|
fix(irgen): starttime/stoptime 函数名恢复为 _sysy_starttime/_sysy_stoptime
平台运行时库期望 _sysy_starttime(int) 和 _sysy_stoptime(int) 签名,
之前错误地生成 starttime(void) / stoptime(void),
导致所有程序链接到错误函数而崩溃返回 1。
恢复队友原版:下划线前缀 + 行号参数。
|
3 days ago |
lzkk
|
56b37ac060
|
chore: 删除死代码——LinearScanAlloc/GreedyAlloc/InstLiveness(共2072行)
三个文件未被 CMakeLists 引用、无头文件、无 MIR.h 声明、无调用方。
当前唯一寄存器分配器为 RegAlloc.cpp。
|
3 days ago |
lzkk
|
862c1bfe7b
|
第一次优化
|
3 days ago |
lzkk
|
1149d53d42
|
chore: 移除 LICM.cpp 空桩——实现已在 LoopInfo.cpp (ir_analysis)
|
3 days ago |
lzkk
|
0eb1cf4a7f
|
chore: 移除空桩文件(PassManager.cpp/ConstEval.cpp)从构建
这些文件仅含注释或include,无实际代码。
|
3 days ago |
lzkk
|
5d43539290
|
chore: 代码彻底清理——删除死代码、旧备份、生成文件
删除:
- warning/ src.bak.full/ llvm/ docs/superpowers/ (95MB+ 磁盘释放)
- Inline.cpp (621行,从未正确集成)
- PassManagerModule 死类 + 3个未使用pass声明 (PassManager.h)
- RunStrengthReduction/RunLoopUnrolling/RunLoopFission (LoopInfo.cpp 805行)
- FindInductionVars/AllUsesInLoop/IsSRLoopInvariantValue 死辅助函数
- 生成文件: Error.txt results.csv/json time_opt.txt settings.json
更新 .gitignore 防止未来污染
|
3 days ago |
lzkk
|
39e4dada13
|
perf(mir): 添加 Madd(乘加)指令——sum+a*b → madd sum,a,b,sum
限制:仅折合非常量乘数(常量有 shift 优化更优)。
SSA 单使用 Mul 被跳过,由 Add 处统一发射 Madd。
|
3 days ago |
lzkk
|
035f83b209
|
fix(mir): 模2^n AND优化——修复 x<0 且 x%2^n==0 时的零值错误
-4%2 应得 0,但 AND+符号修正路径算出 -2。
增加 cmp masked,#0; csel dst,wzr,temp,EQ 零值保护。
平台无 -O 时该路径被触发,导致 48_assign_complex_expr WA。
|
3 days ago |
lzkk
|
2cfc9e2fc8
|
perf(mir): MIR预分配 MovImm 转发——消除常数二次传递
mov v1,#N; mov v2,v1(v1 无其他使用)→ mov v2,#N
matmul -3.3%, optim_sched -10.2%, 01_mm -4.4%。33基线更新。
|
3 days ago |
lzkk
|
bf5956e3cc
|
perf(mir): Pettis-Hansen 基本块重排序——链合并+频率排序
基于 CFG 回边检测 + 块频率估计,贪心合并链使热路径 fallthrough。
huffman -10, h-8 -9(-2.6%), crypto -13。21基线更新。
|
3 days ago |
lzkk
|
e23d047e5f
|
feat(scripts): 添加 LLVM/clang 差分测试脚本 diff_test_llvm.sh
支持 --baseline/--diff/--perf 三种模式,--llvm-opt 0/1/2/3/s/z。
自动检测系统 clang 并添加 --target=aarch64-linux-gnu + -std=gnu89。
|
3 days ago |
lzkk
|
c277aa2226
|
perf(mir): 帧槽按大小重排序——小槽优先获得 ldur 范围内偏移
4字节标量优先分配,大数组靠后,使热访问在 [-256,0] 的 ldur 范围。
crypto -176(-10.3%),消除大量 mov x13,x29 + sub 地址计算链。
|
3 days ago |
lzkk
|
f65fe9fc20
|
perf(mir): 扩展缩放寻址到 EmitStatement Load 路径(ptr/float/int)
h-8 -58(-14.6%), sort -66(-10.7%), h-5 -35(-10.9%), crypto -43, shuffle -37
24 基线更新,此轮优化累计巨大收益。
|
3 days ago |
lzkk
|
be3a5640ee
|
perf(mir): AArch64 缩放寻址——GEP+Load/Store 直接生成 ldr/str [base, idx, uxtw #2]
消除数组访问中的 sxtw+shl+add 链,替换为单条缩放寻址指令。
crypto -76(-4.2%), shuffle -39(-8.3%), sort -22(-3.4%), matmul -16(-4.3%)
|
3 days ago |
lzkk
|
3ece3d09f4
|
perf(mir): CMP常量lhs交换——mov+cmp优化为cmp#imm+条件翻转
|
3 days ago |
lzkk
|
e826f9ee57
|
perf(mir): 负除数模2^n同样使用AND优化
|
3 days ago |
lzkk
|
421df18c81
|
perf(mir): 模2^n运算优化——AND+符号修正替代 Msub
x % 2^n: (x & (2^n-1)) + cmp + csel 替代 asr+msub
huffman -20, crypto -33, crc -13, h-9 -7
|
3 days ago |
lzkk
|
2a67ef0f06
|
perf(mir): FixFallThrough——CondBr 条件反转消除冗余 Br
块尾 CondBr+Br 模式:当 CondBr 目标是下个块时,反转条件交换目标并删除 Br。
huffman -7, matmul -2.6%, h-10 -3.0%, many_mat_cal -3.1%。
|
3 days ago |
lzkk
|
667c342c51
|
perf(mir): Lowering 立即数折叠——AddRR/SubRR/CmpRR 常量 rhs 直接用 Imm
值 0-4095 可直接嵌入 add/sub/cmp,省去一条 MovImm。
配合 IR 迭代常量折叠生效。
|
3 days ago |
lzkk
|
d51cbc49f1
|
perf(mir): RegAlloc 偏置着色调和(copy_edges coalescing)
收集 MovReg 两端 vreg 为 copy_edges,逆向着色时优先选源操作数颜色。
减少无意义 MovReg 残留,全用例改善(matmul -3.5%, h-10 -3.5%)。
|
3 days ago |
lzkk
|
9095cbe0db
|
perf(ir): 启用 LICM + 迭代优化循环(ConstFold/ConstProp/CSE/DCE 收敛)
管线从 Mem2Reg+ConstFold+DCE+CFGSimplify 升级为:
Mem2Reg+LICM+(ConstFold+ConstProp+CFGSimplify+CSE+DCE)×10收敛
huffman -6.4%, crypto -5.6%, h-8 -11.7%, crc -7.6%
|
3 days ago |
lzkk
|
1993380d4a
|
chore: 移除 git 冲突残留文件
|
3 days ago |
lzkk
|
ee3b42ac40
|
feat(opt): 切换至队友代码基线——100%功能正确
Chaitin-Briggs 图着色寄存器分配,K=16无需spill。
IRGen starttime/stoptime 修复(去掉 _sysy_ 前缀和 lineno 参数)。
此提交为后续优化工作的安全起点。
|
3 days ago |
lzkk
|
bfe105c2cd
|
fix(mir): 别名无条件冲突 + per-round reserve防指针失效
两个安全修复:
1. GPR32/GPR64别名检查移除segments.empty()条件
Wn/Xn是同一硬件寄存器,GPR32和GPR64 vreg在同一phys_reg上总是冲突
2. 每轮EnhancerIntervals后reserve*16,防止push_back导致reg_assignments_指针失效
当前正确率:94% (94/100)
|
3 days ago |
lzkk
|
d6f42a2a2e
|
fix(mir): 回退到稳定版本——PhysReg映射+spill reload+别名无条件冲突
稳定在94%正确率。包含三个关键修复:
1. PhysReg映射修正: Ptr +31, Float +62, FP_ALLOCATABLE排除S0-S1
2. Spill reload为每次use创建新vreg
3. GPR32/GPR64别名无条件冲突
Mem2Reg交互问题(65_color, 94_nested_loops)已精确诊断为:
高寄存器压力→未分配vreg→共享回退寄存器X16→地址计算错误→SIGSEGV
完整修复需要LLVM SplitKit级别的活范围区域分裂。
|
3 days ago |
lzkk
|
0f1b545568
|
fix(mir): 分配顺序改为FirstUsePos + 别名无条件冲突 + per-round reserve
三处改进:
1. 新vreg按FirstUsePos升序分配(指令顺序),确保重叠vreg在干涉检查时可见
替代之前的Length()排序(弦图最优序近似)
2. GPR32/GPR64别名无条件冲突(移除segments.empty()条件)
3. 每轮EnhancerIntervals后reserve *16 防止push_back指针失效
Mem2Reg问题已精确诊断:高寄存器压力下,多个Ptr vreg的重叠段未被子涉检
测捕获,导致地址计算base和index共享同一物理寄存器。
当前正确率:94% (94/100),剩余2个Mem2Reg交互失败+4个预存缺陷。
|
4 days ago |
lzkk
|
83228a8123
|
fix(mir): GPR32/GPR64别名检查移除segments.empty()条件
Wn和Xn是同一硬件寄存器(如W12和X12),GPR32和GPR64 vreg
在同一phys_reg上总是冲突,无论segments是否为空。
原代码要求!segments.empty(),导致某些情况下别名冲突被漏检。
参考: AArch64寄存器别名机制,Wn为Xn的低32位
|
4 days ago |