From d0a5e8e1a84bdd6ce915c3be65da8af2552cd49e Mon Sep 17 00:00:00 2001 From: Xionghu Luo Date: Sun, 21 Mar 2021 21:14:02 -0500 Subject: [PATCH] rs6000: Convert the vector set variable idx to DImode [PR98914] vec_insert defines the element argument type to be signed int by ELFv2 ABI. When expanding a vector with a variable rtx, convert the rtx type to DImode to support both intrinsic usage and other callers from rs6000_expand_vector_init produced by v[k] = val when k is long type. gcc/ChangeLog: 2021-03-21 Xionghu Luo PR target/98914 * config/rs6000/rs6000.c (rs6000_expand_vector_set_var_p9): Convert idx to DImode. (rs6000_expand_vector_set_var_p8): Likewise. gcc/testsuite/ChangeLog: 2021-03-21 Xionghu Luo PR target/98914 * gcc.target/powerpc/pr98914.c: New test. --- gcc/config/rs6000/rs6000.c | 39 ++++++++++------------ gcc/testsuite/gcc.target/powerpc/pr98914.c | 11 ++++++ 2 files changed, 29 insertions(+), 21 deletions(-) create mode 100644 gcc/testsuite/gcc.target/powerpc/pr98914.c diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 712dd1c460b3..616dae35bae1 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -7026,21 +7026,21 @@ rs6000_expand_vector_set_var_p9 (rtx target, rtx val, rtx idx) gcc_assert (VECTOR_MEM_VSX_P (mode) && !CONST_INT_P (idx)); - gcc_assert (GET_MODE (idx) == E_SImode); - machine_mode inner_mode = GET_MODE (val); - rtx tmp = gen_reg_rtx (GET_MODE (idx)); int width = GET_MODE_SIZE (inner_mode); gcc_assert (width >= 1 && width <= 8); int shift = exact_log2 (width); + + machine_mode idx_mode = GET_MODE (idx); + idx = convert_modes (DImode, idx_mode, idx, 1); + /* Generate the IDX for permute shift, width is the vector element size. idx = idx * width. */ - emit_insn (gen_ashlsi3 (tmp, idx, GEN_INT (shift))); - - tmp = convert_modes (DImode, SImode, tmp, 1); + rtx tmp = gen_reg_rtx (DImode); + emit_insn (gen_ashldi3 (tmp, idx, GEN_INT (shift))); /* lvsr v1,0,idx. */ rtx pcvr = gen_reg_rtx (V16QImode); @@ -7073,28 +7073,26 @@ rs6000_expand_vector_set_var_p8 (rtx target, rtx val, rtx idx) gcc_assert (VECTOR_MEM_VSX_P (mode) && !CONST_INT_P (idx)); - gcc_assert (GET_MODE (idx) == E_SImode); - machine_mode inner_mode = GET_MODE (val); HOST_WIDE_INT mode_mask = GET_MODE_MASK (inner_mode); - rtx tmp = gen_reg_rtx (GET_MODE (idx)); int width = GET_MODE_SIZE (inner_mode); - gcc_assert (width >= 1 && width <= 4); + int shift = exact_log2 (width); + + machine_mode idx_mode = GET_MODE (idx); + idx = convert_modes (DImode, idx_mode, idx, 1); + + /* idx = idx * width. */ + rtx tmp = gen_reg_rtx (DImode); + emit_insn (gen_ashldi3 (tmp, idx, GEN_INT (shift))); + + /* For LE: idx = idx + 8. */ if (!BYTES_BIG_ENDIAN) - { - /* idx = idx * width. */ - emit_insn (gen_mulsi3 (tmp, idx, GEN_INT (width))); - /* idx = idx + 8. */ - emit_insn (gen_addsi3 (tmp, tmp, GEN_INT (8))); - } + emit_insn (gen_adddi3 (tmp, tmp, GEN_INT (8))); else - { - emit_insn (gen_mulsi3 (tmp, idx, GEN_INT (width))); - emit_insn (gen_subsi3 (tmp, GEN_INT (24 - width), tmp)); - } + emit_insn (gen_subdi3 (tmp, GEN_INT (24 - width), tmp)); /* lxv vs33, mask. DImode: 0xffffffffffffffff0000000000000000 @@ -7144,7 +7142,6 @@ rs6000_expand_vector_set_var_p8 (rtx target, rtx val, rtx idx) emit_insn (gen_rtx_SET (val_v16qi, sub_val)); /* lvsl 13,0,idx. */ - tmp = convert_modes (DImode, SImode, tmp, 1); rtx pcv = gen_reg_rtx (V16QImode); emit_insn (gen_altivec_lvsl_reg (pcv, tmp)); diff --git a/gcc/testsuite/gcc.target/powerpc/pr98914.c b/gcc/testsuite/gcc.target/powerpc/pr98914.c new file mode 100644 index 000000000000..e4d78e3e6b3a --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr98914.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target powerpc_p8vector_ok } */ +/* { dg-options "-Og -mvsx" } */ + +vector int +foo (vector int v) +{ + for (long k = 0; k < 1; ++k) + v[k] = 0; + return v; +}