https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115795
Bug ID: 115795
Summary: RISC-V: vsetvl step causes wrong codegen after fusing
info
Product: gcc
Version: 15.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: jordi.sala at semidynamics dot com
Target Milestone: ---
godbolt: https://godbolt.org/z/9Mf5caEzW
compile option: -march=rv64gv -O1
testcase:
#include <riscv_vector.h>
void foo(int * from, int * to, size_t size) {
size_t vl = __riscv_vsetvl_e32m8(size);
vint32m8_t val = __riscv_vle32_v_i32m8(from, vl);
__riscv_vse32_v_i32m8(to, val, vl);
}
resulting assembly:
foo:
vsetvli a2,a2,e8,m2,ta,ma
vle32.v v8,0(a0)
vse32.v v8,0(a1)
ret
LMUL and SEW of vset vli are not matching the one specified by the intrinsic
__riscv_vle32_v_i32m8. This issue started happening after gcc 14.1.0
After some investigation I've seen that the vsetvl rtl step is fusing a vsetvl
e8,m2 with a vsetvl e32,m8
Logs from vsetvl step
...
Try fuse basic block 2
Ignore curr info since prev info available with it:
prev_info: VALID (insn 29, bb 2)
Demand fields: demand_ratio_only demand_avl
SEW=8, VLMUL=m2, RATIO=4, MAX_SEW=64
TAIL_POLICY=agnostic, MASK_POLICY=agnostic
AVL=(reg:DI 12 a2 [141])
VL=(reg/v:DI 12 a2 [orig:134 vlD.129141 ] [134])
curr_info: VALID (insn 12, bb 2)
Demand fields: demand_ratio_only demand_avl
SEW=32, VLMUL=m8, RATIO=4, MAX_SEW=64
TAIL_POLICY=agnostic, MASK_POLICY=agnostic
AVL=(reg/v:DI 12 a2 [orig:134 vlD.129141 ] [134])
VL=(nil)
...
Fused global info result (lift 0):
Forbidden lift up vsetvl info into bb 0 since there is no vsetvl info
that reaching in is compatible with it:VALID (insn 29, bb 2)
Demand fields: demand_ratio_only demand_avl
SEW=8, VLMUL=m2, RATIO=4, MAX_SEW=64
TAIL_POLICY=agnostic, MASK_POLICY=agnostic
AVL=(reg:DI 12 a2 [141])
VL=(reg/v:DI 12 a2 [orig:134 vlD.129141 ] [134])
curr_info only demands avl and ratio which is shared with prev_info thus it
only uses prev_info for that bb, losing the SEW and LMUL information of the
__riscv_vle32_v_i32m8 intrinsic.
with this bb info it generates the wrong vsetvli.
after applying the following patch
--- a/gcc/config/riscv/riscv-vsetvl.cc
+++ b/gcc/config/riscv/riscv-vsetvl.cc
@@ -1089,23 +1089,17 @@ public:
dflags |= demand_flags::DEMAND_AVL_P;
}
- if (get_attr_ratio (insn->rtl ()) != INVALID_ATTRIBUTE)
- dflags |= demand_flags::DEMAND_RATIO_P;
- else
- {
- if (scalar_move_insn_p (insn->rtl ()) && m_ta)
- {
- dflags |= demand_flags::DEMAND_GE_SEW_P;
- m_max_sew = get_attr_type (insn->rtl ()) == TYPE_VFMOVFV
+ if (scalar_move_insn_p (insn->rtl ()) && m_ta)
+ {
+ dflags |= demand_flags::DEMAND_GE_SEW_P;
+ m_max_sew = get_attr_type (insn->rtl ()) == TYPE_VFMOVFV
? get_max_float_sew ()
: get_max_int_sew ();
- }
- else
- dflags |= demand_flags::DEMAND_SEW_P;
-
- if (!ignore_vlmul_insn_p (insn->rtl ()))
- dflags |= demand_flags::DEMAND_LMUL_P;
- }
+ }
+ else
+ dflags |= demand_flags::DEMAND_SEW_P;
it removes the demand_ratio from non config vector instructions and instead
demands on LMUL and/or SEW, I get the following
resulting assembly:
foo:
vsetvli zero,a2,e32,m8,ta,ma # now using right SEW & LMUL
vle32.v v8,0(a0)
vse32.v v8,0(a1)
ret
Logs from vsetvl step
...
Try fuse basic block 2
Fuse curr info since prev info compatible with it:
prev_info: VALID (insn 27, bb 2)
Demand fields: demand_ratio_only demand_avl
SEW=8, VLMUL=m2, RATIO=4, MAX_SEW=64
TAIL_POLICY=agnostic, MASK_POLICY=agnostic
AVL=(reg:DI 12 a2 [141])
VL=(reg/v:DI 12 a2 [orig:134 vlD.129134 ] [134])
curr_info: VALID (insn 9, bb 2)
Demand fields: demand_sew_lmul demand_avl
SEW=32, VLMUL=m8, RATIO=4, MAX_SEW=64
TAIL_POLICY=agnostic, MASK_POLICY=agnostic
AVL=(reg/v:DI 12 a2 [orig:134 vlD.129134 ] [134])
VL=(nil)
prev_info after fused: VALID (insn 27, bb 2)
Demand fields: demand_sew_lmul demand_avl
SEW=32, VLMUL=m8, RATIO=4, MAX_SEW=64
TAIL_POLICY=agnostic, MASK_POLICY=agnostic
AVL=(reg:DI 12 a2 [141])
VL=(reg/v:DI 12 a2 [orig:134 vlD.129134 ] [134])
...
Fused global info result (lift 0):
Forbidden lift up vsetvl info into bb 0 since there is no vsetvl info
that reaching in is compatible with it:VALID (insn 27, bb 2)
Demand fields: demand_sew_lmul demand_avl
SEW=32, VLMUL=m8, RATIO=4, MAX_SEW=64
TAIL_POLICY=agnostic, MASK_POLICY=agnostic
AVL=(reg:DI 12 a2 [141])
VL=(reg/v:DI 12 a2 [orig:134 vlD.129134 ] [134])
Now the bb information seems to be all right
Problem is that after this change and doing contrib/compare_tests I get the
following:
Tests that now fail, but worked before (1043 tests):
gcc: gcc.dg/vect/costmodel/riscv/rvv/pr111317.c scan-assembler-times vsetvli 1
gcc: gcc.dg/vect/costmodel/riscv/rvv/pr111317.c scan-assembler-times
vsetvli\\s+[a-x0-9]+,\\s*[a-x0-9]+,\\s*e16,\\s*m1,\\s*t[au],\\s*m[au] 1
gcc: gcc.target/riscv/rvv/autovec/partial/slp-1.c scan-assembler \\tvand
gcc: gcc.target/riscv/rvv/autovec/partial/slp-1.c scan-assembler \\tvand
...
I'm assuming more things need to be changed but let me know if you guys think
this is a vsetvl pass bug or not