neon.md (vec_shr_<mode>, [...]): Disable in big-endian mode.
authorJulian Brown <julian@codesourcery.com>
Fri, 8 Jul 2011 17:30:43 +0000 (17:30 +0000)
committerJulian Brown <jules@gcc.gnu.org>
Fri, 8 Jul 2011 17:30:43 +0000 (17:30 +0000)
gcc/
* config/arm/neon.md (vec_shr_<mode>, vec_shl_<mode>): Disable in
big-endian mode.
(reduc_splus_<mode>, reduc_uplus_<mode>, reduc_smin_<mode>)
(reduc_smax_<mode>, reduc_umin_<mode>, reduc_umax_<mode>)
(neon_vec_unpack<US>_lo_<mode>, neon_vec_unpack<US>_hi_<mode>)
(vec_unpack<US>_hi_<mode>, vec_unpack<US>_lo_<mode>)
(neon_vec_<US>mult_lo_<mode>, vec_widen_<US>mult_lo_<mode>)
(neon_vec_<US>mult_hi_<mode>, vec_widen_<US>mult_hi_<mode>)
(vec_pack_trunc_<mode>, neon_vec_pack_trunc_<mode>): Disable for Q
registers in big-endian mode.

gcc/testsuite/
* lib/target-supports.exp
(check_effective_target_arm_little_endian): New.
(check_effective_target_vect_pack_trunc): Use above.
(check_effective_target_vect_unpack): Likewise.
(check_effective_target_vect_element_align): Test
check_effective_target_arm_vect_no_misalign for ARM.

From-SVN: r176050

gcc/ChangeLog
gcc/config/arm/neon.md
gcc/testsuite/ChangeLog
gcc/testsuite/lib/target-supports.exp

index 60cc66d6f08b2aa0f3bf07d47f011e9e947ad227..52f3d7b1fe68ada94b6fdf22479fe5827e1567b5 100644 (file)
@@ -1,3 +1,16 @@
+2011-07-08  Julian Brown  <julian@codesourcery.com>
+
+       * config/arm/neon.md (vec_shr_<mode>, vec_shl_<mode>): Disable in
+       big-endian mode.
+       (reduc_splus_<mode>, reduc_uplus_<mode>, reduc_smin_<mode>)
+       (reduc_smax_<mode>, reduc_umin_<mode>, reduc_umax_<mode>)
+       (neon_vec_unpack<US>_lo_<mode>, neon_vec_unpack<US>_hi_<mode>)
+       (vec_unpack<US>_hi_<mode>, vec_unpack<US>_lo_<mode>)
+       (neon_vec_<US>mult_lo_<mode>, vec_widen_<US>mult_lo_<mode>)
+       (neon_vec_<US>mult_hi_<mode>, vec_widen_<US>mult_hi_<mode>)
+       (vec_pack_trunc_<mode>, neon_vec_pack_trunc_<mode>): Disable for Q
+       registers in big-endian mode.
+
 2011-07-08  Bernd Schmidt  <bernds@codesourcery.com>
 
        * genattrtab.c (evaluate_eq_attr): Allow an attribute to be defined
index 2c109e09ac6c22a35a3972d0c0f081a00123c794..becb5240a321496e103b07b14ada4bd350923ce8 100644 (file)
 ;; shift-count granularity. That's good enough for the middle-end's current
 ;; needs.
 
+;; Note that it's not safe to perform such an operation in big-endian mode,
+;; due to element-ordering issues.
+
 (define_expand "vec_shr_<mode>"
   [(match_operand:VDQ 0 "s_register_operand" "")
    (match_operand:VDQ 1 "s_register_operand" "")
    (match_operand:SI 2 "const_multiple_of_8_operand" "")]
-  "TARGET_NEON"
+  "TARGET_NEON && !BYTES_BIG_ENDIAN"
 {
   rtx zero_reg;
   HOST_WIDE_INT num_bits = INTVAL (operands[2]);
   [(match_operand:VDQ 0 "s_register_operand" "")
    (match_operand:VDQ 1 "s_register_operand" "")
    (match_operand:SI 2 "const_multiple_of_8_operand" "")]
-  "TARGET_NEON"
+  "TARGET_NEON && !BYTES_BIG_ENDIAN"
 {
   rtx zero_reg;
   HOST_WIDE_INT num_bits = INTVAL (operands[2]);
 (define_expand "reduc_splus_<mode>"
   [(match_operand:VQ 0 "s_register_operand" "")
    (match_operand:VQ 1 "s_register_operand" "")]
-  "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
+  "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)
+   && !BYTES_BIG_ENDIAN"
 {
   rtx step1 = gen_reg_rtx (<V_HALF>mode);
   rtx res_d = gen_reg_rtx (<V_HALF>mode);
   [(set (match_operand:V2DI 0 "s_register_operand" "=w")
        (unspec:V2DI [(match_operand:V2DI 1 "s_register_operand" "w")]
                     UNSPEC_VPADD))]
-  "TARGET_NEON"
+  "TARGET_NEON && !BYTES_BIG_ENDIAN"
   "vadd.i64\t%e0, %e1, %f1"
   [(set_attr "neon_type" "neon_int_1")]
 )
 (define_expand "reduc_uplus_<mode>"
   [(match_operand:VDQI 0 "s_register_operand" "")
    (match_operand:VDQI 1 "s_register_operand" "")]
-  "TARGET_NEON"
+  "TARGET_NEON && (<Is_d_reg> || !BYTES_BIG_ENDIAN)"
 {
   emit_insn (gen_reduc_splus_<mode> (operands[0], operands[1]));
   DONE;
 (define_expand "reduc_smin_<mode>"
   [(match_operand:VQ 0 "s_register_operand" "")
    (match_operand:VQ 1 "s_register_operand" "")]
-  "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
+  "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)
+   && !BYTES_BIG_ENDIAN"
 {
   rtx step1 = gen_reg_rtx (<V_HALF>mode);
   rtx res_d = gen_reg_rtx (<V_HALF>mode);
 (define_expand "reduc_smax_<mode>"
   [(match_operand:VQ 0 "s_register_operand" "")
    (match_operand:VQ 1 "s_register_operand" "")]
-  "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)"
+  "TARGET_NEON && (!<Is_float_mode> || flag_unsafe_math_optimizations)
+   && !BYTES_BIG_ENDIAN"
 {
   rtx step1 = gen_reg_rtx (<V_HALF>mode);
   rtx res_d = gen_reg_rtx (<V_HALF>mode);
 (define_expand "reduc_umin_<mode>"
   [(match_operand:VQI 0 "s_register_operand" "")
    (match_operand:VQI 1 "s_register_operand" "")]
-  "TARGET_NEON"
+  "TARGET_NEON && !BYTES_BIG_ENDIAN"
 {
   rtx step1 = gen_reg_rtx (<V_HALF>mode);
   rtx res_d = gen_reg_rtx (<V_HALF>mode);
 (define_expand "reduc_umax_<mode>"
   [(match_operand:VQI 0 "s_register_operand" "")
    (match_operand:VQI 1 "s_register_operand" "")]
-  "TARGET_NEON"
+  "TARGET_NEON && !BYTES_BIG_ENDIAN"
 {
   rtx step1 = gen_reg_rtx (<V_HALF>mode);
   rtx res_d = gen_reg_rtx (<V_HALF>mode);
         (SE:<V_unpack> (vec_select:<V_HALF>
                          (match_operand:VU 1 "register_operand" "w")
                          (match_operand:VU 2 "vect_par_constant_low" ""))))]
-  "TARGET_NEON"
+  "TARGET_NEON && !BYTES_BIG_ENDIAN"
   "vmovl.<US><V_sz_elem> %q0, %e1"
   [(set_attr "neon_type" "neon_shift_1")]
 )
         (SE:<V_unpack> (vec_select:<V_HALF>
                          (match_operand:VU 1 "register_operand" "w")
                          (match_operand:VU 2 "vect_par_constant_high" ""))))]
-  "TARGET_NEON"
+  "TARGET_NEON && !BYTES_BIG_ENDIAN"
   "vmovl.<US><V_sz_elem> %q0, %f1"
   [(set_attr "neon_type" "neon_shift_1")]
 )
 (define_expand "vec_unpack<US>_hi_<mode>"
   [(match_operand:<V_unpack> 0 "register_operand" "")
    (SE:<V_unpack> (match_operand:VU 1 "register_operand"))]
- "TARGET_NEON"
+ "TARGET_NEON && !BYTES_BIG_ENDIAN"
   {
    rtvec v = rtvec_alloc (<V_mode_nunits>/2)  ;
    rtx t1;
 (define_expand "vec_unpack<US>_lo_<mode>"
   [(match_operand:<V_unpack> 0 "register_operand" "")
    (SE:<V_unpack> (match_operand:VU 1 "register_operand" ""))]
- "TARGET_NEON"
+ "TARGET_NEON && !BYTES_BIG_ENDIAN"
   {
    rtvec v = rtvec_alloc (<V_mode_nunits>/2)  ;
    rtx t1;
                        (SE:<V_unpack> (vec_select:<V_HALF>
                            (match_operand:VU 3 "register_operand" "w") 
                            (match_dup 2)))))]
-  "TARGET_NEON"
+  "TARGET_NEON && !BYTES_BIG_ENDIAN"
   "vmull.<US><V_sz_elem> %q0, %e1, %e3"
   [(set_attr "neon_type" "neon_shift_1")]
 )
   [(match_operand:<V_unpack> 0 "register_operand" "")
    (SE:<V_unpack> (match_operand:VU 1 "register_operand" ""))
    (SE:<V_unpack> (match_operand:VU 2 "register_operand" ""))]
- "TARGET_NEON"
+ "TARGET_NEON && !BYTES_BIG_ENDIAN"
  {
    rtvec v = rtvec_alloc (<V_mode_nunits>/2)  ;
    rtx t1;
                       (SE:<V_unpack> (vec_select:<V_HALF>
                            (match_operand:VU 3 "register_operand" "w") 
                            (match_dup 2)))))]
-  "TARGET_NEON"
+  "TARGET_NEON && !BYTES_BIG_ENDIAN"
   "vmull.<US><V_sz_elem> %q0, %f1, %f3"
   [(set_attr "neon_type" "neon_shift_1")]
 )
   [(match_operand:<V_unpack> 0 "register_operand" "")
    (SE:<V_unpack> (match_operand:VU 1 "register_operand" ""))
    (SE:<V_unpack> (match_operand:VU 2 "register_operand" ""))]
- "TARGET_NEON"
+ "TARGET_NEON && !BYTES_BIG_ENDIAN"
  {
    rtvec v = rtvec_alloc (<V_mode_nunits>/2)  ;
    rtx t1;
  }
 )
 
+; FIXME: These instruction patterns can't be used safely in big-endian mode
+; because the ordering of vector elements in Q registers is different from what
+; the semantics of the instructions require.
+
 (define_insn "vec_pack_trunc_<mode>"
  [(set (match_operand:<V_narrow_pack> 0 "register_operand" "=&w")
        (vec_concat:<V_narrow_pack> 
                        (match_operand:VN 1 "register_operand" "w"))
                (truncate:<V_narrow>
                        (match_operand:VN 2 "register_operand" "w"))))]
- "TARGET_NEON"
+ "TARGET_NEON && !BYTES_BIG_ENDIAN"
  "vmovn.i<V_sz_elem>\t%e0, %q1\;vmovn.i<V_sz_elem>\t%f0, %q2"
  [(set_attr "neon_type" "neon_shift_1")
   (set_attr "length" "8")]
 (define_insn "neon_vec_pack_trunc_<mode>"
  [(set (match_operand:<V_narrow> 0 "register_operand" "=w")
        (truncate:<V_narrow> (match_operand:VN 1 "register_operand" "w")))]
- "TARGET_NEON"
+ "TARGET_NEON && !BYTES_BIG_ENDIAN"
  "vmovn.i<V_sz_elem>\t%P0, %q1"
  [(set_attr "neon_type" "neon_shift_1")]
 )
  [(match_operand:<V_narrow_pack> 0 "register_operand" "")
   (match_operand:VSHFT 1 "register_operand" "")
   (match_operand:VSHFT 2 "register_operand")]
- "TARGET_NEON"
+ "TARGET_NEON && !BYTES_BIG_ENDIAN"
 {
   rtx tempreg = gen_reg_rtx (<V_DOUBLE>mode);
   
index 9393815eab77d3108d5c1a67cfee08d602e62656..b2ba49aea53fa9198ad81a6e9b198a66f96c4ef2 100644 (file)
@@ -1,3 +1,12 @@
+2011-07-08  Julian Brown  <julian@codesourcery.com>
+
+       * lib/target-supports.exp
+       (check_effective_target_arm_little_endian): New.
+       (check_effective_target_vect_pack_trunc): Use above.
+       (check_effective_target_vect_unpack): Likewise.
+       (check_effective_target_vect_element_align): Test
+       check_effective_target_arm_vect_no_misalign for ARM.
+
 2011-07-08  Jason Merrill  <jason@redhat.com>
 
        PR c++/49673
index 8b9c386f7a883a745a5b7d0bf28693d3ddbd4e7f..6ef87ab13aef80bb35d0c2b2743106a31d205457 100644 (file)
@@ -1899,6 +1899,15 @@ proc check_effective_target_arm_nothumb { } {
     }]
 }
 
+# Return 1 if this is a little-endian ARM target
+proc check_effective_target_arm_little_endian { } {
+    return [check_no_compiler_messages arm_little_endian assembly {
+       #if !defined(__arm__) || !defined(__ARMEL__)
+       #error FOO
+       #endif
+    }]
+}
+
 # Return 1 if this is an ARM target that only supports aligned vector accesses
 proc check_effective_target_arm_vect_no_misalign { } {
     return [check_no_compiler_messages arm_vect_no_misalign assembly {
@@ -2953,7 +2962,8 @@ proc check_effective_target_vect_pack_trunc { } {
              || [istarget i?86-*-*]
              || [istarget x86_64-*-*]
              || [istarget spu-*-*]
-             || ([istarget arm*-*-*] && [check_effective_target_arm_neon]) } {
+             || ([istarget arm*-*-*] && [check_effective_target_arm_neon]
+                && [check_effective_target_arm_little_endian]) } {
             set et_vect_pack_trunc_saved 1
         }
     }
@@ -2978,7 +2988,8 @@ proc check_effective_target_vect_unpack { } {
              || [istarget x86_64-*-*] 
              || [istarget spu-*-*]
              || [istarget ia64-*-*]
-             || ([istarget arm*-*-*] && [check_effective_target_arm_neon]) } {
+             || ([istarget arm*-*-*] && [check_effective_target_arm_neon]
+                && [check_effective_target_arm_little_endian]) } {
             set et_vect_unpack_saved 1
         }
     }
@@ -3164,7 +3175,8 @@ proc check_effective_target_vect_element_align { } {
        verbose "check_effective_target_vect_element_align: using cached result" 2
     } else {
        set et_vect_element_align 0
-       if { [istarget arm*-*-*]
+       if { ([istarget arm*-*-*]
+             && ![check_effective_target_arm_vect_no_misalign])
             || [check_effective_target_vect_hw_misalign] } {
           set et_vect_element_align 1
        }