已开启
[AArch64] SVE memcpy/memset 内联展开:无条件跳转后缺 barrier 导致 CFG 校验失败,CC 依赖未在 RTL 中建模 #98
huang-xiaoquan创建于 22 小时前
22 小时前 将 huang-xiaoquan 设为负责人
22 小时前 添加了label:sig/Compiler
openeuler-ci-bot
22 小时前 评论:
22 小时前 评论:
Welcome To openEuler Community
Hey @huang-xiaoquan , 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. You can self-configure the PR merge rules for this repository. For more details, please refer to Here.
Contact Guide
If you have any questions, please contact the SIG: Compiler ,
and any of the maintainers: @alexanderbill, @cf-zhao, @chenzheng1030, @eastb233, @kuenking111_admin, @li-yancheng, @neu-mobi, @wangqiang95, @wd-gitcode, @xiezhaokun ,
and any of the committers: @huang-xiaoquan, @huzife, @lin-4682 .


问题描述
AArch64 SVE
memcpy/memset内联展开(aarch64_expand_cpymem_sve/aarch64_expand_setmem_sve)有两处 RTL 生成问题:emit_jump_insn (gen_rtx_SET (pc_rtx, gen_rtx_LABEL_REF (Pmode, end_label)))跳到end_label,后面没有emit_barrier ()。cfgbuild.cc::make_edges依靠 BARRIER 判断能否落到下一个基本块,缺了它会多出一条 fallthru 边,CFG 与指令流不一致。开启内联且保留默认的运行时检查(-maarch64-sve-memcall-runtime-check默认开)时,-fchecking校验失败;用--enable-checking构建的编译器会直接 ICE。gen_rtx_REG (CC_NZCmode, CC_REGNUM)作为回跳条件,但gen_while_ultdivnx16bi对应的@while_<while_optab_cmp><GPI:mode><PRED_ALL:mode>模式对 CC 只有(clobber (reg:CC_NZC CC_REGNUM)),没有set(GCC 12 与 GCC 14 均如此)。目前生成的汇编正确(whilelo后紧跟b.any),但这层依赖没有写进 RTL,在两条指令之间插入或移动改写 CC 的指令都是合法的。该功能默认关闭(
-maarch64-sve-memcall-inlining默认关),不加该选项的编译不受影响。复现
环境:openEuler 24.03 LTS SP3 update 源中的
gcc-12.3.1-111.oe2403sp3(已包含该补丁),aarch64。typedef __SIZE_TYPE__ size_t; void *memcpy (void *, const void *, size_t); void f (char *d, const char *s, size_t n) { memcpy (d, s, n); }补丁自带的测试中,开启运行时检查的
sve-memcall-inline-1.c、-3.c、-4.c、sve-memcall-inline-run-1.c加-fchecking=1同样报错;关闭运行时检查的-2.c、-7.c、run-2.c不报。修复建议
emit_jump_insn (gen_rtx_SET (pc_rtx, gen_rtx_LABEL_REF (Pmode, end_label)))改为emit_jump (end_label)(内部包含emit_barrier ())。aarch64-sve.md中cbranch<mode>4(PRED_ALL)的写法:先用gen_aarch64_ptest<mode>把 CC set 出来再跳转,combine 后仍是一条whilelo加一条b.any,没有额外开销。-fchecking,防止回归。影响范围
源码仓 openeuler/gcc:
master:!380(提交3670a1791)gcc-14:提交ce9fd5f93及后续6506abad5、b8a9c34fc、3729b79b3软件包仓(补丁修复后需同步):
openEuler-24.03-LTS-SP3(#727,已随gcc-12.3.1-111.oe2403sp3发布)、openEuler-24.03-LTS-SP4(#728)、openEuler-24.03-LTS-Next(#729)、master(#752)master、openEuler-24.03-LTS-SP3、openEuler-24.03-LTS-SP4、openEuler-24.03-LTS-Next、openEuler-26.09、openEuler-26.09-DevStation@yly97 @liyunfei33 麻烦看一下。