Pull Request has been successfully merged by openeuler-ci-bot.
(Thank you for haibaoo's contribution.)变更摘要
本 PR 将 GCC 上游 IRA callee-save 成本模型相关修复(PR110071、PR111673、PR117477、PR118497)回移到 GCC 12,使寄存器分配器在选择 callee-saved 寄存器时能更准确地反映最终代码中的保存/恢复成本:在 improve_allocation 阶段计算 callee-save 成本、按函数入口/出口基本块频率缩放、区分首次创建栈帧与已有 spill 的情况、识别已被函数真实引用的硬寄存器,并支持 x86 push/pop、AArch64 STP/LDP 等架构相关的边际成本建模。该修复解决了 IRA 可能错误选择新的 callee-saved 寄存器、引入额外 prologue/epilogue 或导致 shrink-wrapping 失效的问题(最初在分析 SPEC CPU2017 511.povray_r 性能差距时发现)。
主要改动
-
新增两个 target hook:在
target.def中新增TARGET_CALLEE_SAVE_COST和TARGET_FRAME_ALLOCATION_COST,在target.h中新增spill_cost_type(SAVE/RESTORE)与frame_cost_type(ALLOCATION/DEALLOCATION)枚举,在targhooks.cc/h中提供默认实现default_callee_save_cost(无既有 spill 时叠加TARGET_FRAME_ALLOCATION_COST)与default_frame_allocation_cost(默认返回 0),并同步更新gcc/doc/tm.texi与tm.texi.in文档。 -
重构
ira-color.cc成本计算:assign_hard_reg与improve_allocation改用targetm.callee_save_cost计算 save/restore 成本并按REG_FREQ_FROM_BB的入口/出口频率缩放,在平局时倾向 callee-save;新增allocated_memory_p、allocated_callee_save_regs及record_allocation跟踪已发生的 spill 与已选 callee-saved 寄存器,用existing_spills_p区分首次创建栈帧与已有 spill 的场景;calculate_saved_nregs增加ira_hard_regno_nrefs[...] == 0判断,避免对已真实使用的 callee-saved 寄存器重复收费。 -
统计硬寄存器真实 use/def:在
ira.cc中新增setup_hard_regno_nrefs,通过 DF 链统计硬寄存器真实引用次数(排除 artificial ref 与 debug insn),结果存入ira-int.h的target_ira_int新增字段ira_hard_regno_nrefs,并精简了setup_hard_regno_aclass。 -
架构相关边际成本建模:
gcc/config/i386/i386.cc实现ix86_callee_save_cost,建模push/pop的紧凑保存恢复成本(mem_cost - 2,size 优化时返回 1);gcc/config/aarch64/aarch64.cc实现aarch64_callee_save_cost(GPR/FP 成对STP/LDP边际成本、frame link 寄存器计数)与aarch64_frame_allocation_cost(栈帧分配折叠成本),并通过TARGET_CALLEE_SAVE_COST/TARGET_FRAME_ALLOCATION_COST宏注册;同时在hard-reg-set.h中新增hard_reg_set_popcount辅助函数。 -
测试用例:新增 x86
pr110071.c、pr111673.c、pr118497.c,PowerPCpr110071.c、pr111673.c,以及 AArch64callee_save_1.c/callee_save_2.c/callee_save_3.c(验证STP/LDP与 shrink-wrapping);适配现有用例pr103350-1.c(追加-fno-caller-saves)与force-indirect-call-2.c(放宽汇编期望以兼容 GOT memory-indirect 间接跳转)。


Welcome To openEuler Community
Hey @qq_56722097 , thanks for your contribution to the community.
Bot Usage Manual
I'm the Bot here serving you. You can find the instructions on how to interact with me at Here . That means you can comment below every pull request or issue to trigger Bot Commands.
Contact Guide
If you have any questions, please contact the SIG: Compiler ,
and any of the maintainers: @SegFault, @alexanderbill, @cf-zhao, @chenzheng1030, @eastb233, @kuenking111_admin, @li-yancheng, @wangqiang95, @wd-gitcode ,
and any of the committers: @huang-xiaoquan, @huzife, @lin-4682, @xiongzhou4 .


门禁正在运行, 您可以通过以下链接查看实时门禁检查结果.
若您对门禁结果含义不清晰或者遇到问题不知如何解决,可参考门禁指导手册
门禁入口及编码规范检查: multiarch/openeuler/trigger/gcc/108/console


| Check Name | Build Result | 详情 | Build Details | |
|---|---|---|---|---|
| check_code | ❌FAILED | • CodeCheck检查发现代码缺陷,请查看报告: https://www.openlibing.com/apps/entryCheckDashCode/MR_4db573efa5794f57b7a30b91d719e952/0fa4e1fe09231ee3b9d43a4948ca98b5?projectId=300024&codeHostingPlatformFlag=gitcode | #108 | |
| check_package_license | ✅SUCCESS | |||
| x86_64 | check_build | ✅SUCCESS | #116 | |
| aarch64 | check_build | ✅SUCCESS | #108 | |


一般 Minor
AI 代码审阅
优点
- 回移目标明确且可追溯:PR 中列出了 GCC 上游对应提交,功能修改有明确来源,便于后续维护。
- 新增的
TARGET_CALLEE_SAVE_COST/TARGET_FRAME_ALLOCATION_COSTtarget hook 设计清晰,默认实现与文档同步更新,后端覆盖了 AArch64 和 x86。 ira-color.cc中将 save/restore 成本与入口/出口基本块频率结合,比原实现更接近实际生成的 prologue/epilogue 成本。- 引入
ira_hard_regno_nrefs统计硬寄存器真实引用,避免对已经需要保存的 callee-saved 寄存器重复计费,方向合理。 - 测试覆盖了 x86、AArch64、PowerPC,并针对 GCC 12 的差异对期望汇编做了本地适配,且测试结果中未新增 FAIL。
变更文件覆盖检查
部分核心文件未提供完整 full file context,本次审查以 diff 为主要依据。
gcc/hard-reg-set.h的 full file context 与 diff 不一致,已单独标注。
| 文件 | 审查结果 |
|---|---|
gcc/config/aarch64/aarch64.cc |
未见可证明问题 |
gcc/config/i386/i386.cc |
未见可证明问题 |
gcc/doc/tm.texi |
未见可证明问题;文档变更,不影响构建/依赖/运行时 |
gcc/doc/tm.texi.in |
未见可证明问题;hook 文档入口与 target.def 同步 |
gcc/hard-reg-set.h |
input conflict:提供的 full context 未包含新增 hard_reg_set_popcount,以 diff 为准;diff 未发现可证明问题 |
gcc/ira-color.cc |
未见可证明问题;主要 IRA 成本逻辑变更,full context 未提供完整情况下仍以 diff 为准 |
gcc/ira-int.h |
未见可证明问题;新增 ira_hard_regno_nrefs 字段及宏 |
gcc/ira.cc |
未见可证明问题;新增硬寄存器引用计数初始化 |
gcc/target.def |
未见可证明问题;DEFHOOK 语法和默认实现声明一致 |
gcc/target.h |
未见可证明问题;新增 scoped enum 类型 |
gcc/targhooks.cc |
未见可证明问题;默认 hook 实现语义与文档一致 |
gcc/targhooks.h |
未见可证明问题;默认 hook 声明完整 |
gcc/testsuite/gcc.target/aarch64/callee_save_1.c |
未见可证明问题 |
gcc/testsuite/gcc.target/aarch64/callee_save_2.c |
未见可证明问题 |
gcc/testsuite/gcc.target/aarch64/callee_save_3.c |
未见可证明问题 |
gcc/testsuite/gcc.target/aarch64/pr103350-1.c |
未见可证明问题 |
gcc/testsuite/gcc.target/i386/force-indirect-call-2.c |
未见可证明问题 |
gcc/testsuite/gcc.target/i386/pr110071.c |
未见可证明问题 |
gcc/testsuite/gcc.target/i386/pr111673.c |
未见可证明问题 |
gcc/testsuite/gcc.target/i386/pr118497.c |
未见可证明问题 |
gcc/testsuite/gcc.target/powerpc/pr110071.c |
未见可证明问题 |
gcc/testsuite/gcc.target/powerpc/pr111673.c |
未见可证明问题 |
需要修改的问题
未发现明确必须修改的问题。
可优化建议
-
Suggestion: 建议在
gcc/ira-color.cc的improve_allocation附近增加注释,说明该阶段仍使用 legacy 成本公式,而未复用TARGET_CALLEE_SAVE_COST/TARGET_FRAME_ALLOCATION_COST的原因。 -
Reason: 当前
assign_hard_reg已使用新 target hook,并区分 save/restore 的 entry/exit 频率;而improve_allocation仍直接使用ira_memory_move_cost之和,并仅按 entry 频率缩放。若这是上游阶段行为,后续维护者容易误认为此处遗漏了 hook 接入。 -
Example:
/* improve_allocation 仍使用 PR110071/PR111673 引入的 legacy 成本, 新 target hook 在 assign_hard_reg 中处理,避免局部优化阶段重复计算。 */ -
Suggestion: 建议在
gcc/testsuite/gcc.target/aarch64/pr103350-1.c中为新增的-fno-caller-saves添加简短注释。 -
Reason: 该选项是为适配本 PR 的 callee-save 成本变化而加入的,但没有说明原因;后续回移或调整 IRA 成本模型时,维护者可能误删该选项,导致测试回归。
-
Example:
/* The IRA callee-save cost changes alter caller-saved register usage; -fno-caller-saves preserves the original REE test intent. */ /* { dg-additional-options "... -fno-caller-saves" } */
审阅结论
Severity: 通过
Conclusion: 建议通过
结论说明:
该 PR 是对 GCC 上游 IRA callee-save 成本模型修复的回移,代码路径清晰,默认 hook、后端实现和测试适配基本一致。未发现会直接导致编译失败、运行崩溃、数据不一致或安全问题的明确证据。部分 full file context 缺失或不一致,但基于 diff 中的变更未发现必须阻断合入的问题。
Review metadata:
- PR: #397
- Latest commit:
7d4184009876557caf0cf5c41d9f302186464297 - Changed lines: 641
- Review mode: full
- Reviewed files: 22/22


[P1] 请同步回移 PR122827 的 AArch64 SVE 修复
定位:gcc/config/aarch64/aarch64.cc:17825(本 PR 新增 aarch64_callee_save_cost);相关既有代码位于 aarch64_hard_regno_call_part_clobbered(约 5356–5368 行)。
上游后续提交 5cb0842b(PR target/122827) 明确将 SPEC CPU2017 526.blender_r 的静默错算二分定位到本系列包含的 b191e8bdecf(PR117477):新的 callee-save 成本会让 IRA 把 VNx2SF 值放到 V8–V15 并跨普通 AAPCS64 调用存活,而本分支的 aarch64_hard_regno_call_part_clobbered 仍按 GET_MODE_SIZE (mode) 判断。VNx2SF 在 128-bit SVE 下报告 8 字节,因此被误判为完整保存;但 AAPCS64 只保证保存 D8–D15 的低 64 位,SVE 指令却使用完整 Z 寄存器,被调用方可合法破坏高半部分,随后产生错误浮点结果。
该问题可在本树直接触发:aarch64_sve_mode_p、BYTES_PER_SVE_VECTOR、VNx2SF、Neoverse V2 和相关 SVE 选项均已存在。请在合入前回移 5cb0842b 的 aarch64.cc 部分:SVE mode 使用 BYTES_PER_SVE_VECTOR 计算 per_register_size,非 SVE mode 保持原逻辑;同时回移 gcc.target/aarch64/sve/pr122827.c。本 GCC 12 树没有 aarch64-early-ra.cc,因此上游提交的 early-RA 部分不适用;测试选项需把新版本的 sve-only 适配为本树的 --param=aarch64-autovec-preference=2。
建议在 SVE128 AArch64 上验证:PR 当前 head 应能复现用例失败,补齐修复后用例应通过。等价触发选项为 -Ofast -flto=auto -mcpu=neoverse-v2 -msve-vector-bits=128 --param=aarch64-autovec-preference=2。


门禁正在运行, 您可以通过以下链接查看实时门禁检查结果.
若您对门禁结果含义不清晰或者遇到问题不知如何解决,可参考门禁指导手册
门禁入口及编码规范检查: multiarch/openeuler/trigger/gcc/118/console


[P1] 请同步回移 PR122827 的 AArch64 SVE 修复
定位:
gcc/config/aarch64/aarch64.cc:17825(本 PR 新增aarch64_callee_save_cost);相关既有代码位于aarch64_hard_regno_call_part_clobbered(约 5356–5368 行)。上游后续提交
5cb0842b(PR target/122827) 明确将 SPEC CPU2017526.blender_r的静默错算二分定位到本系列包含的b191e8bdecf(PR117477):新的 callee-save 成本会让 IRA 把VNx2SF值放到 V8–V15 并跨普通 AAPCS64 调用存活,而本分支的aarch64_hard_regno_call_part_clobbered仍按GET_MODE_SIZE (mode)判断。VNx2SF在 128-bit SVE 下报告 8 字节,因此被误判为完整保存;但 AAPCS64 只保证保存 D8–D15 的低 64 位,SVE 指令却使用完整 Z 寄存器,被调用方可合法破坏高半部分,随后产生错误浮点结果。该问题可在本树直接触发:
aarch64_sve_mode_p、BYTES_PER_SVE_VECTOR、VNx2SF、Neoverse V2 和相关 SVE 选项均已存在。请在合入前回移5cb0842b的aarch64.cc部分:SVE mode 使用BYTES_PER_SVE_VECTOR计算per_register_size,非 SVE mode 保持原逻辑;同时回移gcc.target/aarch64/sve/pr122827.c。本 GCC 12 树没有aarch64-early-ra.cc,因此上游提交的 early-RA 部分不适用;测试选项需把新版本的sve-only适配为本树的--param=aarch64-autovec-preference=2。建议在 SVE128 AArch64 上验证:PR 当前 head 应能复现用例失败,补齐修复后用例应通过。等价触发选项为
-Ofast -flto=auto -mcpu=neoverse-v2 -msve-vector-bits=128 --param=aarch64-autovec-preference=2。
感谢检视,已按建议同步回移 PR target/122827,对应提交为 2e7d2527e。
已回移 aarch64.cc 中的修复,并同步加入上游gcc.target/aarch64/sve/pr122827.c;测试参数已适配为 GCC 12 使用的--param=aarch64-autovec-preference=2。本分支没有 aarch64-early-ra.cc,因此该部分不适用。
由于 GCC 12 的 vectorizer 无法稳定通过上游源用例触发错误分配,另外增加了确定性的 RTL 回归用例。该用例修复前为 1 PASS、1 FAIL,修复后为 2 PASS;与现有 AArch64 callee-save 用例合计 13 PASS。


| Check Name | Build Result | 详情 | Build Details | |
|---|---|---|---|---|
| check_code | ❌FAILED | • CodeCheck检查发现代码缺陷,请查看报告: https://www.openlibing.com/apps/entryCheckDashCode/MR_e63a3204342b4a0c8f961c8cf1b35aff/58a731dc2dddd3a418e9e483b70ca630?projectId=300024&codeHostingPlatformFlag=gitcode | #118 | |
| check_package_license | ✅SUCCESS | |||
| x86_64 | check_build | ✅SUCCESS | #126 | |
| aarch64 | check_build | ✅SUCCESS | #118 | |


/lgtm
/approve


PR功能描述 / 为什么需要这个合入:
本 PR 回移 GCC 上游 IRA callee-save 成本模型相关修复,包括PR110071、PR111673、PR117477 和 PR118497,并补充回移 PR122827,修复 PR117477 暴露的 AArch64 SVE callee-save 正确性问题。
原有 IRA 寄存器分配成本模型在选择 callee-saved 寄存器时,不能完整反映最终生成代码中的实际成本,主要包括:
improve_allocation阶段没有计算新增 callee-saved 寄存器所需的 save/restore 成本;push/pop、AArch64STP/LDP等架构相关的边际成本。上述问题可能导致 IRA 错误选择新的 callee-saved 寄存器,引入额外的
prologue/epilogue,或者使 shrink-wrapping 无法生效。该问题是在分析
SPEC CPU2017 511.povray_r 的性能差距时发现的。
原有的 SVE partial mode call-clobber 判断问题更容易被触发。对于
VNx2SF 等 SVE partial mode,
GET_MODE_SIZE只反映有效数据大小,但相关 SVE 指令实际使用完整 Z 寄存器。如果把 V8-V15 误认为在普通
AAPCS64 调用间完整保留,可能造成寄存器上半部分被调用过程破坏并产生
错误代码。PR122827 修复了这一问题。
本 PR 主要完成以下修改:
improve_allocation中计算 callee-save 的保存和恢复成本;TARGET_CALLEE_SAVE_COST和TARGET_FRAME_ALLOCATION_COSTtarget hook;计算真实的边际成本;
push/pop保存和恢复成本;STP/LDP成对保存、frame link 和栈帧分配折叠;callee-saved 寄存器重复收费;
BYTES_PER_SVE_VECTOR判断callee-save 范围,避免把 V8-V15 错误视为完整保留;
回归用例。
上游提交参考:
https://gcc.gnu.org/cgit/gcc/commit/?id=677249a23243b5b51832611767366d6eb199bdc7
https://gcc.gnu.org/cgit/gcc/commit/?id=3b9b8d6cfdf59337f4b7ce10ce92a98044b2657b
https://gcc.gnu.org/cgit/gcc/commit/?id=e8262c9041feddd7446840a9532cf458452f3587
https://gcc.gnu.org/cgit/gcc/commit/?id=b191e8bdecf881d11c1544c441e38f4c18392a15
https://gcc.gnu.org/cgit/gcc/commit/?id=c4dae80357ccf2e035d8e9ec0a3bb319344c5b41
https://gcc.gnu.org/cgit/gcc/commit/?id=5f34558100e8466aa70373e2f930bf1013192ba8
https://gcc.gnu.org/cgit/gcc/commit/?id=5cb0842b8b86f8495a110018fb8af3c4c3316605
希望检视人员了解的内容:
本 PR 共包含 9 个 commit。其中编译器功能修改均来自 GCC 上游,
EulerGCC 本地修改仅涉及 GCC 12 testsuite 期望适配、x86 回归测试以及
用于稳定复现 PR122827 的 AArch64 RTL 回归用例,没有引入私有的 IRA
优化算法。
GCC 12 与上游新版本存在以下差异:
TARGET_IRA_CALLEE_SAVED_REGISTER_COST_SCALEhook,因此不需要执行上游补丁中的旧 hook 删除操作;
vartrack-1.c正则调整在 GCC 12 上不需要,原测试继续通过;
callee_save_2.c和callee_save_3.c仅调整了汇编期望,被验证的优化语义保持不变;
因此同步回移了
force-indirect-call-2.c的上游测试修复;aarch64-early-ra.cc,因此 PR122827 中对应的early-RA 修改不适用于本分支,只回移
aarch64.cc中的修复;PR122827 用例中的
sve-only适配为数值2。由于 GCC 12vectorizer 无法稳定使该源文件触发错误分配,额外增加了直接构造
VNx2SF 跨调用存活场景的 RTL 回归用例。
Checklist:
PR格式
git config commit.template .gitee/commit_message功能验证
修改涉及后端架构
[ x] GCC自举构建是否通过,参考[Wiki](https://gitee.com/openeuler/gcc/wikis/如何贡献 openEuler GCC 社区)
[ x] GCC deja测试是否通过,并附上测试结果
gcc.sum:
expected passes 178390 178394
unexpected failures 212 212 0
unexpected successes 60 60
expected failures 1347 1347
unresolved 14 14
unsupported 6051 6052
g++.sum:
expected passes 229343 229343
unexpected failures 83 83 0
expected failures 1921 1921
unresolved 1 1
unsupported 10215 10215
gfortran.sum:
expected passes 66515 66515
unexpected failures 1 1 0
expected failures 272 272
unsupported 81 81
AArch64 PR122827 定向验证:
rtl.exp=pr122827.c:1 PASS,1 FAIL;rtl.exp=pr122827.c:2 PASS;rtl.exp=pr122827.c和aarch64.exp=callee_save_*.c合计:13 PASS;