[PATCH v2] RISC-V: convert the mulh with 0 to mov 0 to the reg.

2023-07-28 Thread yanzhang.wang--- via Gcc-patches
From: Yanzhang Wang 

This patch will optimize the below mulh example,

vint32m1_t shortcut_for_riscv_vmulh_case_0(vint32m1_t v1, size_t vl) {
  return __riscv_vmulh_vx_i32m1(v1, 0, vl);
}

from mulh pattern

vsetvli   zero, a2, e32, m1, ta, ma
vmulh.vx  v24, v24, zero
vs1r.vv24, 0(a0)

to below vmv.

vsetvli zero,a2,e32,m1,ta,ma
vmv.v.i v1,0
vs1r.v  v1,0(a0)

It will elimate the mul with const 0 instruction to the simple mov
instruction.

Signed-off-by: Yanzhang Wang 

gcc/ChangeLog:

* config/riscv/autovec-opt.md: Add a split pattern.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/rvv/base/binop_vx_constraint-121.c: The mul
  with 0 will be simplified to vmv.v.i.
* gcc.target/riscv/rvv/autovec/vmulh-with-zero.cc: New test.
---
 gcc/config/riscv/autovec-opt.md   | 58 +++
 gcc/config/riscv/riscv-protos.h   |  2 +
 gcc/config/riscv/riscv-v.cc   | 57 ++
 .../riscv/rvv/autovec/vmulh-with-zero.cc  | 19 ++
 .../riscv/rvv/base/binop_vx_constraint-121.c  |  3 +-
 5 files changed, 138 insertions(+), 1 deletion(-)
 create mode 100644 
gcc/testsuite/gcc.target/riscv/rvv/autovec/vmulh-with-zero.cc

diff --git a/gcc/config/riscv/autovec-opt.md b/gcc/config/riscv/autovec-opt.md
index 28040805b23..0d87572d1a4 100644
--- a/gcc/config/riscv/autovec-opt.md
+++ b/gcc/config/riscv/autovec-opt.md
@@ -405,3 +405,61 @@
   "vmv.x.s\t%0,%1"
   [(set_attr "type" "vimovvx")
(set_attr "mode" "")])
+
+;;; Simplify the mulh with 0 to move
+(define_split
+  [(set (match_operand:VI_QHS 0 "register_operand")
+ (if_then_else:VI_QHS
+   (unspec:
+[(match_operand: 1 "vector_all_trues_mask_operand")
+  (match_operand 5 "vector_length_operand")
+  (match_operand 6 "const_int_operand")
+  (match_operand 7 "const_int_operand")
+  (match_operand 8 "const_int_operand")
+  (reg:SI VL_REGNUM)
+  (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+   (unspec:VI_QHS
+[(vec_duplicate:VI_QHS
+   (match_operand: 4 "reg_or_0_operand"))
+  (match_operand:VI_QHS 3 "register_operand")] VMULH)
+   (match_operand:VI_QHS 2 "vector_merge_operand")
+   ))]
+  "TARGET_VECTOR
+ && rtx_equal_p (operands[4], CONST0_RTX (GET_MODE (operands[4])))"
+  [(const_int 0)]
+{
+  riscv_vector::simplify_unspec_operations (operands, UNSPEC,
+, mode) ;
+  DONE;
+})
+
+;;; Simplify vmadc + vadc with 0 to a simple move.
+(define_split
+  [(set (match_operand:VI 0 "register_operand")
+ (if_then_else:VI
+   (unspec:
+[(match_operand 4 "vector_length_operand")
+  (match_operand 5 "const_int_operand")
+  (match_operand 6 "const_int_operand")
+  (reg:SI VL_REGNUM)
+  (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+   (unspec:VI
+[(match_operand:VI 2 "register_operand")
+  (unspec:
+[(match_operand:VI 3 "register_operand")
+  (unspec:
+[(match_operand 7 "vector_length_operand")
+  (match_operand 8 "const_int_operand")
+  (reg:SI VL_REGNUM)
+  (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+  ] UNSPEC_OVERFLOW)
+  ] UNSPEC_VADC)
+   (match_operand:VI 1 "vector_merge_operand")))]
+  "TARGET_VECTOR"
+  [(const_int 0)]
+{
+  riscv_vector::simplify_unspec_operations (operands, PLUS, UNSPEC_VADC,
+   mode);
+  DONE;
+})
+
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index f052757cede..6a188a3d0ef 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -228,6 +228,8 @@ bool neg_simm5_p (rtx);
 bool has_vi_variant_p (rtx_code, rtx);
 void expand_vec_cmp (rtx, rtx_code, rtx, rtx);
 bool expand_vec_cmp_float (rtx, rtx_code, rtx, rtx, bool);
+void simplify_complement (rtx *, rtx_code, machine_mode);
+void simplify_unspec_operations (rtx*, rtx_code, int, machine_mode);
 #endif
 bool sew64_scalar_helper (rtx *, rtx *, rtx, machine_mode,
  bool, void (*)(rtx *, rtx));
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 839a2c6ba71..9a9428ce18d 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -2721,4 +2721,61 @@ expand_select_vl (rtx *ops)
   emit_insn (gen_no_side_effects_vsetvl_rtx (rvv_mode, ops[0], ops[1]));
 }
 
+void simplify_mulh (rtx *operands,
+   machine_mode mode)
+{
+  rtx zero_operand = CONST0_RTX(GET_MODE(operands[4]));
+  if (rtx_equal_p(operands[4], zero_operand))
+{
+  machine_mode mask_mode = riscv_vector::get_mask_mode (mode).require ();
+  emit_insn (gen_pred_mov (mode, operands[0], CONST1_RTX (mask_mode),
+  RVV_VUNDEF (mode),
+  CONST0_RTX (GET_MODE (operands[0])),
+  ope

[PATCH] RISC-V: Support simplify (-1-x) for vector.

2023-08-16 Thread yanzhang.wang--- via Gcc-patches
From: Yanzhang Wang 

The pattern is enabled for scalar but not for vector. The patch try to
make it consistent and will convert below code,

shortcut_for_riscv_vrsub_case_1_32:
vl1re32.v   v1,0(a1)
vsetvli zero,a2,e32,m1,ta,ma
vrsub.viv1,v1,-1
vs1r.v  v1,0(a0)
ret

to,

shortcut_for_riscv_vrsub_case_1_32:
vl1re32.v   v1,0(a1)
vsetvli zero,a2,e32,m1,ta,ma
vnot.v  v1,v1
vs1r.v  v1,0(a0)
ret

gcc/ChangeLog:

* simplify-rtx.cc (simplify_context::simplify_binary_operation_1):
Get -1 with mode.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/rvv/base/simplify-vrsub.c: New test.

Signed-off-by: Yanzhang Wang 
---
 gcc/simplify-rtx.cc|  2 +-
 .../gcc.target/riscv/rvv/base/simplify-vrsub.c | 18 ++
 2 files changed, 19 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/simplify-vrsub.c

diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc
index d7315d82aa3..eb1ac120832 100644
--- a/gcc/simplify-rtx.cc
+++ b/gcc/simplify-rtx.cc
@@ -3071,7 +3071,7 @@ simplify_context::simplify_binary_operation_1 (rtx_code 
code,
   /* (-1 - a) is ~a, unless the expression contains symbolic
 constants, in which case not retaining additions and
 subtractions could cause invalid assembly to be produced.  */
-  if (trueop0 == constm1_rtx
+  if (trueop0 == CONSTM1_RTX (mode)
  && !contains_symbolic_reference_p (op1))
return simplify_gen_unary (NOT, mode, op1, mode);
 
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/simplify-vrsub.c 
b/gcc/testsuite/gcc.target/riscv/rvv/base/simplify-vrsub.c
new file mode 100644
index 000..df87ed94ea4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/simplify-vrsub.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+#define VRSUB_WITH_LMUL(LMUL, DTYPE)\
+  vint##DTYPE##m##LMUL##_t  \
+  shortcut_for_riscv_vrsub_case_##LMUL##_##DTYPE\
+  (vint##DTYPE##m##LMUL##_t v1, \
+   size_t vl)   \
+  { \
+return __riscv_vrsub_vx_i##DTYPE##m##LMUL (v1, -1, vl); \
+  }
+
+VRSUB_WITH_LMUL (1, 16)
+VRSUB_WITH_LMUL (1, 32)
+
+/* { dg-final { scan-assembler-times {vnot\.v} 2 } } */
-- 
2.41.0



[PATCH] Bug 111071: fix the subr with -1 to not due to the simplify.

2023-08-29 Thread yanzhang.wang--- via Gcc-patches
From: Yanzhang Wang 

gcc/testsuite/ChangeLog:

* gcc.target/aarch64/sve/acle/asm/subr_s8.c: Modify subr with -1
to not.

Signed-off-by: Yanzhang Wang 
---

Tested on my local arm environment and passed. Thanks Andrew Pinski's comment
the code is the same with that.

 gcc/testsuite/gcc.target/aarch64/sve/acle/asm/subr_s8.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/subr_s8.c 
b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/subr_s8.c
index b9615de6655..1cf6916a5e0 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/subr_s8.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/subr_s8.c
@@ -76,8 +76,7 @@ TEST_UNIFORM_Z (subr_1_s8_m_untied, svint8_t,
 
 /*
 ** subr_m1_s8_m:
-** mov (z[0-9]+\.b), #-1
-** subrz0\.b, p0/m, z0\.b, \1
+** not z0.b, p0/m, z0.b
 ** ret
 */
 TEST_UNIFORM_Z (subr_m1_s8_m, svint8_t,
-- 
2.41.0



[PATCH v4] RISC-V: Add vector psabi checking.

2023-06-08 Thread yanzhang.wang--- via Gcc-patches
From: Yanzhang Wang 

This patch adds support to check function's argument or return is vector type
and throw warning if yes.

There're two exceptions,
  - The vector_size attribute.
  - The intrinsic functions.

gcc/ChangeLog:

* config/riscv/riscv-protos.h (riscv_init_cumulative_args): Set
  warning flag if func is not builtin
* config/riscv/riscv.cc
(riscv_scalable_vector_type_p): Determine whether the type is scalable 
vector.
(riscv_arg_has_vector): Determine whether the arg is vector type.
(riscv_pass_in_vector_p): Check the vector type param is passed by 
value.
(riscv_init_cumulative_args): The same as header.
(riscv_get_arg_info): Add the checking.
(riscv_function_value): Check the func return and set warning flag
* config/riscv/riscv.h (INIT_CUMULATIVE_ARGS): Add a flag to
  determine whether warning psabi or not.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/vector-abi-1.c: New test.
* gcc.target/riscv/vector-abi-2.c: New test.
* gcc.target/riscv/vector-abi-3.c: New test.
* gcc.target/riscv/vector-abi-4.c: New test.
* gcc.target/riscv/vector-abi-5.c: New test.
* gcc.target/riscv/vector-abi-6.c: New test.

Signed-off-by: Yanzhang Wang 
Co-authored-by: Kito Cheng 
---
 gcc/config/riscv/riscv-protos.h   |   2 +
 gcc/config/riscv/riscv.cc | 112 +-
 gcc/config/riscv/riscv.h  |   5 +-
 gcc/testsuite/gcc.target/riscv/vector-abi-1.c |  14 +++
 gcc/testsuite/gcc.target/riscv/vector-abi-2.c |  15 +++
 gcc/testsuite/gcc.target/riscv/vector-abi-3.c |  14 +++
 gcc/testsuite/gcc.target/riscv/vector-abi-4.c |  16 +++
 gcc/testsuite/gcc.target/riscv/vector-abi-5.c |  15 +++
 gcc/testsuite/gcc.target/riscv/vector-abi-6.c |  20 
 9 files changed, 211 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-4.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-5.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-6.c

diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index e41f65a0894..d8f42778565 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -235,4 +235,6 @@ extern const char*
 th_mempair_output_move (rtx[4], bool, machine_mode, RTX_CODE);
 #endif
 
+void riscv_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int);
+
 #endif /* ! GCC_RISCV_PROTOS_H */
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 76eee4a55e9..3286656ecba 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -3728,6 +3728,99 @@ riscv_pass_fpr_pair (machine_mode mode, unsigned regno1,
   GEN_INT (offset2;
 }
 
+/* Use the TYPE_SIZE to distinguish the type with vector_size attribute and
+   intrinsic vector type.  Because we can't get the decl for the params.  */
+
+static bool
+riscv_scalable_vector_type_p (const_tree type)
+{
+  tree size = TYPE_SIZE (type);
+  if (size && TREE_CODE (size) == INTEGER_CST)
+return false;
+
+  /* For the data type like vint32m1_t, the size code is POLY_INT_CST.  */
+  return true;
+}
+
+static bool
+riscv_arg_has_vector (const_tree type)
+{
+  bool is_vector = false;
+
+  switch (TREE_CODE (type))
+{
+case RECORD_TYPE:
+  if (!COMPLETE_TYPE_P (type))
+   break;
+
+  for (tree f = TYPE_FIELDS (type); f; f = DECL_CHAIN (f))
+   if (TREE_CODE (f) == FIELD_DECL)
+ {
+   tree field_type = TREE_TYPE (f);
+   if (!TYPE_P (field_type))
+ break;
+
+   /* Ignore it if it's fixed length vector.  */
+   if (VECTOR_TYPE_P (field_type))
+ is_vector = riscv_scalable_vector_type_p (field_type);
+   else
+ is_vector = riscv_arg_has_vector (field_type);
+ }
+
+  break;
+
+case VECTOR_TYPE:
+  is_vector = riscv_scalable_vector_type_p (type);
+  break;
+
+default:
+  is_vector = false;
+  break;
+}
+
+  return is_vector;
+}
+
+/* Pass the type to check whether it's a vector type or contains vector type.
+   Only check the value type and no checking for vector pointer type.  */
+
+static void
+riscv_pass_in_vector_p (const_tree type)
+{
+  static int warned = 0;
+
+  if (type && riscv_arg_has_vector (type) && !warned)
+{
+  warning (OPT_Wpsabi, "ABI for the scalable vector type is currently in "
+  "experimental stage and may changes in the upcoming version of "
+  "GCC.");
+  warned = 1;
+}
+}
+
+/* Initialize a variable CUM of type CUMULATIVE_ARGS
+   for a call to a function whose data type is FNTYPE.
+   For a library call, FNTYPE

[PATCH v5] RISC-V: Add vector psabi checking.

2023-06-12 Thread yanzhang.wang--- via Gcc-patches
From: Yanzhang Wang 

This patch adds support to check function's argument or return is vector type
and throw warning if yes.

There're two exceptions,
  - The vector_size attribute.
  - The intrinsic functions.

gcc/ChangeLog:

* config/riscv/riscv-protos.h (riscv_init_cumulative_args): Set
  warning flag if func is not builtin
* config/riscv/riscv.cc
(riscv_scalable_vector_type_p): Determine whether the type is scalable 
vector.
(riscv_arg_has_vector): Determine whether the arg is vector type.
(riscv_pass_in_vector_p): Check the vector type param is passed by 
value.
(riscv_init_cumulative_args): The same as header.
(riscv_get_arg_info): Add the checking.
(riscv_function_value): Check the func return and set warning flag
* config/riscv/riscv.h (INIT_CUMULATIVE_ARGS): Add a flag to
  determine whether warning psabi or not.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/rvv/rvv.exp: Add -Wno-psabi
* gcc.target/riscv/vector-abi-1.c: New test.
* gcc.target/riscv/vector-abi-2.c: New test.
* gcc.target/riscv/vector-abi-3.c: New test.
* gcc.target/riscv/vector-abi-4.c: New test.
* gcc.target/riscv/vector-abi-5.c: New test.
* gcc.target/riscv/vector-abi-6.c: New test.

Signed-off-by: Yanzhang Wang 
Co-authored-by: Kito Cheng 
---
 gcc/config/riscv/riscv-protos.h   |   2 +
 gcc/config/riscv/riscv.cc | 112 +-
 gcc/config/riscv/riscv.h  |   5 +-
 gcc/testsuite/gcc.target/riscv/rvv/rvv.exp|   2 +-
 gcc/testsuite/gcc.target/riscv/vector-abi-1.c |  14 +++
 gcc/testsuite/gcc.target/riscv/vector-abi-2.c |  15 +++
 gcc/testsuite/gcc.target/riscv/vector-abi-3.c |  14 +++
 gcc/testsuite/gcc.target/riscv/vector-abi-4.c |  16 +++
 gcc/testsuite/gcc.target/riscv/vector-abi-5.c |  15 +++
 gcc/testsuite/gcc.target/riscv/vector-abi-6.c |  20 
 10 files changed, 212 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-4.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-5.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-6.c

diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 66c1f535d60..90fde5f8be3 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -302,4 +302,6 @@ th_mempair_output_move (rtx[4], bool, machine_mode, 
RTX_CODE);
 #endif
 
 extern bool riscv_use_divmod_expander (void);
+void riscv_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int);
+
 #endif /* ! GCC_RISCV_PROTOS_H */
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index de30bf4e567..dd5361c2bd2 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -3795,6 +3795,99 @@ riscv_pass_fpr_pair (machine_mode mode, unsigned regno1,
   GEN_INT (offset2;
 }
 
+/* Use the TYPE_SIZE to distinguish the type with vector_size attribute and
+   intrinsic vector type.  Because we can't get the decl for the params.  */
+
+static bool
+riscv_scalable_vector_type_p (const_tree type)
+{
+  tree size = TYPE_SIZE (type);
+  if (size && TREE_CODE (size) == INTEGER_CST)
+return false;
+
+  /* For the data type like vint32m1_t, the size code is POLY_INT_CST.  */
+  return true;
+}
+
+static bool
+riscv_arg_has_vector (const_tree type)
+{
+  bool is_vector = false;
+
+  switch (TREE_CODE (type))
+{
+case RECORD_TYPE:
+  if (!COMPLETE_TYPE_P (type))
+   break;
+
+  for (tree f = TYPE_FIELDS (type); f; f = DECL_CHAIN (f))
+   if (TREE_CODE (f) == FIELD_DECL)
+ {
+   tree field_type = TREE_TYPE (f);
+   if (!TYPE_P (field_type))
+ break;
+
+   /* Ignore it if it's fixed length vector.  */
+   if (VECTOR_TYPE_P (field_type))
+ is_vector = riscv_scalable_vector_type_p (field_type);
+   else
+ is_vector = riscv_arg_has_vector (field_type);
+ }
+
+  break;
+
+case VECTOR_TYPE:
+  is_vector = riscv_scalable_vector_type_p (type);
+  break;
+
+default:
+  is_vector = false;
+  break;
+}
+
+  return is_vector;
+}
+
+/* Pass the type to check whether it's a vector type or contains vector type.
+   Only check the value type and no checking for vector pointer type.  */
+
+static void
+riscv_pass_in_vector_p (const_tree type)
+{
+  static int warned = 0;
+
+  if (type && riscv_arg_has_vector (type) && !warned)
+{
+  warning (OPT_Wpsabi, "ABI for the scalable vector type is currently in "
+  "experimental stage and may changes in the upcoming version of "
+  "GCC.");
+  warned = 1;
+}
+}
+

[PATCH v6] RISC-V: Add vector psabi checking.

2023-06-12 Thread yanzhang.wang--- via Gcc-patches
From: Yanzhang Wang 

This patch adds support to check function's argument or return is vector type
and throw warning if yes.

There're two exceptions,
  - The vector_size attribute.
  - The intrinsic functions.

Some cases that need to add -Wno-psabi to ignore the warning.

gcc/ChangeLog:

* config/riscv/riscv-protos.h (riscv_init_cumulative_args): Set
  warning flag if func is not builtin
* config/riscv/riscv.cc
(riscv_scalable_vector_type_p): Determine whether the type is scalable 
vector.
(riscv_arg_has_vector): Determine whether the arg is vector type.
(riscv_pass_in_vector_p): Check the vector type param is passed by 
value.
(riscv_init_cumulative_args): The same as header.
(riscv_get_arg_info): Add the checking.
(riscv_function_value): Check the func return and set warning flag
* config/riscv/riscv.h (INIT_CUMULATIVE_ARGS): Add a flag to
  determine whether warning psabi or not.

gcc/testsuite/ChangeLog:

* g++.target/riscv/rvv/base/pr109244.C: Add the -Wno-psabi.
* g++.target/riscv/rvv/base/pr109535.C: Same
* gcc.target/riscv/rvv/base/binop_vx_constraint-120.c: Same
* gcc.target/riscv/rvv/base/integer_compare_insn_shortcut.c:
  Same
* gcc.target/riscv/rvv/base/mask_insn_shortcut.c: Same
* gcc.target/riscv/rvv/base/misc_vreinterpret_vbool_vint.c: Same
* gcc.target/riscv/rvv/base/pr110109-2.c: Same
* gcc.target/riscv/rvv/base/scalar_move-9.c: Same
* gcc.target/riscv/rvv/base/spill-10.c: Same
* gcc.target/riscv/rvv/base/spill-11.c: Same
* gcc.target/riscv/rvv/base/spill-9.c: Same
* gcc.target/riscv/rvv/base/vlmul_ext-1.c: Same
* gcc.target/riscv/rvv/base/zero_base_load_store_optimization.c:
  Same
* gcc.target/riscv/rvv/base/zvfh-intrinsic.c: Same
* gcc.target/riscv/rvv/base/zvfh-over-zvfhmin.c: Same
* gcc.target/riscv/rvv/base/zvfhmin-intrinsic.c: Same
* gcc.target/riscv/rvv/vsetvl/vsetvl-1.c: Same
* gcc.target/riscv/vector-abi-1.c: New test.
* gcc.target/riscv/vector-abi-2.c: New test.
* gcc.target/riscv/vector-abi-3.c: New test.
* gcc.target/riscv/vector-abi-4.c: New test.
* gcc.target/riscv/vector-abi-5.c: New test.
* gcc.target/riscv/vector-abi-6.c: New test.

Signed-off-by: Yanzhang Wang 
Co-authored-by: Kito Cheng 
---
 gcc/config/riscv/riscv-protos.h   |   2 +
 gcc/config/riscv/riscv.cc | 112 +-
 gcc/config/riscv/riscv.h  |   5 +-
 .../g++.target/riscv/rvv/base/pr109244.C  |   2 +-
 .../g++.target/riscv/rvv/base/pr109535.C  |   2 +-
 .../riscv/rvv/base/binop_vx_constraint-120.c  |   2 +-
 .../rvv/base/integer_compare_insn_shortcut.c  |   2 +-
 .../riscv/rvv/base/mask_insn_shortcut.c   |   2 +-
 .../rvv/base/misc_vreinterpret_vbool_vint.c   |   2 +-
 .../gcc.target/riscv/rvv/base/pr110109-2.c|   2 +-
 .../gcc.target/riscv/rvv/base/scalar_move-9.c |   2 +-
 .../gcc.target/riscv/rvv/base/spill-10.c  |   2 +-
 .../gcc.target/riscv/rvv/base/spill-11.c  |   2 +-
 .../gcc.target/riscv/rvv/base/spill-9.c   |   2 +-
 .../gcc.target/riscv/rvv/base/vlmul_ext-1.c   |   2 +-
 .../base/zero_base_load_store_optimization.c  |   2 +-
 .../riscv/rvv/base/zvfh-intrinsic.c   |   2 +-
 .../riscv/rvv/base/zvfh-over-zvfhmin.c|   2 +-
 .../riscv/rvv/base/zvfhmin-intrinsic.c|   2 +-
 .../gcc.target/riscv/rvv/vsetvl/vsetvl-1.c|   2 +-
 gcc/testsuite/gcc.target/riscv/vector-abi-1.c |  14 +++
 gcc/testsuite/gcc.target/riscv/vector-abi-2.c |  15 +++
 gcc/testsuite/gcc.target/riscv/vector-abi-3.c |  14 +++
 gcc/testsuite/gcc.target/riscv/vector-abi-4.c |  16 +++
 gcc/testsuite/gcc.target/riscv/vector-abi-5.c |  15 +++
 gcc/testsuite/gcc.target/riscv/vector-abi-6.c |  20 
 26 files changed, 228 insertions(+), 19 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-4.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-5.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-6.c

diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 66c1f535d60..90fde5f8be3 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -302,4 +302,6 @@ th_mempair_output_move (rtx[4], bool, machine_mode, 
RTX_CODE);
 #endif
 
 extern bool riscv_use_divmod_expander (void);
+void riscv_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int);
+
 #endif /* ! GCC_RISCV_PROTOS_H */
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index de30bf4e567..dd5361c2bd2 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.

[PATCH] RISC-V: convert the mulh with 0 to mov 0 to the reg.

2023-06-20 Thread yanzhang.wang--- via Gcc-patches
From: Yanzhang Wang 

This patch will optimize the below mulh example,

vint32m1_t shortcut_for_riscv_vmulh_case_0(vint32m1_t v1, size_t vl) {
  return __riscv_vmulh_vx_i32m1(v1, 0, vl);
}

from mulh pattern

vsetvli   zero, a2, e32, m1, ta, ma
vmulh.vx  v24, v24, zero
vs1r.vv24, 0(a0)

to below vmv.

vsetvli zero,a2,e32,m1,ta,ma
vmv.v.i v1,0
vs1r.v  v1,0(a0)

It will elimate the mul with const 0 instruction to the simple mov
instruction.

Signed-off-by: Yanzhang Wang 

gcc/ChangeLog:

* config/riscv/autovec-opt.md: Add a split pattern.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/rvv/base/binop_vx_constraint-121.c: The mul
  with 0 will be simplified to vmv.v.i.
* gcc.target/riscv/rvv/autovec/vmulh-with-zero.cc: New test.
---
 gcc/config/riscv/autovec-opt.md   | 30 +++
 .../riscv/rvv/autovec/vmulh-with-zero.cc  | 19 
 .../riscv/rvv/base/binop_vx_constraint-121.c  |  3 +-
 3 files changed, 51 insertions(+), 1 deletion(-)
 create mode 100644 
gcc/testsuite/gcc.target/riscv/rvv/autovec/vmulh-with-zero.cc

diff --git a/gcc/config/riscv/autovec-opt.md b/gcc/config/riscv/autovec-opt.md
index 28040805b23..9c14be964b5 100644
--- a/gcc/config/riscv/autovec-opt.md
+++ b/gcc/config/riscv/autovec-opt.md
@@ -405,3 +405,33 @@
   "vmv.x.s\t%0,%1"
   [(set_attr "type" "vimovvx")
(set_attr "mode" "")])
+
+;; Simplify VMULH (V, 0) Instructions to vmv.v.i.
+(define_split
+  [(set (match_operand:VI_QHS 0 "register_operand")
+   (if_then_else:VI_QHS
+ (unspec:
+   [(match_operand: 1 "vector_all_trues_mask_operand")
+ (match_operand 5 "vector_length_operand")
+ (match_operand 6 "const_int_operand")
+ (match_operand 7 "const_int_operand")
+ (match_operand 8 "const_int_operand")
+ (reg:SI VL_REGNUM)
+ (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
+ (unspec:VI_QHS
+   [(vec_duplicate:VI_QHS
+  (match_operand: 4 "reg_or_0_operand"))
+ (match_operand:VI_QHS 3 "register_operand")] VMULH)
+ (match_operand:VI_QHS 2 "vector_merge_operand")))]
+  "TARGET_VECTOR
+ && rtx_equal_p (operands[4], CONST0_RTX (GET_MODE (operands[4])))"
+  [(const_int 0)]
+  {
+machine_mode mask_mode = riscv_vector::get_mask_mode (mode)
+  .require ();
+emit_insn (gen_pred_mov (mode, operands[0], CONST1_RTX (mask_mode),
+ RVV_VUNDEF (mode), CONST0_RTX (GET_MODE (operands[0])),
+ operands[5], operands[6], operands[7], operands[8]));
+DONE;
+  }
+)
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vmulh-with-zero.cc 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vmulh-with-zero.cc
new file mode 100644
index 000..6e4a3d62bc0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vmulh-with-zero.cc
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64 -O3 -Wno-psabi" } */
+
+#include "riscv_vector.h"
+
+#define VMULH_WITH_LMUL(X) \
+  vint32m##X##_t shortcut_for_riscv_vmulh_case_##X (vint32m##X##_t v1,\
+size_t vl) {  \
+return __riscv_vmulh_vx_i32m ##X (v1, 0, vl); \
+  }
+
+
+VMULH_WITH_LMUL (1)
+VMULH_WITH_LMUL (2)
+VMULH_WITH_LMUL (4)
+VMULH_WITH_LMUL (8)
+VMULH_WITH_LMUL (f2)
+
+/* { dg-final { scan-assembler-times {vmv\.v\.i\sv[0-9]+,0} 5} */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/binop_vx_constraint-121.c 
b/gcc/testsuite/gcc.target/riscv/rvv/base/binop_vx_constraint-121.c
index 4d2de91bc14..d1473274137 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/base/binop_vx_constraint-121.c
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/binop_vx_constraint-121.c
@@ -50,6 +50,7 @@ void f6 (void * in, void *out, int32_t x)
 __riscv_vse64_v_i64m1 (out, v3, 4);
 }
 
-/* { dg-final { scan-assembler-times {vmulh\.vx\s+v[0-9]+,\s*v[0-9]+,zero} 2 } 
} */
+/* { dg-final { scan-assembler-times {vmv\.v\.i\sv[0-9]+,0} 1 } } */
+/* { dg-final { scan-assembler-times {vmulh\.vx\s+v[0-9]+,\s*v[0-9]+,zero} 1 } 
} */
 /* { dg-final { scan-assembler-times {vdiv\.vx\s+v[0-9]+,\s*v[0-9]+,zero} 2 } 
} */
 /* { dg-final { scan-assembler-times {vrem\.vx\s+v[0-9]+,\s*v[0-9]+,zero} 2 } 
} */
-- 
2.40.1



[PATCH] RISCV: Add -m(no)-omit-leaf-frame-pointer support.

2023-07-12 Thread yanzhang.wang--- via Gcc-patches
From: Yanzhang Wang 

gcc/ChangeLog:

* config/riscv/riscv.cc (riscv_save_reg_p): Save ra for leaf
  when enabling -mno-omit-leaf-frame-pointer
(riscv_option_override): Override omit-frame-pointer.
(riscv_frame_pointer_required): Save s0 for non-leaf function
(TARGET_FRAME_POINTER_REQUIRED): Override defination
* config/riscv/riscv.opt: Add option support.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/omit-frame-pointer-1.c: New test.
* gcc.target/riscv/omit-frame-pointer-2.c: New test.
* gcc.target/riscv/omit-frame-pointer-3.c: New test.
* gcc.target/riscv/omit-frame-pointer-4.c: New test.
* gcc.target/riscv/omit-frame-pointer-test.c: New test.

Signed-off-by: Yanzhang Wang 
---
 gcc/config/riscv/riscv.cc | 34 ++-
 gcc/config/riscv/riscv.opt|  4 +++
 .../gcc.target/riscv/omit-frame-pointer-1.c   |  7 
 .../gcc.target/riscv/omit-frame-pointer-2.c   |  7 
 .../gcc.target/riscv/omit-frame-pointer-3.c   |  7 
 .../gcc.target/riscv/omit-frame-pointer-4.c   |  7 
 .../riscv/omit-frame-pointer-test.c   | 13 +++
 7 files changed, 78 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/omit-frame-pointer-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/omit-frame-pointer-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/omit-frame-pointer-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/omit-frame-pointer-4.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/omit-frame-pointer-test.c

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 706c18416db..caae6168c29 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -379,6 +379,10 @@ static const struct riscv_tune_info 
riscv_tune_info_table[] = {
 #include "riscv-cores.def"
 };
 
+/* Global variable to distinguish whether we should save and restore s0/fp for
+   function.  */
+static bool riscv_save_frame_pointer;
+
 void riscv_frame_info::reset(void)
 {
   total_size = 0;
@@ -4948,7 +4952,11 @@ riscv_save_reg_p (unsigned int regno)
   if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed)
 return true;
 
-  if (regno == RETURN_ADDR_REGNUM && crtl->calls_eh_return)
+  /* Need not to use ra for leaf when frame pointer is turned off by option
+ whatever the omit-leaf-frame's value.  */
+  bool keep_leaf_ra = frame_pointer_needed && crtl->is_leaf
+&& !TARGET_OMIT_LEAF_FRAME_POINTER;
+  if (regno == RETURN_ADDR_REGNUM && (crtl->calls_eh_return || keep_leaf_ra))
 return true;
 
   /* If this is an interrupt handler, then must save extra registers.  */
@@ -6577,6 +6585,21 @@ riscv_option_override (void)
   if (flag_pic)
 riscv_cmodel = CM_PIC;
 
+  /* We need to save the fp with ra for non-leaf functions with no fp and ra
+ for leaf functions while no-omit-frame-pointer with
+ omit-leaf-frame-pointer.  The x_flag_omit_frame_pointer has the first
+ priority to determine whether the frame pointer is needed.  If we do not
+ override it, the fp and ra will be stored for leaf functions, which is not
+ our wanted.  */
+  riscv_save_frame_pointer = false;
+  if (TARGET_OMIT_LEAF_FRAME_POINTER_P (global_options.x_target_flags))
+{
+  if (!global_options.x_flag_omit_frame_pointer)
+   riscv_save_frame_pointer = true;
+
+  global_options.x_flag_omit_frame_pointer = 1;
+}
+
   /* We get better code with explicit relocs for CM_MEDLOW, but
  worse code for the others (for now).  Pick the best default.  */
   if ((target_flags_explicit & MASK_EXPLICIT_RELOCS) == 0)
@@ -7857,6 +7880,12 @@ riscv_preferred_else_value (unsigned, tree, unsigned int 
nops, tree *ops)
   return nops == 3 ? ops[2] : ops[0];
 }
 
+static bool
+riscv_frame_pointer_required (void)
+{
+  return riscv_save_frame_pointer && !crtl->is_leaf;
+}
+
 /* Initialize the GCC target structure.  */
 #undef TARGET_ASM_ALIGNED_HI_OP
 #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
@@ -8161,6 +8190,9 @@ riscv_preferred_else_value (unsigned, tree, unsigned int 
nops, tree *ops)
 #undef TARGET_PREFERRED_ELSE_VALUE
 #define TARGET_PREFERRED_ELSE_VALUE riscv_preferred_else_value
 
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED riscv_frame_pointer_required
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-riscv.h"
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index dd062f1c8bd..8e6a94fd01a 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -138,6 +138,10 @@ Enable the CSR checking for the ISA-dependent CRS and the 
read-only CSR.
 The ISA-dependent CSR are only valid when the specific ISA is set.  The
 read-only CSR can not be written by the CSR instructions.
 
+momit-leaf-frame-pointer
+Target Mask (OMIT_LEAF_FRAME_POINTER) Save
+Omit the frame pointer in leaf functions.
+
 Mask(64BIT)
 
 Mask(MUL)
diff --git a/gcc/te

[PATCH v3] RISCV: Add -m(no)-omit-leaf-frame-pointer support.

2023-07-18 Thread yanzhang.wang--- via Gcc-patches
From: Yanzhang Wang 

gcc/ChangeLog:

* config/riscv/riscv.cc (riscv_save_reg_p): Save ra for leaf
  when enabling -mno-omit-leaf-frame-pointer
(riscv_option_override): Override omit-frame-pointer.
(riscv_frame_pointer_required): Save s0 for non-leaf function
(TARGET_FRAME_POINTER_REQUIRED): Override defination
* config/riscv/riscv.opt: Add option support.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/omit-frame-pointer-1.c: New test.
* gcc.target/riscv/omit-frame-pointer-2.c: New test.
* gcc.target/riscv/omit-frame-pointer-3.c: New test.
* gcc.target/riscv/omit-frame-pointer-4.c: New test.
* gcc.target/riscv/omit-frame-pointer-test.c: New test.

Signed-off-by: Yanzhang Wang 
---
 gcc/config/riscv/riscv.cc | 34 ++-
 gcc/config/riscv/riscv.opt|  4 +++
 .../gcc.target/riscv/omit-frame-pointer-1.c   |  7 
 .../gcc.target/riscv/omit-frame-pointer-2.c   |  7 
 .../gcc.target/riscv/omit-frame-pointer-3.c   |  7 
 .../gcc.target/riscv/omit-frame-pointer-4.c   |  7 
 .../riscv/omit-frame-pointer-test.c   | 13 +++
 7 files changed, 78 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/omit-frame-pointer-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/omit-frame-pointer-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/omit-frame-pointer-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/omit-frame-pointer-4.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/omit-frame-pointer-test.c

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 706c18416db..caae6168c29 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -379,6 +379,10 @@ static const struct riscv_tune_info 
riscv_tune_info_table[] = {
 #include "riscv-cores.def"
 };
 
+/* Global variable to distinguish whether we should save and restore s0/fp for
+   function.  */
+static bool riscv_save_frame_pointer;
+
 void riscv_frame_info::reset(void)
 {
   total_size = 0;
@@ -4948,7 +4952,11 @@ riscv_save_reg_p (unsigned int regno)
   if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed)
 return true;
 
-  if (regno == RETURN_ADDR_REGNUM && crtl->calls_eh_return)
+  /* Need not to use ra for leaf when frame pointer is turned off by option
+ whatever the omit-leaf-frame's value.  */
+  bool keep_leaf_ra = frame_pointer_needed && crtl->is_leaf
+&& !TARGET_OMIT_LEAF_FRAME_POINTER;
+  if (regno == RETURN_ADDR_REGNUM && (crtl->calls_eh_return || keep_leaf_ra))
 return true;
 
   /* If this is an interrupt handler, then must save extra registers.  */
@@ -6577,6 +6585,21 @@ riscv_option_override (void)
   if (flag_pic)
 riscv_cmodel = CM_PIC;
 
+  /* We need to save the fp with ra for non-leaf functions with no fp and ra
+ for leaf functions while no-omit-frame-pointer with
+ omit-leaf-frame-pointer.  The x_flag_omit_frame_pointer has the first
+ priority to determine whether the frame pointer is needed.  If we do not
+ override it, the fp and ra will be stored for leaf functions, which is not
+ our wanted.  */
+  riscv_save_frame_pointer = false;
+  if (TARGET_OMIT_LEAF_FRAME_POINTER_P (global_options.x_target_flags))
+{
+  if (!global_options.x_flag_omit_frame_pointer)
+   riscv_save_frame_pointer = true;
+
+  global_options.x_flag_omit_frame_pointer = 1;
+}
+
   /* We get better code with explicit relocs for CM_MEDLOW, but
  worse code for the others (for now).  Pick the best default.  */
   if ((target_flags_explicit & MASK_EXPLICIT_RELOCS) == 0)
@@ -7857,6 +7880,12 @@ riscv_preferred_else_value (unsigned, tree, unsigned int 
nops, tree *ops)
   return nops == 3 ? ops[2] : ops[0];
 }
 
+static bool
+riscv_frame_pointer_required (void)
+{
+  return riscv_save_frame_pointer && !crtl->is_leaf;
+}
+
 /* Initialize the GCC target structure.  */
 #undef TARGET_ASM_ALIGNED_HI_OP
 #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
@@ -8161,6 +8190,9 @@ riscv_preferred_else_value (unsigned, tree, unsigned int 
nops, tree *ops)
 #undef TARGET_PREFERRED_ELSE_VALUE
 #define TARGET_PREFERRED_ELSE_VALUE riscv_preferred_else_value
 
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED riscv_frame_pointer_required
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-riscv.h"
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index dd062f1c8bd..4dfd8f78ad5 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -138,6 +138,10 @@ Enable the CSR checking for the ISA-dependent CRS and the 
read-only CSR.
 The ISA-dependent CSR are only valid when the specific ISA is set.  The
 read-only CSR can not be written by the CSR instructions.
 
+momit-leaf-frame-pointer
+Target Mask(OMIT_LEAF_FRAME_POINTER) Save
+Omit the frame pointer in leaf functions.
+
 Mask(64BIT)
 
 Mask(MUL)
diff --git a/gcc/tes

[PATCH] RISCV: Add -m(no)-omit-leaf-frame-pointer support.

2023-06-02 Thread yanzhang.wang--- via Gcc-patches
From: Yanzhang Wang 

gcc/ChangeLog:

* config/riscv/riscv.cc (riscv_save_reg_p): Save ra for leaf
  when enabling -mno-omit-leaf-frame-pointer
(riscv_option_override): Override omit-frame-pointer.
(riscv_frame_pointer_required): Save s0 for non-leaf function
(TARGET_FRAME_POINTER_REQUIRED): Override defination
* config/riscv/riscv.opt: Add option support.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/omit-frame-pointer-1.c: New test.
* gcc.target/riscv/omit-frame-pointer-2.c: New test.
* gcc.target/riscv/omit-frame-pointer-3.c: New test.
* gcc.target/riscv/omit-frame-pointer-4.c: New test.
* gcc.target/riscv/omit-frame-pointer-test.c: New test.

Signed-off-by: Yanzhang Wang 
---
 gcc/config/riscv/riscv.cc | 31 ++-
 gcc/config/riscv/riscv.opt|  4 +++
 .../gcc.target/riscv/omit-frame-pointer-1.c   |  7 +
 .../gcc.target/riscv/omit-frame-pointer-2.c   |  7 +
 .../gcc.target/riscv/omit-frame-pointer-3.c   |  7 +
 .../gcc.target/riscv/omit-frame-pointer-4.c   |  7 +
 .../riscv/omit-frame-pointer-test.c   | 13 
 7 files changed, 75 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/omit-frame-pointer-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/omit-frame-pointer-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/omit-frame-pointer-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/omit-frame-pointer-4.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/omit-frame-pointer-test.c

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 5d2550871c7..e02f9cb50a4 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -408,6 +408,10 @@ static const struct riscv_tune_info 
riscv_tune_info_table[] = {
 #include "riscv-cores.def"
 };
 
+/* Global variable to distinguish whether we should save and restore s0/fp for
+   function.  */
+static bool riscv_save_frame_pointer;
+
 void riscv_frame_info::reset(void)
 {
   total_size = 0;
@@ -4744,7 +4748,11 @@ riscv_save_reg_p (unsigned int regno)
   if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed)
 return true;
 
-  if (regno == RETURN_ADDR_REGNUM && crtl->calls_eh_return)
+  /* Need not to use ra for leaf when frame pointer is turned off by option
+ whatever the omit-leaf-frame's value.  */
+  bool keep_leaf_ra = frame_pointer_needed && crtl->is_leaf
+&& !TARGET_OMIT_LEAF_FRAME_POINTER;
+  if (regno == RETURN_ADDR_REGNUM && (crtl->calls_eh_return || keep_leaf_ra))
 return true;
 
   /* If this is an interrupt handler, then must save extra registers.  */
@@ -6287,6 +6295,15 @@ riscv_option_override (void)
   if (flag_pic)
 riscv_cmodel = CM_PIC;
 
+  riscv_save_frame_pointer = false;
+  if (TARGET_OMIT_LEAF_FRAME_POINTER_P (global_options.x_target_flags))
+{
+  if (!global_options.x_flag_omit_frame_pointer)
+   riscv_save_frame_pointer = true;
+
+  global_options.x_flag_omit_frame_pointer = 1;
+}
+
   /* We get better code with explicit relocs for CM_MEDLOW, but
  worse code for the others (for now).  Pick the best default.  */
   if ((target_flags_explicit & MASK_EXPLICIT_RELOCS) == 0)
@@ -7158,6 +7175,15 @@ riscv_zero_call_used_regs (HARD_REG_SET 
need_zeroed_hardregs)
& ~zeroed_hardregs);
 }
 
+static bool
+riscv_frame_pointer_required (void)
+{
+  if (riscv_save_frame_pointer && !crtl->is_leaf)
+return true;
+
+  return false;
+}
+
 /* Initialize the GCC target structure.  */
 #undef TARGET_ASM_ALIGNED_HI_OP
 #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
@@ -7412,6 +7438,9 @@ riscv_zero_call_used_regs (HARD_REG_SET 
need_zeroed_hardregs)
 #undef TARGET_ZERO_CALL_USED_REGS
 #define TARGET_ZERO_CALL_USED_REGS riscv_zero_call_used_regs
 
+#undef TARGET_FRAME_POINTER_REQUIRED
+#define TARGET_FRAME_POINTER_REQUIRED riscv_frame_pointer_required
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-riscv.h"
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index ff1dd4ddd4f..c3e2e7c1da4 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -138,6 +138,10 @@ Enable the CSR checking for the ISA-dependent CRS and the 
read-only CSR.
 The ISA-dependent CSR are only valid when the specific ISA is set.  The
 read-only CSR can not be written by the CSR instructions.
 
+momit-leaf-frame-pointer
+Target Mask (OMIT_LEAF_FRAME_POINTER) Save
+Omit the frame pointer in leaf functions.
+
 Mask(64BIT)
 
 Mask(MUL)
diff --git a/gcc/testsuite/gcc.target/riscv/omit-frame-pointer-1.c 
b/gcc/testsuite/gcc.target/riscv/omit-frame-pointer-1.c
new file mode 100644
index 000..c96123ea702
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/omit-frame-pointer-1.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64 -O2 -fno-omit-frame-pointer 

[PATCH] RISC-V: Fix regression of -fzero-call-used-regs=all

2023-04-06 Thread yanzhang.wang--- via Gcc-patches
From: Yanzhang Wang 

This patch registers a riscv specific function to
TARGET_ZERO_CALL_USED_REGS instead of default in targhooks.cc. It will
clean gpr and vector relevant registers.

PR 109104

gcc/ChangeLog:

* config/riscv/riscv-v.cc (default_zero_call_used_regs):
(riscv_zero_call_used_regs):
* config/riscv/riscv.cc (riscv_zero_call_used_regs):
(TARGET_ZERO_CALL_USED_REGS):

gcc/testsuite/ChangeLog:

* gcc.target/riscv/zero-scratch-regs-1.c: New test.
* gcc.target/riscv/zero-scratch-regs-2.c: New test.

Signed-off-by: Yanzhang Wang 
Co-authored-by: Pan Li 
Co-authored-by: Ju-Zhe Zhong 
Co-authored-by: Kito Cheng 
---
 gcc/config/riscv/riscv-v.cc   | 79 +++
 gcc/config/riscv/riscv.cc |  6 ++
 .../gcc.target/riscv/zero-scratch-regs-1.c|  9 +++
 .../gcc.target/riscv/zero-scratch-regs-2.c| 24 ++
 4 files changed, 118 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/riscv/zero-scratch-regs-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/zero-scratch-regs-2.c

diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 2e91d019f6c..90c69b52bb4 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -43,6 +43,7 @@
 #include "optabs.h"
 #include "tm-constrs.h"
 #include "rtx-vector-builder.h"
+#include "diagnostic-core.h"
 
 using namespace riscv_vector;
 
@@ -724,4 +725,82 @@ gen_avl_for_scalar_move (rtx avl)
 }
 }
 
+/* Generate a sequence of instructions that zero registers specified by
+   NEED_ZEROED_HARDREGS.  Return the ZEROED_HARDREGS that are actually
+   zeroed.  */
+static HARD_REG_SET
+gpr_zero_call_used_regs (HARD_REG_SET need_zeroed_hardregs)
+{
+  HARD_REG_SET zeroed_hardregs;
+  CLEAR_HARD_REG_SET (zeroed_hardregs);
+
+  for (unsigned regno = GP_REG_FIRST; regno <= GP_REG_LAST; ++regno)
+{
+  if (!TEST_HARD_REG_BIT (need_zeroed_hardregs, regno))
+   continue;
+
+  rtx reg = regno_reg_rtx[regno];
+  machine_mode mode = GET_MODE (reg);
+  emit_move_insn (reg, CONST0_RTX (mode));
+
+  SET_HARD_REG_BIT (zeroed_hardregs, regno);
+}
+
+  return zeroed_hardregs;
+}
+
+static HARD_REG_SET
+vector_zero_call_used_regs (HARD_REG_SET need_zeroed_hardregs)
+{
+  HARD_REG_SET zeroed_hardregs;
+  CLEAR_HARD_REG_SET (zeroed_hardregs);
+
+  /* Find a register to hold vl.  */
+  unsigned vl_regno = GP_REG_LAST + 1;
+  for (unsigned regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
+{
+  /* If vl and avl both are x0, the existing vl is kept.  */
+  if (TEST_HARD_REG_BIT (need_zeroed_hardregs, regno) && regno != 
X0_REGNUM)
+   {
+ vl_regno = regno;
+ break;
+   }
+}
+
+  if (vl_regno > GP_REG_LAST)
+sorry ("can't allocate vl register for %qs on this target",
+  "-fzero-call-used-regs");
+
+  rtx vl = gen_rtx_REG (Pmode, vl_regno); /* vl is VLMAX.  */
+  for (unsigned regno = V_REG_FIRST; regno <= V_REG_LAST; ++regno)
+{
+  if (TEST_HARD_REG_BIT (need_zeroed_hardregs, regno))
+   {
+ rtx target = regno_reg_rtx[regno];
+ machine_mode mode = GET_MODE (target);
+ poly_uint16 nunits = GET_MODE_NUNITS (mode);
+ machine_mode mask_mode = get_vector_mode (BImode, nunits).require ();
+
+ emit_vlmax_vsetvl (mode, vl);
+ emit_vlmax_op (code_for_pred_mov (mode), target, CONST0_RTX (mode),
+vl, mask_mode);
+
+ SET_HARD_REG_BIT (zeroed_hardregs, regno);
+   }
+}
+
+  return zeroed_hardregs;
+}
+
+HARD_REG_SET
+riscv_zero_call_used_regs (HARD_REG_SET need_zeroed_hardregs)
+{
+  HARD_REG_SET zeroed_hardregs;
+  CLEAR_HARD_REG_SET (zeroed_hardregs);
+
+  if (TARGET_VECTOR)
+zeroed_hardregs |= vector_zero_call_used_regs (need_zeroed_hardregs);
+
+  return zeroed_hardregs | gpr_zero_call_used_regs (need_zeroed_hardregs);
+}
 } // namespace riscv_vector
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 5f542932d13..e176f2d9f34 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -7317,6 +7317,12 @@ riscv_shamt_matches_mask_p (int shamt, HOST_WIDE_INT 
mask)
 #undef TARGET_DWARF_POLY_INDETERMINATE_VALUE
 #define TARGET_DWARF_POLY_INDETERMINATE_VALUE 
riscv_dwarf_poly_indeterminate_value
 
+namespace riscv_vector {
+extern HARD_REG_SET riscv_zero_call_used_regs (HARD_REG_SET);
+}
+#undef TARGET_ZERO_CALL_USED_REGS
+#define TARGET_ZERO_CALL_USED_REGS riscv_vector::riscv_zero_call_used_regs
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-riscv.h"
diff --git a/gcc/testsuite/gcc.target/riscv/zero-scratch-regs-1.c 
b/gcc/testsuite/gcc.target/riscv/zero-scratch-regs-1.c
new file mode 100644
index 000..2d9dfeb9dc2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zero-scratch-regs-1.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fzero-call-used-regs=used -fno-stack-protector -fno-PIC" 
} *

[PATCH v2] RISC-V: Fix regression of -fzero-call-used-regs=all

2023-04-07 Thread yanzhang.wang--- via Gcc-patches
From: Yanzhang Wang 

This patch registers a riscv specific function to
TARGET_ZERO_CALL_USED_REGS instead of default in targhooks.cc. It will
clean gpr and vector relevant registers.

PR 109104

gcc/ChangeLog:

* config/riscv/riscv-protos.h (GCC_RISCV_PROTOS_H):
(emit_hard_vlmax_vsetvl):
(vector_zero_call_used_regs):
* config/riscv/riscv-v.cc (emit_hard_vlmax_vsetvl):
(emit_vlmax_vsetvl):
(vector_zero_call_used_regs):
* config/riscv/riscv.cc (riscv_zero_call_used_regs):
(TARGET_ZERO_CALL_USED_REGS):

gcc/testsuite/ChangeLog:

* gcc.target/riscv/zero-scratch-regs-1.c: New test.
* gcc.target/riscv/zero-scratch-regs-2.c: New test.
* gcc.target/riscv/zero-scratch-regs-3.c: New test.

Signed-off-by: Yanzhang Wang 
Co-authored-by: Pan Li 
Co-authored-by: Ju-Zhe Zhong 
Co-authored-by: Kito Cheng 
---
 gcc/config/riscv/riscv-protos.h   |  5 ++
 gcc/config/riscv/riscv-v.cc   | 67 ++-
 gcc/config/riscv/riscv.cc | 21 ++
 .../gcc.target/riscv/zero-scratch-regs-1.c|  9 +++
 .../gcc.target/riscv/zero-scratch-regs-2.c| 24 +++
 .../gcc.target/riscv/zero-scratch-regs-3.c| 57 
 6 files changed, 180 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/zero-scratch-regs-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/zero-scratch-regs-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/zero-scratch-regs-3.c

diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 4611447ddde..7ab0ec4b8be 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -22,6 +22,8 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_RISCV_PROTOS_H
 #define GCC_RISCV_PROTOS_H
 
+#include "hard-reg-set.h"
+
 /* Symbol types we understand.  The order of this list must match that of
the unspec enum in riscv.md, subsequent to UNSPEC_ADDRESS_FIRST.  */
 enum riscv_symbol_type {
@@ -159,6 +161,7 @@ bool check_builtin_call (location_t, vec, 
unsigned int,
 bool const_vec_all_same_in_range_p (rtx, HOST_WIDE_INT, HOST_WIDE_INT);
 bool legitimize_move (rtx, rtx, machine_mode);
 void emit_vlmax_vsetvl (machine_mode, rtx);
+void emit_hard_vlmax_vsetvl (machine_mode, rtx);
 void emit_vlmax_op (unsigned, rtx, rtx, machine_mode);
 void emit_vlmax_op (unsigned, rtx, rtx, rtx, machine_mode);
 void emit_nonvlmax_op (unsigned, rtx, rtx, rtx, machine_mode);
@@ -206,6 +209,8 @@ enum vlen_enum
 bool slide1_sew64_helper (int, machine_mode, machine_mode,
  machine_mode, rtx *);
 rtx gen_avl_for_scalar_move (rtx);
+
+HARD_REG_SET vector_zero_call_used_regs (HARD_REG_SET);
 }
 
 /* We classify builtin types into two classes:
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 2e91d019f6c..aad046240ee 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -43,6 +43,8 @@
 #include "optabs.h"
 #include "tm-constrs.h"
 #include "rtx-vector-builder.h"
+#include "diagnostic-core.h"
+#include "targhooks.h"
 
 using namespace riscv_vector;
 
@@ -118,6 +120,17 @@ const_vec_all_same_in_range_p (rtx x, HOST_WIDE_INT minval,
  && IN_RANGE (INTVAL (elt), minval, maxval));
 }
 
+/* Emit a vlmax vsetvl instruction with side effect, this should be only used
+   when optimization is tune off or emit after vsetvl insertion pass.  */
+void
+emit_hard_vlmax_vsetvl (machine_mode vmode, rtx vl)
+{
+  unsigned int sew = get_sew (vmode);
+  emit_insn (gen_vsetvl (Pmode, vl, RVV_VLMAX, gen_int_mode (sew, Pmode),
+gen_int_mode (get_vlmul (vmode), Pmode), const0_rtx,
+const0_rtx));
+}
+
 void
 emit_vlmax_vsetvl (machine_mode vmode, rtx vl)
 {
@@ -126,9 +139,7 @@ emit_vlmax_vsetvl (machine_mode vmode, rtx vl)
   unsigned int ratio = calculate_ratio (sew, vlmul);
 
   if (!optimize)
-emit_insn (gen_vsetvl (Pmode, vl, RVV_VLMAX, gen_int_mode (sew, Pmode),
-  gen_int_mode (get_vlmul (vmode), Pmode), const0_rtx,
-  const0_rtx));
+emit_hard_vlmax_vsetvl (vmode, vl);
   else
 emit_insn (gen_vlmax_avl (Pmode, vl, gen_int_mode (ratio, Pmode)));
 }
@@ -724,4 +735,54 @@ gen_avl_for_scalar_move (rtx avl)
 }
 }
 
+HARD_REG_SET
+vector_zero_call_used_regs (HARD_REG_SET need_zeroed_hardregs)
+{
+  HARD_REG_SET zeroed_hardregs;
+  CLEAR_HARD_REG_SET (zeroed_hardregs);
+
+  /* Find a register to hold vl.  */
+  unsigned vl_regno = INVALID_REGNUM;
+  /* Skip the first GPR, otherwise the existing vl is kept due to the same
+ between vl and avl.  */
+  for (unsigned regno = GP_REG_FIRST + 1; regno <= GP_REG_LAST; regno++)
+{
+  if (TEST_HARD_REG_BIT (need_zeroed_hardregs, regno))
+   {
+ vl_regno = regno;
+ break;
+   }
+}
+
+  if (vl_regno > GP_REG_LAST)
+sorry ("can't allocate vl regis

[PATCH v3] RISC-V: Fix regression of -fzero-call-used-regs=all

2023-04-07 Thread yanzhang.wang--- via Gcc-patches
From: Yanzhang Wang 

This patch registers a riscv specific function to
TARGET_ZERO_CALL_USED_REGS instead of default in targhooks.cc. It will
clean gpr and vector relevant registers.

PR 109104

gcc/ChangeLog:

* config/riscv/riscv-protos.h (emit_hard_vlmax_vsetvl):
* config/riscv/riscv-v.cc (emit_hard_vlmax_vsetvl):
(emit_vlmax_vsetvl):
* config/riscv/riscv.cc (vector_zero_call_used_regs):
(riscv_zero_call_used_regs):
(TARGET_ZERO_CALL_USED_REGS):

gcc/testsuite/ChangeLog:

* gcc.target/riscv/zero-scratch-regs-1.c: New test.
* gcc.target/riscv/zero-scratch-regs-2.c: New test.
* gcc.target/riscv/zero-scratch-regs-3.c: New test.

Signed-off-by: Yanzhang Wang 
Co-authored-by: Pan Li 
Co-authored-by: Ju-Zhe Zhong 
Co-authored-by: Kito Cheng 
---
 gcc/config/riscv/riscv-protos.h   |  1 +
 gcc/config/riscv/riscv-v.cc   | 15 +++-
 gcc/config/riscv/riscv.cc | 71 +++
 .../gcc.target/riscv/zero-scratch-regs-1.c|  9 +++
 .../gcc.target/riscv/zero-scratch-regs-2.c| 24 +++
 .../gcc.target/riscv/zero-scratch-regs-3.c| 57 +++
 6 files changed, 174 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/zero-scratch-regs-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/zero-scratch-regs-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/zero-scratch-regs-3.c

diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 4611447ddde..5244e8dcbf0 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -159,6 +159,7 @@ bool check_builtin_call (location_t, vec, 
unsigned int,
 bool const_vec_all_same_in_range_p (rtx, HOST_WIDE_INT, HOST_WIDE_INT);
 bool legitimize_move (rtx, rtx, machine_mode);
 void emit_vlmax_vsetvl (machine_mode, rtx);
+void emit_hard_vlmax_vsetvl (machine_mode, rtx);
 void emit_vlmax_op (unsigned, rtx, rtx, machine_mode);
 void emit_vlmax_op (unsigned, rtx, rtx, rtx, machine_mode);
 void emit_nonvlmax_op (unsigned, rtx, rtx, rtx, machine_mode);
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 2e91d019f6c..13dd6639c9f 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -118,6 +118,17 @@ const_vec_all_same_in_range_p (rtx x, HOST_WIDE_INT minval,
  && IN_RANGE (INTVAL (elt), minval, maxval));
 }
 
+/* Emit a vlmax vsetvl instruction with side effect, this should be only used
+   when optimization is tune off or emit after vsetvl insertion pass.  */
+void
+emit_hard_vlmax_vsetvl (machine_mode vmode, rtx vl)
+{
+  unsigned int sew = get_sew (vmode);
+  emit_insn (gen_vsetvl (Pmode, vl, RVV_VLMAX, gen_int_mode (sew, Pmode),
+gen_int_mode (get_vlmul (vmode), Pmode), const0_rtx,
+const0_rtx));
+}
+
 void
 emit_vlmax_vsetvl (machine_mode vmode, rtx vl)
 {
@@ -126,9 +137,7 @@ emit_vlmax_vsetvl (machine_mode vmode, rtx vl)
   unsigned int ratio = calculate_ratio (sew, vlmul);
 
   if (!optimize)
-emit_insn (gen_vsetvl (Pmode, vl, RVV_VLMAX, gen_int_mode (sew, Pmode),
-  gen_int_mode (get_vlmul (vmode), Pmode), const0_rtx,
-  const0_rtx));
+emit_hard_vlmax_vsetvl (vmode, vl);
   else
 emit_insn (gen_vlmax_avl (Pmode, vl, gen_int_mode (ratio, Pmode)));
 }
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 5f542932d13..a6a610f5901 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -7066,6 +7066,74 @@ riscv_shamt_matches_mask_p (int shamt, HOST_WIDE_INT 
mask)
   return shamt == ctz_hwi (mask);
 }
 
+HARD_REG_SET
+vector_zero_call_used_regs (HARD_REG_SET need_zeroed_hardregs)
+{
+  HARD_REG_SET zeroed_hardregs;
+  CLEAR_HARD_REG_SET (zeroed_hardregs);
+
+  /* Find a register to hold vl.  */
+  unsigned vl_regno = INVALID_REGNUM;
+  /* Skip the first GPR, otherwise the existing vl is kept due to the same
+ between vl and avl.  */
+  for (unsigned regno = GP_REG_FIRST + 1; regno <= GP_REG_LAST; regno++)
+{
+  if (TEST_HARD_REG_BIT (need_zeroed_hardregs, regno))
+   {
+ vl_regno = regno;
+ break;
+   }
+}
+
+  if (vl_regno > GP_REG_LAST)
+sorry ("cannot allocate vl register for %qs on this target",
+  "-fzero-call-used-regs");
+
+  bool emitted_vlmax_vsetvl = false;
+  rtx vl = gen_rtx_REG (Pmode, vl_regno); /* vl is VLMAX.  */
+  for (unsigned regno = V_REG_FIRST; regno <= V_REG_LAST; ++regno)
+{
+  if (TEST_HARD_REG_BIT (need_zeroed_hardregs, regno))
+   {
+ rtx target = regno_reg_rtx[regno];
+ machine_mode mode = GET_MODE (target);
+ poly_uint16 nunits = GET_MODE_NUNITS (mode);
+ machine_mode mask_mode = riscv_vector::get_vector_mode (BImode,
+ nunits)
+   .require ();
+
+ if (!

[PATCH v4] RISC-V: Fix regression of -fzero-call-used-regs=all

2023-04-09 Thread yanzhang.wang--- via Gcc-patches
From: Yanzhang Wang 

This patch registers a riscv specific function to
TARGET_ZERO_CALL_USED_REGS instead of default in targhooks.cc. It will
clean gpr and vector relevant registers.

PR 109104

gcc/ChangeLog:

* config/riscv/riscv-protos.h (emit_hard_vlmax_vsetvl):
* config/riscv/riscv-v.cc (emit_hard_vlmax_vsetvl):
(emit_vlmax_vsetvl):
* config/riscv/riscv.cc (vector_zero_call_used_regs):
(riscv_zero_call_used_regs):
(TARGET_ZERO_CALL_USED_REGS):

gcc/testsuite/ChangeLog:

* gcc.target/riscv/zero-scratch-regs-1.c: New test.
* gcc.target/riscv/zero-scratch-regs-2.c: New test.
* gcc.target/riscv/zero-scratch-regs-3.c: New test.

Signed-off-by: Yanzhang Wang 
Co-authored-by: Pan Li 
Co-authored-by: Ju-Zhe Zhong 
Co-authored-by: Kito Cheng 
---
 gcc/config/riscv/riscv-protos.h   |  1 +
 gcc/config/riscv/riscv-v.cc   | 15 +++-
 gcc/config/riscv/riscv.cc | 76 +++
 .../gcc.target/riscv/zero-scratch-regs-1.c|  9 +++
 .../gcc.target/riscv/zero-scratch-regs-2.c| 24 ++
 .../gcc.target/riscv/zero-scratch-regs-3.c| 57 ++
 6 files changed, 179 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/zero-scratch-regs-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/zero-scratch-regs-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/zero-scratch-regs-3.c

diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 4611447ddde..5244e8dcbf0 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -159,6 +159,7 @@ bool check_builtin_call (location_t, vec, 
unsigned int,
 bool const_vec_all_same_in_range_p (rtx, HOST_WIDE_INT, HOST_WIDE_INT);
 bool legitimize_move (rtx, rtx, machine_mode);
 void emit_vlmax_vsetvl (machine_mode, rtx);
+void emit_hard_vlmax_vsetvl (machine_mode, rtx);
 void emit_vlmax_op (unsigned, rtx, rtx, machine_mode);
 void emit_vlmax_op (unsigned, rtx, rtx, rtx, machine_mode);
 void emit_nonvlmax_op (unsigned, rtx, rtx, rtx, machine_mode);
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 2e91d019f6c..e6c46b0a6a3 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -118,6 +118,17 @@ const_vec_all_same_in_range_p (rtx x, HOST_WIDE_INT minval,
  && IN_RANGE (INTVAL (elt), minval, maxval));
 }
 
+/* Emit a vlmax vsetvl instruction. This should only be used when
+   optimization is disabled or after vsetvl insertion pass.  */
+void
+emit_hard_vlmax_vsetvl (machine_mode vmode, rtx vl)
+{
+  unsigned int sew = get_sew (vmode);
+  emit_insn (gen_vsetvl (Pmode, vl, RVV_VLMAX, gen_int_mode (sew, Pmode),
+gen_int_mode (get_vlmul (vmode), Pmode), const0_rtx,
+const0_rtx));
+}
+
 void
 emit_vlmax_vsetvl (machine_mode vmode, rtx vl)
 {
@@ -126,9 +137,7 @@ emit_vlmax_vsetvl (machine_mode vmode, rtx vl)
   unsigned int ratio = calculate_ratio (sew, vlmul);
 
   if (!optimize)
-emit_insn (gen_vsetvl (Pmode, vl, RVV_VLMAX, gen_int_mode (sew, Pmode),
-  gen_int_mode (get_vlmul (vmode), Pmode), const0_rtx,
-  const0_rtx));
+emit_hard_vlmax_vsetvl (vmode, vl);
   else
 emit_insn (gen_vlmax_avl (Pmode, vl, gen_int_mode (ratio, Pmode)));
 }
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 5f542932d13..d50ca9c02ea 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -7066,6 +7066,79 @@ riscv_shamt_matches_mask_p (int shamt, HOST_WIDE_INT 
mask)
   return shamt == ctz_hwi (mask);
 }
 
+HARD_REG_SET
+vector_zero_call_used_regs (HARD_REG_SET need_zeroed_hardregs)
+{
+  HARD_REG_SET zeroed_hardregs;
+  CLEAR_HARD_REG_SET (zeroed_hardregs);
+
+  /* Find a register to hold vl.  */
+  unsigned vl_regno = INVALID_REGNUM;
+  /* Skip the first GPR, otherwise the existing vl is kept due to the same
+ between vl and avl.  */
+  for (unsigned regno = GP_REG_FIRST + 1; regno <= GP_REG_LAST; regno++)
+{
+  if (TEST_HARD_REG_BIT (need_zeroed_hardregs, regno))
+   {
+ vl_regno = regno;
+ break;
+   }
+}
+
+  if (vl_regno > GP_REG_LAST)
+sorry ("cannot allocate vl register for %qs on this target",
+  "-fzero-call-used-regs");
+
+  /* We will not save and restore existing configurations set by
+ vsetvl. By design, most RVV instructions require the user to
+ issue vsetvl first before using. Those remaining instructions
+ will not be affected by vsetvl.  */
+
+  bool emitted_vlmax_vsetvl = false;
+  rtx vl = gen_rtx_REG (Pmode, vl_regno); /* vl is VLMAX.  */
+  for (unsigned regno = V_REG_FIRST; regno <= V_REG_LAST; ++regno)
+{
+  if (TEST_HARD_REG_BIT (need_zeroed_hardregs, regno))
+   {
+ rtx target = regno_reg_rtx[regno];
+ machine_mode mode = GET_MODE (target);
+ poly_uint16 nu

[PATCH v5] RISC-V: Fix regression of -fzero-call-used-regs=all

2023-04-11 Thread yanzhang.wang--- via Gcc-patches
From: Yanzhang Wang 

This patch registers a riscv specific function to
TARGET_ZERO_CALL_USED_REGS instead of default in targhooks.cc. It will
clean gpr and vector relevant registers.

PR 109104

gcc/ChangeLog:

* config/riscv/riscv-protos.h (emit_hard_vlmax_vsetvl):
* config/riscv/riscv-v.cc (emit_hard_vlmax_vsetvl):
(emit_vlmax_vsetvl):
* config/riscv/riscv.cc (vector_zero_call_used_regs):
(riscv_zero_call_used_regs):
(TARGET_ZERO_CALL_USED_REGS):

gcc/testsuite/ChangeLog:

* gcc.target/riscv/zero-scratch-regs-1.c: New test.
* gcc.target/riscv/zero-scratch-regs-2.c: New test.
* gcc.target/riscv/zero-scratch-regs-3.c: New test.

Signed-off-by: Yanzhang Wang 
Co-authored-by: Pan Li 
Co-authored-by: Ju-Zhe Zhong 
Co-authored-by: Kito Cheng 
---
 gcc/config/riscv/riscv-protos.h   |  1 +
 gcc/config/riscv/riscv-v.cc   | 15 +++-
 gcc/config/riscv/riscv.cc | 75 +++
 .../gcc.target/riscv/zero-scratch-regs-1.c|  9 +++
 .../gcc.target/riscv/zero-scratch-regs-2.c| 24 ++
 .../gcc.target/riscv/zero-scratch-regs-3.c| 57 ++
 6 files changed, 178 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/zero-scratch-regs-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/zero-scratch-regs-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/zero-scratch-regs-3.c

diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 4611447ddde..5244e8dcbf0 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -159,6 +159,7 @@ bool check_builtin_call (location_t, vec, 
unsigned int,
 bool const_vec_all_same_in_range_p (rtx, HOST_WIDE_INT, HOST_WIDE_INT);
 bool legitimize_move (rtx, rtx, machine_mode);
 void emit_vlmax_vsetvl (machine_mode, rtx);
+void emit_hard_vlmax_vsetvl (machine_mode, rtx);
 void emit_vlmax_op (unsigned, rtx, rtx, machine_mode);
 void emit_vlmax_op (unsigned, rtx, rtx, rtx, machine_mode);
 void emit_nonvlmax_op (unsigned, rtx, rtx, rtx, machine_mode);
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 2e91d019f6c..392f5d02e17 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -118,6 +118,17 @@ const_vec_all_same_in_range_p (rtx x, HOST_WIDE_INT minval,
  && IN_RANGE (INTVAL (elt), minval, maxval));
 }
 
+/* Emit a vlmax vsetvl instruction.  This should only be used when
+   optimization is disabled or after vsetvl insertion pass.  */
+void
+emit_hard_vlmax_vsetvl (machine_mode vmode, rtx vl)
+{
+  unsigned int sew = get_sew (vmode);
+  emit_insn (gen_vsetvl (Pmode, vl, RVV_VLMAX, gen_int_mode (sew, Pmode),
+gen_int_mode (get_vlmul (vmode), Pmode), const0_rtx,
+const0_rtx));
+}
+
 void
 emit_vlmax_vsetvl (machine_mode vmode, rtx vl)
 {
@@ -126,9 +137,7 @@ emit_vlmax_vsetvl (machine_mode vmode, rtx vl)
   unsigned int ratio = calculate_ratio (sew, vlmul);
 
   if (!optimize)
-emit_insn (gen_vsetvl (Pmode, vl, RVV_VLMAX, gen_int_mode (sew, Pmode),
-  gen_int_mode (get_vlmul (vmode), Pmode), const0_rtx,
-  const0_rtx));
+emit_hard_vlmax_vsetvl (vmode, vl);
   else
 emit_insn (gen_vlmax_avl (Pmode, vl, gen_int_mode (ratio, Pmode)));
 }
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 5f542932d13..a9c9e1aa32b 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -7066,6 +7066,78 @@ riscv_shamt_matches_mask_p (int shamt, HOST_WIDE_INT 
mask)
   return shamt == ctz_hwi (mask);
 }
 
+HARD_REG_SET
+vector_zero_call_used_regs (HARD_REG_SET need_zeroed_hardregs)
+{
+  HARD_REG_SET zeroed_hardregs;
+  CLEAR_HARD_REG_SET (zeroed_hardregs);
+
+  /* Find a register to hold vl.  */
+  unsigned vl_regno = INVALID_REGNUM;
+  /* Skip the first GPR, otherwise the existing vl is kept due to the same
+ between vl and avl.  */
+  for (unsigned regno = GP_REG_FIRST + 1; regno <= GP_REG_LAST; regno++)
+{
+  if (TEST_HARD_REG_BIT (need_zeroed_hardregs, regno))
+   {
+ vl_regno = regno;
+ break;
+   }
+}
+
+  if (vl_regno > GP_REG_LAST)
+sorry ("cannot allocate vl register for %qs on this target",
+  "-fzero-call-used-regs");
+
+  /* Vector configurations need not be saved and restored here.  The
+ -fzero-call-used-regs=* option will zero all vector registers and
+ return.  So there's no vector operations between them.  */
+
+  bool emitted_vlmax_vsetvl = false;
+  rtx vl = gen_rtx_REG (Pmode, vl_regno); /* vl is VLMAX.  */
+  for (unsigned regno = V_REG_FIRST; regno <= V_REG_LAST; ++regno)
+{
+  if (TEST_HARD_REG_BIT (need_zeroed_hardregs, regno))
+   {
+ rtx target = regno_reg_rtx[regno];
+ machine_mode mode = GET_MODE (target);
+ poly_uint16 nunits = GET_MODE_NUNITS (mode);
+   

[PATCH] RISC-V: ICE for vlmul_ext_v intrinsic API

2023-04-26 Thread yanzhang.wang--- via Gcc-patches
From: Yanzhang Wang 

PR 109617

gcc/ChangeLog:

* config/riscv/vector-iterators.md:

gcc/testsuite/ChangeLog:

* gcc.target/riscv/rvv/base/vlmul_ext-1.c: New test.

Signed-off-by: Yanzhang Wang 
Co-authored-by: Pan Li 
---
 gcc/config/riscv/vector-iterators.md   |  3 ++-
 .../gcc.target/riscv/rvv/base/vlmul_ext-1.c| 14 ++
 2 files changed, 16 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/vlmul_ext-1.c

diff --git a/gcc/config/riscv/vector-iterators.md 
b/gcc/config/riscv/vector-iterators.md
index a8e856161d3..033659930d1 100644
--- a/gcc/config/riscv/vector-iterators.md
+++ b/gcc/config/riscv/vector-iterators.md
@@ -189,6 +189,7 @@
   (VNx1HI "TARGET_MIN_VLEN < 128") VNx2HI VNx4HI VNx8HI (VNx16HI 
"TARGET_MIN_VLEN >= 128")
   (VNx1SI "TARGET_MIN_VLEN < 128") VNx2SI VNx4SI (VNx8SI "TARGET_MIN_VLEN >= 
128")
   (VNx1DI "TARGET_VECTOR_ELEN_64 && TARGET_MIN_VLEN < 128") (VNx2DI 
"TARGET_VECTOR_ELEN_64")
+  (VNx4DI "TARGET_VECTOR_ELEN_64")
   (VNx1SF "TARGET_VECTOR_ELEN_FP_32 && TARGET_MIN_VLEN < 128")
   (VNx2SF "TARGET_VECTOR_ELEN_FP_32")
   (VNx4SF "TARGET_VECTOR_ELEN_FP_32")
@@ -220,7 +221,7 @@
 
 (define_mode_iterator VLMULEXT32 [
   (VNx1QI "TARGET_MIN_VLEN < 128") VNx2QI (VNx4QI "TARGET_MIN_VLEN >= 128")
-  (VNx1HI "TARGET_MIN_VLEN < 128")
+  (VNx1HI "TARGET_MIN_VLEN < 128") (VNx2HI "TARGET_MIN_VLEN >= 128")
 ])
 
 (define_mode_iterator VLMULEXT64 [
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/vlmul_ext-1.c 
b/gcc/testsuite/gcc.target/riscv/rvv/base/vlmul_ext-1.c
new file mode 100644
index 000..501d98c5897
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/vlmul_ext-1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d -O3 -fno-schedule-insns 
-fno-schedule-insns2" } */
+
+#include 
+
+vint16m8_t test_vlmul_ext_v_i16mf4_i16m8(vint16mf4_t op1) {
+  return __riscv_vlmul_ext_v_i16mf4_i16m8(op1);
+}
+
+vint64m8_t test_vlmul_ext_v_i64m2_i64m8(vint64m2_t op1) {
+  return __riscv_vlmul_ext_v_i64m2_i64m8(op1);
+}
+
+/* { dg-final { scan-assembler-times {vs8r.v\s+[,\sa-x0-9()]+} 2} } */
-- 
2.39.2



[PATCH] RISCV: Add vector psabi checking.

2023-04-26 Thread yanzhang.wang--- via Gcc-patches
From: Yanzhang Wang 

This patch adds support to check function's argument or return is vector type
and throw warning if yes.

gcc/ChangeLog:

* config/riscv/riscv.cc (riscv_scalable_vector_type_p):
(riscv_arg_has_vector):
(riscv_pass_in_vector_p):
(riscv_get_arg_info):

gcc/testsuite/ChangeLog:

* gcc.target/riscv/vector-abi-1.c: New test.
* gcc.target/riscv/vector-abi-2.c: New test.
* gcc.target/riscv/vector-abi-3.c: New test.
* gcc.target/riscv/vector-abi-4.c: New test.
* gcc.target/riscv/vector-abi-5.c: New test.

Signed-off-by: Yanzhang Wang 
Co-authored-by: Kito Cheng 
---
 gcc/config/riscv/riscv.cc | 73 +++
 gcc/testsuite/gcc.target/riscv/vector-abi-1.c | 14 
 gcc/testsuite/gcc.target/riscv/vector-abi-2.c | 14 
 gcc/testsuite/gcc.target/riscv/vector-abi-3.c | 14 
 gcc/testsuite/gcc.target/riscv/vector-abi-4.c | 16 
 gcc/testsuite/gcc.target/riscv/vector-abi-5.c | 15 
 6 files changed, 146 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-4.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-5.c

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 76eee4a55e9..06e9fe7d924 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -3728,6 +3728,76 @@ riscv_pass_fpr_pair (machine_mode mode, unsigned regno1,
   GEN_INT (offset2;
 }
 
+/* Use the TYPE_SIZE to distinguish the type with vector_size attribute and
+   intrinsic vector type.  Because we can't get the decl for the params.  */
+
+static bool
+riscv_scalable_vector_type_p (const_tree type)
+{
+  tree size = TYPE_SIZE (type);
+  if (size && TREE_CODE (size) == INTEGER_CST)
+return false;
+
+  /* For the data type like vint32m1_t, the size code is POLY_INT_CST.  */
+  return true;
+}
+
+static bool
+riscv_arg_has_vector (const_tree type)
+{
+  bool is_vector = false;
+
+  switch (TREE_CODE (type))
+{
+case RECORD_TYPE:
+  if (!COMPLETE_TYPE_P (type))
+   break;
+
+  for (tree f = TYPE_FIELDS (type); f; f = DECL_CHAIN (f))
+   if (TREE_CODE (f) == FIELD_DECL)
+ {
+   tree field_type = TREE_TYPE (f);
+   if (!TYPE_P (field_type))
+ break;
+
+   /* Ignore it if it's fixed length vector.  */
+   if (VECTOR_TYPE_P (field_type))
+ is_vector = riscv_scalable_vector_type_p (field_type);
+   else
+ is_vector = riscv_arg_has_vector (field_type);
+ }
+
+  break;
+
+case VECTOR_TYPE:
+  is_vector = riscv_scalable_vector_type_p (type);
+  break;
+
+default:
+  is_vector = false;
+  break;
+}
+
+  return is_vector;
+}
+
+/* Pass the type to check whether it's a vector type or contains vector type.
+   Only check the value type and no checking for vector pointer type.  */
+
+static void
+riscv_pass_in_vector_p (const_tree type)
+{
+  static int warned = 0;
+
+  if (type && riscv_arg_has_vector (type) && !warned)
+{
+  warning (OPT_Wpsabi, "ABI for the scalable vector type is currently in "
+  "experimental stage and may changes in the upcoming version of "
+  "GCC.");
+  warned = 1;
+}
+}
+
 /* Fill INFO with information about a single argument, and return an
RTL pattern to pass or return the argument.  CUM is the cumulative
state for earlier arguments.  MODE is the mode of this argument and
@@ -3812,6 +3882,9 @@ riscv_get_arg_info (struct riscv_arg_info *info, const 
CUMULATIVE_ARGS *cum,
}
 }
 
+  /* Only check existing of vector type.  */
+  riscv_pass_in_vector_p (type);
+
   /* Work out the size of the argument.  */
   num_bytes = type ? int_size_in_bytes (type) : GET_MODE_SIZE 
(mode).to_constant ();
   num_words = (num_bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
diff --git a/gcc/testsuite/gcc.target/riscv/vector-abi-1.c 
b/gcc/testsuite/gcc.target/riscv/vector-abi-1.c
new file mode 100644
index 000..114ee6de483
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/vector-abi-1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -march=rv64gcv -mabi=lp64d" } */
+
+#include "riscv_vector.h"
+
+void
+fun (vint32m1_t a) { } /* { dg-warning "the vector type" } */
+
+void
+bar ()
+{
+  vint32m1_t a;
+  fun (a);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/vector-abi-2.c 
b/gcc/testsuite/gcc.target/riscv/vector-abi-2.c
new file mode 100644
index 000..fd4569535cc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/vector-abi-2.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d" } */
+
+#include "riscv_vector.h"
+
+vint32m1_t
+fun (vint32m1_t* a) {  return *a; }

[PATCH v2] RISC-V: ICE for vlmul_ext_v intrinsic API

2023-04-26 Thread yanzhang.wang--- via Gcc-patches
From: Yanzhang Wang 

PR 109617

gcc/ChangeLog:

* config/riscv/vector-iterators.md: Support VNx2HI and VNX4DI when 
MIN_VLEN >= 128.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/rvv/base/vlmul_ext-1.c: New test.

Signed-off-by: Yanzhang Wang 
Co-authored-by: Pan Li 
---
 gcc/config/riscv/vector-iterators.md   |  3 ++-
 .../gcc.target/riscv/rvv/base/vlmul_ext-1.c| 14 ++
 2 files changed, 16 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/vlmul_ext-1.c

diff --git a/gcc/config/riscv/vector-iterators.md 
b/gcc/config/riscv/vector-iterators.md
index a8e856161d3..033659930d1 100644
--- a/gcc/config/riscv/vector-iterators.md
+++ b/gcc/config/riscv/vector-iterators.md
@@ -189,6 +189,7 @@
   (VNx1HI "TARGET_MIN_VLEN < 128") VNx2HI VNx4HI VNx8HI (VNx16HI 
"TARGET_MIN_VLEN >= 128")
   (VNx1SI "TARGET_MIN_VLEN < 128") VNx2SI VNx4SI (VNx8SI "TARGET_MIN_VLEN >= 
128")
   (VNx1DI "TARGET_VECTOR_ELEN_64 && TARGET_MIN_VLEN < 128") (VNx2DI 
"TARGET_VECTOR_ELEN_64")
+  (VNx4DI "TARGET_VECTOR_ELEN_64")
   (VNx1SF "TARGET_VECTOR_ELEN_FP_32 && TARGET_MIN_VLEN < 128")
   (VNx2SF "TARGET_VECTOR_ELEN_FP_32")
   (VNx4SF "TARGET_VECTOR_ELEN_FP_32")
@@ -220,7 +221,7 @@
 
 (define_mode_iterator VLMULEXT32 [
   (VNx1QI "TARGET_MIN_VLEN < 128") VNx2QI (VNx4QI "TARGET_MIN_VLEN >= 128")
-  (VNx1HI "TARGET_MIN_VLEN < 128")
+  (VNx1HI "TARGET_MIN_VLEN < 128") (VNx2HI "TARGET_MIN_VLEN >= 128")
 ])
 
 (define_mode_iterator VLMULEXT64 [
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/vlmul_ext-1.c 
b/gcc/testsuite/gcc.target/riscv/rvv/base/vlmul_ext-1.c
new file mode 100644
index 000..501d98c5897
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/vlmul_ext-1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d -O3 -fno-schedule-insns 
-fno-schedule-insns2" } */
+
+#include 
+
+vint16m8_t test_vlmul_ext_v_i16mf4_i16m8(vint16mf4_t op1) {
+  return __riscv_vlmul_ext_v_i16mf4_i16m8(op1);
+}
+
+vint64m8_t test_vlmul_ext_v_i64m2_i64m8(vint64m2_t op1) {
+  return __riscv_vlmul_ext_v_i64m2_i64m8(op1);
+}
+
+/* { dg-final { scan-assembler-times {vs8r.v\s+[,\sa-x0-9()]+} 2} } */
-- 
2.39.2



[PATCH v2] RISCV: Add vector psabi checking.

2023-04-26 Thread yanzhang.wang--- via Gcc-patches
From: Yanzhang Wang 

This patch adds support to check function's argument or return is vector type
and throw warning if yes.

gcc/ChangeLog:

* config/riscv/riscv.cc:
(riscv_scalable_vector_type_p): Determine whether the type is scalable 
vector.
(riscv_arg_has_vector): Determine whether the arg is vector type.
(riscv_pass_in_vector_p): Check the vector type param is passed by 
value.
(riscv_get_arg_info): Add the checking.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/vector-abi-1.c: New test.
* gcc.target/riscv/vector-abi-2.c: New test.
* gcc.target/riscv/vector-abi-3.c: New test.
* gcc.target/riscv/vector-abi-4.c: New test.
* gcc.target/riscv/vector-abi-5.c: New test.

Signed-off-by: Yanzhang Wang 
Co-authored-by: Kito Cheng 
---
 gcc/config/riscv/riscv.cc | 73 +++
 gcc/testsuite/gcc.target/riscv/vector-abi-1.c | 14 
 gcc/testsuite/gcc.target/riscv/vector-abi-2.c | 14 
 gcc/testsuite/gcc.target/riscv/vector-abi-3.c | 14 
 gcc/testsuite/gcc.target/riscv/vector-abi-4.c | 16 
 gcc/testsuite/gcc.target/riscv/vector-abi-5.c | 15 
 6 files changed, 146 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-4.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-5.c

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 76eee4a55e9..06e9fe7d924 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -3728,6 +3728,76 @@ riscv_pass_fpr_pair (machine_mode mode, unsigned regno1,
   GEN_INT (offset2;
 }
 
+/* Use the TYPE_SIZE to distinguish the type with vector_size attribute and
+   intrinsic vector type.  Because we can't get the decl for the params.  */
+
+static bool
+riscv_scalable_vector_type_p (const_tree type)
+{
+  tree size = TYPE_SIZE (type);
+  if (size && TREE_CODE (size) == INTEGER_CST)
+return false;
+
+  /* For the data type like vint32m1_t, the size code is POLY_INT_CST.  */
+  return true;
+}
+
+static bool
+riscv_arg_has_vector (const_tree type)
+{
+  bool is_vector = false;
+
+  switch (TREE_CODE (type))
+{
+case RECORD_TYPE:
+  if (!COMPLETE_TYPE_P (type))
+   break;
+
+  for (tree f = TYPE_FIELDS (type); f; f = DECL_CHAIN (f))
+   if (TREE_CODE (f) == FIELD_DECL)
+ {
+   tree field_type = TREE_TYPE (f);
+   if (!TYPE_P (field_type))
+ break;
+
+   /* Ignore it if it's fixed length vector.  */
+   if (VECTOR_TYPE_P (field_type))
+ is_vector = riscv_scalable_vector_type_p (field_type);
+   else
+ is_vector = riscv_arg_has_vector (field_type);
+ }
+
+  break;
+
+case VECTOR_TYPE:
+  is_vector = riscv_scalable_vector_type_p (type);
+  break;
+
+default:
+  is_vector = false;
+  break;
+}
+
+  return is_vector;
+}
+
+/* Pass the type to check whether it's a vector type or contains vector type.
+   Only check the value type and no checking for vector pointer type.  */
+
+static void
+riscv_pass_in_vector_p (const_tree type)
+{
+  static int warned = 0;
+
+  if (type && riscv_arg_has_vector (type) && !warned)
+{
+  warning (OPT_Wpsabi, "ABI for the scalable vector type is currently in "
+  "experimental stage and may changes in the upcoming version of "
+  "GCC.");
+  warned = 1;
+}
+}
+
 /* Fill INFO with information about a single argument, and return an
RTL pattern to pass or return the argument.  CUM is the cumulative
state for earlier arguments.  MODE is the mode of this argument and
@@ -3812,6 +3882,9 @@ riscv_get_arg_info (struct riscv_arg_info *info, const 
CUMULATIVE_ARGS *cum,
}
 }
 
+  /* Only check existing of vector type.  */
+  riscv_pass_in_vector_p (type);
+
   /* Work out the size of the argument.  */
   num_bytes = type ? int_size_in_bytes (type) : GET_MODE_SIZE 
(mode).to_constant ();
   num_words = (num_bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
diff --git a/gcc/testsuite/gcc.target/riscv/vector-abi-1.c 
b/gcc/testsuite/gcc.target/riscv/vector-abi-1.c
new file mode 100644
index 000..114ee6de483
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/vector-abi-1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -march=rv64gcv -mabi=lp64d" } */
+
+#include "riscv_vector.h"
+
+void
+fun (vint32m1_t a) { } /* { dg-warning "the vector type" } */
+
+void
+bar ()
+{
+  vint32m1_t a;
+  fun (a);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/vector-abi-2.c 
b/gcc/testsuite/gcc.target/riscv/vector-abi-2.c
new file mode 100644
index 000..fd4569535cc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/vector-abi-2.c
@@ -0,

[PATCH v3] RISCV: Add vector psabi checking.

2023-04-26 Thread yanzhang.wang--- via Gcc-patches
From: Yanzhang Wang 

This patch adds support to check function's argument or return is vector type
and throw warning if yes.

gcc/ChangeLog:

* config/riscv/riscv.cc:
(riscv_scalable_vector_type_p): Determine whether the type is scalable 
vector.
(riscv_arg_has_vector): Determine whether the arg is vector type.
(riscv_pass_in_vector_p): Check the vector type param is passed by 
value.
(riscv_get_arg_info): Add the checking.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/vector-abi-1.c: New test.
* gcc.target/riscv/vector-abi-2.c: New test.
* gcc.target/riscv/vector-abi-3.c: New test.
* gcc.target/riscv/vector-abi-4.c: New test.
* gcc.target/riscv/vector-abi-5.c: New test.

Signed-off-by: Yanzhang Wang 
Co-authored-by: Kito Cheng 
---
 gcc/config/riscv/riscv.cc | 73 +++
 gcc/testsuite/gcc.target/riscv/vector-abi-1.c | 14 
 gcc/testsuite/gcc.target/riscv/vector-abi-2.c | 14 
 gcc/testsuite/gcc.target/riscv/vector-abi-3.c | 14 
 gcc/testsuite/gcc.target/riscv/vector-abi-4.c | 16 
 gcc/testsuite/gcc.target/riscv/vector-abi-5.c | 15 
 6 files changed, 146 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-4.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/vector-abi-5.c

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 76eee4a55e9..06e9fe7d924 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -3728,6 +3728,76 @@ riscv_pass_fpr_pair (machine_mode mode, unsigned regno1,
   GEN_INT (offset2;
 }
 
+/* Use the TYPE_SIZE to distinguish the type with vector_size attribute and
+   intrinsic vector type.  Because we can't get the decl for the params.  */
+
+static bool
+riscv_scalable_vector_type_p (const_tree type)
+{
+  tree size = TYPE_SIZE (type);
+  if (size && TREE_CODE (size) == INTEGER_CST)
+return false;
+
+  /* For the data type like vint32m1_t, the size code is POLY_INT_CST.  */
+  return true;
+}
+
+static bool
+riscv_arg_has_vector (const_tree type)
+{
+  bool is_vector = false;
+
+  switch (TREE_CODE (type))
+{
+case RECORD_TYPE:
+  if (!COMPLETE_TYPE_P (type))
+   break;
+
+  for (tree f = TYPE_FIELDS (type); f; f = DECL_CHAIN (f))
+   if (TREE_CODE (f) == FIELD_DECL)
+ {
+   tree field_type = TREE_TYPE (f);
+   if (!TYPE_P (field_type))
+ break;
+
+   /* Ignore it if it's fixed length vector.  */
+   if (VECTOR_TYPE_P (field_type))
+ is_vector = riscv_scalable_vector_type_p (field_type);
+   else
+ is_vector = riscv_arg_has_vector (field_type);
+ }
+
+  break;
+
+case VECTOR_TYPE:
+  is_vector = riscv_scalable_vector_type_p (type);
+  break;
+
+default:
+  is_vector = false;
+  break;
+}
+
+  return is_vector;
+}
+
+/* Pass the type to check whether it's a vector type or contains vector type.
+   Only check the value type and no checking for vector pointer type.  */
+
+static void
+riscv_pass_in_vector_p (const_tree type)
+{
+  static int warned = 0;
+
+  if (type && riscv_arg_has_vector (type) && !warned)
+{
+  warning (OPT_Wpsabi, "ABI for the scalable vector type is currently in "
+  "experimental stage and may changes in the upcoming version of "
+  "GCC.");
+  warned = 1;
+}
+}
+
 /* Fill INFO with information about a single argument, and return an
RTL pattern to pass or return the argument.  CUM is the cumulative
state for earlier arguments.  MODE is the mode of this argument and
@@ -3812,6 +3882,9 @@ riscv_get_arg_info (struct riscv_arg_info *info, const 
CUMULATIVE_ARGS *cum,
}
 }
 
+  /* Only check existing of vector type.  */
+  riscv_pass_in_vector_p (type);
+
   /* Work out the size of the argument.  */
   num_bytes = type ? int_size_in_bytes (type) : GET_MODE_SIZE 
(mode).to_constant ();
   num_words = (num_bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
diff --git a/gcc/testsuite/gcc.target/riscv/vector-abi-1.c 
b/gcc/testsuite/gcc.target/riscv/vector-abi-1.c
new file mode 100644
index 000..969f14277a4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/vector-abi-1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -march=rv64gcv -mabi=lp64d" } */
+
+#include "riscv_vector.h"
+
+void
+fun (vint32m1_t a) { } /* { dg-warning "the scalable vector type" } */
+
+void
+bar ()
+{
+  vint32m1_t a;
+  fun (a);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/vector-abi-2.c 
b/gcc/testsuite/gcc.target/riscv/vector-abi-2.c
new file mode 100644
index 000..b752760b76f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/vector-abi-2