Commit e3783e82 by Ramana Radhakrishnan Committed by Ramana Radhakrishnan

re PR target/54252 (Bad alignment code generated for Neon loads)

Fix PR target/54252

2012-08-29  Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
	    Richard Earnshaw  <richard.earnshaw@arm.com>

	PR target/54252
	* config/arm/arm.c (neon_dereference_pointer): Adjust nelems by
	element size. Use elem_type from the formal parameter. New parameter
	fcode.
	(neon_expand_args): Adjust call to neon_dereference_pointer.



Co-Authored-By: Richard Earnshaw <rearnsha@arm.com>

From-SVN: r190800
parent d5359108
2012-08-29 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
Richard Earnshaw <richard.earnshaw@arm.com>
PR target/54252
* config/arm/arm.c (neon_dereference_pointer): Adjust nelems by
element size. Use elem_type from the formal parameter. New parameter
fcode.
(neon_expand_args): Adjust call to neon_dereference_pointer.
2012-08-29 Steven Bosscher <steven@gcc.gnu.org> 2012-08-29 Steven Bosscher <steven@gcc.gnu.org>
* cfg.c (dump_bb_info): Print a newline if there were no edges to dump. * cfg.c (dump_bb_info): Print a newline if there were no edges to dump.
......
...@@ -20351,12 +20351,13 @@ typedef enum { ...@@ -20351,12 +20351,13 @@ typedef enum {
and return an expression for the accessed memory. and return an expression for the accessed memory.
The intrinsic function operates on a block of registers that has The intrinsic function operates on a block of registers that has
mode REG_MODE. This block contains vectors of type TYPE_MODE. mode REG_MODE. This block contains vectors of type TYPE_MODE. The
The function references the memory at EXP in mode MEM_MODE; function references the memory at EXP of type TYPE and in mode
this mode may be BLKmode if no more suitable mode is available. */ MEM_MODE; this mode may be BLKmode if no more suitable mode is
available. */
static tree static tree
neon_dereference_pointer (tree exp, enum machine_mode mem_mode, neon_dereference_pointer (tree exp, tree type, enum machine_mode mem_mode,
enum machine_mode reg_mode, enum machine_mode reg_mode,
neon_builtin_type_mode type_mode) neon_builtin_type_mode type_mode)
{ {
...@@ -20374,18 +20375,18 @@ neon_dereference_pointer (tree exp, enum machine_mode mem_mode, ...@@ -20374,18 +20375,18 @@ neon_dereference_pointer (tree exp, enum machine_mode mem_mode,
gcc_assert (reg_size % vector_size == 0); gcc_assert (reg_size % vector_size == 0);
nvectors = reg_size / vector_size; nvectors = reg_size / vector_size;
/* Work out the type of each element. */
gcc_assert (POINTER_TYPE_P (type));
elem_type = TREE_TYPE (type);
/* Work out how many elements are being loaded or stored. /* Work out how many elements are being loaded or stored.
MEM_MODE == REG_MODE implies a one-to-one mapping between register MEM_MODE == REG_MODE implies a one-to-one mapping between register
and memory elements; anything else implies a lane load or store. */ and memory elements; anything else implies a lane load or store. */
if (mem_mode == reg_mode) if (mem_mode == reg_mode)
nelems = vector_size * nvectors; nelems = vector_size * nvectors / int_size_in_bytes (elem_type);
else else
nelems = nvectors; nelems = nvectors;
/* Work out the type of each element. */
gcc_assert (POINTER_TYPE_P (TREE_TYPE (exp)));
elem_type = TREE_TYPE (TREE_TYPE (exp));
/* Create a type that describes the full access. */ /* Create a type that describes the full access. */
upper_bound = build_int_cst (size_type_node, nelems - 1); upper_bound = build_int_cst (size_type_node, nelems - 1);
array_type = build_array_type (elem_type, build_index_type (upper_bound)); array_type = build_array_type (elem_type, build_index_type (upper_bound));
...@@ -20399,12 +20400,14 @@ neon_dereference_pointer (tree exp, enum machine_mode mem_mode, ...@@ -20399,12 +20400,14 @@ neon_dereference_pointer (tree exp, enum machine_mode mem_mode,
static rtx static rtx
arm_expand_neon_args (rtx target, int icode, int have_retval, arm_expand_neon_args (rtx target, int icode, int have_retval,
neon_builtin_type_mode type_mode, neon_builtin_type_mode type_mode,
tree exp, ...) tree exp, int fcode, ...)
{ {
va_list ap; va_list ap;
rtx pat; rtx pat;
tree arg[NEON_MAX_BUILTIN_ARGS]; tree arg[NEON_MAX_BUILTIN_ARGS];
rtx op[NEON_MAX_BUILTIN_ARGS]; rtx op[NEON_MAX_BUILTIN_ARGS];
tree arg_type;
tree formals;
enum machine_mode tmode = insn_data[icode].operand[0].mode; enum machine_mode tmode = insn_data[icode].operand[0].mode;
enum machine_mode mode[NEON_MAX_BUILTIN_ARGS]; enum machine_mode mode[NEON_MAX_BUILTIN_ARGS];
enum machine_mode other_mode; enum machine_mode other_mode;
...@@ -20417,7 +20420,9 @@ arm_expand_neon_args (rtx target, int icode, int have_retval, ...@@ -20417,7 +20420,9 @@ arm_expand_neon_args (rtx target, int icode, int have_retval,
|| !(*insn_data[icode].operand[0].predicate) (target, tmode))) || !(*insn_data[icode].operand[0].predicate) (target, tmode)))
target = gen_reg_rtx (tmode); target = gen_reg_rtx (tmode);
va_start (ap, exp); va_start (ap, fcode);
formals = TYPE_ARG_TYPES (TREE_TYPE (arm_builtin_decls[fcode]));
for (;;) for (;;)
{ {
...@@ -20430,12 +20435,15 @@ arm_expand_neon_args (rtx target, int icode, int have_retval, ...@@ -20430,12 +20435,15 @@ arm_expand_neon_args (rtx target, int icode, int have_retval,
opno = argc + have_retval; opno = argc + have_retval;
mode[argc] = insn_data[icode].operand[opno].mode; mode[argc] = insn_data[icode].operand[opno].mode;
arg[argc] = CALL_EXPR_ARG (exp, argc); arg[argc] = CALL_EXPR_ARG (exp, argc);
arg_type = TREE_VALUE (formals);
if (thisarg == NEON_ARG_MEMORY) if (thisarg == NEON_ARG_MEMORY)
{ {
other_mode = insn_data[icode].operand[1 - opno].mode; other_mode = insn_data[icode].operand[1 - opno].mode;
arg[argc] = neon_dereference_pointer (arg[argc], mode[argc], arg[argc] = neon_dereference_pointer (arg[argc], arg_type,
other_mode, type_mode); mode[argc], other_mode,
type_mode);
} }
op[argc] = expand_normal (arg[argc]); op[argc] = expand_normal (arg[argc]);
switch (thisarg) switch (thisarg)
...@@ -20472,6 +20480,7 @@ arm_expand_neon_args (rtx target, int icode, int have_retval, ...@@ -20472,6 +20480,7 @@ arm_expand_neon_args (rtx target, int icode, int have_retval,
} }
argc++; argc++;
formals = TREE_CHAIN (formals);
} }
} }
...@@ -20554,7 +20563,7 @@ arm_expand_neon_builtin (int fcode, tree exp, rtx target) ...@@ -20554,7 +20563,7 @@ arm_expand_neon_builtin (int fcode, tree exp, rtx target)
case NEON_UNOP: case NEON_UNOP:
case NEON_CONVERT: case NEON_CONVERT:
case NEON_DUPLANE: case NEON_DUPLANE:
return arm_expand_neon_args (target, icode, 1, type_mode, exp, return arm_expand_neon_args (target, icode, 1, type_mode, exp, fcode,
NEON_ARG_COPY_TO_REG, NEON_ARG_CONSTANT, NEON_ARG_STOP); NEON_ARG_COPY_TO_REG, NEON_ARG_CONSTANT, NEON_ARG_STOP);
case NEON_BINOP: case NEON_BINOP:
...@@ -20564,89 +20573,89 @@ arm_expand_neon_builtin (int fcode, tree exp, rtx target) ...@@ -20564,89 +20573,89 @@ arm_expand_neon_builtin (int fcode, tree exp, rtx target)
case NEON_SCALARMULH: case NEON_SCALARMULH:
case NEON_SHIFTINSERT: case NEON_SHIFTINSERT:
case NEON_LOGICBINOP: case NEON_LOGICBINOP:
return arm_expand_neon_args (target, icode, 1, type_mode, exp, return arm_expand_neon_args (target, icode, 1, type_mode, exp, fcode,
NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG, NEON_ARG_CONSTANT, NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG, NEON_ARG_CONSTANT,
NEON_ARG_STOP); NEON_ARG_STOP);
case NEON_TERNOP: case NEON_TERNOP:
return arm_expand_neon_args (target, icode, 1, type_mode, exp, return arm_expand_neon_args (target, icode, 1, type_mode, exp, fcode,
NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG,
NEON_ARG_CONSTANT, NEON_ARG_STOP); NEON_ARG_CONSTANT, NEON_ARG_STOP);
case NEON_GETLANE: case NEON_GETLANE:
case NEON_FIXCONV: case NEON_FIXCONV:
case NEON_SHIFTIMM: case NEON_SHIFTIMM:
return arm_expand_neon_args (target, icode, 1, type_mode, exp, return arm_expand_neon_args (target, icode, 1, type_mode, exp, fcode,
NEON_ARG_COPY_TO_REG, NEON_ARG_CONSTANT, NEON_ARG_CONSTANT, NEON_ARG_COPY_TO_REG, NEON_ARG_CONSTANT, NEON_ARG_CONSTANT,
NEON_ARG_STOP); NEON_ARG_STOP);
case NEON_CREATE: case NEON_CREATE:
return arm_expand_neon_args (target, icode, 1, type_mode, exp, return arm_expand_neon_args (target, icode, 1, type_mode, exp, fcode,
NEON_ARG_COPY_TO_REG, NEON_ARG_STOP); NEON_ARG_COPY_TO_REG, NEON_ARG_STOP);
case NEON_DUP: case NEON_DUP:
case NEON_SPLIT: case NEON_SPLIT:
case NEON_REINTERP: case NEON_REINTERP:
return arm_expand_neon_args (target, icode, 1, type_mode, exp, return arm_expand_neon_args (target, icode, 1, type_mode, exp, fcode,
NEON_ARG_COPY_TO_REG, NEON_ARG_STOP); NEON_ARG_COPY_TO_REG, NEON_ARG_STOP);
case NEON_COMBINE: case NEON_COMBINE:
case NEON_VTBL: case NEON_VTBL:
return arm_expand_neon_args (target, icode, 1, type_mode, exp, return arm_expand_neon_args (target, icode, 1, type_mode, exp, fcode,
NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG, NEON_ARG_STOP); NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG, NEON_ARG_STOP);
case NEON_RESULTPAIR: case NEON_RESULTPAIR:
return arm_expand_neon_args (target, icode, 0, type_mode, exp, return arm_expand_neon_args (target, icode, 0, type_mode, exp, fcode,
NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG,
NEON_ARG_STOP); NEON_ARG_STOP);
case NEON_LANEMUL: case NEON_LANEMUL:
case NEON_LANEMULL: case NEON_LANEMULL:
case NEON_LANEMULH: case NEON_LANEMULH:
return arm_expand_neon_args (target, icode, 1, type_mode, exp, return arm_expand_neon_args (target, icode, 1, type_mode, exp, fcode,
NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG, NEON_ARG_CONSTANT, NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG, NEON_ARG_CONSTANT,
NEON_ARG_CONSTANT, NEON_ARG_STOP); NEON_ARG_CONSTANT, NEON_ARG_STOP);
case NEON_LANEMAC: case NEON_LANEMAC:
return arm_expand_neon_args (target, icode, 1, type_mode, exp, return arm_expand_neon_args (target, icode, 1, type_mode, exp, fcode,
NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG,
NEON_ARG_CONSTANT, NEON_ARG_CONSTANT, NEON_ARG_STOP); NEON_ARG_CONSTANT, NEON_ARG_CONSTANT, NEON_ARG_STOP);
case NEON_SHIFTACC: case NEON_SHIFTACC:
return arm_expand_neon_args (target, icode, 1, type_mode, exp, return arm_expand_neon_args (target, icode, 1, type_mode, exp, fcode,
NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG, NEON_ARG_CONSTANT, NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG, NEON_ARG_CONSTANT,
NEON_ARG_CONSTANT, NEON_ARG_STOP); NEON_ARG_CONSTANT, NEON_ARG_STOP);
case NEON_SCALARMAC: case NEON_SCALARMAC:
return arm_expand_neon_args (target, icode, 1, type_mode, exp, return arm_expand_neon_args (target, icode, 1, type_mode, exp, fcode,
NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG,
NEON_ARG_CONSTANT, NEON_ARG_STOP); NEON_ARG_CONSTANT, NEON_ARG_STOP);
case NEON_SELECT: case NEON_SELECT:
case NEON_VTBX: case NEON_VTBX:
return arm_expand_neon_args (target, icode, 1, type_mode, exp, return arm_expand_neon_args (target, icode, 1, type_mode, exp, fcode,
NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG, NEON_ARG_COPY_TO_REG,
NEON_ARG_STOP); NEON_ARG_STOP);
case NEON_LOAD1: case NEON_LOAD1:
case NEON_LOADSTRUCT: case NEON_LOADSTRUCT:
return arm_expand_neon_args (target, icode, 1, type_mode, exp, return arm_expand_neon_args (target, icode, 1, type_mode, exp, fcode,
NEON_ARG_MEMORY, NEON_ARG_STOP); NEON_ARG_MEMORY, NEON_ARG_STOP);
case NEON_LOAD1LANE: case NEON_LOAD1LANE:
case NEON_LOADSTRUCTLANE: case NEON_LOADSTRUCTLANE:
return arm_expand_neon_args (target, icode, 1, type_mode, exp, return arm_expand_neon_args (target, icode, 1, type_mode, exp, fcode,
NEON_ARG_MEMORY, NEON_ARG_COPY_TO_REG, NEON_ARG_CONSTANT, NEON_ARG_MEMORY, NEON_ARG_COPY_TO_REG, NEON_ARG_CONSTANT,
NEON_ARG_STOP); NEON_ARG_STOP);
case NEON_STORE1: case NEON_STORE1:
case NEON_STORESTRUCT: case NEON_STORESTRUCT:
return arm_expand_neon_args (target, icode, 0, type_mode, exp, return arm_expand_neon_args (target, icode, 0, type_mode, exp, fcode,
NEON_ARG_MEMORY, NEON_ARG_COPY_TO_REG, NEON_ARG_STOP); NEON_ARG_MEMORY, NEON_ARG_COPY_TO_REG, NEON_ARG_STOP);
case NEON_STORE1LANE: case NEON_STORE1LANE:
case NEON_STORESTRUCTLANE: case NEON_STORESTRUCTLANE:
return arm_expand_neon_args (target, icode, 0, type_mode, exp, return arm_expand_neon_args (target, icode, 0, type_mode, exp, fcode,
NEON_ARG_MEMORY, NEON_ARG_COPY_TO_REG, NEON_ARG_CONSTANT, NEON_ARG_MEMORY, NEON_ARG_COPY_TO_REG, NEON_ARG_CONSTANT,
NEON_ARG_STOP); NEON_ARG_STOP);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment