已合并
[Backport] Add GIMPLE switch support to loop unswitching #391
[Backport] Add GIMPLE switch support to loop unswitching #391
已合并
haibaoo创建于 8月17日
haibaoo
haibaoo
8月17日

PR功能描述 / 为什么需要这个合入:
回移 GCC trunk 中 GIMPLE switch loop unswitching 的实现及相关后续修复。

原有 loop unswitching 主要处理循环中的不变 if 条件。本 PR 增加对循环不变 switch index 的支持:预先收集循环中的 unswitch predicates,
复制循环后使用 Ranger 提供的值域信息简化各个版本中的 switch 和条件分支。

同时重构 unswitch 成本模型,对同一个原始循环的所有 unswitch 机会使用统一的代码增长预算,并优先选择 profile count 最高的条件,避免先处理收
益较低的分支。

本 PR 还回移了 switch unswitching 后续发现的类型转换、异常 SSA、CFG dominator 更新和 guard hoisting 修复,并增加 EulerGCC 本地预算修复,
防止 hottest predicate 绕过正常的循环复制成本检查。

希望检视人员了解的内容:

  1. 本 PR 包含以下 8 个 GCC 上游提交:

  2. 主要上游修改包括:

    • 支持根据循环不变的 switch index 进行 loop unswitching。
    • 使用 Ranger 值域信息简化循环副本中的 switch 和条件语句。
    • 对同一原始循环使用统一的语句增长预算。
    • 根据 profile count 优先选择最热的 unswitch predicate。
    • 避免对 abnormal SSA_NAME 执行 Ranger 查询。
    • 将 case label 的上下界转换为 switch index 类型,修复不同整数类型导致的 ICE。
    • 删除不可达 switch edge 后重新计算 dominator 信息。
    • 修复 guard hoisting 过程中条件语句的插入位置。
  3. 本 PR 包含一个 EulerGCC 本地 bugfix:

    hottest-first 实现会直接选中最热 predicate,但原逻辑没有为该 predicate 计算两个特化循环的大小,因此可能绕过统一的代码增长预算。

    本地修复让预选的 hottest predicate 和普通 DFS predicate 共用相同的成本计算及预算检查。当复制后的两个循环超过预算时,不再执行该次
    unswitch。

  4. 本 PR 包含一个 EulerGCC 本地运行时测试 loop-unswitch-18.c,覆盖:

    • signed switch range;
    • unsigned case value;
    • case fallthrough;
    • default edge;
    • switch unswitching 前后的运行结果和副作用次数。
  5. 本 PR 共新增 21 个测试文件,并调整 3 个已有 loop-unswitch dump 测试。相关上游问题包括:

    • PR tree-optimization/105763
    • PR tree-optimization/105770
    • PR tree-optimization/105802
    • PR tree-optimization/107876
    • PR tree-optimization/111917
  6. 核心修改位于 GCC 通用 GIMPLE loop unswitching Pass,不包含 AArch64 或 x86 后端专用功能修改。验证在 x86_64-linux-gnu 上完成。

Checklist:
PR格式

功能验证

  • 修改涉及后端架构

  • 1448cecd0d080d0084746440ba14d9d189e2f0da
    

    patched:

    f3e378d6b1838be1162142ac2ac934c2396ed6b5
    

    回归测试通过。本 PR 新增 switch loop unswitching、后续 bugfix 及本地预算和运行时测试,因此 expected PASS 数量有所增加。

    baseline:

            === gcc/g++/gfortran aggregate Summary ===
    
    # of expected passes            474373
    # of unexpected failures        34
    # of unexpected successes       18
    # of expected failures          3769
    # of unresolved testcases       15
    # of unsupported tests          16355
    

    patched:

            === gcc/g++/gfortran aggregate Summary ===
    
    # of expected passes            474464
    # of unexpected failures        34
    # of unexpected successes       18
    # of expected failures          3769
    # of unresolved testcases       15
    # of unsupported tests          16357
    

    contrib/compare_tests 未发现新增 FAIL:

    • gcc.sum 新增 75 个预期 PASS。
    • g++.sum 新增 19 个预期 PASS。
    • gfortran.sum 没有变化。
    • 3 个旧 dump 扫描项因输出由 Unswitching 调整为 unswitching 而被新的扫描项替代,不是测试回归。
    • 两个新增 C++ 测试在 gnu++98 模式下按预期标记为 UNSUPPORTED。
    • expected PASS 净增加 91,所有失败相关统计与 baseline 保持一致。
likedislike
Pull Request已成功合入, 合并人@openeuler-ci-bot
(感谢 haibaoo 的贡献)
haibaoohaibaoo
8月17日 创建了 pull request,commit eafcb284
atomgit-bot
atomgit-bot
8月17日 评论:

变更摘要

本 PR 回移 GCC trunk 中 GIMPLE switch loop unswitching 的实现及相关后续修复,核心改动集中在 gcc/tree-ssa-loop-unswitch.cc:将原先仅处理循环不变 if 条件的逻辑重写为同时支持 gswitch,引入 unswitch_predicate 缓存、gimple_ranger 值域查询、predicate path 简化机制,并重构统一代码增长预算与 hottest predicate 优先选择策略;同时回移类型转换、异常 SSA、CFG dominator 更新和 guard hoisting 等修复,移除 max-unswitch-level 参数并新增 21 个测试、调整 3 个已有 dump 扫描项。

主要改动

  • 新增 switch 循环解开关支持:find_unswitching_predicates_for_bb 现在同时识别 gcond 与 gswitch,将 switch 的非 default 边(含 case range)转换为 unswitch_predicate 并按 gimple_uid 缓存,支持基于循环不变 switch index 的 loop unswitching。
  • 重构成本模型与 hottest 优先选择:tree_unswitch_single_loop 对同一原始循环维护统一 budget,通过 evaluate_loop_insns_for_predicate 计算 true/false 两个版本的指令数,并按 profile count 优先选择最热的 predicate;本地修复让预选的 hottest predicate 也经过 check_predicate 的统一预算检查。
  • 引入 Ranger 值域与 predicate path 简化:新增 gimple_ranger、predicate_path 及 evaluate_control_stmt_using_entry_checks、simplify_loop_version,利用值域和符号等价折叠 gcond、标记不可达 switch 边,并在 clean_up_after_unswitching 中删除不可达边且重新计算 dominator 信息。
  • 参数与调试项调整:删除 param_max_unswitch_level 及其在 gcc/params.opt、gcc/doc/invoke.texi 中的定义和文档,并新增 loop_unswitch debug counter。
  • 辅助修复与测试补充:gcc/tree-cfg.cc 的 gimple_lv_add_condition_to_bb 在插入前先对 cond_expr 调用 force_gimple_operand_gsi_1,修复 guard hoisting 中条件语句的插入位置;gcc/cfgloopmanip.cc 移除 bb->aux = 0 以免覆盖新成本信息;新增 21 个测试文件并调整 3 个 dump 扫描项的大小写。
likedislike
不准确?
atomgit-bot
atomgit-bot
8月17日 评论:

代码审查

✅ 未发现问题

likedislike
不准确?
openeuler-ci-botopeneuler-ci-bot成员
8月17日 将alexanderbill,li-yancheng,cf-zhao,eastb233,wangqiang95,kuenking111_admin,SegFault,wd-gitcode,chenzheng1030设为审查人
openeuler-ci-botopeneuler-ci-bot成员
8月17日 添加了label:sig/Compiler
openeuler-ci-bot
openeuler-ci-bot成员
8月17日 评论:

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 .

likedislike
openeuler-ci-botopeneuler-ci-bot成员
8月17日 添加了label:stat/needs-squash
openeuler-ci-botopeneuler-ci-bot成员
8月17日 添加了label:openeuler-cla/yes
openeuler-ci-bot
openeuler-ci-bot成员
8月17日 评论:

CLA Signature Pass

qq_56722097, thanks for your pull request. All authors of the commits have signed the CLA. 👍

likedislike
openeuler-ci-botopeneuler-ci-bot成员
8月17日 添加了label:ci_processing
openeuler-ci-bot
openeuler-ci-bot成员
8月17日 评论:

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

likedislike
openeuler-ci-botopeneuler-ci-bot成员
8月17日 删除了label:ci_processing
openeuler-ci-bot
openeuler-ci-bot成员
8月17日 评论:
Check Name Build Result 详情 Build Details
check_code ❌FAILED • CodeCheck检查发现代码缺陷,请查看报告: https://www.openlibing.com/apps/entryCheckDashCode/MR_0205ffe168ff4c7980b122df31043530/6469105bb58f4f0ab4303b17310a774d?projectId=300024&codeHostingPlatformFlag=gitcode #100
check_package_license ✅SUCCESS
x86_64 check_build ✅SUCCESS #108
aarch64 check_build ✅SUCCESS #100
likedislike
openeuler-ci-botopeneuler-ci-bot成员
8月17日 添加了label:ci_failed
openeuler-ci-bot
openeuler-ci-bot成员
8月17日 评论:
likedislike
zhuzhibiao1
8月20日 评论:

通过 Pass

AI 代码审阅

优点

  • 该 PR 回移的是 GCC 上游 GIMPLE switch loop unswitching 功能,整体结构清晰:引入 unswitch_predicate、Ranger 值域信息、统一预算和 hottest-first 选择,符合上游演进方向。
  • gcc/tree-cfg.cc 中先通过 force_gimple_operand_gsi_1 将条件转换为合法 GIMPLE,再插入新条件,修改点集中,修复意图明确。
  • 新增测试覆盖较全,包括 signed/unsigned switch、range case、fallthrough、default edge、运行时副作用次数等;其中 loop-unswitch-18.c 为运行时测试,能验证优化前后语义一致性。
  • gcc/dbgcnt.def 新增 loop_unswitch debug counter,便于后续二分定位该 pass 的变换问题。
  • gcc/doc/invoke.texi 与 gcc/params.opt 对 max-unswitch-level 的删除保持一致,未发现文档与参数定义不同步。
  • PR 描述给出了 baseline 与 patched 回归测试对比,新增 PASS 与存量 FAIL 统计清晰,验证信息充分。

变更文件覆盖检查

文件 审查结果
gcc/cfgloopmanip.cc no proven issue;删除 bb->aux = 0 与新的 aux 生命周期管理相关,但本文件上下文未完全展示,未发现可见 diff 中的确定性缺陷
gcc/dbgcnt.def no proven issue;新增 counter 位置符合字母顺序
gcc/doc/invoke.texi no proven issue;仅删除 max-unswitch-level 文档
gcc/params.opt no proven issue;参数定义删除与文档一致,影响构建期生成的参数列表和用户命令行兼容性
gcc/testsuite/g++.dg/opt/pr105802.C no proven issue;新增编译回归用例
gcc/testsuite/g++.dg/tree-ssa/pr107876-2.C no proven issue;编译与 dump 扫描用例
gcc/testsuite/g++.dg/tree-ssa/pr107876.C no proven issue;编译与 dump 扫描用例
gcc/testsuite/gcc.dg/alias-10.c no proven issue;仅 dump 文本大小写适配
gcc/testsuite/gcc.dg/loop-unswitch-1.c no proven issue;仅 dump 文本大小写适配
gcc/testsuite/gcc.dg/loop-unswitch-10.c optional suggestion;存在 defaut: 拼写,疑似应为 default:
gcc/testsuite/gcc.dg/loop-unswitch-11.c optional suggestion;同上
gcc/testsuite/gcc.dg/loop-unswitch-12.c no proven issue
gcc/testsuite/gcc.dg/loop-unswitch-13.c no proven issue
gcc/testsuite/gcc.dg/loop-unswitch-14.c optional suggestion;存在 defaut: 拼写,疑似应为 default:
gcc/testsuite/gcc.dg/loop-unswitch-15.c no proven issue
gcc/testsuite/gcc.dg/loop-unswitch-16.c no proven issue
gcc/testsuite/gcc.dg/loop-unswitch-17.c no proven issue
gcc/testsuite/gcc.dg/loop-unswitch-18.c no proven issue;运行时断言值经核查与循环副作用次数一致
gcc/testsuite/gcc.dg/loop-unswitch-7.c no proven issue
gcc/testsuite/gcc.dg/loop-unswitch-8.c no proven issue
gcc/testsuite/gcc.dg/loop-unswitch-9.c no proven issue
gcc/testsuite/gcc.dg/pr105763.c no proven issue
gcc/testsuite/gcc.dg/pr105770.c no proven issue
gcc/testsuite/gcc.dg/torture/20220518-1.c no proven issue
gcc/testsuite/gcc.dg/torture/20220518-2.c no proven issue
gcc/testsuite/gcc.dg/torture/20220525-1.c no proven issue
gcc/testsuite/gcc.dg/torture/pr111917.c no proven issue
gcc/testsuite/gcc.dg/tree-ssa/loop-6.c no proven issue;仅 dump 文本大小写适配
gcc/tree-cfg.cc no proven issue;force_gimple_operand_gsi_1 修复合理
gcc/tree-ssa-loop-unswitch.cc no proven issue in visible diff;但该文件 diff 被截断,未能审查后续约 900 行核心实现和成本逻辑

需要修改的问题

未发现明确必须修改的问题。

可优化建议

  • Suggestion: 将 gcc/testsuite/gcc.dg/loop-unswitch-10.c、loop-unswitch-11.c、loop-unswitch-14.c 中的 defaut: 更正为 default:。

    • Reason: 从上下文看,这里显然是想给 switch 提供一个不可达的 default 分支并调用 __builtin_unreachable()。拼成 defaut: 只是一个普通 label,并不会成为 switch 的 default edge,因此测试语义与注释/意图不一致,且无法覆盖“default 不可达”的路径。
    • Example:
      switch (order)
        {
        case 0:
          ...
          break;
        ...
        default:
          __builtin_unreachable ();
        }
      
  • Suggestion: 确认移除 --param max-unswitch-level 的用户可见兼容性是否需要额外说明。

    • Reason: params.opt 中删除该参数后,已有构建脚本、调优配置或用户命令行若显式传入 --param max-unswitch-level=N,可能直接报错。上游移除通常可接受,但作为发行版 backport,建议确认是否需要 release note 或兼容性提示。
    • Example: 暂不提供代码修改;如果关注兼容性,可保留为 deprecated/ignored 参数,并在文档中注明不再生效。

审阅结论

Severity: 通过

Conclusion: 建议通过

结论说明:

基于当前可见 diff,未发现确定性的编译错误、运行时语义错误或必须阻断合入的缺陷。gcc/tree-ssa-loop-unswitch.cc 是本次变更的核心文件,但 diff 被截断,后半部分 tree_unswitch_single_loop 的预算计算、CFG 简化、Ranger value-range 使用等关键逻辑未能完整审查;在 PR 自述的自举和 deja 回归通过的前提下,本次审阅不阻断合入。建议合入前顺手修正测试中 defaut 拼写,并确认移除 max-unswitch-level 参数对下游用户的影响。


Review metadata:

  • PR: #391
  • Latest commit: bf5a9bd4886dd197880e65dc7af567b0d412e13c
  • Changed lines: 1940
  • Review mode: focused
  • Reviewed files: 30/30
likedislike
wd-gitcode成员
9月7日 评论:

/lgtm
/approve

likedislike
openeuler-ci-botopeneuler-ci-bot成员
9月7日 添加了label:approvedlgtm
openeuler-ci-bot
openeuler-ci-bot成员
9月7日 评论:

Review Code Feedback

  • The label lgtm, approved was added to this pull request. It means that wd-gitcode reviewed the code changes. 👋
Tips
  • If this pull request is not merged while all conditions are met, comment /check-pr to try again. 😄
likedislike
openeuler-ci-botopeneuler-ci-bot成员
9月7日 合入了pull request,合并节点 SHA:a5dff9be88006a743a8255e6e675fcd9fb11aaef