[arm] Fix BE index for single-var vector initialisers (PR91060)
authorRichard Sandiford <richard.sandiford@arm.com>
Wed, 10 Jul 2019 18:41:44 +0000 (18:41 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Wed, 10 Jul 2019 18:41:44 +0000 (18:41 +0000)
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

gcc/ChangeLog
gcc/config/arm/arm.c
gcc/config/arm/iterators.md
gcc/config/arm/neon.md

index e7004e3b95c0e6ab04b4bf7e02fab373c2166142..4c75120a61a3e3243b868f802317d11234a2bcce 100644 (file)
@@ -1,3 +1,13 @@
+2019-07-10  Richard Sandiford  <richard.sandiford@arm.com>
+
+       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>.
+
 2019-07-10  Vladimir Makarov  <vmakarov@redhat.com>
 
        PR target/91102
index f42a7b1d4edb04f4a26617f9cda1730dcd7c393a..81286cadf32f908e045d704128c5e06842e0cc92 100644 (file)
@@ -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;
     }
 
index e03a7202417586808f6033864432bc77e63d746f..eca16636ade577d84dc62523d066e72f79dc38f6 100644 (file)
 ;; Modes with 8-bit elements.
 (define_mode_iterator VE [V8QI V16QI])
 
+;; V2DI only (for use with @ patterns).
+(define_mode_iterator V2DI_ONLY [V2DI])
+
 ;; Modes with 64-bit elements only.
 (define_mode_iterator V64 [DI V2DI])
 
index 4bfe770f827301c234aaa2775f3d86a95f329fd9..6333e0ea3ea68d73bed1f7c4d8ca090090ad68cc 100644 (file)
   "vld1.<V_sz_elem>\t{%q0}, %A1"
   [(set_attr "type" "neon_load1_1reg<q>")])
 
-(define_insn "vec_set<mode>_internal"
+(define_insn "@vec_set<mode>_internal"
   [(set (match_operand:VD_LANE 0 "s_register_operand" "=w,w")
         (vec_merge:VD_LANE
           (vec_duplicate:VD_LANE
 }
   [(set_attr "type" "neon_load1_all_lanes<q>,neon_from_gp<q>")])
 
-(define_insn "vec_set<mode>_internal"
+(define_insn "@vec_set<mode>_internal"
   [(set (match_operand:VQ2 0 "s_register_operand" "=w,w")
         (vec_merge:VQ2
           (vec_duplicate:VQ2
   [(set_attr "type" "neon_load1_all_lanes<q>,neon_from_gp<q>")]
 )
 
-(define_insn "vec_setv2di_internal"
-  [(set (match_operand:V2DI 0 "s_register_operand" "=w,w")
-        (vec_merge:V2DI
-          (vec_duplicate:V2DI
+(define_insn "@vec_set<mode>_internal"
+  [(set (match_operand:V2DI_ONLY 0 "s_register_operand" "=w,w")
+        (vec_merge:V2DI_ONLY
+          (vec_duplicate:V2DI_ONLY
             (match_operand:DI 1 "nonimmediate_operand" "Um,r"))
-          (match_operand:V2DI 3 "s_register_operand" "0,0")
+          (match_operand:V2DI_ONLY 3 "s_register_operand" "0,0")
           (match_operand:SI 2 "immediate_operand" "i,i")))]
   "TARGET_NEON"
 {