Since XTheadvector does not support vsetivli, vl needs to be put into
registers during the expand phase.

        PR 116593

gcc/ChangeLog:

        * config/riscv/riscv-vector-builtins.cc 
(function_expander::add_input_operand):
        Put const to GPR for vl.
        * config/riscv/thead-vector.md (@th_pred_vl_mov<mode>): New.

gcc/testsuite/ChangeLog:

        * g++.target/riscv/xtheadvector/pr116593.C: New test.
        * g++.target/riscv/xtheadvector/xtheadvector.exp: New test.

Reported-by: nihui <shuizhuyuan...@gmail.com>
---
 gcc/config/riscv/riscv-vector-builtins.cc     | 18 +++++++-
 gcc/config/riscv/thead-vector.md              | 13 ++++++
 .../g++.target/riscv/xtheadvector/pr116593.C  | 45 +++++++++++++++++++
 .../riscv/xtheadvector/xtheadvector.exp       | 37 +++++++++++++++
 4 files changed, 112 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.target/riscv/xtheadvector/pr116593.C
 create mode 100644 gcc/testsuite/g++.target/riscv/xtheadvector/xtheadvector.exp

diff --git a/gcc/config/riscv/riscv-vector-builtins.cc 
b/gcc/config/riscv/riscv-vector-builtins.cc
index b9b9d33adab6..cced0461a7bb 100644
--- a/gcc/config/riscv/riscv-vector-builtins.cc
+++ b/gcc/config/riscv/riscv-vector-builtins.cc
@@ -4089,7 +4089,23 @@ function_expander::add_input_operand (unsigned argno)
 {
   tree arg = CALL_EXPR_ARG (exp, argno);
   rtx x = expand_normal (arg);
-  add_input_operand (TYPE_MODE (TREE_TYPE (arg)), x);
+
+  /* Since the parameter vl of XTheadVector does not support
+     immediate numbers, we need to put it in the register
+     in advance.  */
+  if (TARGET_XTHEADVECTOR
+      && CONST_INT_P (x)
+      && base->apply_vl_p ()
+      && argno == (unsigned) (call_expr_nargs (exp) - 1)
+      && x != CONST0_RTX (GET_MODE (x)))
+    {
+      rtx tmp = gen_reg_rtx (word_mode);
+      /* Use UNSPEC to avoid being optimized before vsetvl pass.  */
+      emit_insn (gen_th_pred_vl_mov (word_mode, tmp, x));
+      add_input_operand (TYPE_MODE (TREE_TYPE (arg)), tmp);
+    }
+  else
+    add_input_operand (TYPE_MODE (TREE_TYPE (arg)), x);
 }
 
 /* Since we may normalize vop/vop_tu/vop_m/vop_tumu.. into a single patter.
diff --git a/gcc/config/riscv/thead-vector.md b/gcc/config/riscv/thead-vector.md
index 5fe9ba08c4eb..0e00514c6b2d 100644
--- a/gcc/config/riscv/thead-vector.md
+++ b/gcc/config/riscv/thead-vector.md
@@ -25,6 +25,7 @@ (define_c_enum "unspec" [
   UNSPEC_TH_VSUXW
 
   UNSPEC_TH_VWLDST
+  UNSPEC_TH_VL_MOV
 ])
 
 (define_int_iterator UNSPEC_TH_VLMEM_OP [
@@ -93,6 +94,18 @@ (define_int_iterator UNSPEC_TH_VSXMEM_OP [
 (define_mode_iterator V_VLS_VT [V VLS VT])
 (define_mode_iterator V_VB_VLS_VT [V VB VLS VT])
 
+(define_insn_and_split "@th_pred_vl_mov<mode>"
+  [(set (match_operand:P 0 "register_operand"    "=r")
+       (unspec:P
+         [(match_operand:P 1 "const_int_operand" " i")]
+       UNSPEC_TH_VL_MOV))]
+  "TARGET_XTHEADVECTOR"
+  "li\t%0,%1"
+  "&& epilogue_completed"
+  [(set (match_dup 0) (match_dup 1))]
+  {}
+  [(set_attr "type" "arith")])
+
 (define_split
   [(set (match_operand:V_VB_VLS_VT 0 "reg_or_mem_operand")
        (match_operand:V_VB_VLS_VT 1 "reg_or_mem_operand"))]
diff --git a/gcc/testsuite/g++.target/riscv/xtheadvector/pr116593.C 
b/gcc/testsuite/g++.target/riscv/xtheadvector/pr116593.C
new file mode 100644
index 000000000000..e44e7437ad70
--- /dev/null
+++ b/gcc/testsuite/g++.target/riscv/xtheadvector/pr116593.C
@@ -0,0 +1,45 @@
+/* Test that we do not have ice when compile */
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_zfh_xtheadvector -mabi=ilp32d -O2" { target { 
rv32 } } } */
+/* { dg-options "-march=rv64gc_zfh_xtheadvector -mabi=lp64d -O2" { target { 
rv64 } } } */
+
+#include <math.h>
+#include <riscv_vector.h>
+#include <vector>
+
+static vfloat32m8_t atan2_ps(vfloat32m8_t a, vfloat32m8_t b, size_t vl)
+{
+  std::vector<float> tmpx(vl);
+  std::vector<float> tmpy(vl);
+  __riscv_vse32_v_f32m8(tmpx.data(), a, vl);
+  __riscv_vse32_v_f32m8(tmpy.data(), b, vl);
+  for (size_t i = 0; i < vl; i++)
+  {
+    tmpx[i] = atan2(tmpx[i], tmpy[i]);
+  }
+  return __riscv_vle32_v_f32m8(tmpx.data(), vl);
+}
+
+void atan2(const float *x, const float *y, float *out, int size, int ch)
+{
+  for (int i = 0; i < ch; i++)
+  {
+    const float *xx = x + size * i;
+    const float *yy = y + size * i;
+    float *zz = out + size * i;
+
+    int n = size;
+    while (n > 0)
+    {
+      size_t vl = __riscv_vsetvl_e32m8(n);
+      vfloat32m8_t _xx = __riscv_vle32_v_f32m8(xx, vl);
+      vfloat32m8_t _yy = __riscv_vle32_v_f32m8(yy, vl);
+      vfloat32m8_t _zz = atan2_ps(_xx, _yy, vl);
+      __riscv_vse32_v_f32m8(zz, _zz, vl);
+      n -= vl;
+      xx += vl;
+      yy += vl;
+      zz += vl;
+    }
+  }
+}
diff --git a/gcc/testsuite/g++.target/riscv/xtheadvector/xtheadvector.exp 
b/gcc/testsuite/g++.target/riscv/xtheadvector/xtheadvector.exp
new file mode 100644
index 000000000000..551fd9c92670
--- /dev/null
+++ b/gcc/testsuite/g++.target/riscv/xtheadvector/xtheadvector.exp
@@ -0,0 +1,37 @@
+# Copyright (C) 2023-2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Test the front-end for C++.
+# We don't need to test back-end code-gen in RV32 system for C++
+# Because it is already tested in C.
+# Exit immediately if this isn't a RISC-V target.
+if ![istarget riscv*-*-*] then {
+  return
+}
+
+# Load support procs.
+load_lib g++-dg.exp
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C]] "" ""
+
+# All done.
+dg-finish
-- 
2.25.1

Reply via email to