]> git.ipfire.org Git - thirdparty/gcc.git/commit
RISC-V: Consider uses for vsetvl LCM transparency. [PR122448]
authorRobin Dapp <rdapp@oss.qualcomm.com>
Thu, 19 Feb 2026 14:44:38 +0000 (15:44 +0100)
committerRobin Dapp <rdapp@oss.qualcomm.com>
Thu, 26 Feb 2026 14:26:38 +0000 (15:26 +0100)
commit0635bfb53a145cc005a15657635abf8ea9e6e9ba
treef0cf2f06f386466d034a70e9177563474dd3b8a3
parent9c7141fbd9f2b61ed685068803c73ed5596daec9
RISC-V: Consider uses for vsetvl LCM transparency. [PR122448]

Until now we didn't consider (pre-existing) uses of vsetvl's destination
registers when computing transparency for vsetvl LCM.  In rare instances,
this can lead to hoisting vsetvls beyond blocks that have uses on such
registers.

We already check transparency when hoisting but here LCM computes edge
insertion points.

For vsetvl a5,zero,e16,m1 in BB 65 we have the following, not
particularly uncommon, situation:

                BB 63
                 |  \
                 |   \
 |    \
 v     |
BB 64  |
                 |     |
 |    /
 |   /
 | /
 v
BB 65

BB 64 uses a5, so is not transparent with respect to the vsetvl.
BB 63 -> BB 65 is an edge LCM computes as earliest.
But we're not inserting the vsetvl on just that edge like in regular LCM
where we could have a new block along that edge but instead insert it at
the end of BB 63.  At that point, though, the other outgoing edges and
successor blocks have to be considered as well.

The patch is two-fold.  It adds a new bitmap m_reg_use_loc that keeps
track of uses of vsetvl destinations, rather than just new definitions
and adds them to the transparency bitmap.  This correct LCM's
computations with respect to uses.  Then, as described above, it
prevents hoisting into the target block (BB 63) if the vsetvl's
destination register is used outside of vsetvls in any other
successor (BB 64).

In regular, non-speculating LCM we would be able to just check ANTOUT but
as we are hoisting speculatively this won't work.  We don't require all
successors to have a vsetvl in order to hoist it to a block.
Therefore the patch computes reaching definitions for all vsetvl's
destination registers up to their AVL uses.  Knowing a block's live-in
and the reaching definitions we can deduce that a use must be non-vsetvl
and prone to clobbering.

PR target/122448

gcc/ChangeLog:

* config/riscv/riscv-vsetvl.cc (compute_reaching_defintion):
Rename...
(compute_reaching_definition): ...To this.
(pre_vsetvl::compute_vsetvl_def_data):  Compute reaching
definitions for vsetvl VL -> vsetvl AVL.
(pre_vsetvl::compute_transparent): Include VL uses.
(pre_vsetvl::fuse_local_vsetvl_info): Initialize m_reg_use_loc.
(pre_vsetvl::earliest_fuse_vsetvl_info): Don't hoist if any
successor would use VL.

gcc/testsuite/ChangeLog:

* g++.target/riscv/rvv/base/pr122448.C: New test.
gcc/config/riscv/riscv-vsetvl.cc
gcc/testsuite/g++.target/riscv/rvv/base/pr122448.C [new file with mode: 0644]