From aee288240a592521bda4a6b5d6d700d41e48444c Mon Sep 17 00:00:00 2001 From: yroux Date: Tue, 26 Aug 2014 11:47:28 +0000 Subject: [PATCH] 2014-08-26 Yvan Roux Backport from trunk r213378. 2014-07-31 James Greenhalgh * config/aarch64/aarch64.c (aarch64_simd_vect_par_cnst_half): Vary the generated mask based on BYTES_BIG_ENDIAN. (aarch64_simd_check_vect_par_cnst_half): New. * config/aarch64/aarch64-protos.h (aarch64_simd_check_vect_par_cnst_half): New. * config/aarch64/predicates.md (vect_par_cnst_hi_half): Refactor the check out to aarch64_simd_check_vect_par_cnst_half. (vect_par_cnst_lo_half): Likewise. * config/aarch64/aarch64-simd.md (aarch64_simd_move_hi_quad_): Always use vec_par_cnst_lo_half. (move_hi_quad_): Always generate a low mask. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/linaro/gcc-4_9-branch@214502 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog.linaro | 17 ++++++++++ gcc/config/aarch64/aarch64-protos.h | 2 ++ gcc/config/aarch64/aarch64-simd.md | 4 +-- gcc/config/aarch64/aarch64.c | 64 +++++++++++++++++++++++++++++++++++-- gcc/config/aarch64/predicates.md | 51 ++--------------------------- 5 files changed, 84 insertions(+), 54 deletions(-) diff --git a/gcc/ChangeLog.linaro b/gcc/ChangeLog.linaro index 3781582..90e1289 100644 --- a/gcc/ChangeLog.linaro +++ b/gcc/ChangeLog.linaro @@ -1,3 +1,20 @@ +2014-08-26 Yvan Roux + + Backport from trunk r213378. + 2014-07-31 James Greenhalgh + + * config/aarch64/aarch64.c (aarch64_simd_vect_par_cnst_half): Vary + the generated mask based on BYTES_BIG_ENDIAN. + (aarch64_simd_check_vect_par_cnst_half): New. + * config/aarch64/aarch64-protos.h + (aarch64_simd_check_vect_par_cnst_half): New. + * config/aarch64/predicates.md (vect_par_cnst_hi_half): Refactor + the check out to aarch64_simd_check_vect_par_cnst_half. + (vect_par_cnst_lo_half): Likewise. + * config/aarch64/aarch64-simd.md + (aarch64_simd_move_hi_quad_): Always use vec_par_cnst_lo_half. + (move_hi_quad_): Always generate a low mask. + 2014-08-22 Yvan Roux Backport from trunk r212927, r213304. diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index c4f75b3..f3273be 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -200,6 +200,8 @@ bool aarch64_pad_arg_upward (enum machine_mode, const_tree); bool aarch64_pad_reg_upward (enum machine_mode, const_tree, bool); bool aarch64_regno_ok_for_base_p (int, bool); bool aarch64_regno_ok_for_index_p (int, bool); +bool aarch64_simd_check_vect_par_cnst_half (rtx op, enum machine_mode mode, + bool high); bool aarch64_simd_imm_scalar_p (rtx x, enum machine_mode mode); bool aarch64_simd_imm_zero_p (rtx, enum machine_mode); bool aarch64_simd_scalar_immediate_valid_for_move (rtx, enum machine_mode); diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md index 58ccf1f..947ed4e 100644 --- a/gcc/config/aarch64/aarch64-simd.md +++ b/gcc/config/aarch64/aarch64-simd.md @@ -1022,7 +1022,7 @@ (match_operand: 1 "register_operand" "w,r") (vec_select: (match_dup 0) - (match_operand:VQ 2 "vect_par_cnst_hi_half" ""))))] + (match_operand:VQ 2 "vect_par_cnst_lo_half" ""))))] "TARGET_SIMD && BYTES_BIG_ENDIAN" "@ ins\\t%0.d[1], %1.d[0] @@ -1035,7 +1035,7 @@ (match_operand: 1 "register_operand" "")] "TARGET_SIMD" { - rtx p = aarch64_simd_vect_par_cnst_half (mode, BYTES_BIG_ENDIAN); + rtx p = aarch64_simd_vect_par_cnst_half (mode, false); if (BYTES_BIG_ENDIAN) emit_insn (gen_aarch64_simd_move_hi_quad_be_ (operands[0], operands[1], p)); diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 91821ed..efa28af 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -7885,23 +7885,81 @@ aarch64_simd_scalar_immediate_valid_for_move (rtx op, enum machine_mode mode) return aarch64_simd_valid_immediate (op_v, vmode, false, NULL); } -/* Construct and return a PARALLEL RTX vector. */ +/* Construct and return a PARALLEL RTX vector with elements numbering the + lanes of either the high (HIGH == TRUE) or low (HIGH == FALSE) half of + the vector - from the perspective of the architecture. This does not + line up with GCC's perspective on lane numbers, so we end up with + different masks depending on our target endian-ness. The diagram + below may help. We must draw the distinction when building masks + which select one half of the vector. An instruction selecting + architectural low-lanes for a big-endian target, must be described using + a mask selecting GCC high-lanes. + + Big-Endian Little-Endian + +GCC 0 1 2 3 3 2 1 0 + | x | x | x | x | | x | x | x | x | +Architecture 3 2 1 0 3 2 1 0 + +Low Mask: { 2, 3 } { 0, 1 } +High Mask: { 0, 1 } { 2, 3 } +*/ + rtx aarch64_simd_vect_par_cnst_half (enum machine_mode mode, bool high) { int nunits = GET_MODE_NUNITS (mode); rtvec v = rtvec_alloc (nunits / 2); - int base = high ? nunits / 2 : 0; + int high_base = nunits / 2; + int low_base = 0; + int base; rtx t1; int i; - for (i=0; i < nunits / 2; i++) + if (BYTES_BIG_ENDIAN) + base = high ? low_base : high_base; + else + base = high ? high_base : low_base; + + for (i = 0; i < nunits / 2; i++) RTVEC_ELT (v, i) = GEN_INT (base + i); t1 = gen_rtx_PARALLEL (mode, v); return t1; } +/* Check OP for validity as a PARALLEL RTX vector with elements + numbering the lanes of either the high (HIGH == TRUE) or low lanes, + from the perspective of the architecture. See the diagram above + aarch64_simd_vect_par_cnst_half for more details. */ + +bool +aarch64_simd_check_vect_par_cnst_half (rtx op, enum machine_mode mode, + bool high) +{ + rtx ideal = aarch64_simd_vect_par_cnst_half (mode, high); + HOST_WIDE_INT count_op = XVECLEN (op, 0); + HOST_WIDE_INT count_ideal = XVECLEN (ideal, 0); + int i = 0; + + if (!VECTOR_MODE_P (mode)) + return false; + + if (count_op != count_ideal) + return false; + + for (i = 0; i < count_ideal; i++) + { + rtx elt_op = XVECEXP (op, 0, i); + rtx elt_ideal = XVECEXP (ideal, 0, i); + + if (GET_CODE (elt_op) != CONST_INT + || INTVAL (elt_ideal) != INTVAL (elt_op)) + return false; + } + return true; +} + /* Bounds-check lanes. Ensure OPERAND lies between LOW (inclusive) and HIGH (exclusive). */ void diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md index 2702a3c..95d1910 100644 --- a/gcc/config/aarch64/predicates.md +++ b/gcc/config/aarch64/predicates.md @@ -207,62 +207,15 @@ (define_special_predicate "vect_par_cnst_hi_half" (match_code "parallel") { - HOST_WIDE_INT count = XVECLEN (op, 0); - int nunits = GET_MODE_NUNITS (mode); - int i; - - if (count < 1 - || count != nunits / 2) - return false; - - if (!VECTOR_MODE_P (mode)) - return false; - - for (i = 0; i < count; i++) - { - rtx elt = XVECEXP (op, 0, i); - int val; - - if (GET_CODE (elt) != CONST_INT) - return false; - - val = INTVAL (elt); - if (val != (nunits / 2) + i) - return false; - } - return true; + return aarch64_simd_check_vect_par_cnst_half (op, mode, true); }) (define_special_predicate "vect_par_cnst_lo_half" (match_code "parallel") { - HOST_WIDE_INT count = XVECLEN (op, 0); - int nunits = GET_MODE_NUNITS (mode); - int i; - - if (count < 1 - || count != nunits / 2) - return false; - - if (!VECTOR_MODE_P (mode)) - return false; - - for (i = 0; i < count; i++) - { - rtx elt = XVECEXP (op, 0, i); - int val; - - if (GET_CODE (elt) != CONST_INT) - return false; - - val = INTVAL (elt); - if (val != i) - return false; - } - return true; + return aarch64_simd_check_vect_par_cnst_half (op, mode, false); }) - (define_special_predicate "aarch64_simd_lshift_imm" (match_code "const_vector") { -- 2.7.4