Daily bump.
[official-gcc.git] / gcc / config / riscv / riscv-selftests.cc
blob34d01ac76b75799f36d8da4815dcb7a5163e06d7
1 /* This file is part of GCC.
3 GCC is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 3, or (at your option)
6 any later version.
8 GCC is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with GCC; see the file COPYING3. If not see
15 <http://www.gnu.org/licenses/>. */
17 #define IN_TARGET_CODE 1
19 #define INCLUDE_STRING
20 #define INCLUDE_MAP
21 #define INCLUDE_VECTOR
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "rtl.h"
27 #include "tree.h"
28 #include "stringpool.h"
29 #include "function.h"
30 #include "memmodel.h"
31 #include "emit-rtl.h"
32 #include "tm_p.h"
33 #include "expr.h"
34 #include "selftest.h"
35 #include "selftest-rtl.h"
36 #include "insn-attr.h"
37 #include "target.h"
38 #include "optabs.h"
40 #if CHECKING_P
41 using namespace selftest;
42 class riscv_selftest_arch_abi_setter
44 private:
45 std::string m_arch_backup;
46 enum riscv_abi_type m_abi_backup;
48 public:
49 riscv_selftest_arch_abi_setter (const char *arch, enum riscv_abi_type abi)
50 : m_arch_backup (riscv_arch_str ()), m_abi_backup (riscv_abi)
52 riscv_parse_arch_string (arch, &global_options, UNKNOWN_LOCATION);
53 riscv_abi = abi;
54 riscv_reinit ();
56 ~riscv_selftest_arch_abi_setter ()
58 riscv_parse_arch_string (m_arch_backup.c_str (), &global_options,
59 UNKNOWN_LOCATION);
60 riscv_abi = m_abi_backup;
61 riscv_reinit ();
65 static poly_int64
66 eval_value (rtx x, std::map<unsigned, rtx> &regno_to_rtx)
68 if (!REG_P (x))
70 debug (x);
71 gcc_unreachable ();
74 rtx expr = NULL_RTX;
75 unsigned regno = REGNO (x);
76 expr = regno_to_rtx[regno];
78 poly_int64 op1_val = 0;
79 poly_int64 op2_val = 0;
80 if (UNARY_P (expr))
82 op1_val = eval_value (XEXP (expr, 0), regno_to_rtx);
84 if (BINARY_P (expr))
86 op1_val = eval_value (XEXP (expr, 0), regno_to_rtx);
87 op2_val = eval_value (XEXP (expr, 1), regno_to_rtx);
90 switch (GET_CODE (expr))
92 case CONST_POLY_INT:
93 return rtx_to_poly_int64 (expr);
94 case CONST_INT:
95 return INTVAL (expr);
97 case MULT:
98 if (op1_val.is_constant ())
99 return op1_val.to_constant () * op2_val;
100 else if (op2_val.is_constant ())
101 return op1_val * op2_val.to_constant ();
102 else
103 gcc_unreachable ();
104 case PLUS:
105 return op1_val + op2_val;
106 default:
107 gcc_unreachable ();
111 /* Calculate the value of x register in the sequence. */
112 static poly_int64
113 calculate_x_in_sequence (rtx reg)
115 std::map<unsigned, rtx> regno_to_rtx;
116 rtx_insn *insn;
117 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
119 rtx pat = PATTERN (insn);
120 rtx dest = SET_DEST (pat);
122 if (GET_CODE (pat) == CLOBBER)
123 continue;
125 if (SUBREG_P (dest))
126 continue;
128 gcc_assert (REG_P (dest));
129 rtx note = find_reg_equal_equiv_note (insn);
130 unsigned regno = REGNO (dest);
131 if (note)
132 regno_to_rtx[regno] = XEXP (note, 0);
133 else
134 regno_to_rtx[regno] = SET_SRC (pat);
137 return eval_value (reg, regno_to_rtx);
140 typedef enum
142 POLY_TEST_DIMODE,
143 POLY_TEST_PMODE
144 } poly_test_mode_t;
146 static void
147 simple_poly_selftest (const char *arch, enum riscv_abi_type abi,
148 const std::vector<machine_mode> &modes)
150 riscv_selftest_arch_abi_setter rv (arch, abi);
151 rtl_dump_test t (SELFTEST_LOCATION, locate_file ("riscv/empty-func.rtl"));
152 set_new_first_and_last_insn (NULL, NULL);
154 for (machine_mode mode : modes)
155 emit_move_insn (gen_reg_rtx (mode),
156 gen_int_mode (BYTES_PER_RISCV_VECTOR, mode));
159 static void
160 run_poly_int_selftest (const char *arch, enum riscv_abi_type abi,
161 poly_test_mode_t test_mode,
162 const std::vector<poly_int64> &worklist)
164 riscv_selftest_arch_abi_setter rv (arch, abi);
165 rtl_dump_test t (SELFTEST_LOCATION, locate_file ("riscv/empty-func.rtl"));
166 set_new_first_and_last_insn (NULL, NULL);
167 machine_mode mode = VOIDmode;
169 switch (test_mode)
171 case POLY_TEST_DIMODE:
172 mode = DImode;
173 break;
174 case POLY_TEST_PMODE:
175 mode = Pmode;
176 break;
177 default:
178 gcc_unreachable ();
181 for (const poly_int64 &poly_val : worklist)
183 start_sequence ();
184 rtx dest = gen_reg_rtx (mode);
185 emit_move_insn (dest, gen_int_mode (poly_val, mode));
186 ASSERT_TRUE (known_eq (calculate_x_in_sequence (dest), poly_val));
187 end_sequence ();
191 static void
192 run_poly_int_selftests (void)
194 std::vector<poly_int64> worklist
195 = {BYTES_PER_RISCV_VECTOR, BYTES_PER_RISCV_VECTOR * 8,
196 BYTES_PER_RISCV_VECTOR * 32, -BYTES_PER_RISCV_VECTOR * 8,
197 -BYTES_PER_RISCV_VECTOR * 32, BYTES_PER_RISCV_VECTOR * 7,
198 BYTES_PER_RISCV_VECTOR * 31, -BYTES_PER_RISCV_VECTOR * 7,
199 -BYTES_PER_RISCV_VECTOR * 31, BYTES_PER_RISCV_VECTOR * 9,
200 BYTES_PER_RISCV_VECTOR * 33, -BYTES_PER_RISCV_VECTOR * 9,
201 -BYTES_PER_RISCV_VECTOR * 33, poly_int64 (207, 0),
202 poly_int64 (-207, 0), poly_int64 (0, 207),
203 poly_int64 (0, -207), poly_int64 (5555, 0),
204 poly_int64 (0, 5555), poly_int64 (4096, 4096),
205 poly_int64 (17, 4088), poly_int64 (3889, 4104),
206 poly_int64 (-4096, -4096), poly_int64 (219, -4088),
207 poly_int64 (-4309, -4104), poly_int64 (-7337, 88),
208 poly_int64 (9317, -88), poly_int64 (4, 4),
209 poly_int64 (17, 4), poly_int64 (-7337, 4),
210 poly_int64 (-4, -4), poly_int64 (-389, -4),
211 poly_int64 (4789, -4), poly_int64 (-5977, 1508),
212 poly_int64 (219, -1508), poly_int64 (2, 2),
213 poly_int64 (33, 2), poly_int64 (-7337, 2),
214 poly_int64 (-2, -2), poly_int64 (-389, -2),
215 poly_int64 (4789, -2), poly_int64 (-3567, 954),
216 poly_int64 (945, -954), poly_int64 (1, 1),
217 poly_int64 (977, 1), poly_int64 (-339, 1),
218 poly_int64 (-1, -1), poly_int64 (-12, -1),
219 poly_int64 (44, -1), poly_int64 (9567, 77),
220 poly_int64 (3467, -77)};
222 simple_poly_selftest ("rv64imafdv", ABI_LP64D,
223 {QImode, HImode, SImode, DImode});
224 simple_poly_selftest ("rv32imafdv", ABI_ILP32D, {QImode, HImode, SImode});
226 run_poly_int_selftest ("rv64imafdv", ABI_LP64D, POLY_TEST_PMODE, worklist);
227 run_poly_int_selftest ("rv64imafd_zve32x1p0", ABI_LP64D, POLY_TEST_PMODE,
228 worklist);
229 run_poly_int_selftest ("rv32imafdv", ABI_ILP32, POLY_TEST_PMODE, worklist);
230 run_poly_int_selftest ("rv32imafdv", ABI_ILP32, POLY_TEST_DIMODE, worklist);
231 run_poly_int_selftest ("rv32imafd_zve32x1p0", ABI_ILP32D, POLY_TEST_PMODE,
232 worklist);
233 run_poly_int_selftest ("rv32imafd_zve32x1p0", ABI_ILP32D, POLY_TEST_DIMODE,
234 worklist);
235 simple_poly_selftest ("rv64imafdv_zvl256b", ABI_LP64D,
236 {QImode, HImode, SImode, DImode});
237 simple_poly_selftest ("rv64imafdv_zvl512b", ABI_LP64D,
238 {QImode, HImode, SImode, DImode});
239 simple_poly_selftest ("rv64imafdv_zvl1024b", ABI_LP64D,
240 {QImode, HImode, SImode, DImode});
241 simple_poly_selftest ("rv64imafdv_zvl2048b", ABI_LP64D,
242 {QImode, HImode, SImode, DImode});
243 simple_poly_selftest ("rv64imafdv_zvl4096b", ABI_LP64D,
244 {QImode, HImode, SImode, DImode});
247 static void
248 run_const_vector_selftests (void)
250 /* We dont't need to do the redundant tests in different march && mabi.
251 Just pick up the march && mabi which fully support all RVV modes. */
252 riscv_selftest_arch_abi_setter rv ("rv64imafdcv", ABI_LP64D);
253 rtl_dump_test t (SELFTEST_LOCATION, locate_file ("riscv/empty-func.rtl"));
254 set_new_first_and_last_insn (NULL, NULL);
256 machine_mode mode;
257 std::vector<HOST_WIDE_INT> worklist = {-111, -17, -16, 7, 15, 16, 111};
259 FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_INT)
261 if (riscv_v_ext_vector_mode_p (mode))
263 for (const HOST_WIDE_INT &val : worklist)
265 start_sequence ();
266 rtx dest = gen_reg_rtx (mode);
267 rtx dup = gen_const_vec_duplicate (mode, GEN_INT (val));
268 emit_move_insn (dest, dup);
269 rtx_insn *insn = get_last_insn ();
270 rtx src = SET_SRC (PATTERN (insn));
271 /* 1. Should be vmv.v.i for in rang of -16 ~ 15.
272 2. Should be vmv.v.x for exceed -16 ~ 15. */
273 if (IN_RANGE (val, -16, 15))
274 ASSERT_TRUE (
275 rtx_equal_p (XEXP (SET_SRC (PATTERN (insn)), 1), dup));
276 else
277 ASSERT_TRUE (GET_CODE (src) == VEC_DUPLICATE);
278 end_sequence ();
283 FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_FLOAT)
285 if (riscv_v_ext_vector_mode_p (mode))
287 scalar_mode inner_mode = GET_MODE_INNER (mode);
288 REAL_VALUE_TYPE f = REAL_VALUE_ATOF ("0.2928932", inner_mode);
289 rtx ele = const_double_from_real_value (f, inner_mode);
291 start_sequence ();
292 rtx dest = gen_reg_rtx (mode);
293 rtx dup = gen_const_vec_duplicate (mode, ele);
294 emit_move_insn (dest, dup);
295 rtx_insn *insn = get_last_insn ();
296 rtx src = SET_SRC (PATTERN (insn));
297 /* Should always be vfmv.v.f. */
298 ASSERT_TRUE (GET_CODE (src) == VEC_DUPLICATE);
299 end_sequence ();
303 FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_BOOL)
305 /* Test vmset.m. */
306 if (riscv_v_ext_vector_mode_p (mode))
308 start_sequence ();
309 rtx dest = gen_reg_rtx (mode);
310 emit_move_insn (dest, CONSTM1_RTX (mode));
311 rtx_insn *insn = get_last_insn ();
312 rtx src = XEXP (SET_SRC (PATTERN (insn)), 1);
313 ASSERT_TRUE (rtx_equal_p (src, CONSTM1_RTX (mode)));
314 end_sequence ();
319 static void
320 run_broadcast_selftests (void)
322 /* We dont't need to do the redundant tests in different march && mabi.
323 Just pick up the march && mabi which fully support all RVV modes. */
324 riscv_selftest_arch_abi_setter rv ("rv64imafdcv", ABI_LP64D);
325 rtl_dump_test t (SELFTEST_LOCATION, locate_file ("riscv/empty-func.rtl"));
326 set_new_first_and_last_insn (NULL, NULL);
328 machine_mode mode;
330 #define BROADCAST_TEST(MODE_CLASS) \
331 FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_INT) \
333 if (riscv_v_ext_vector_mode_p (mode)) \
335 rtx_insn *insn; \
336 rtx src; \
337 scalar_mode inner_mode = GET_MODE_INNER (mode); \
338 /* Test vlse.v with zero stride. */ \
339 start_sequence (); \
340 rtx addr = gen_reg_rtx (Pmode); \
341 rtx mem = gen_rtx_MEM (inner_mode, addr); \
342 expand_vector_broadcast (mode, mem); \
343 insn = get_last_insn (); \
344 src = SET_SRC (PATTERN (insn)); \
345 ASSERT_TRUE (MEM_P (XEXP (src, 0))); \
346 ASSERT_TRUE ( \
347 rtx_equal_p (src, gen_rtx_VEC_DUPLICATE (mode, XEXP (src, 0)))); \
348 end_sequence (); \
349 /* Test vmv.v.x or vfmv.v.f. */ \
350 start_sequence (); \
351 rtx reg = gen_reg_rtx (inner_mode); \
352 expand_vector_broadcast (mode, reg); \
353 insn = get_last_insn (); \
354 src = SET_SRC (PATTERN (insn)); \
355 ASSERT_TRUE (REG_P (XEXP (src, 0))); \
356 ASSERT_TRUE ( \
357 rtx_equal_p (src, gen_rtx_VEC_DUPLICATE (mode, XEXP (src, 0)))); \
358 end_sequence (); \
362 BROADCAST_TEST (MODE_VECTOR_INT)
363 BROADCAST_TEST (MODE_VECTOR_FLOAT)
366 namespace selftest {
367 /* Run all target-specific selftests. */
368 void
369 riscv_run_selftests (void)
371 if (!BYTES_PER_RISCV_VECTOR.is_constant ())
372 /* We can know POLY value = [4, 4] when BYTES_PER_RISCV_VECTOR
373 is !is_constant () since we can use csrr vlenb and scalar shift
374 instruction to compute such POLY value and store it into a scalar
375 register. Wheras, we can't know [4, 4] on it is specified as
376 FIXED-VLMAX since BYTES_PER_RISCV_VECTOR = 16 for -march=rv64gcv
377 and csrr vlenb is 16 which is totally unrelated to any
378 compile-time unknown POLY value.
380 Since we never need to compute a compile-time unknown POLY value
381 when -mrvv-vector-bits=zvl, disable poly
382 selftests in such situation. */
383 run_poly_int_selftests ();
384 run_const_vector_selftests ();
385 run_broadcast_selftests ();
387 } // namespace selftest
388 #endif /* #if CHECKING_P */