https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123806
--- Comment #7 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Robin Dapp <[email protected]>: https://gcc.gnu.org/g:6a1578c1f6745b8b6cc09f83d26ac1333786e6a1 commit r16-7149-g6a1578c1f6745b8b6cc09f83d26ac1333786e6a1 Author: Robin Dapp <[email protected]> Date: Mon Jan 26 15:24:10 2026 +0100 RISC-V: Handle VL-setting FoF loads. [PR123806] For PR122869 I thought I fixed the issue of VL-spills clobbering explicit VL reads after fault-only-first (FoF) loads but it turns out the fix is insufficient. Even though it avoided the original issue, we can still have spills that clobber VL before the read_vl RTL pattern. That's mostly due to us hiding the VL data flow from the optimizers so a regular spill to memory can and will introduce a VL clobber. In vsetvl we catch all the regular cases but not the FoF-load case of PR123806 and PR122869. This patch adds specific FoF patterns that emit the same instruction but have a register-setting VL pattern inside the insn's PARALLEL. It serves as a marker for the vsetvl pass that can recognize that we clobber VL before reading its value. In that case we now emit an explicit csrr ..,vl. After vsetvl it's safe to emit the read_vls because at that point the VL dataflow has been established and we can be sure to not clobber VL anymore. Thus, the main changes are: - Unify read_vl si and di and make it an UNSPEC. We don't optimize it anyway so a unified one is easier to include in the new FoF VL-setter variants. - Introduce VL-setting variants of FoF loads and handle them like read_vl()s in the vsetvl pass. - Emit read_vl()s after vsetvl insertion is done. What this doesn't get rid of is the XFAIL in ff-load-3.c that I introduced for PR122869. The code is still "good" at -O1 and "bad" at -O2 upwards. PR target/123806 gcc/ChangeLog: * config/riscv/riscv-string.cc (expand_rawmemchr): Use unified vl_read. (expand_strcmp): Ditto. * config/riscv/riscv-vector-builtins-bases.cc: * config/riscv/riscv-vector-builtins.cc (function_expander::use_fof_load_insn): Only emit the store and not the VL read. * config/riscv/riscv-vsetvl.cc (get_fof_set_vl_reg): New function. (init_rtl_ssa): New wrapper. (finish_rtl_ssa): Ditto. (emit_fof_read_vls): Emit read_vl after each fault-only-first load. (pass_vsetvl::simple_vsetvl): Call emit_fof_read_vls (). (pass_vsetvl::lazy_vsetvl): Ditto. * config/riscv/vector-iterators.md: Add read_vl unspec. * config/riscv/vector.md (read_vlsi): Unify. (@read_vl<mode>): Ditto. (read_vldi_zero_extend): Ditto. (@pred_fault_load_set_vl<V_VLS:mode><P:mode>): New FoF variant that saves VL in a register. (@pred_fault_load_set_vl<VT:mode><P:mode>): Ditto. gcc/testsuite/ChangeLog: * g++.target/riscv/rvv/base/pr123806.C: New test. * g++.target/riscv/rvv/base/pr123808.C: New test. * g++.target/riscv/rvv/base/pr123808-2.C: New test.
