diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2019-07-10 18:41:44 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2019-07-10 18:41:44 +0000 |
commit | 8ba8ebffc4621552febf47eea470c260488418b5 (patch) | |
tree | 5fe02dc25c3ed66bc8fbe055e569aaae21a0fede /gcc/config/arm/arm.c | |
parent | 4b8d9b23371d3ee0f7a9c1d99e80745400542930 (diff) | |
download | gcc-8ba8ebffc4621552febf47eea470c260488418b5.tar.gz |
[arm] Fix BE index for single-var vector initialisers (PR91060)
If a vector constructor has a single nonconstant element,
neon_expand_vector_init loads the constant lanes and then inserts the
nonconstant value. The problem was that it was doing the insertion
using the arm_neon.h neon_vset_lane<mode> patterns, which use
architectural lane numbering rather than GCC lane numbering.
2019-07-10 Richard Sandiford <richard.sandiford@arm.com>
gcc/
PR target/91060
* config/arm/iterators.md (V2DI_ONLY): New mode iterator.
* config/arm/neon.md (vec_set<mode>_internal): Add a '@' prefix.
(vec_setv2di_internal): Reexpress as...
(@vec_set<V2DI_ONLY:mode>_internal): ...this.
* config/arm/arm.c (neon_expand_vector_init): Use gen_vec_set_internal
rather than gen_neon_vset_lane<mode>.
From-SVN: r273365
Diffstat (limited to 'gcc/config/arm/arm.c')
-rw-r--r-- | gcc/config/arm/arm.c | 35 |
1 files changed, 2 insertions, 33 deletions
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index f42a7b1d4ed..81286cadf32 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -12471,7 +12471,7 @@ neon_expand_vector_init (rtx target, rtx vals) if (n_var == 1) { rtx copy = copy_rtx (vals); - rtx index = GEN_INT (one_var); + rtx merge_mask = GEN_INT (1 << one_var); /* Load constant part of vector, substitute neighboring value for varying element. */ @@ -12480,38 +12480,7 @@ neon_expand_vector_init (rtx target, rtx vals) /* Insert variable. */ x = copy_to_mode_reg (inner_mode, XVECEXP (vals, 0, one_var)); - switch (mode) - { - case E_V8QImode: - emit_insn (gen_neon_vset_lanev8qi (target, x, target, index)); - break; - case E_V16QImode: - emit_insn (gen_neon_vset_lanev16qi (target, x, target, index)); - break; - case E_V4HImode: - emit_insn (gen_neon_vset_lanev4hi (target, x, target, index)); - break; - case E_V8HImode: - emit_insn (gen_neon_vset_lanev8hi (target, x, target, index)); - break; - case E_V2SImode: - emit_insn (gen_neon_vset_lanev2si (target, x, target, index)); - break; - case E_V4SImode: - emit_insn (gen_neon_vset_lanev4si (target, x, target, index)); - break; - case E_V2SFmode: - emit_insn (gen_neon_vset_lanev2sf (target, x, target, index)); - break; - case E_V4SFmode: - emit_insn (gen_neon_vset_lanev4sf (target, x, target, index)); - break; - case E_V2DImode: - emit_insn (gen_neon_vset_lanev2di (target, x, target, index)); - break; - default: - gcc_unreachable (); - } + emit_insn (gen_vec_set_internal (mode, target, x, merge_mask, target)); return; } |