]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
RISC-V: Fix ICE and codegen error of scalar move in RV32 system.
authorJuzhe-Zhong <juzhe.zhong@rivai.ai>
Wed, 29 Mar 2023 02:42:59 +0000 (10:42 +0800)
committerKito Cheng <kito.cheng@sifive.com>
Sun, 2 Apr 2023 08:27:32 +0000 (16:27 +0800)
We need to reset the AVL to 0 or 1 for scalar move for RV32 system,
For any non-zero AVL input, we set that to 1, and zero will keep as zero.

We are using wrong way (by andi with 1) before to achieve that, and it
will cause ICE with const_int, and also wrong behavior, so now we have
two code path, one for const_int and one for non-const_int.

bug.C:144:2: error: unrecognizable insn:
  144 |  }
      |  ^
(insn 684 683 685 26 (set (reg:SI 513)
        (and:SI (const_int 4 [0x4])
            (const_int 1 [0x1]))) "bug.C":115:47 -1
     (nil))

andi a4,a4,1 ===> sgtu a4,a4,zero
vsetlvi tu        vsetvli tu
vlse              vlse

gcc/ChangeLog:

* config/riscv/riscv-protos.h (gen_avl_for_scalar_move): New function.
* config/riscv/riscv-v.cc (gen_avl_for_scalar_move): New function.
* config/riscv/vector.md: Fix scalar move bug.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/rvv/base/scalar_move-6.c: Adapt test.
* gcc.target/riscv/rvv/base/scalar_move-9.c: New test.

gcc/config/riscv/riscv-protos.h
gcc/config/riscv/riscv-v.cc
gcc/config/riscv/vector.md
gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-6.c
gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-9.c [new file with mode: 0644]

index e41f65a08941d435544227bce7056760044140e1..4611447dddeb0f7f160678eb5228459f12e5d4d0 100644 (file)
@@ -205,6 +205,7 @@ enum vlen_enum
 };
 bool slide1_sew64_helper (int, machine_mode, machine_mode,
                          machine_mode, rtx *);
+rtx gen_avl_for_scalar_move (rtx);
 }
 
 /* We classify builtin types into two classes:
index d7b77fd61238a738a01d8a604315e3a01dd575dc..2e91d019f6cd8b7619d3e73bf15b7592d609934c 100644 (file)
@@ -701,4 +701,27 @@ slide1_sew64_helper (int unspec, machine_mode mode, machine_mode demote_mode,
   return true;
 }
 
+rtx
+gen_avl_for_scalar_move (rtx avl)
+{
+  /* AVL for scalar move has different behavior between 0 and large than 0.  */
+  if (CONST_INT_P (avl))
+    {
+      /* So we could just set AVL to 1 for any constant other than 0.  */
+      if (rtx_equal_p (avl, const0_rtx))
+       return const0_rtx;
+      else
+       return const1_rtx;
+    }
+  else
+    {
+      /* For non-constant value, we set any non zero value to 1 by
+        `sgtu new_avl,input_avl,zero` + `vsetvli`.  */
+      rtx tmp = gen_reg_rtx (Pmode);
+      emit_insn (
+       gen_rtx_SET (tmp, gen_rtx_fmt_ee (GTU, Pmode, avl, const0_rtx)));
+      return tmp;
+    }
+}
+
 } // namespace riscv_vector
index 1ddc1d3fd390a967239b26e5c19d78841d0e298f..89927c33a017052ecf3b02a33b4fd683d126ac46 100644 (file)
           else if (GET_MODE_BITSIZE (<VEL>mode) > GET_MODE_BITSIZE (Pmode))
             {
              // Case 2: vmv.s.x (TU) ==> andi vl + vlse.v (TU) in RV32 system.
-             rtx tmp = gen_reg_rtx (Pmode);
-              emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (Pmode, operands[4], const1_rtx)));
-             operands[4] = tmp;
+             operands[4] = riscv_vector::gen_avl_for_scalar_move (operands[4]);
              operands[1] = CONSTM1_RTX (<VM>mode);
            }
           else
        vlse64.v  */
     if (satisfies_constraint_Wb1 (operands[1]))
       {
-       rtx tmp = gen_reg_rtx (Pmode);
-        emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (Pmode, operands[4], const1_rtx)));
-        operands[4] = tmp;
+       operands[4] = riscv_vector::gen_avl_for_scalar_move (operands[4]);
        operands[1] = CONSTM1_RTX (<VM>mode);
       }
   }
index 268ddd7c1164f533c4f16228a5739dcb566bb224..f27f85cdb5866563d129d6db61e25d9bb71f9b7a 100644 (file)
@@ -37,8 +37,6 @@ void foo2 (void *base, void *out, size_t vl)
 /*
 ** foo3:
 ** ...
-** andi\t[a-x0-9]+,\s*[a-x0-9]+,\s*1
-** ...
 ** vlse64.v\tv[0-9]+,0\([a-x0-9]+\),zero
 ** ...
 ** ret
@@ -54,8 +52,6 @@ void foo3 (void *base, void *out, size_t vl)
 /*
 ** foo4:
 ** ...
-** andi\t[a-x0-9]+,\s*[a-x0-9]+,\s*1
-** ...
 ** vlse64.v\tv[0-9]+,0\([a-x0-9]+\),zero
 ** ...
 ** ret
@@ -137,8 +133,6 @@ void foo9 (void *base, void *out, size_t vl)
 /*
 ** foo10:
 ** ...
-** andi\t[a-x0-9]+,\s*[a-x0-9]+,\s*1
-** ...
 ** vmv.v.i\tv[0-9]+,\s*-15
 ** ...
 */
@@ -167,8 +161,6 @@ void foo11 (void *base, void *out, size_t vl)
 /*
 ** foo12:
 ** ...
-** andi\t[a-x0-9]+,\s*[a-x0-9]+,\s*1
-** ...
 ** vmv.v.i\tv[0-9]+,\s*0
 ** ...
 ** ret
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-9.c b/gcc/testsuite/gcc.target/riscv/rvv/base/scalar_move-9.c
new file mode 100644 (file)
index 0000000..80ee1b5
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gcv -mabi=ilp32d -fno-schedule-insns -fno-schedule-insns2 -O3" } */
+
+#include "riscv_vector.h"
+
+vuint64m2_t f1(vuint64m2_t var_17, uint64_t var_60)
+{
+  vuint64m2_t var_16 = __riscv_vmv_s_x_u64m2_tu(var_17,var_60, 0);
+  return var_16;
+}
+
+vuint64m2_t f2(vuint64m2_t var_17, uint64_t var_60)
+{
+  vuint64m2_t var_16 = __riscv_vmv_s_x_u64m2_tu(var_17,var_60, 4);
+  return var_16;
+}
+
+vuint64m2_t f3(vuint64m2_t var_17, uint64_t var_60, size_t vl)
+{
+  vuint64m2_t var_16 = __riscv_vmv_s_x_u64m2_tu(var_17,var_60, vl);
+  return var_16;
+}
+
+/* { dg-final { scan-assembler-times {vsetivli\s+zero,\s*0,\s*e64,\s*m2,\s*t[au],\s*m[au]} 1 } } */
+/* { dg-final { scan-assembler-times {vsetivli\s+zero,\s*1,\s*e64,\s*m2,\s*t[au],\s*m[au]} 1 } } */
+/* { dg-final { scan-assembler-times {sgtu} 1 } } */