Message ID | 1435851584-16430-2-git-send-email-charles.baylis@linaro.org |
---|---|
State | New |
Headers | show |
I note some parts of this duplicate my https://gcc.gnu.org/ml/gcc-patches/2015-01/msg01422.html , which has been pinged a couple of times. Both Charles' patch, and my two, contain parts the other does not... Cheers, Alan Charles Baylis wrote: > gcc/ChangeLog: > > <DATE> Charles Baylis <charles.baylis@linaro.org> > > * config/arm/arm-builtins.c (enum arm_type_qualifiers): New enumerators > qualifier_lane_index, qualifier_struct_load_store_lane_index. > (arm_expand_neon_args): New parameter. Remove ellipsis. Handle NEON > argument qualifiers. > (arm_expand_neon_builtin): Handle NEON argument qualifiers. > * config/arm/arm-protos.h: (arm_neon_lane_bounds) New prototype. > * config/arm/arm.c (arm_neon_lane_bounds): New function. > * config/arm/arm.h (ENDIAN_LANE_N): New macro. > > Change-Id: Iaa14d8736879fa53776319977eda2089f0a26647 > --- > gcc/config/arm/arm-builtins.c | 65 ++++++++++++++++++++++++++++++++----------- > gcc/config/arm/arm-protos.h | 4 +++ > gcc/config/arm/arm.c | 20 +++++++++++++ > gcc/config/arm/arm.h | 3 ++ > 4 files changed, 75 insertions(+), 17 deletions(-) > > diff --git a/gcc/config/arm/arm-builtins.c b/gcc/config/arm/arm-builtins.c > index f960e0a..8f1253e 100644 > --- a/gcc/config/arm/arm-builtins.c > +++ b/gcc/config/arm/arm-builtins.c > @@ -77,7 +77,11 @@ enum arm_type_qualifiers > /* qualifier_const_pointer | qualifier_map_mode */ > qualifier_const_pointer_map_mode = 0x86, > /* Polynomial types. */ > - qualifier_poly = 0x100 > + qualifier_poly = 0x100, > + /* Lane indices - must be in range, and flipped for bigendian. */ > + 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 > @@ -1927,6 +1931,8 @@ arm_expand_unop_builtin (enum insn_code icode, > typedef enum { > 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; > @@ -1984,9 +1990,9 @@ neon_dereference_pointer (tree exp, tree type, machine_mode mem_mode, > /* 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) > { > - va_list ap; > rtx pat; > tree arg[SIMD_MAX_BUILTIN_ARGS]; > rtx op[SIMD_MAX_BUILTIN_ARGS]; > @@ -2001,13 +2007,11 @@ arm_expand_neon_args (rtx target, machine_mode map_mode, int fcode, > || !(*insn_data[icode].operand[0].predicate) (target, tmode))) > target = gen_reg_rtx (tmode); > > - va_start (ap, exp); > - > 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; > @@ -2043,17 +2047,46 @@ arm_expand_neon_args (rtx target, machine_mode map_mode, int fcode, > 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])) > + { > + arm_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 (ENDIAN_LANE_N (map_mode, INTVAL (op[argc]))); > + } > + goto constant_arg; > + > + case NEON_ARG_LANE_INDEX: > + /* Must be a previous operand into which this is an index. */ > + gcc_assert (argc > 0); > + if (CONST_INT_P (op[argc])) > + { > + machine_mode vmode = insn_data[icode].operand[argc - 1].mode; > + arm_neon_lane_bounds (op[argc], > + 0, GET_MODE_NUNITS (vmode), exp); > + /* Keep to GCC-vector-extension lane indices in the RTL. */ > + op[argc] = GEN_INT (ENDIAN_LANE_N (vmode, INTVAL (op[argc]))); > + } > + /* Fall through - if the lane index isn't a constant then > + the next case will error. */ > case NEON_ARG_CONSTANT: > +constant_arg: > 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; > + } > break; > + > case NEON_ARG_MEMORY: > /* Check if expand failed. */ > if (op[argc] == const0_rtx) > { > - va_end (ap); > return 0; > } > gcc_assert (MEM_P (op[argc])); > @@ -2076,8 +2109,6 @@ arm_expand_neon_args (rtx target, machine_mode map_mode, int fcode, > } > } > > - va_end (ap); > - > if (have_retval) > switch (argc) > { > @@ -2170,7 +2201,11 @@ arm_expand_neon_builtin (int fcode, tree exp, rtx target) > int operands_k = k - is_void; > int expr_args_k = k - 1; > > - if (d->qualifiers[qualifiers_k] & qualifier_immediate) > + 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) > { > @@ -2195,11 +2230,7 @@ arm_expand_neon_builtin (int fcode, tree exp, rtx target) > 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); > + &args[1]); > } > > /* Expand an expression EXP that calls a built-in function, > diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h > index 62f91ef..0b4bef5 100644 > --- a/gcc/config/arm/arm-protos.h > +++ b/gcc/config/arm/arm-protos.h > @@ -343,6 +343,10 @@ extern void arm_cpu_builtins (struct cpp_reader *, int); > > extern bool arm_is_constant_pool_ref (rtx); > > +void arm_neon_lane_bounds (rtx operand, HOST_WIDE_INT low, HOST_WIDE_INT high, > + const_tree exp); > + > + > /* Flags used to identify the presence of processor capabilities. */ > > /* Bit values used to identify processor capabilities. */ > diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c > index d794fc0..2cbfd64 100644 > --- a/gcc/config/arm/arm.c > +++ b/gcc/config/arm/arm.c > @@ -29652,4 +29652,24 @@ arm_sched_fusion_priority (rtx_insn *insn, int max_pri, > *pri = tmp; > return; > } > + > +/* Bounds-check lanes. Ensure OPERAND lies between LOW (inclusive) and > + HIGH (exclusive). */ > +void > +arm_neon_lane_bounds (rtx operand, HOST_WIDE_INT low, HOST_WIDE_INT high, > + const_tree exp) > +{ > + HOST_WIDE_INT lane; > + gcc_assert (CONST_INT_P (operand)); > + lane = INTVAL (operand); > + > + if (lane < low || lane >= high) > + { > + if (exp) > + error ("%Klane %ld out of range %ld - %ld", exp, lane, low, high - 1); > + else > + error ("lane %ld out of range %ld - %ld", lane, low, high - 1); > + } > +} > + > #include "gt-arm.h" > diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h > index 373dc85..1a55ac8 100644 > --- a/gcc/config/arm/arm.h > +++ b/gcc/config/arm/arm.h > @@ -298,6 +298,9 @@ extern void (*arm_lang_output_object_attributes_hook)(void); > #define TARGET_BPABI false > #endif > > +#define 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 > -- > 1.9.1 > >
Alan Lawrence wrote: > I note some parts of this duplicate my > https://gcc.gnu.org/ml/gcc-patches/2015-01/msg01422.html , which has been pinged > a couple of times. Both Charles' patch, and my two, contain parts the other does > not... > > Cheers, Alan > > Charles Baylis wrote: >> gcc/ChangeLog: >> >> <DATE> Charles Baylis <charles.baylis@linaro.org> >> >> * config/arm/arm-builtins.c (enum arm_type_qualifiers): New enumerators >> qualifier_lane_index, qualifier_struct_load_store_lane_index. >> (arm_expand_neon_args): New parameter. Remove ellipsis. Handle NEON >> argument qualifiers. >> (arm_expand_neon_builtin): Handle NEON argument qualifiers. >> * config/arm/arm-protos.h: (arm_neon_lane_bounds) New prototype. >> * config/arm/arm.c (arm_neon_lane_bounds): New function. Further to that - the main difference/conflict between Charles' patch and mine looks to be that I added the const_tree parameter to the existing neon_lane_bounds method, whereas Charles' patch adds a new method arm_neon_lane_bounds. --Alan
On 6 July 2015 at 11:18, Alan Lawrence <alan.lawrence@arm.com> wrote: > I note some parts of this duplicate my > https://gcc.gnu.org/ml/gcc-patches/2015-01/msg01422.html , which has been > pinged a couple of times. Both Charles' patch, and my two, contain parts the > other does not... To resolve the conflicts, I suggest that Alan's patches should be applied as-is first, and I'll rebase mine afterwards. ...and... > Further to that - the main difference/conflict between Charles' patch and mine > looks to be that I added the const_tree parameter to the existing > neon_lane_bounds method, whereas Charles' patch adds a new method > arm_neon_lane_bounds. ... I'll clean up this duplication when I do.
diff --git a/gcc/config/arm/arm-builtins.c b/gcc/config/arm/arm-builtins.c index f960e0a..8f1253e 100644 --- a/gcc/config/arm/arm-builtins.c +++ b/gcc/config/arm/arm-builtins.c @@ -77,7 +77,11 @@ enum arm_type_qualifiers /* qualifier_const_pointer | qualifier_map_mode */ qualifier_const_pointer_map_mode = 0x86, /* Polynomial types. */ - qualifier_poly = 0x100 + qualifier_poly = 0x100, + /* Lane indices - must be in range, and flipped for bigendian. */ + 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 @@ -1927,6 +1931,8 @@ arm_expand_unop_builtin (enum insn_code icode, typedef enum { 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; @@ -1984,9 +1990,9 @@ neon_dereference_pointer (tree exp, tree type, machine_mode mem_mode, /* 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) { - va_list ap; rtx pat; tree arg[SIMD_MAX_BUILTIN_ARGS]; rtx op[SIMD_MAX_BUILTIN_ARGS]; @@ -2001,13 +2007,11 @@ arm_expand_neon_args (rtx target, machine_mode map_mode, int fcode, || !(*insn_data[icode].operand[0].predicate) (target, tmode))) target = gen_reg_rtx (tmode); - va_start (ap, exp); - 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; @@ -2043,17 +2047,46 @@ arm_expand_neon_args (rtx target, machine_mode map_mode, int fcode, 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])) + { + arm_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 (ENDIAN_LANE_N (map_mode, INTVAL (op[argc]))); + } + goto constant_arg; + + case NEON_ARG_LANE_INDEX: + /* Must be a previous operand into which this is an index. */ + gcc_assert (argc > 0); + if (CONST_INT_P (op[argc])) + { + machine_mode vmode = insn_data[icode].operand[argc - 1].mode; + arm_neon_lane_bounds (op[argc], + 0, GET_MODE_NUNITS (vmode), exp); + /* Keep to GCC-vector-extension lane indices in the RTL. */ + op[argc] = GEN_INT (ENDIAN_LANE_N (vmode, INTVAL (op[argc]))); + } + /* Fall through - if the lane index isn't a constant then + the next case will error. */ case NEON_ARG_CONSTANT: +constant_arg: 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; + } break; + case NEON_ARG_MEMORY: /* Check if expand failed. */ if (op[argc] == const0_rtx) { - va_end (ap); return 0; } gcc_assert (MEM_P (op[argc])); @@ -2076,8 +2109,6 @@ arm_expand_neon_args (rtx target, machine_mode map_mode, int fcode, } } - va_end (ap); - if (have_retval) switch (argc) { @@ -2170,7 +2201,11 @@ arm_expand_neon_builtin (int fcode, tree exp, rtx target) int operands_k = k - is_void; int expr_args_k = k - 1; - if (d->qualifiers[qualifiers_k] & qualifier_immediate) + 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) { @@ -2195,11 +2230,7 @@ arm_expand_neon_builtin (int fcode, tree exp, rtx target) 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); + &args[1]); } /* Expand an expression EXP that calls a built-in function, diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h index 62f91ef..0b4bef5 100644 --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -343,6 +343,10 @@ extern void arm_cpu_builtins (struct cpp_reader *, int); extern bool arm_is_constant_pool_ref (rtx); +void arm_neon_lane_bounds (rtx operand, HOST_WIDE_INT low, HOST_WIDE_INT high, + const_tree exp); + + /* Flags used to identify the presence of processor capabilities. */ /* Bit values used to identify processor capabilities. */ diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index d794fc0..2cbfd64 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -29652,4 +29652,24 @@ arm_sched_fusion_priority (rtx_insn *insn, int max_pri, *pri = tmp; return; } + +/* Bounds-check lanes. Ensure OPERAND lies between LOW (inclusive) and + HIGH (exclusive). */ +void +arm_neon_lane_bounds (rtx operand, HOST_WIDE_INT low, HOST_WIDE_INT high, + const_tree exp) +{ + HOST_WIDE_INT lane; + gcc_assert (CONST_INT_P (operand)); + lane = INTVAL (operand); + + if (lane < low || lane >= high) + { + if (exp) + error ("%Klane %ld out of range %ld - %ld", exp, lane, low, high - 1); + else + error ("lane %ld out of range %ld - %ld", lane, low, high - 1); + } +} + #include "gt-arm.h" diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 373dc85..1a55ac8 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -298,6 +298,9 @@ extern void (*arm_lang_output_object_attributes_hook)(void); #define TARGET_BPABI false #endif +#define 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