Thanks. The attached v2 goes with your suggestion and adds a vec_extract<mode>bi expander. Apart from that it keeps the MODE_PRECISION changes from before and uses insn_data[icode].operand[0]'s mode.
Apart from that no changes on the riscv side. Bootstrapped and regtested on x86 and aarch64. On cfarm185 (aarch64) I saw several segmentation faults that only were internal compiler errors in the unpatched run but they didn't seem related to my patch at all. It looks like several patches aarch64 testsuite patches have landed in the past days so I can re-try tomorrow or so. Regtested on riscv64. Regards Robin Subject: [PATCH v2] expmed: Use GET_MODE_PRECISION and expander's output mode. This changes the vec_extract path of extract_bit_field to use GET_MODE_PRECISION instead of GET_MODE_BITSIZE and uses the mode obtained from insn_data[icode].operand[0] as target mode. Also, it adds a vec_extract<mode>bi expander for riscv that maps to vec_extract<mode>qi. This fixes an ICE on riscv where we did not find a vec_extract optab and continued with the generic code which requires 1-byte alignment that riscv mask modes do not provide. Apart from that it adds poly_int support to riscv's vec_extract expander and makes the RVV..BImode -> QImode expander call emit_vec_extract in order not to duplicate code. gcc/ChangeLog: PR target/112773 * config/riscv/autovec.md (vec_extract<mode>bi): New expander calling vec_extract<mode>qi. * config/riscv/riscv-protos.h (riscv_legitimize_poly_move): Export. (emit_vec_extract): Change argument from poly_int64 to rtx. * config/riscv/riscv-v.cc (shuffle_extract_and_slide1up_patterns): Ditto. * config/riscv/riscv.cc (riscv_legitimize_poly_move): Export. (riscv_legitimize_move): Use rtx instead of poly_int64. * expmed.cc (store_bit_field_1): Change BITSIZE to PRECISION. (extract_bit_field_1): Change BITSIZE to PRECISION and use return mode from insn_data as target mode. gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/autovec/partial/pr112773.c: New test. --- gcc/config/riscv/autovec.md | 46 +++++++++++++------ gcc/config/riscv/riscv-protos.h | 3 +- gcc/config/riscv/riscv-v.cc | 14 +++--- gcc/config/riscv/riscv.cc | 6 +-- gcc/expmed.cc | 18 +++++--- .../riscv/rvv/autovec/partial/pr112773.c | 20 ++++++++ 6 files changed, 75 insertions(+), 32 deletions(-) create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/partial/pr112773.c diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md index 55d3ae50c8b..8b8a92f10a1 100644 --- a/gcc/config/riscv/autovec.md +++ b/gcc/config/riscv/autovec.md @@ -1396,12 +1396,23 @@ (define_expand "vec_extract<mode><vel>" rtx tmp = NULL_RTX; if (operands[2] != const0_rtx) { - /* Emit the slide down to index 0 in a new vector. */ - tmp = gen_reg_rtx (<MODE>mode); - operands[2] = gen_lowpart (Pmode, operands[2]); - rtx ops[] = {tmp, operands[1], operands[2]}; - riscv_vector::emit_vlmax_insn - (code_for_pred_slide (UNSPEC_VSLIDEDOWN, <MODE>mode), riscv_vector::BINARY_OP, ops); + /* Properly convert a poly_int value and put the result into a + register. */ + if (CONST_POLY_INT_P (operands[2])) + { + rtx pos = gen_reg_rtx (Pmode); + riscv_legitimize_poly_move (Pmode, pos, gen_reg_rtx (Pmode), + operands[2]); + operands[2] = pos; + } + + /* Emit the slide down to index 0 in a new vector. */ + tmp = gen_reg_rtx (<MODE>mode); + operands[2] = gen_lowpart (Pmode, operands[2]); + rtx ops[] = {tmp, operands[1], operands[2]}; + riscv_vector::emit_vlmax_insn + (code_for_pred_slide (UNSPEC_VSLIDEDOWN, <MODE>mode), + riscv_vector::BINARY_OP, ops); } /* Emit v(f)mv.[xf].s. */ @@ -1433,16 +1444,21 @@ (define_expand "vec_extract<mode>qi" riscv_vector::emit_vlmax_insn (code_for_pred_merge (qimode), riscv_vector::MERGE_OP, ops1); - /* Slide down the requested byte element. */ - rtx tmp2 = gen_reg_rtx (qimode); - - rtx ops2[] = {tmp2, tmp1, operands[2]}; - riscv_vector::emit_vlmax_insn - (code_for_pred_slide (UNSPEC_VSLIDEDOWN, qimode), - riscv_vector::BINARY_OP, ops2); + /* Extract from it. */ + riscv_vector::emit_vec_extract (operands[0], tmp1, operands[2]); + DONE; +}) - /* Extract it. */ - emit_insn (gen_pred_extract_first (qimode, operands[0], tmp2)); +;; Same for a BImode but still return a QImode. +(define_expand "vec_extract<mode>bi" + [(set (match_operand:QI 0 "register_operand") + (vec_select:QI + (match_operand:VB 1 "register_operand") + (parallel + [(match_operand 2 "nonmemory_operand")])))] + "TARGET_VECTOR" +{ + emit_insn (gen_vec_extract<mode>qi (operands[0], operands[1], operands[2])); DONE; }) diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index 20bbb5b859c..83515c9b8e1 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -129,6 +129,7 @@ extern void riscv_asm_output_alias (FILE *, const tree, const tree); extern void riscv_asm_output_external (FILE *, const tree, const char *); extern bool riscv_zcmp_valid_stack_adj_bytes_p (HOST_WIDE_INT, int); +extern void riscv_legitimize_poly_move (machine_mode, rtx, rtx, rtx); #ifdef RTX_CODE extern void riscv_expand_int_scc (rtx, enum rtx_code, rtx, rtx, bool *invert_ptr = 0); @@ -559,7 +560,7 @@ void expand_cond_ternop (unsigned, rtx *); void expand_popcount (rtx *); void expand_rawmemchr (machine_mode, rtx, rtx, rtx, bool = false); bool expand_strcmp (rtx, rtx, rtx, rtx, unsigned HOST_WIDE_INT, bool); -void emit_vec_extract (rtx, rtx, poly_int64); +void emit_vec_extract (rtx, rtx, rtx); /* Rounding mode bitfield for fixed point VXRM. */ enum fixed_point_rounding_mode diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc index 944b37b5df7..e18c758d1fd 100644 --- a/gcc/config/riscv/riscv-v.cc +++ b/gcc/config/riscv/riscv-v.cc @@ -3420,7 +3420,7 @@ shuffle_extract_and_slide1up_patterns (struct expand_vec_perm_d *d) /* Extract the last element of the first vector. */ scalar_mode smode = GET_MODE_INNER (d->vmode); rtx tmp = gen_reg_rtx (smode); - emit_vec_extract (tmp, d->op0, nunits - 1); + emit_vec_extract (tmp, d->op0, gen_int_mode (nunits - 1, Pmode)); /* Insert the scalar into element 0. */ unsigned int unspec @@ -4887,9 +4887,8 @@ can_be_broadcasted_p (rtx op) return can_create_pseudo_p () && nonmemory_operand (op, mode); } -/* Helper function to emit vec_extract_optab. */ void -emit_vec_extract (rtx target, rtx src, poly_int64 index) +emit_vec_extract (rtx target, rtx src, rtx index) { machine_mode vmode = GET_MODE (src); machine_mode smode = GET_MODE (target); @@ -4900,10 +4899,13 @@ emit_vec_extract (rtx target, rtx src, poly_int64 index) create_output_operand (&ops[0], target, smode); ops[0].target = 1; create_input_operand (&ops[1], src, vmode); - if (index.is_constant ()) - create_integer_operand (&ops[2], index); + + poly_int64 val; + if (poly_int_rtx_p (index, &val)) + create_integer_operand (&ops[2], val); else - create_input_operand (&ops[2], gen_int_mode (index, Pmode), Pmode); + create_input_operand (&ops[2], index, Pmode); + expand_insn (icode, 3, ops); if (ops[0].value != target) emit_move_insn (target, ops[0].value); diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 3f111fa0393..84771ee98bc 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -431,7 +431,6 @@ static const struct riscv_tune_param optimize_size_tune_info = { static bool riscv_avoid_shrink_wrapping_separate (); static tree riscv_handle_fndecl_attribute (tree *, tree, tree, int, bool *); static tree riscv_handle_type_attribute (tree *, tree, tree, int, bool *); -static void riscv_legitimize_poly_move (machine_mode, rtx, rtx, rtx); /* Defining target-specific uses of __attribute__. */ TARGET_GNU_ATTRIBUTES (riscv_attribute_table, @@ -2422,7 +2421,7 @@ riscv_expand_mult_with_const_int (machine_mode mode, rtx dest, rtx multiplicand, /* Analyze src and emit const_poly_int mov sequence. */ -static void +void riscv_legitimize_poly_move (machine_mode mode, rtx dest, rtx tmp, rtx src) { poly_int64 value = rtx_to_poly_int64 (src); @@ -2637,7 +2636,8 @@ riscv_legitimize_move (machine_mode mode, rtx dest, rtx src) else result = gen_reg_rtx (smode); - riscv_vector::emit_vec_extract (result, v, index + i); + riscv_vector::emit_vec_extract (result, v, + gen_int_mode (index + i, Pmode)); if (i == 1) { diff --git a/gcc/expmed.cc b/gcc/expmed.cc index b294eabb08d..ed17850ff74 100644 --- a/gcc/expmed.cc +++ b/gcc/expmed.cc @@ -43,6 +43,7 @@ along with GCC; see the file COPYING3. If not see #include "expr.h" #include "langhooks.h" #include "tree-vector-builder.h" +#include "recog.h" struct target_expmed default_target_expmed; #if SWITCHABLE_TARGET @@ -772,8 +773,8 @@ store_bit_field_1 (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum, && !MEM_P (op0) && optab_handler (vec_set_optab, outermode) != CODE_FOR_nothing && fieldmode == innermode - && known_eq (bitsize, GET_MODE_BITSIZE (innermode)) - && multiple_p (bitnum, GET_MODE_BITSIZE (innermode), &pos)) + && known_eq (bitsize, GET_MODE_PRECISION (innermode)) + && multiple_p (bitnum, GET_MODE_PRECISION (innermode), &pos)) { class expand_operand ops[3]; enum insn_code icode = optab_handler (vec_set_optab, outermode); @@ -1675,7 +1676,7 @@ extract_bit_field_1 (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum, if (VECTOR_MODE_P (GET_MODE (op0)) && !MEM_P (op0) && VECTOR_MODE_P (tmode) - && known_eq (bitsize, GET_MODE_BITSIZE (tmode)) + && known_eq (bitsize, GET_MODE_PRECISION (tmode)) && maybe_gt (GET_MODE_SIZE (GET_MODE (op0)), GET_MODE_SIZE (tmode))) { machine_mode new_mode = GET_MODE (op0); @@ -1758,16 +1759,19 @@ extract_bit_field_1 (rtx str_rtx, poly_uint64 bitsize, poly_uint64 bitnum, if (VECTOR_MODE_P (outermode) && !MEM_P (op0)) { scalar_mode innermode = GET_MODE_INNER (outermode); enum insn_code icode = convert_optab_handler (vec_extract_optab, outermode, innermode); poly_uint64 pos; - if (icode != CODE_FOR_nothing - && known_eq (bitsize, GET_MODE_BITSIZE (innermode)) - && multiple_p (bitnum, GET_MODE_BITSIZE (innermode), &pos)) + if ((icode != CODE_FOR_nothing + && known_eq (bitsize, GET_MODE_PRECISION (innermode)) + && multiple_p (bitnum, GET_MODE_PRECISION (innermode), &pos))) { class expand_operand ops[3]; - create_output_operand (&ops[0], target, innermode); + create_output_operand (&ops[0], target, + insn_data[icode].operand[0].mode); ops[0].target = 1; create_input_operand (&ops[1], op0, outermode); create_integer_operand (&ops[2], pos); diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/partial/pr112773.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/partial/pr112773.c new file mode 100644 index 00000000000..5f7374b0040 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/partial/pr112773.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv32gcv_zvl256b -mabi=ilp32d -O3" } */ + +long long a; +int b, c; +int *d; +void e(unsigned f) { + for (;; ++c) + if (f) { + a = 0; + for (; a <= 3; a++) { + f = 0; + for (; f <= 0; f++) + if ((long)a) + break; + } + if (b) + *d = f; + } +} -- 2.43.0