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)
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
21 #define INCLUDE_VECTOR
24 #include "coretypes.h"
28 #include "stringpool.h"
35 #include "selftest-rtl.h"
36 #include "insn-attr.h"
41 using namespace selftest
;
42 class riscv_selftest_arch_abi_setter
45 std::string m_arch_backup
;
46 enum riscv_abi_type m_abi_backup
;
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
);
56 ~riscv_selftest_arch_abi_setter ()
58 riscv_parse_arch_string (m_arch_backup
.c_str (), &global_options
,
60 riscv_abi
= m_abi_backup
;
66 eval_value (rtx x
, std::map
<unsigned, rtx
> ®no_to_rtx
)
75 unsigned regno
= REGNO (x
);
76 expr
= regno_to_rtx
[regno
];
78 poly_int64 op1_val
= 0;
79 poly_int64 op2_val
= 0;
82 op1_val
= eval_value (XEXP (expr
, 0), regno_to_rtx
);
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
))
93 return rtx_to_poly_int64 (expr
);
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 ();
105 return op1_val
+ op2_val
;
111 /* Calculate the value of x register in the sequence. */
113 calculate_x_in_sequence (rtx reg
)
115 std::map
<unsigned, rtx
> regno_to_rtx
;
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
)
128 gcc_assert (REG_P (dest
));
129 rtx note
= find_reg_equal_equiv_note (insn
);
130 unsigned regno
= REGNO (dest
);
132 regno_to_rtx
[regno
] = XEXP (note
, 0);
134 regno_to_rtx
[regno
] = SET_SRC (pat
);
137 return eval_value (reg
, regno_to_rtx
);
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
));
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
;
171 case POLY_TEST_DIMODE
:
174 case POLY_TEST_PMODE
:
181 for (const poly_int64
&poly_val
: worklist
)
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
));
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
,
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
,
233 run_poly_int_selftest ("rv32imafd_zve32x1p0", ABI_ILP32D
, POLY_TEST_DIMODE
,
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
});
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
);
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
)
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))
275 rtx_equal_p (XEXP (SET_SRC (PATTERN (insn
)), 1), dup
));
277 ASSERT_TRUE (GET_CODE (src
) == VEC_DUPLICATE
);
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
);
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
);
303 FOR_EACH_MODE_IN_CLASS (mode
, MODE_VECTOR_BOOL
)
306 if (riscv_v_ext_vector_mode_p (mode
))
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
)));
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
);
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)) \
337 scalar_mode inner_mode = GET_MODE_INNER (mode); \
338 /* Test vlse.v with zero stride. */ \
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))); \
347 rtx_equal_p (src, gen_rtx_VEC_DUPLICATE (mode, XEXP (src, 0)))); \
349 /* Test vmv.v.x or vfmv.v.f. */ \
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))); \
357 rtx_equal_p (src, gen_rtx_VEC_DUPLICATE (mode, XEXP (src, 0)))); \
362 BROADCAST_TEST (MODE_VECTOR_INT
)
363 BROADCAST_TEST (MODE_VECTOR_FLOAT
)
367 /* Run all target-specific selftests. */
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 */