diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-09-05 08:56:12 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-09-05 08:56:12 +0000 |
commit | 6a802d8242d059d55f3cdd558199403c3b8fbb05 (patch) | |
tree | d128c5095aaa3608ec7c87a3c747396d6d736929 /gcc/config/arm/arm.c | |
parent | bf4993e7e79a3b597ba502231bf74f5676b08c19 (diff) | |
download | gcc-6a802d8242d059d55f3cdd558199403c3b8fbb05.tar.gz |
2012-09-05 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 190965 using svnmerge.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@190968 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/arm/arm.c')
-rw-r--r-- | gcc/config/arm/arm.c | 97 |
1 files changed, 84 insertions, 13 deletions
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 9ce3c0f068a..4001f350f2f 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -20959,7 +20959,7 @@ arm_expand_builtin (tree exp, else if (icode == CODE_FOR_iwmmxt_tinsrw && (selector < 0 ||selector > 1)) error ("the range of selector should be in 0 to 1"); mask <<= selector; - op2 = gen_rtx_CONST_INT (SImode, mask); + op2 = GEN_INT (mask); } if (target == 0 || GET_MODE (target) != tmode @@ -21862,7 +21862,7 @@ thumb1_extra_regs_pushed (arm_stack_offsets *offsets, bool for_prologue) unsigned long l_mask = live_regs_mask & (for_prologue ? 0x40ff : 0xff); /* Then count how many other high registers will need to be pushed. */ unsigned long high_regs_pushed = bit_count (live_regs_mask & 0x0f00); - int n_free, reg_base; + int n_free, reg_base, size; if (!for_prologue && frame_pointer_needed) amount = offsets->locals_base - offsets->saved_regs; @@ -21901,7 +21901,8 @@ thumb1_extra_regs_pushed (arm_stack_offsets *offsets, bool for_prologue) n_free = 0; if (!for_prologue) { - reg_base = arm_size_return_regs () / UNITS_PER_WORD; + size = arm_size_return_regs (); + reg_base = ARM_NUM_INTS (size); live_regs_mask >>= reg_base; } @@ -21955,8 +21956,7 @@ thumb1_unexpanded_epilogue (void) if (extra_pop > 0) { unsigned long extra_mask = (1 << extra_pop) - 1; - live_regs_mask |= extra_mask << ((size + UNITS_PER_WORD - 1) - / UNITS_PER_WORD); + live_regs_mask |= extra_mask << ARM_NUM_INTS (size); } /* The prolog may have pushed some high registers to use as @@ -25937,6 +25937,72 @@ arm_evpc_neon_vtrn (struct expand_vec_perm_d *d) return true; } +/* Recognize patterns for the VEXT insns. */ + +static bool +arm_evpc_neon_vext (struct expand_vec_perm_d *d) +{ + unsigned int i, nelt = d->nelt; + rtx (*gen) (rtx, rtx, rtx, rtx); + rtx offset; + + unsigned int location; + + unsigned int next = d->perm[0] + 1; + + /* TODO: Handle GCC's numbering of elements for big-endian. */ + if (BYTES_BIG_ENDIAN) + return false; + + /* Check if the extracted indexes are increasing by one. */ + for (i = 1; i < nelt; next++, i++) + { + /* If we hit the most significant element of the 2nd vector in + the previous iteration, no need to test further. */ + if (next == 2 * nelt) + return false; + + /* If we are operating on only one vector: it could be a + rotation. If there are only two elements of size < 64, let + arm_evpc_neon_vrev catch it. */ + if (d->one_vector_p && (next == nelt)) + { + if ((nelt == 2) && (d->vmode != V2DImode)) + return false; + else + next = 0; + } + + if (d->perm[i] != next) + return false; + } + + location = d->perm[0]; + + switch (d->vmode) + { + case V16QImode: gen = gen_neon_vextv16qi; break; + case V8QImode: gen = gen_neon_vextv8qi; break; + case V4HImode: gen = gen_neon_vextv4hi; break; + case V8HImode: gen = gen_neon_vextv8hi; break; + case V2SImode: gen = gen_neon_vextv2si; break; + case V4SImode: gen = gen_neon_vextv4si; break; + case V2SFmode: gen = gen_neon_vextv2sf; break; + case V4SFmode: gen = gen_neon_vextv4sf; break; + case V2DImode: gen = gen_neon_vextv2di; break; + default: + return false; + } + + /* Success! */ + if (d->testing_p) + return true; + + offset = GEN_INT (location); + emit_insn (gen (d->target, d->op0, d->op1, offset)); + return true; +} + /* The NEON VTBL instruction is a fully variable permuation that's even stronger than what we expose via VEC_PERM_EXPR. What it doesn't do is mask the index operand as VEC_PERM_EXPR requires. Therefore we @@ -25976,6 +26042,12 @@ arm_evpc_neon_vtbl (struct expand_vec_perm_d *d) static bool arm_expand_vec_perm_const_1 (struct expand_vec_perm_d *d) { + /* Check if the input mask matches vext before reordering the + operands. */ + if (TARGET_NEON) + if (arm_evpc_neon_vext (d)) + return true; + /* The pattern matching functions above are written to look for a small number to begin the sequence (0, 1, N/2). If we begin with an index from the second operand, we can swap the operands. */ @@ -26218,12 +26290,12 @@ arm_emit_coreregs_64bit_shift (enum rtx_code code, rtx out, rtx in, /* Macros to make following code more readable. */ #define SUB_32(DEST,SRC) \ - gen_addsi3 ((DEST), (SRC), gen_rtx_CONST_INT (VOIDmode, -32)) + gen_addsi3 ((DEST), (SRC), GEN_INT (-32)) #define RSB_32(DEST,SRC) \ - gen_subsi3 ((DEST), gen_rtx_CONST_INT (VOIDmode, 32), (SRC)) + gen_subsi3 ((DEST), GEN_INT (32), (SRC)) #define SUB_S_32(DEST,SRC) \ gen_addsi3_compare0 ((DEST), (SRC), \ - gen_rtx_CONST_INT (VOIDmode, -32)) + GEN_INT (-32)) #define SET(DEST,SRC) \ gen_rtx_SET (SImode, (DEST), (SRC)) #define SHIFT(CODE,SRC,AMOUNT) \ @@ -26259,7 +26331,7 @@ arm_emit_coreregs_64bit_shift (enum rtx_code code, rtx out, rtx in, { if (code == ASHIFTRT) { - rtx const31_rtx = gen_rtx_CONST_INT (VOIDmode, 31); + rtx const31_rtx = GEN_INT (31); emit_insn (SET (out_down, SHIFT (code, in_up, const31_rtx))); emit_insn (SET (out_up, SHIFT (code, in_up, const31_rtx))); } @@ -26271,8 +26343,7 @@ arm_emit_coreregs_64bit_shift (enum rtx_code code, rtx out, rtx in, else if (INTVAL (amount) < 32) { /* Shifts by a constant less than 32. */ - rtx reverse_amount = gen_rtx_CONST_INT (VOIDmode, - 32 - INTVAL (amount)); + rtx reverse_amount = GEN_INT (32 - INTVAL (amount)); emit_insn (SET (out_down, LSHIFT (code, in_down, amount))); emit_insn (SET (out_down, @@ -26283,12 +26354,12 @@ arm_emit_coreregs_64bit_shift (enum rtx_code code, rtx out, rtx in, else { /* Shifts by a constant greater than 31. */ - rtx adj_amount = gen_rtx_CONST_INT (VOIDmode, INTVAL (amount) - 32); + rtx adj_amount = GEN_INT (INTVAL (amount) - 32); emit_insn (SET (out_down, SHIFT (code, in_up, adj_amount))); if (code == ASHIFTRT) emit_insn (gen_ashrsi3 (out_up, in_up, - gen_rtx_CONST_INT (VOIDmode, 31))); + GEN_INT (31))); else emit_insn (SET (out_up, const0_rtx)); } |