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 <[email protected]>
---
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