2015-11-11 Charles Baylis <charles.baylis@linaro.org>
PR target/63870
* config/arm/arm-builtins.c (enum arm_type_qualifiers): New enumerator
qualifier_struct_load_store_lane_index.
(builtin_arg): New enumerator NEON_ARG_STRUCT_LOAD_STORE_LANE_INDEX.
(arm_expand_neon_args): New parameter. Remove ellipsis. Handle NEON
argument qualifiers.
(arm_expand_neon_builtin): Handle new NEON argument qualifier.
* config/arm/arm.h (NEON_ENDIAN_LANE_N): New macro.
From-SVN: r230142
+2015-11-11 Charles Baylis <charles.baylis@linaro.org>
+
+ PR target/63870
+ * config/arm/arm-builtins.c (enum arm_type_qualifiers): New enumerator
+ qualifier_struct_load_store_lane_index.
+ (builtin_arg): New enumerator NEON_ARG_STRUCT_LOAD_STORE_LANE_INDEX.
+ (arm_expand_neon_args): New parameter. Remove ellipsis. Handle NEON
+ argument qualifiers.
+ (arm_expand_neon_builtin): Handle new NEON argument qualifier.
+ * config/arm/arm.h (NEON_ENDIAN_LANE_N): New macro.
+
2015-11-10 Nathan Sidwell <nathan@codesourcery.com>
* config/nvptx/nvptx.opt (moptimize): New flag.
2015-11-10 Nathan Sidwell <nathan@codesourcery.com>
* config/nvptx/nvptx.opt (moptimize): New flag.
/* Polynomial types. */
qualifier_poly = 0x100,
/* Lane indices - must be within range of previous argument = a vector. */
/* Polynomial types. */
qualifier_poly = 0x100,
/* Lane indices - must be within range of previous argument = a vector. */
- qualifier_lane_index = 0x200
+ qualifier_lane_index = 0x200,
+ /* Lane indices for single lane structure loads and stores. */
+ qualifier_struct_load_store_lane_index = 0x400
};
/* The qualifier_internal allows generation of a unary builtin from
};
/* The qualifier_internal allows generation of a unary builtin from
NEON_ARG_COPY_TO_REG,
NEON_ARG_CONSTANT,
NEON_ARG_LANE_INDEX,
NEON_ARG_COPY_TO_REG,
NEON_ARG_CONSTANT,
NEON_ARG_LANE_INDEX,
+ NEON_ARG_STRUCT_LOAD_STORE_LANE_INDEX,
NEON_ARG_MEMORY,
NEON_ARG_STOP
} builtin_arg;
NEON_ARG_MEMORY,
NEON_ARG_STOP
} builtin_arg;
/* Expand a Neon builtin. */
static rtx
arm_expand_neon_args (rtx target, machine_mode map_mode, int fcode,
/* Expand a Neon builtin. */
static rtx
arm_expand_neon_args (rtx target, machine_mode map_mode, int fcode,
- int icode, int have_retval, tree exp, ...)
+ int icode, int have_retval, tree exp,
+ builtin_arg *args)
rtx pat;
tree arg[SIMD_MAX_BUILTIN_ARGS];
rtx op[SIMD_MAX_BUILTIN_ARGS];
rtx pat;
tree arg[SIMD_MAX_BUILTIN_ARGS];
rtx op[SIMD_MAX_BUILTIN_ARGS];
|| !(*insn_data[icode].operand[0].predicate) (target, tmode)))
target = gen_reg_rtx (tmode);
|| !(*insn_data[icode].operand[0].predicate) (target, tmode)))
target = gen_reg_rtx (tmode);
formals = TYPE_ARG_TYPES (TREE_TYPE (arm_builtin_decls[fcode]));
for (;;)
{
formals = TYPE_ARG_TYPES (TREE_TYPE (arm_builtin_decls[fcode]));
for (;;)
{
- builtin_arg thisarg = (builtin_arg) va_arg (ap, int);
+ builtin_arg thisarg = args[argc];
if (thisarg == NEON_ARG_STOP)
break;
if (thisarg == NEON_ARG_STOP)
break;
op[argc] = copy_to_mode_reg (mode[argc], op[argc]);
break;
op[argc] = copy_to_mode_reg (mode[argc], op[argc]);
break;
+ case NEON_ARG_STRUCT_LOAD_STORE_LANE_INDEX:
+ gcc_assert (argc > 1);
+ if (CONST_INT_P (op[argc]))
+ {
+ neon_lane_bounds (op[argc], 0,
+ GET_MODE_NUNITS (map_mode), exp);
+ /* Keep to GCC-vector-extension lane indices in the RTL. */
+ op[argc] =
+ GEN_INT (NEON_ENDIAN_LANE_N (map_mode, INTVAL (op[argc])));
+ }
+ goto constant_arg;
+
case NEON_ARG_LANE_INDEX:
/* Previous argument must be a vector, which this indexes. */
gcc_assert (argc > 0);
case NEON_ARG_LANE_INDEX:
/* Previous argument must be a vector, which this indexes. */
gcc_assert (argc > 0);
}
/* Fall through - if the lane index isn't a constant then
the next case will error. */
}
/* Fall through - if the lane index isn't a constant then
the next case will error. */
if (!(*insn_data[icode].operand[opno].predicate)
(op[argc], mode[argc]))
if (!(*insn_data[icode].operand[opno].predicate)
(op[argc], mode[argc]))
- error_at (EXPR_LOCATION (exp), "incompatible type for argument %d, "
- "expected %<const int%>", argc + 1);
+ {
+ error ("%Kargument %d must be a constant immediate",
+ exp, argc + 1);
+ return const0_rtx;
+ }
case NEON_ARG_MEMORY:
/* Check if expand failed. */
if (op[argc] == const0_rtx)
case NEON_ARG_MEMORY:
/* Check if expand failed. */
if (op[argc] == const0_rtx)
gcc_assert (MEM_P (op[argc]));
PUT_MODE (op[argc], mode[argc]);
/* ??? arm_neon.h uses the same built-in functions for signed
gcc_assert (MEM_P (op[argc]));
PUT_MODE (op[argc], mode[argc]);
/* ??? arm_neon.h uses the same built-in functions for signed
if (have_retval)
switch (argc)
{
if (have_retval)
switch (argc)
{
if (d->qualifiers[qualifiers_k] & qualifier_lane_index)
args[k] = NEON_ARG_LANE_INDEX;
if (d->qualifiers[qualifiers_k] & qualifier_lane_index)
args[k] = NEON_ARG_LANE_INDEX;
+ else if (d->qualifiers[qualifiers_k] & qualifier_struct_load_store_lane_index)
+ args[k] = NEON_ARG_STRUCT_LOAD_STORE_LANE_INDEX;
else if (d->qualifiers[qualifiers_k] & qualifier_immediate)
args[k] = NEON_ARG_CONSTANT;
else if (d->qualifiers[qualifiers_k] & qualifier_maybe_immediate)
else if (d->qualifiers[qualifiers_k] & qualifier_immediate)
args[k] = NEON_ARG_CONSTANT;
else if (d->qualifiers[qualifiers_k] & qualifier_maybe_immediate)
the function is void, and a 1 if it is not. */
return arm_expand_neon_args
(target, d->mode, fcode, icode, !is_void, exp,
the function is void, and a 1 if it is not. */
return arm_expand_neon_args
(target, d->mode, fcode, icode, !is_void, exp,
- args[1],
- args[2],
- args[3],
- args[4],
- NEON_ARG_STOP);
}
/* Expand an expression EXP that calls a built-in function,
}
/* Expand an expression EXP that calls a built-in function,
#define TARGET_BPABI false
#endif
#define TARGET_BPABI false
#endif
+/* Transform lane numbers on big endian targets. This is used to allow for the
+ endianness difference between NEON architectural lane numbers and those
+ used in RTL */
+#define NEON_ENDIAN_LANE_N(mode, n) \
+ (BYTES_BIG_ENDIAN ? GET_MODE_NUNITS (mode) - 1 - n : n)
+
/* Support for a compile-time default CPU, et cetera. The rules are:
--with-arch is ignored if -march or -mcpu are specified.
--with-cpu is ignored if -march or -mcpu are specified, and is overridden
/* Support for a compile-time default CPU, et cetera. The rules are:
--with-arch is ignored if -march or -mcpu are specified.
--with-cpu is ignored if -march or -mcpu are specified, and is overridden