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

Reply via email to