diff options
author | Richard Earnshaw <rearnsha@arm.com> | 2011-11-19 13:47:35 +0000 |
---|---|---|
committer | Richard Earnshaw <rearnsha@gcc.gnu.org> | 2011-11-19 13:47:35 +0000 |
commit | 78811dd3b7d84c74392048bec3122d7222596253 (patch) | |
tree | 574f7789a94ddef4c81768c221499716fb99b920 /gcc | |
parent | 40353fb3aa64e07ac3dd27fc2306b5c5010b91d2 (diff) | |
download | gcc-78811dd3b7d84c74392048bec3122d7222596253.zip gcc-78811dd3b7d84c74392048bec3122d7222596253.tar.gz gcc-78811dd3b7d84c74392048bec3122d7222596253.tar.bz2 |
re PR target/50493 (ICE in neon_disambiguate_copy, at config/arm/arm.c:20388)
PR target/50493
* arm.c (neon_disambiguate_copy): Correctly handle partial overlap
of src and dest operands.
From-SVN: r181508
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 45 |
2 files changed, 26 insertions, 25 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 27dace6..43de112 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2011-11-19 Richard Earnshaw <rearnsha@arm.com> + + PR target/50493 + * arm.c (neon_disambiguate_copy): Correctly handle partial overlap + of src and dest operands. + 2011-11-19 Iain Sandoe <iains@gcc.gnu.org> * config/darwin.h (ASM_DEBUG_SPEC): New. diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 4846d72..e3b0b88 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -20728,39 +20728,34 @@ neon_emit_pair_result_insn (enum machine_mode mode, emit_move_insn (mem, tmp2); } -/* Set up operands for a register copy from src to dest, taking care not to - clobber registers in the process. - FIXME: This has rather high polynomial complexity (O(n^3)?) but shouldn't - be called with a large N, so that should be OK. */ +/* Set up OPERANDS for a register copy from SRC to DEST, taking care + not to early-clobber SRC registers in the process. + We assume that the operands described by SRC and DEST represent a + decomposed copy of OPERANDS[1] into OPERANDS[0]. COUNT is the + number of components into which the copy has been decomposed. */ void neon_disambiguate_copy (rtx *operands, rtx *dest, rtx *src, unsigned int count) { - unsigned int copied = 0, opctr = 0; - unsigned int done = (1 << count) - 1; - unsigned int i, j; + unsigned int i; - while (copied != done) + if (!reg_overlap_mentioned_p (operands[0], operands[1]) + || REGNO (operands[0]) < REGNO (operands[1])) { for (i = 0; i < count; i++) - { - int good = 1; - - for (j = 0; good && j < count; j++) - if (i != j && (copied & (1 << j)) == 0 - && reg_overlap_mentioned_p (src[j], dest[i])) - good = 0; - - if (good) - { - operands[opctr++] = dest[i]; - operands[opctr++] = src[i]; - copied |= 1 << i; - } - } + { + operands[2 * i] = dest[i]; + operands[2 * i + 1] = src[i]; + } + } + else + { + for (i = 0; i < count; i++) + { + operands[2 * i] = dest[count - i - 1]; + operands[2 * i + 1] = src[count - i - 1]; + } } - - gcc_assert (opctr == count * 2); } /* Expand an expression EXP that calls a built-in function, |