https://gcc.gnu.org/g:5dbc6f027e972f9311caa291b01d38f6ea4284af
commit r17-5255-g5dbc6f027e972f9311caa291b01d38f6ea4284af Author: Zhongyao Chen <[email protected]> Date: Wed Sep 30 03:47:16 2026 +0000 RISC-V: Support vector initialization from two halves This patch adds vec_concat and vec_init expanders to construct a full vector from two half-width vectors (e.g. [0 1 2 3] + [4 5 6 7] -> [0 1 2 3 4 5 6 7]) via vslideup. Key changes: - Implement @vec_concat and vec_init expanders, restricted to LMUL <= 1. - Extend VLS_HAS_HALF to include Float16 (HF) and BFloat16 (BF) modes. - Add VLA_HAS_HALF to support VLA modes. - Unify them under V_HAS_HALF and generalize V_HALF/v_half (also updating vec_extract). - Update comments in shuffle_even_odd_patterns. Changes in v2: - Restrict vec_concat and vec_init to LMUL <= 1 to avoid multi-register spills. - Revert changes in shuffle_even_odd_patterns: vec_concat doesn't handle mixed modes, using vec_concat while keeping a fallback makes the code messy, so just update comments. - Update vec-concat-1.c slideup expectations and comments. Regtested on rv64gcv. gcc/ChangeLog: * config/riscv/autovec.md (vec_init<mode><v_half>): New expander. (vec_extract<mode><v_half>): Use <V_HALF>. * config/riscv/riscv-v.cc (shuffle_even_odd_patterns): Update comments. * config/riscv/vector.md (@vec_concat<mode>): New expander. * config/riscv/vector-iterators.md (VLS_HAS_HALF): Add HF and BF modes. (VLA_HAS_HALF, V_HAS_HALF): New mode iterators. (V_HALF, v_half): Rename from VLS_HALF and vls_half. gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/autovec/vec-concat-1.c: New test. * gcc.target/riscv/rvv/autovec/vec-concat-2.c: Likewise. Signed-off-by: Zhongyao Chen <[email protected]> Diff: --- gcc/config/riscv/autovec.md | 31 +++- gcc/config/riscv/riscv-v.cc | 10 +- gcc/config/riscv/vector-iterators.md | 201 ++++++++++++++++++++- gcc/config/riscv/vector.md | 24 +++ .../gcc.target/riscv/rvv/autovec/vec-concat-1.c | 68 +++++++ .../gcc.target/riscv/rvv/autovec/vec-concat-2.c | 16 ++ 6 files changed, 338 insertions(+), 12 deletions(-) diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md index 12538c8f162a..f6157b8d4d53 100644 --- a/gcc/config/riscv/autovec.md +++ b/gcc/config/riscv/autovec.md @@ -452,6 +452,27 @@ } ) +;; ------------------------------------------------------------------------- +;; ---- [INT,FP] Initialize from two half-width vectors +;; ------------------------------------------------------------------------- + +(define_expand "vec_init<mode><v_half>" + [(match_operand:V_HAS_HALF 0 "register_operand") + (match_operand 1 "")] + "TARGET_VECTOR + && known_le (GET_MODE_SIZE (<MODE>mode), + riscv_regmode_natural_size (<MODE>mode))" +{ + gcc_assert (GET_CODE (operands[1]) == PARALLEL); + gcc_assert (XVECLEN (operands[1], 0) == 2); + + rtx low = force_reg (<V_HALF>mode, XVECEXP (operands[1], 0, 0)); + rtx high = force_reg (<V_HALF>mode, XVECEXP (operands[1], 0, 1)); + + emit_insn (gen_vec_concat (<MODE>mode, operands[0], low, high)); + DONE; +}) + ;; Slide an RVV vector left and insert a scalar into element 0. (define_expand "vec_shl_insert_<mode>" [(match_operand:V_VLSI 0 "register_operand") @@ -1523,15 +1544,15 @@ ;; For now this helps optimize VLS subregs like (subreg:V2DI (reg:V4DI) 16) ;; that would otherwise need to go via memory. -(define_expand "vec_extract<mode><vls_half>" - [(set (match_operand:<VLS_HALF> 0 "nonimmediate_operand") - (vec_select:<VLS_HALF> +(define_expand "vec_extract<mode><v_half>" + [(set (match_operand:<V_HALF> 0 "nonimmediate_operand") + (vec_select:<V_HALF> (match_operand:VLS_HAS_HALF 1 "register_operand") (parallel [(match_operand 2 "immediate_operand")])))] "TARGET_VECTOR" { - int sz = GET_MODE_NUNITS (<VLS_HALF>mode).to_constant (); + int sz = GET_MODE_NUNITS (<V_HALF>mode).to_constant (); int part = INTVAL (operands[2]); rtx start = GEN_INT (part * sz); @@ -1547,7 +1568,7 @@ riscv_vector::BINARY_OP, ops); } - emit_move_insn (operands[0], gen_lowpart (<VLS_HALF>mode, tmp)); + emit_move_insn (operands[0], gen_lowpart (<V_HALF>mode, tmp)); DONE; }) diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc index dd453aa320b6..7cccc09dc229 100644 --- a/gcc/config/riscv/riscv-v.cc +++ b/gcc/config/riscv/riscv-v.cc @@ -4058,9 +4058,8 @@ shuffle_even_odd_patterns (struct expand_vec_perm_d *d) vnsrl instructions, each extracting the even/odd elements of one source, and a vslideup instruction to merge them into one vector. - Until we have a "widening" vector concat pattern (just like slideup here - but with the proper modes) we still need the natural-size check for - LMUL > 1 cases. */ + We still need the natural-size check to avoid multi-register spills + for LMUL > 1 cases. */ unsigned int max_elen = TARGET_VECTOR_ELEN_64 ? 64 : 32; if (GET_MODE_BITSIZE (GET_MODE_INNER (vmode)) * 2 <= max_elen && known_le (GET_MODE_SIZE (vmode), riscv_regmode_natural_size (vmode))) @@ -4074,8 +4073,9 @@ shuffle_even_odd_patterns (struct expand_vec_perm_d *d) machine_mode vmode_half = get_vector_mode (smode, vlen / 2).require (); unsigned int shift_amt = even ? 0 : elen; insn_code icode = code_for_pred_narrow_scalar (LSHIFTRT, vmode_elen2x); - /* TODO these lowpart subreg workarounds should go, this is actually a - simple concatenation of two "half"-sized vectors. */ + /* TODO: Although vec_concat is supported, it does not cover mixed + VLA/VLS modes under -mrvv-vector-bits=zvl. Keep these lowpart + subreg workarounds for now. */ rtx tmp = gen_reg_rtx (vmode); rtx ops_shift1[] = {gen_lowpart (vmode_half, d->target), diff --git a/gcc/config/riscv/vector-iterators.md b/gcc/config/riscv/vector-iterators.md index f236e71c67c7..c0475b6b72af 100644 --- a/gcc/config/riscv/vector-iterators.md +++ b/gcc/config/riscv/vector-iterators.md @@ -6012,6 +6012,14 @@ (V4DI "riscv_vector::vls_mode_valid_p (V4DImode) && TARGET_VECTOR_ELEN_64") (V8DI "riscv_vector::vls_mode_valid_p (V8DImode) && TARGET_VECTOR_ELEN_64 && TARGET_MIN_VLEN >= 64") (V16DI "riscv_vector::vls_mode_valid_p (V16DImode) && TARGET_VECTOR_ELEN_64 && TARGET_MIN_VLEN >= 128") + (V2HF "riscv_vector::vls_mode_valid_p (V2HFmode) && TARGET_VECTOR_ELEN_FP_16") + (V4HF "riscv_vector::vls_mode_valid_p (V4HFmode) && TARGET_VECTOR_ELEN_FP_16") + (V8HF "riscv_vector::vls_mode_valid_p (V8HFmode) && TARGET_VECTOR_ELEN_FP_16") + (V16HF "riscv_vector::vls_mode_valid_p (V16HFmode) && TARGET_VECTOR_ELEN_FP_16") + (V2BF "riscv_vector::vls_mode_valid_p (V2BFmode) && TARGET_VECTOR_ELEN_BF_16") + (V4BF "riscv_vector::vls_mode_valid_p (V4BFmode) && TARGET_VECTOR_ELEN_BF_16") + (V8BF "riscv_vector::vls_mode_valid_p (V8BFmode) && TARGET_VECTOR_ELEN_BF_16") + (V16BF "riscv_vector::vls_mode_valid_p (V16BFmode) && TARGET_VECTOR_ELEN_BF_16") (V2SF "riscv_vector::vls_mode_valid_p (V2SFmode) && TARGET_VECTOR_ELEN_FP_32") (V4SF "riscv_vector::vls_mode_valid_p (V4SFmode) && TARGET_VECTOR_ELEN_FP_32") (V8SF "riscv_vector::vls_mode_valid_p (V8SFmode) && TARGET_VECTOR_ELEN_FP_32") @@ -6046,6 +6054,20 @@ (V128DI "riscv_vector::vls_mode_valid_p (V128DImode) && TARGET_VECTOR_ELEN_64 && TARGET_MIN_VLEN >= 1024") (V256DI "riscv_vector::vls_mode_valid_p (V256DImode) && TARGET_VECTOR_ELEN_64 && TARGET_MIN_VLEN >= 2048") (V512DI "riscv_vector::vls_mode_valid_p (V512DImode) && TARGET_VECTOR_ELEN_64 && TARGET_MIN_VLEN >= 4096") + (V32HF "riscv_vector::vls_mode_valid_p (V32HFmode) && TARGET_VECTOR_ELEN_FP_16 && TARGET_MIN_VLEN >= 64") + (V64HF "riscv_vector::vls_mode_valid_p (V64HFmode) && TARGET_VECTOR_ELEN_FP_16 && TARGET_MIN_VLEN >= 128") + (V128HF "riscv_vector::vls_mode_valid_p (V128HFmode) && TARGET_VECTOR_ELEN_FP_16 && TARGET_MIN_VLEN >= 256") + (V256HF "riscv_vector::vls_mode_valid_p (V256HFmode) && TARGET_VECTOR_ELEN_FP_16 && TARGET_MIN_VLEN >= 512") + (V512HF "riscv_vector::vls_mode_valid_p (V512HFmode) && TARGET_VECTOR_ELEN_FP_16 && TARGET_MIN_VLEN >= 1024") + (V1024HF "riscv_vector::vls_mode_valid_p (V1024HFmode) && TARGET_VECTOR_ELEN_FP_16 && TARGET_MIN_VLEN >= 2048") + (V2048HF "riscv_vector::vls_mode_valid_p (V2048HFmode) && TARGET_VECTOR_ELEN_FP_16 && TARGET_MIN_VLEN >= 4096") + (V32BF "riscv_vector::vls_mode_valid_p (V32BFmode) && TARGET_VECTOR_ELEN_BF_16 && TARGET_MIN_VLEN >= 64") + (V64BF "riscv_vector::vls_mode_valid_p (V64BFmode) && TARGET_VECTOR_ELEN_BF_16 && TARGET_MIN_VLEN >= 128") + (V128BF "riscv_vector::vls_mode_valid_p (V128BFmode) && TARGET_VECTOR_ELEN_BF_16 && TARGET_MIN_VLEN >= 256") + (V256BF "riscv_vector::vls_mode_valid_p (V256BFmode) && TARGET_VECTOR_ELEN_BF_16 && TARGET_MIN_VLEN >= 512") + (V512BF "riscv_vector::vls_mode_valid_p (V512BFmode) && TARGET_VECTOR_ELEN_BF_16 && TARGET_MIN_VLEN >= 1024") + (V1024BF "riscv_vector::vls_mode_valid_p (V1024BFmode) && TARGET_VECTOR_ELEN_BF_16 && TARGET_MIN_VLEN >= 2048") + (V2048BF "riscv_vector::vls_mode_valid_p (V2048BFmode) && TARGET_VECTOR_ELEN_BF_16 && TARGET_MIN_VLEN >= 4096") (V32SF "riscv_vector::vls_mode_valid_p (V32SFmode) && TARGET_VECTOR_ELEN_FP_32 && TARGET_MIN_VLEN >= 128") (V64SF "riscv_vector::vls_mode_valid_p (V64SFmode) && TARGET_VECTOR_ELEN_FP_32 && TARGET_MIN_VLEN >= 256") (V128SF "riscv_vector::vls_mode_valid_p (V128SFmode) && TARGET_VECTOR_ELEN_FP_32 && TARGET_MIN_VLEN >= 512") @@ -6059,7 +6081,98 @@ (V512DF "riscv_vector::vls_mode_valid_p (V512DFmode) && TARGET_VECTOR_ELEN_FP_64 && TARGET_MIN_VLEN >= 4096") ]) -(define_mode_attr VLS_HALF [ +;; Scalable (VLA) vector modes with a supported half-width vector. +(define_mode_iterator VLA_HAS_HALF [ + RVVM8QI + RVVM4QI + RVVM2QI + (RVVM1QI "!TARGET_XTHEADVECTOR") + (RVVMF2QI "!TARGET_XTHEADVECTOR") + (RVVMF4QI "!TARGET_XTHEADVECTOR && TARGET_VECTOR_ELEN_64") + + RVVM8HI + RVVM4HI + RVVM2HI + (RVVM1HI "!TARGET_XTHEADVECTOR") + (RVVMF2HI "!TARGET_XTHEADVECTOR && TARGET_VECTOR_ELEN_64") + + RVVM8SI + RVVM4SI + RVVM2SI + (RVVM1SI "!TARGET_XTHEADVECTOR && TARGET_VECTOR_ELEN_64") + + (RVVM8DI "TARGET_VECTOR_ELEN_64") + (RVVM4DI "TARGET_VECTOR_ELEN_64") + (RVVM2DI "TARGET_VECTOR_ELEN_64") + + (RVVM8HF "TARGET_VECTOR_ELEN_FP_16") + (RVVM4HF "TARGET_VECTOR_ELEN_FP_16") + (RVVM2HF "TARGET_VECTOR_ELEN_FP_16") + (RVVM1HF "TARGET_VECTOR_ELEN_FP_16 && !TARGET_XTHEADVECTOR") + (RVVMF2HF "TARGET_VECTOR_ELEN_FP_16 && !TARGET_XTHEADVECTOR + && TARGET_VECTOR_ELEN_64") + + (RVVM8BF "TARGET_VECTOR_ELEN_BF_16") + (RVVM4BF "TARGET_VECTOR_ELEN_BF_16") + (RVVM2BF "TARGET_VECTOR_ELEN_BF_16") + (RVVM1BF "TARGET_VECTOR_ELEN_BF_16 && !TARGET_XTHEADVECTOR") + (RVVMF2BF "TARGET_VECTOR_ELEN_BF_16 && !TARGET_XTHEADVECTOR + && TARGET_VECTOR_ELEN_64") + + (RVVM8SF "TARGET_VECTOR_ELEN_FP_32") + (RVVM4SF "TARGET_VECTOR_ELEN_FP_32") + (RVVM2SF "TARGET_VECTOR_ELEN_FP_32") + (RVVM1SF "TARGET_VECTOR_ELEN_FP_32 && !TARGET_XTHEADVECTOR + && TARGET_VECTOR_ELEN_64") + + (RVVM8DF "TARGET_VECTOR_ELEN_FP_64") + (RVVM4DF "TARGET_VECTOR_ELEN_FP_64") + (RVVM2DF "TARGET_VECTOR_ELEN_FP_64") +]) + +;; All vector modes (VLS and VLA) with a supported half-width vector. +(define_mode_iterator V_HAS_HALF [ + VLS_HAS_HALF + VLA_HAS_HALF +]) + +(define_mode_attr V_HALF [ + (RVVM8QI "RVVM4QI") + (RVVM4QI "RVVM2QI") + (RVVM2QI "RVVM1QI") + (RVVM1QI "RVVMF2QI") + (RVVMF2QI "RVVMF4QI") + (RVVMF4QI "RVVMF8QI") + (RVVM8HI "RVVM4HI") + (RVVM4HI "RVVM2HI") + (RVVM2HI "RVVM1HI") + (RVVM1HI "RVVMF2HI") + (RVVMF2HI "RVVMF4HI") + (RVVM8SI "RVVM4SI") + (RVVM4SI "RVVM2SI") + (RVVM2SI "RVVM1SI") + (RVVM1SI "RVVMF2SI") + (RVVM8DI "RVVM4DI") + (RVVM4DI "RVVM2DI") + (RVVM2DI "RVVM1DI") + (RVVM8HF "RVVM4HF") + (RVVM4HF "RVVM2HF") + (RVVM2HF "RVVM1HF") + (RVVM1HF "RVVMF2HF") + (RVVMF2HF "RVVMF4HF") + (RVVM8BF "RVVM4BF") + (RVVM4BF "RVVM2BF") + (RVVM2BF "RVVM1BF") + (RVVM1BF "RVVMF2BF") + (RVVMF2BF "RVVMF4BF") + (RVVM8SF "RVVM4SF") + (RVVM4SF "RVVM2SF") + (RVVM2SF "RVVM1SF") + (RVVM1SF "RVVMF2SF") + (RVVM8DF "RVVM4DF") + (RVVM4DF "RVVM2DF") + (RVVM2DF "RVVM1DF") + (V2QI "V1QI") (V4QI "V2QI") (V8QI "V4QI") @@ -6106,6 +6219,30 @@ (V256DI "V128DI") (V512DI "V256DI") + (V2HF "V1HF") + (V4HF "V2HF") + (V8HF "V4HF") + (V16HF "V8HF") + (V32HF "V16HF") + (V64HF "V32HF") + (V128HF "V64HF") + (V256HF "V128HF") + (V512HF "V256HF") + (V1024HF "V512HF") + (V2048HF "V1024HF") + + (V2BF "V1BF") + (V4BF "V2BF") + (V8BF "V4BF") + (V16BF "V8BF") + (V32BF "V16BF") + (V64BF "V32BF") + (V128BF "V64BF") + (V256BF "V128BF") + (V512BF "V256BF") + (V1024BF "V512BF") + (V2048BF "V1024BF") + (V2SF "V1SF") (V4SF "V2SF") (V8SF "V4SF") @@ -6128,7 +6265,43 @@ (V512DF "V256DF") ]) -(define_mode_attr vls_half [ +(define_mode_attr v_half [ + (RVVM8QI "rvvm4qi") + (RVVM4QI "rvvm2qi") + (RVVM2QI "rvvm1qi") + (RVVM1QI "rvvmf2qi") + (RVVMF2QI "rvvmf4qi") + (RVVMF4QI "rvvmf8qi") + (RVVM8HI "rvvm4hi") + (RVVM4HI "rvvm2hi") + (RVVM2HI "rvvm1hi") + (RVVM1HI "rvvmf2hi") + (RVVMF2HI "rvvmf4hi") + (RVVM8SI "rvvm4si") + (RVVM4SI "rvvm2si") + (RVVM2SI "rvvm1si") + (RVVM1SI "rvvmf2si") + (RVVM8DI "rvvm4di") + (RVVM4DI "rvvm2di") + (RVVM2DI "rvvm1di") + (RVVM8HF "rvvm4hf") + (RVVM4HF "rvvm2hf") + (RVVM2HF "rvvm1hf") + (RVVM1HF "rvvmf2hf") + (RVVMF2HF "rvvmf4hf") + (RVVM8BF "rvvm4bf") + (RVVM4BF "rvvm2bf") + (RVVM2BF "rvvm1bf") + (RVVM1BF "rvvmf2bf") + (RVVMF2BF "rvvmf4bf") + (RVVM8SF "rvvm4sf") + (RVVM4SF "rvvm2sf") + (RVVM2SF "rvvm1sf") + (RVVM1SF "rvvmf2sf") + (RVVM8DF "rvvm4df") + (RVVM4DF "rvvm2df") + (RVVM2DF "rvvm1df") + (V2QI "v1qi") (V4QI "v2qi") (V8QI "v4qi") @@ -6175,6 +6348,30 @@ (V256DI "v128di") (V512DI "v256di") + (V2HF "v1hf") + (V4HF "v2hf") + (V8HF "v4hf") + (V16HF "v8hf") + (V32HF "v16hf") + (V64HF "v32hf") + (V128HF "v64hf") + (V256HF "v128hf") + (V512HF "v256hf") + (V1024HF "v512hf") + (V2048HF "v1024hf") + + (V2BF "v1bf") + (V4BF "v2bf") + (V8BF "v4bf") + (V16BF "v8bf") + (V32BF "v16bf") + (V64BF "v32bf") + (V128BF "v64bf") + (V256BF "v128bf") + (V512BF "v256bf") + (V1024BF "v512bf") + (V2048BF "v1024bf") + (V2SF "v1sf") (V4SF "v2sf") (V8SF "v4sf") diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md index a3eeb84231ba..b994125fe088 100644 --- a/gcc/config/riscv/vector.md +++ b/gcc/config/riscv/vector.md @@ -8371,6 +8371,30 @@ [(set_attr "type" "vfmovvf") (set_attr "mode" "<MODE>")]) +;; Concatenate two half-width vectors via vslideup. +(define_expand "@vec_concat<mode>" + [(set (match_operand:V_HAS_HALF 0 "register_operand") + (vec_concat:V_HAS_HALF + (match_operand:<V_HALF> 1 "register_operand") + (match_operand:<V_HALF> 2 "register_operand")))] + "TARGET_VECTOR + && known_le (GET_MODE_SIZE (<MODE>mode), + riscv_regmode_natural_size (<MODE>mode))" +{ + rtx low = gen_reg_rtx (<MODE>mode); + rtx high = gen_reg_rtx (<MODE>mode); + emit_clobber (low); + emit_move_insn (gen_lowpart (<V_HALF>mode, low), operands[1]); + emit_clobber (high); + emit_move_insn (gen_lowpart (<V_HALF>mode, high), operands[2]); + rtx offset = gen_int_mode (GET_MODE_NUNITS (<V_HALF>mode), Pmode); + rtx ops[] = {operands[0], low, high, offset}; + insn_code icode = code_for_pred_slide (UNSPEC_VSLIDEUP, <MODE>mode); + riscv_vector::emit_vlmax_insn (icode, + riscv_vector::SLIDEUP_OP_MERGE, ops); + DONE; +}) + ;; vslide instructions (define_insn "@pred_slide<ud><mode>" [(set (match_operand:V_VLS 0 "register_operand" "<ud_constraint>") diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vec-concat-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vec-concat-1.c new file mode 100644 index 000000000000..0fdd169bcef5 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vec-concat-1.c @@ -0,0 +1,68 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv64gcv_zvfhmin_zvfbfmin -mabi=lp64d -mrvv-vector-bits=scalable -mrvv-max-lmul=m8" } */ + +/* Test VLS vector concatenation via shufflevector across all data types. */ + +#define INDICES_2(x) (x), (x + 1) +#define INDICES_4(x) INDICES_2 (x), INDICES_2 (x + 2) +#define INDICES_8(x) INDICES_4 (x), INDICES_4 (x + 4) +#define INDICES_16(x) INDICES_8 (x), INDICES_8 (x + 8) +#define INDICES_32(x) INDICES_16 (x), INDICES_16 (x + 16) +#define INDICES_64(x) INDICES_32 (x), INDICES_32 (x + 32) + +#define TEST_MODES(T) \ + T (signed char, qi, 2) \ + T (signed char, qi, 4) \ + T (signed char, qi, 8) \ + T (signed char, qi, 16) \ + T (signed char, qi, 32) \ + T (signed char, qi, 64) \ + T (short, hi, 2) \ + T (short, hi, 4) \ + T (short, hi, 8) \ + T (short, hi, 16) \ + T (short, hi, 32) \ + T (int, si, 2) \ + T (int, si, 4) \ + T (int, si, 8) \ + T (int, si, 16) \ + T (long long, di, 2) \ + T (long long, di, 4) \ + T (long long, di, 8) \ + T (float, sf, 2) \ + T (float, sf, 4) \ + T (float, sf, 8) \ + T (float, sf, 16) \ + T (double, df, 2) \ + T (double, df, 4) \ + T (double, df, 8) \ + T (_Float16, hf, 2) \ + T (_Float16, hf, 4) \ + T (_Float16, hf, 8) \ + T (_Float16, hf, 16) \ + T (_Float16, hf, 32) \ + T (__bf16, bf, 2) \ + T (__bf16, bf, 4) \ + T (__bf16, bf, 8) \ + T (__bf16, bf, 16) \ + T (__bf16, bf, 32) + +#define DEF_CONCAT(TYPE, ID, N) \ + typedef TYPE half_##ID##N \ + __attribute__ ((vector_size (N * sizeof (TYPE)))); \ + typedef TYPE full_##ID##N \ + __attribute__ ((vector_size (2 * N * sizeof (TYPE)))); \ + __attribute__ ((noipa)) full_##ID##N \ + concat_##ID##N (half_##ID##N a, half_##ID##N b) \ + { \ + return __builtin_shufflevector (a, b, INDICES_##N (0), INDICES_##N (N)); \ + } + +TEST_MODES (DEF_CONCAT) + +/* LMUL <= 1: 11 funcs x 3 slideups (using vec_concat, from spills + 1 slideup + to no spills + 3 slideups). + LMUL > 1: 24 funcs x 1 slideup (no vec_concat, using fallback instead, + nothing changed from trunk). */ +/* { dg-final { scan-assembler-times "vslideup" 57 } } */ +/* { dg-final { scan-assembler-not "vslide1down" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vec-concat-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vec-concat-2.c new file mode 100644 index 000000000000..deab622faecb --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vec-concat-2.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=rv64gcv -mabi=lp64d -mrvv-vector-bits=scalable -mrvv-max-lmul=m1 -fno-vect-cost-model -fdump-tree-vect-details" } */ + +__attribute__ ((noipa)) void +test_strided_concat (int *restrict dst, const int *restrict src, long stride) +{ +#pragma GCC unroll 1 + for (int i = 0; i < 32; ++i) + { + dst[2 * i] = src[i * stride]; + dst[2 * i + 1] = src[i * stride + 1]; + } +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */ +/* { dg-final { scan-assembler-times "vslideup" 1 } } */
