tree arg1;
tree arg2;
tree arg1_type;
- tree arg1_inner_type;
tree decl, stmt;
- tree innerptrtype;
machine_mode mode;
/* No second or third arguments. */
return build_call_expr (call, 3, arg1, arg0, arg2);
}
- /* Build *(((arg1_inner_type*)&(vector type){arg1})+arg2) = arg0. */
- arg1_inner_type = TREE_TYPE (arg1_type);
+ /* Build *(((arg1_inner_type*)&(vector type){arg1})+arg2) = arg0 with
+ VIEW_CONVERT_EXPR. i.e.:
+ D.3192 = v1;
+ _1 = n & 3;
+ VIEW_CONVERT_EXPR<int[4]>(D.3192)[_1] = i;
+ v1 = D.3192;
+ D.3194 = v1; */
if (TYPE_VECTOR_SUBPARTS (arg1_type) == 1)
arg2 = build_int_cst (TREE_TYPE (arg2), 0);
else
TREE_USED (decl) = 1;
TREE_TYPE (decl) = arg1_type;
TREE_READONLY (decl) = TYPE_READONLY (arg1_type);
+ TREE_ADDRESSABLE (decl) = 1;
if (c_dialect_cxx ())
{
stmt = build4 (TARGET_EXPR, arg1_type, decl, arg1,
{
DECL_INITIAL (decl) = arg1;
stmt = build1 (DECL_EXPR, arg1_type, decl);
- TREE_ADDRESSABLE (decl) = 1;
SET_EXPR_LOCATION (stmt, loc);
stmt = build1 (COMPOUND_LITERAL_EXPR, arg1_type, stmt);
}
-
- innerptrtype = build_pointer_type (arg1_inner_type);
-
- stmt = build_unary_op (loc, ADDR_EXPR, stmt, 0);
- stmt = convert (innerptrtype, stmt);
- stmt = build_binary_op (loc, PLUS_EXPR, stmt, arg2, 1);
- stmt = build_indirect_ref (loc, stmt, RO_NULL);
- stmt = build2 (MODIFY_EXPR, TREE_TYPE (stmt), stmt,
- convert (TREE_TYPE (stmt), arg0));
+ stmt = build_array_ref (loc, stmt, arg2);
+ stmt = fold_build2 (MODIFY_EXPR, TREE_TYPE (arg0), stmt,
+ convert (TREE_TYPE (stmt), arg0));
stmt = build2 (COMPOUND_EXPR, arg1_type, stmt, decl);
return stmt;
}
extern void rs6000_expand_float128_convert (rtx, rtx, bool);
extern void rs6000_expand_vector_init (rtx, rtx);
extern void rs6000_expand_vector_set (rtx, rtx, rtx);
+extern void rs6000_expand_vector_set_var (rtx, rtx, rtx);
extern void rs6000_expand_vector_extract (rtx, rtx, rtx);
extern void rs6000_split_vec_extract_var (rtx, rtx, rtx, rtx, rtx);
extern rtx rs6000_adjust_vec_address (rtx, rtx, rtx, rtx, machine_mode);
if (VECTOR_MEM_VSX_P (mode))
{
+ if (!CONST_INT_P (elt_rtx))
+ {
+ rs6000_expand_vector_set_var (target, val, elt_rtx);
+ return;
+ }
+
rtx insn = NULL_RTX;
if (mode == V2DFmode)
emit_insn (gen_rtx_SET (target, x));
}
+/* Insert VAL into IDX of TARGET, VAL size is same of the vector element, IDX
+ is variable and also counts by vector element size. */
+
+void
+rs6000_expand_vector_set_var (rtx target, rtx val, rtx idx)
+{
+ machine_mode mode = GET_MODE (target);
+
+ 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);
+ /* 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);
+
+ /* lvsr v1,0,idx. */
+ rtx pcvr = gen_reg_rtx (V16QImode);
+ emit_insn (gen_altivec_lvsr_reg (pcvr, tmp));
+
+ /* lvsl v2,0,idx. */
+ rtx pcvl = gen_reg_rtx (V16QImode);
+ emit_insn (gen_altivec_lvsl_reg (pcvl, tmp));
+
+ rtx sub_target = simplify_gen_subreg (V16QImode, target, mode, 0);
+
+ rtx permr
+ = gen_altivec_vperm_v8hiv16qi (sub_target, sub_target, sub_target, pcvr);
+ emit_insn (permr);
+
+ rs6000_expand_vector_set (target, val, const0_rtx);
+
+ rtx perml
+ = gen_altivec_vperm_v8hiv16qi (sub_target, sub_target, sub_target, pcvl);
+ emit_insn (perml);
+}
+
/* Extract field ELT from VEC into TARGET. */
void
--- /dev/null
+/* { dg-options "-O2 -maltivec" } */
+
+#include <stddef.h>
+#include <altivec.h>
+#include "pr79251.h"
+
+TEST_VEC_INSERT_ALL (test)
+
+#define run_test(TYPE, num) \
+ { \
+ vector TYPE v; \
+ vector TYPE u = {0x0}; \
+ for (long k = 0; k < 16 / sizeof (TYPE); k++) \
+ v[k] = 0xaa; \
+ for (long k = 0; k < 16 / sizeof (TYPE); k++) \
+ { \
+ u = test##num (v, 254, k); \
+ if (u[k] != (TYPE) 254) \
+ __builtin_abort (); \
+ } \
+ }
+
+int
+main (void)
+{
+ TEST_VEC_INSERT_ALL (run_test)
+ return 0;
+}
--- /dev/null
+
+#define test(TYPE, num) \
+ __attribute__ ((noinline, noclone)) \
+ vector TYPE test##num (vector TYPE v, TYPE i, signed int n) \
+ { \
+ return vec_insert (i, v, n); \
+ }
+
+#define TEST_VEC_INSERT_ALL(T) \
+ T (char, 0) \
+ T (unsigned char, 1) \
+ T (short, 2) \
+ T (unsigned short, 3) \
+ T (int, 4) \
+ T (unsigned int, 5) \
+ T (long long, 6) \
+ T (unsigned long long, 7) \
+ T (float, 8) \
+ T (double, 9)
--- /dev/null
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-O2 -mdejagnu-cpu=power9 -maltivec" } */
+
+#include <stddef.h>
+#include <altivec.h>
+#include "pr79251.h"
+
+TEST_VEC_INSERT_ALL (test)
+
+/* { dg-final { scan-assembler-not {\mstxw\M} } } */
+/* { dg-final { scan-assembler-times {\mlvsl\M} 10 } } */
+/* { dg-final { scan-assembler-times {\mlvsr\M} 10 } } */
+/* { dg-final { scan-assembler-times {\mxxperm\M} 20 } } */
+/* { dg-final { scan-assembler-times {\mxxinsertw\M} 3 } } */
+/* { dg-final { scan-assembler-times {\mvinserth\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mvinsertb\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mxxpermdi\M} 3 } } */