Ventus libclc linked bitcode 构建阶段大量打印 Impossible RISCV physreg copy
摘要
在 dev-thu-sfu-mma 分支上执行:
bash build-ventus.sh --build libclc
构建尾部会大量打印:
Impossible RISCV physreg copy: dst=X5 src=V0
Impossible RISCV physreg copy: dst=X5 src=V1
Impossible RISCV physreg copy: dst=X5 src=V3
...
当前顶层脚本仍通过 || true 吞掉 libclc/build_riscv32clc.sh 的状态,所以顶层命令返回 0。但这些诊断说明后端仍生成了非法的 VGPR 到 GPR 物理寄存器 copy,属于真实 codegen 问题,不应按普通 warning 处理。copyPhysReg() 禁止 VGPR -> GPR/GPRF32 是 Ventus SIMT 寄存器模型下的预期行为;问题在于更早阶段不应生成这种 copy。
问题根因在 main 分支存在,编译中途可见生成的错误代码,但恰好都被后续 Pass 常量优化掉了,因此未暴露问题。
dev-thu-sfu-mma 分支修改了 libclc 编译流程,导致 inline 机会增加,生成了一些不可被常量优化掉的 VGPR 到 SGPR 错误拷贝,导致问题暴露
相关 commit
当前出问题的分支:
518173e25cb69c6364ba57f93c9f6ad39849fada
[Ventus] Preserve SFU MMA features on dev-thu base
对照的 main:
95fb0ba3a88151b6c90a1c25b7161246be6fd3b5
[VENTUS][FEAT] Enable promote small-vector alloca
dev-thu-sfu-mma 在 main 之后的相关提交包括:
518173e25cb6 [Ventus] Preserve SFU MMA features on dev-thu base
86558bf02778 [Ventus] Wire MMA pseudo lowering on dev-thu base
73157331f871 code cleanup
32b89a8c3eae [Ventus] Add MMA lowering on dev-thu base
712c32dcb712 [Ventus] Build libclc from linked bitcode
7d5ffac57176 [RISCV][Ventus] Specialize private-derived generic pointers
25321e824d52 [RISCV][Ventus] Temporarily disable SGPR SIMT checker
e9d0eaecfd84 [Ventus] Fix SIMT SGPR shadow checks
复现方式
为了避免海量日志刷屏,建议在仓库根目录重定向到文件:
bash build-ventus.sh --build libclc > ventus-libclc-build-check.log 2>&1
echo $?
wc -l ventus-libclc-build-check.log
rg -c "Impossible RISCV physreg copy" ventus-libclc-build-check.log
rg -n "Building riscv32|Impossible RISCV physreg copy|error:|FAILED|clang|builtins.link|riscv32clc" \
ventus-libclc-build-check.log | sed -n '1,120p'
tail -n 80 ventus-libclc-build-check.log
本地实测:
exit=0
3128 ventus-libclc-build-check.log
1977 lines match "Impossible RISCV physreg copy"
第一处诊断出现在:
************* Building riscv32 libclc object file ************
Impossible RISCV physreg copy: dst=X5 src=V0
Impossible RISCV physreg copy: dst=X5 src=V1
...
对应的脚本调用位于 build-ventus.sh:
bash ${DIR}/libclc/build_riscv32clc.sh ${DIR}/libclc ${LIBCLC_BUILD_DIR} ${VENTUS_INSTALL_PREFIX} || true
因此当前顶层命令返回 0,不是因为没有问题,而是因为这一阶段仍被 || true 吞掉状态。
实际触发的子命令
libclc/build_riscv32clc.sh 当前逻辑为:
BUILTINS_BC=${LIBCLC_BUILD_DIR}/builtins.link.riscv32--.bc
OUTPUT_OBJ=${LIBCLC_BUILD_DIR}/riscv32clc.o
${BINARY_DIR}/bin/clang -target riscv32 -mcpu=ventus-gpgpu \
-cl-std=CL2.0 \
-Wno-override-module \
-ffunction-sections -fdata-sections \
-c "${BUILTINS_BC}" \
-o "${OUTPUT_OBJ}"
直接运行 clang 子命令也能复现大量诊断:
rm -f riscv32clc-direct.o ventus-libclc-clang-direct.log
install/bin/clang -target riscv32 -mcpu=ventus-gpgpu \
-cl-std=CL2.0 \
-Wno-override-module \
-ffunction-sections -fdata-sections \
-c build-libclc/builtins.link.riscv32--.bc \
-o riscv32clc-direct.o \
> ventus-libclc-clang-direct.log 2>&1
echo $?
wc -l ventus-libclc-clang-direct.log
rg -c "Impossible RISCV physreg copy" ventus-libclc-clang-direct.log
本地实测:
exit=0
1977 ventus-libclc-clang-direct.log
1977
对象文件仍会生成:
这说明当前本地 install/bin/clang 表现为没有因该 llvm_unreachable 中止编译,但后端确实走到了 impossible copy 路径。不同 LLVM 构建配置下,llvm_unreachable 的运行时表现可能不同,因此不应依赖当前退出码为 0 来判断问题是否无害。
关键 MIR 线索
在仓库根目录用 __divdf3 可以复现早期寄存器类混用:
install/bin/llvm-extract --func=__divdf3 \
build-libclc/builtins.link.riscv32--.bc \
-o divdf3.check.bc
install/bin/llc \
-mtriple=riscv32 -mcpu=ventus-gpgpu \
-stop-after=amdgpu-isel \
divdf3.check.bc \
-o divdf3.after-isel.check.mir
rg -n "%[0-9]+:gpr = COPY %[0-9]+|%[0-9]+:vgpr = COPY \\$x0" \
divdf3.after-isel.check.mir | sed -n '1,120p'
实测 MIR 中可见:
%351:vgpr = COPY $x0
%22:vgpr = COPY %351
%350:gpr = COPY %351
%349:gpr = COPY %351
这里 %351 是 vgpr,但 %350/%349 是 gpr,即虚拟寄存器阶段已经出现了 VGPR -> GPR 方向的 copy。
注意:这个单函数 MIR 片段是定位 register-class 传播问题的早期线索,不等价于证明 __divdf3 单独完整 codegen 一定会走到最终的 Impossible RISCV physreg copy。在 main 上用同一函数实测,-stop-after=amdgpu-isel 后也能看到相同形态,但 llc /tmp/main-divdf3.check.bc 可以完整生成汇编。最终构建阶段的大量 Impossible RISCV physreg copy 仍需以完整 linked bitcode codegen 的实测日志为准。
进一步追踪 main 上的 __divdf3,这类早期 copy 在后续阶段会被合法化。例如早期 MIR 中有:
%351:vgpr = COPY $x0
%350:gpr = COPY %351
%349:gpr = COPY %351
用默认 llc 路径追踪时,到 virtregrewriter 后还能看到短暂的物理寄存器形式:
$v3 = COPY $x0
$x5 = COPY $v3
$x6 = COPY $v3
而更接近旧 libclc clang -c 行为的 -regalloc=fast 路径中,到 postrapseudos 前该片段已经被传播成:
$v3 = COPY $x0
$x5 = COPY $x0
$x6 = COPY $x0
随后 postrapseudos 后变为合法的 scalar/vector 分别取零:
$v3 = VMV_V_X $x0
$x5 = ADDI $x0, 0
$x6 = ADDI $x0, 0
$v10 = VMV_V_X $x0
$v9 = VMV_V_X $x0
也就是说,main 上这个具体 __divdf3 片段没有把 VGPR -> GPR copy 保留到最终机器指令;它被后续 pass 识别为来自 $x0 的零值,并改写成合法的 GPR 赋零和 VGPR broadcast zero。当前 issue 的最终错误来自完整 linked bitcode codegen 中仍有其他非法 VGPR -> GPR copy 存活到 copyPhysReg()。
相关源码点:
// llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
// vGPR -> sGPR move
if (RISCV::GPRRegClass.contains(DstReg) &&
RISCV::VGPRRegClass.contains(SrcReg)) {
llvm_unreachable("Illegal copy from VGPR to SGPR");
}
VGPR -> GPR 在 Ventus SIMT 模型下是非法方向。这里的非法不是 copyPhysReg() 缺功能;如果这种方向的 copy 存活到物理寄存器 copy 阶段,copyPhysReg() 拒绝它是正确的目标约束。修复必须保持该方向 copy 被禁止,不能通过实现 VGPR -> GPR/GPRF32 copy、恢复 VMV_X_S / VFMV_F_S,或其他方式把 per-lane 值静默拉回 scalar 域来绕过。
与 main 的对比
main 对应版本的 libclc/build_riscv32clc.sh 仍是旧流程:
# Collect all the object files in build directory
OBJECT_FILE_LIST=""
for item in $(find ${LIBCLC_BUILD_DIR} -name "*.bc.o")
do
OBJECT_FILE_LIST="${OBJECT_FILE_LIST} ${item}"
done
# Compile other left IR files
for item in $(ls ${LIBCLC_DIR}/generic/lib | grep ll)
do
${BINARY_DIR}/bin/clang ... -c ${LIBCLC_DIR}/generic/lib/${item} ...
OBJECT_FILE_LIST="${OBJECT_FILE_LIST} ${LIBCLC_BUILD_DIR}/${item}.o"
done
${BINARY_DIR}/bin/ld.lld --relocatable ${OBJECT_FILE_LIST} \
--allow-multiple-definition \
-o ${LIBCLC_BUILD_DIR}/riscv32clc.o
也就是说,main 没有把完整 builtins.link.riscv32--.bc 直接送进一次后端 codegen 来生成最终 riscv32clc.o,因此不会以同样方式暴露该问题。
这不表示 main 中完全没有早期 SGPR/VGPR register-class 混用线索。实际检查 main 的 __divdf3 可见同类早期 MIR copy,但该函数单独完整 codegen 时后续 pass 会把这类来自 $x0 的 copy 合法化,最终汇编没有保留对应的非法 VGPR -> GPR 机器指令。
额外验证:如果在 main 上手动直接编译 linked bitcode:
install/bin/clang -target riscv32 -mcpu=ventus-gpgpu \
-cl-std=CL2.0 \
-Wno-override-module \
-ffunction-sections -fdata-sections \
-c build-libclc/builtins.link.riscv32--.bc \
-o main-riscv32clc-direct.o
它不会走到这串 Impossible RISCV physreg copy,而是先死在另一个旧问题:
fatal error: error in backend: Cannot select: i32 = RISCVISD::FCVT_X
In function: _Z16convert_char_rtef
dev-thu-sfu-mma 中的 712c32dcb712 同时增加了 riscv_fcvt_x/riscv_fcvt_xu 的 Zfinx pattern,使 linked bitcode 编译能越过这个更早的 FCVT 选择失败,继续暴露后面的 VGPR/GPR copy 问题。
commit 分层分析
1. 高置信根因方向:Ventus divergence/register-class 传播不完整
当前证据能严格确认:完整 linked bitcode codegen 会在物理寄存器 copy 阶段触发 VGPR -> GPR;虚拟寄存器阶段也能看到 VGPR -> GPR 方向的早期 copy 线索。更具体的触发点仍需继续缩小到 PHI、return copy、tuple copy、constant zero lowering、后续 copy 消除未覆盖的路径,或其他 lowering 路径。
根因方向不在 copyPhysReg() 缺少 VGPR -> GPR 实现。相反,copyPhysReg() 拒绝该方向是正确的目标约束。
问题本质是 Ventus 后端在 SelectionDAG/ISel 及后续 PHI/tuple/return copy 路径中,仍会让 divergent/VGPR 值流向 GPR use,产生非法跨域 COPY。
相关逻辑包括:
// llvm/lib/Target/RISCV/RISCVISelLowering.cpp
if (Subtarget.hasVInstructions()) {
addRegisterClass(MVT::i32, &RISCV::VGPRRegClass);
addRegisterClass(MVT::f32, &RISCV::VGPRRegClass);
}
以及:
const TargetRegisterClass *
RISCVTargetLowering::getRegClassFor(MVT VT, bool isDivergent) const {
const TargetRegisterClass *RC = TargetLoweringBase::getRegClassFor(VT, false);
const RISCVRegisterInfo *TRI = Subtarget.getRegisterInfo();
if (!TRI->isSGPRClass(RC) && !isDivergent)
return VT == MVT::i32 ? &RISCV::GPRRegClass : &RISCV::GPRF32RegClass;
else if (TRI->isSGPRClass(RC) && isDivergent)
return &RISCV::VGPRRegClass;
return RC;
}
以及 non-kernel 参数取入 VGPR 的逻辑:
// Setting isDivergent = true is essential to use VGPR
const TargetRegisterClass *RC = TLI.getRegClassFor(LocVT.getSimpleVT(), true);
Register VReg = RegInfo.createVirtualRegister(RC);
RegInfo.addLiveIn(VA.getLocReg(), VReg);
SDValue Val = DAG.getCopyFromReg(Chain, DL, VReg, LocVT);
这些规则组合后,在 soft-float helper 这类既有 divergent 参数又有大量 scalar 控制流/常量/PHI 的函数中,容易让同一个值在不同 use 上被分配到不同 register class。
2. 构建暴露变更:712c32dcb712
712c32dcb712 [Ventus] Build libclc from linked bitcode
该提交将 riscv32clc.o 从 linked bitcode 直接 codegen:
- ${BINARY_DIR}/bin/ld.lld --relocatable ${OBJECT_FILE_LIST} ...
+ ${BINARY_DIR}/bin/clang ... -c "${BUILTINS_BC}" -o "${OUTPUT_OBJ}"
它的 commit message 已明确说明影响:
Building the final riscv32clc.o now runs code generation over the whole
linked libclc module, which may take longer and can expose real backend
issues that were previously hidden by per-file codegen.
这正是当前问题的主要暴露条件。
3. 使 linked bitcode 继续向后暴露的次级变更:同一提交中的 FCVT pattern
712c32dcb712 还增加了:
def : Pat<(i32 (riscv_fcvt_x GPRF32:$rs1, timm:$frm)),
(FCVT_W_S $rs1, timm:$frm)>;
def : Pat<(i32 (riscv_fcvt_xu GPRF32:$rs1, timm:$frm)),
(FCVT_WU_S $rs1, timm:$frm)>;
这让当前分支越过了 main 上 linked bitcode 编译会先遇到的 Cannot select RISCVISD::FCVT_X。
4. 日志可见变更:518173e25cb6
518173e25cb6 [Ventus] Preserve SFU MMA features on dev-thu base
该提交修改了 RISCVInstrInfo::copyPhysReg(),新增了:
errs() << "Impossible RISCV physreg copy: dst=" << TRI.getName(DstReg)
<< " src=" << TRI.getName(SrcReg) << '\n';
llvm_unreachable("Impossible reg-to-reg copy");
因此当前分支会明确打印 dst/src,例如:
Impossible RISCV physreg copy: dst=X5 src=V0
main 同一位置没有这条 errs(),只有 llvm_unreachable("Impossible reg-to-reg copy")。因此可以确认 518173e25cb6 让这类 impossible copy 的 dst/src 日志变得可见。该提交本身还包含其他后端改动;若要严格证明它没有影响触发路径,需要进一步逐 commit/bisection 验证。
当前判断
分层结论:
已确认的问题:
完整 linked bitcode codegen 会触发 VGPR -> GPR 物理寄存器 copy;
物理寄存器分配前能看到 VGPR -> GPR 方向的早期 COPY 线索;
copyPhysReg() 禁止该方向 copy 是预期行为,不应放宽。
高置信根因方向:
Ventus SGPR/VGPR divergence/register-class 传播不完整,后端能生成非法 VGPR -> GPR COPY。
构建暴露变更:
712c32dcb712 [Ventus] Build libclc from linked bitcode。
它让最终 riscv32clc.o 从完整 linked bitcode 一次性 codegen。
次级暴露条件:
712c32dcb712 同时修了 main 上 linked bitcode 会先遇到的 FCVT_X selection failure,
因此当前分支可以继续走到 VGPR/GPR copy 问题。
日志可见变更:
518173e25cb6 [Ventus] Preserve SFU MMA features on dev-thu base。
它在 copyPhysReg impossible 分支打印 dst/src;该提交是否还影响触发路径需另行 bisection 才能严格确认。
不建议的修复方向
不建议:
1. 在 copyPhysReg() 中实现 VGPR -> GPR/GPRF32。禁止该方向 copy 是 Ventus SIMT 模型的预期约束,不是待补功能。
2. 恢复或依赖 VMV_X_S / VFMV_F_S,把 per-lane 值静默拉回 scalar 域。
3. 在构建脚本里过滤日志或继续扩大 silent fallback。
4. 关闭 cl_khr_fp64 或跳过 soft-float helper 来绕过。
5. 静默删除非法 COPY。
这些做法会隐藏真正的 SGPR/VGPR 域约束问题。
建议的修复方向
更合理的修复方向是在 ISel / machine pass 层保证 register class 一致性:
1. divergent 值一旦进入 VGPR 域,不应通过普通 COPY 被拉回 GPR。
2. 需要 GPR operand 的 pattern 必须只接受 uniform/SGPR 来源。
3. i32/f32 register class 不能只按类型决定,必须稳定结合 divergence。
4. PHI、return tuple、constant zero、COPY_TO_REGCLASS 等路径需要统一处理。
5. 对 Ventus 增加 verifier,在 finalize-isel 或 Ventus VV conversion 后尽早报出非法 VGPR -> GPR COPY。
已有 VentusFixMixedPHI 能处理一部分 mixed PHI,但当前问题说明覆盖面还不完整,特别是 linked libclc 输入下的 soft-float helper、tuple copy、return value copy 或 constant zero lowering 路径仍可能留下非法形态。
验证方式
修复后至少验证:
bash build-ventus.sh --build libclc > ventus-libclc-build-fixed.log 2>&1
rg -n "Impossible RISCV physreg copy|Illegal copy from VGPR|VGPR to SGPR" \
ventus-libclc-build-fixed.log
并检查单函数 MIR:
install/bin/llvm-extract --func=__divdf3 \
build-libclc/builtins.link.riscv32--.bc \
-o divdf3.fixed.bc
install/bin/llc \
-mtriple=riscv32 -mcpu=ventus-gpgpu \
-stop-after=amdgpu-isel \
divdf3.fixed.bc \
-o divdf3.after-isel.fixed.mir
rg -n "%[0-9]+:gpr = COPY %[0-9]+|%[0-9]+:gpr = COPY %[0-9]+:vgpr" \
divdf3.after-isel.fixed.mir
更稳妥的验证方式是新增 MachineFunction verifier,根据 MachineRegisterInfo 查询 src/dst register class,而不是依赖文本 grep。
附件:更多相关讨论总结
dialogue-summary.md
Ventus libclc linked bitcode 构建阶段大量打印
Impossible RISCV physreg copy摘要
在
dev-thu-sfu-mma分支上执行:构建尾部会大量打印:
当前顶层脚本仍通过
|| true吞掉libclc/build_riscv32clc.sh的状态,所以顶层命令返回0。但这些诊断说明后端仍生成了非法的 VGPR 到 GPR 物理寄存器 copy,属于真实 codegen 问题,不应按普通 warning 处理。copyPhysReg()禁止VGPR -> GPR/GPRF32是 Ventus SIMT 寄存器模型下的预期行为;问题在于更早阶段不应生成这种 copy。问题根因在 main 分支存在,编译中途可见生成的错误代码,但恰好都被后续 Pass 常量优化掉了,因此未暴露问题。
dev-thu-sfu-mma 分支修改了 libclc 编译流程,导致 inline 机会增加,生成了一些不可被常量优化掉的 VGPR 到 SGPR 错误拷贝,导致问题暴露
相关 commit
当前出问题的分支:
对照的
main:dev-thu-sfu-mma在main之后的相关提交包括:复现方式
为了避免海量日志刷屏,建议在仓库根目录重定向到文件:
本地实测:
第一处诊断出现在:
对应的脚本调用位于
build-ventus.sh:因此当前顶层命令返回
0,不是因为没有问题,而是因为这一阶段仍被|| true吞掉状态。实际触发的子命令
libclc/build_riscv32clc.sh当前逻辑为:直接运行 clang 子命令也能复现大量诊断:
本地实测:
对象文件仍会生成:
这说明当前本地
install/bin/clang表现为没有因该llvm_unreachable中止编译,但后端确实走到了 impossible copy 路径。不同 LLVM 构建配置下,llvm_unreachable的运行时表现可能不同,因此不应依赖当前退出码为0来判断问题是否无害。关键 MIR 线索
在仓库根目录用
__divdf3可以复现早期寄存器类混用:实测 MIR 中可见:
这里
%351是vgpr,但%350/%349是gpr,即虚拟寄存器阶段已经出现了VGPR -> GPR方向的 copy。注意:这个单函数 MIR 片段是定位 register-class 传播问题的早期线索,不等价于证明
__divdf3单独完整 codegen 一定会走到最终的Impossible RISCV physreg copy。在main上用同一函数实测,-stop-after=amdgpu-isel后也能看到相同形态,但llc /tmp/main-divdf3.check.bc可以完整生成汇编。最终构建阶段的大量Impossible RISCV physreg copy仍需以完整 linked bitcode codegen 的实测日志为准。进一步追踪
main上的__divdf3,这类早期 copy 在后续阶段会被合法化。例如早期 MIR 中有:用默认
llc路径追踪时,到virtregrewriter后还能看到短暂的物理寄存器形式:而更接近旧 libclc
clang -c行为的-regalloc=fast路径中,到postrapseudos前该片段已经被传播成:随后
postrapseudos后变为合法的 scalar/vector 分别取零:也就是说,
main上这个具体__divdf3片段没有把VGPR -> GPRcopy 保留到最终机器指令;它被后续 pass 识别为来自$x0的零值,并改写成合法的 GPR 赋零和 VGPR broadcast zero。当前 issue 的最终错误来自完整 linked bitcode codegen 中仍有其他非法VGPR -> GPRcopy 存活到copyPhysReg()。相关源码点:
VGPR -> GPR在 Ventus SIMT 模型下是非法方向。这里的非法不是copyPhysReg()缺功能;如果这种方向的 copy 存活到物理寄存器 copy 阶段,copyPhysReg()拒绝它是正确的目标约束。修复必须保持该方向 copy 被禁止,不能通过实现VGPR -> GPR/GPRF32copy、恢复VMV_X_S/VFMV_F_S,或其他方式把 per-lane 值静默拉回 scalar 域来绕过。与 main 的对比
main对应版本的libclc/build_riscv32clc.sh仍是旧流程:也就是说,
main没有把完整builtins.link.riscv32--.bc直接送进一次后端 codegen 来生成最终riscv32clc.o,因此不会以同样方式暴露该问题。这不表示
main中完全没有早期 SGPR/VGPR register-class 混用线索。实际检查main的__divdf3可见同类早期 MIR copy,但该函数单独完整 codegen 时后续 pass 会把这类来自$x0的 copy 合法化,最终汇编没有保留对应的非法VGPR -> GPR机器指令。额外验证:如果在
main上手动直接编译 linked bitcode:它不会走到这串
Impossible RISCV physreg copy,而是先死在另一个旧问题:dev-thu-sfu-mma中的712c32dcb712同时增加了riscv_fcvt_x/riscv_fcvt_xu的 Zfinx pattern,使 linked bitcode 编译能越过这个更早的 FCVT 选择失败,继续暴露后面的 VGPR/GPR copy 问题。commit 分层分析
1. 高置信根因方向:Ventus divergence/register-class 传播不完整
当前证据能严格确认:完整 linked bitcode codegen 会在物理寄存器 copy 阶段触发
VGPR -> GPR;虚拟寄存器阶段也能看到VGPR -> GPR方向的早期 copy 线索。更具体的触发点仍需继续缩小到 PHI、return copy、tuple copy、constant zero lowering、后续 copy 消除未覆盖的路径,或其他 lowering 路径。根因方向不在
copyPhysReg()缺少VGPR -> GPR实现。相反,copyPhysReg()拒绝该方向是正确的目标约束。问题本质是 Ventus 后端在 SelectionDAG/ISel 及后续 PHI/tuple/return copy 路径中,仍会让 divergent/VGPR 值流向 GPR use,产生非法跨域 COPY。
相关逻辑包括:
以及:
以及 non-kernel 参数取入 VGPR 的逻辑:
这些规则组合后,在 soft-float helper 这类既有 divergent 参数又有大量 scalar 控制流/常量/PHI 的函数中,容易让同一个值在不同 use 上被分配到不同 register class。
2. 构建暴露变更:
712c32dcb712该提交将
riscv32clc.o从 linked bitcode 直接 codegen:它的 commit message 已明确说明影响:
这正是当前问题的主要暴露条件。
3. 使 linked bitcode 继续向后暴露的次级变更:同一提交中的 FCVT pattern
712c32dcb712还增加了:这让当前分支越过了
main上 linked bitcode 编译会先遇到的Cannot select RISCVISD::FCVT_X。4. 日志可见变更:
518173e25cb6该提交修改了
RISCVInstrInfo::copyPhysReg(),新增了:因此当前分支会明确打印 dst/src,例如:
main同一位置没有这条errs(),只有llvm_unreachable("Impossible reg-to-reg copy")。因此可以确认518173e25cb6让这类 impossible copy 的 dst/src 日志变得可见。该提交本身还包含其他后端改动;若要严格证明它没有影响触发路径,需要进一步逐 commit/bisection 验证。当前判断
分层结论:
不建议的修复方向
不建议:
这些做法会隐藏真正的 SGPR/VGPR 域约束问题。
建议的修复方向
更合理的修复方向是在 ISel / machine pass 层保证 register class 一致性:
已有
VentusFixMixedPHI能处理一部分 mixed PHI,但当前问题说明覆盖面还不完整,特别是 linked libclc 输入下的 soft-float helper、tuple copy、return value copy 或 constant zero lowering 路径仍可能留下非法形态。验证方式
修复后至少验证:
并检查单函数 MIR:
install/bin/llvm-extract --func=__divdf3 \ build-libclc/builtins.link.riscv32--.bc \ -o divdf3.fixed.bc install/bin/llc \ -mtriple=riscv32 -mcpu=ventus-gpgpu \ -stop-after=amdgpu-isel \ divdf3.fixed.bc \ -o divdf3.after-isel.fixed.mir rg -n "%[0-9]+:gpr = COPY %[0-9]+|%[0-9]+:gpr = COPY %[0-9]+:vgpr" \ divdf3.after-isel.fixed.mir更稳妥的验证方式是新增 MachineFunction verifier,根据
MachineRegisterInfo查询 src/dst register class,而不是依赖文本 grep。附件:更多相关讨论总结
dialogue-summary.md