]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR target/59163 (program compiled with g++ -O3 segfaults)
authorJakub Jelinek <jakub@redhat.com>
Wed, 4 Dec 2013 11:11:24 +0000 (12:11 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 4 Dec 2013 11:11:24 +0000 (12:11 +0100)
PR target/59163
* config/i386/i386.c (ix86_legitimate_combined_insn): If for
!TARGET_AVX there is misaligned MEM operand with vector mode
and get_attr_ssememalign is 0, return false.
(ix86_expand_special_args_builtin): Add get_pointer_alignment
computed alignment and for non-temporal loads/stores also
at least GET_MODE_ALIGNMENT as MEM_ALIGN.
* config/i386/sse.md
(<sse>_loadu<ssemodesuffix><avxsizesuffix><mask_name>,
<sse>_storeu<ssemodesuffix><avxsizesuffix>,
<sse2_avx_avx512f>_loaddqu<mode><mask_name>,
<sse2_avx_avx512f>_storedqu<mode>, <sse3>_lddqu<avxsizesuffix>,
sse_vmrcpv4sf2, sse_vmrsqrtv4sf2, sse2_cvtdq2pd, sse_movhlps,
sse_movlhps, sse_storehps, sse_loadhps, sse_loadlps,
*vec_interleave_highv2df, *vec_interleave_lowv2df,
*vec_extractv2df_1_sse, sse2_movsd, sse4_1_<code>v8qiv8hi2,
sse4_1_<code>v4qiv4si2, sse4_1_<code>v4hiv4si2,
sse4_1_<code>v2qiv2di2, sse4_1_<code>v2hiv2di2,
sse4_1_<code>v2siv2di2, sse4_2_pcmpestr, *sse4_2_pcmpestr_unaligned,
sse4_2_pcmpestri, sse4_2_pcmpestrm, sse4_2_pcmpestr_cconly,
sse4_2_pcmpistr, *sse4_2_pcmpistr_unaligned, sse4_2_pcmpistri,
sse4_2_pcmpistrm, sse4_2_pcmpistr_cconly): Add ssememalign attribute.
* config/i386/i386.md (ssememalign): New define_attr.

* g++.dg/torture/pr59163.C: New test.

Co-Authored-By: Uros Bizjak <ubizjak@gmail.com>
From-SVN: r205661

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/config/i386/i386.md
gcc/config/i386/sse.md
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/torture/pr59163.C [new file with mode: 0644]

index 92a8651c56294684b80c83ffabac94b8c93aec98..56b4f477f785df38c210c3941f427f348ede47b8 100644 (file)
@@ -1,3 +1,30 @@
+2013-12-04  Jakub Jelinek  <jakub@redhat.com>
+           Uros Bizjak  <ubizjak@gmail.com>
+
+       PR target/59163
+       * config/i386/i386.c (ix86_legitimate_combined_insn): If for
+       !TARGET_AVX there is misaligned MEM operand with vector mode
+       and get_attr_ssememalign is 0, return false.
+       (ix86_expand_special_args_builtin): Add get_pointer_alignment
+       computed alignment and for non-temporal loads/stores also
+       at least GET_MODE_ALIGNMENT as MEM_ALIGN.
+       * config/i386/sse.md
+       (<sse>_loadu<ssemodesuffix><avxsizesuffix><mask_name>,
+       <sse>_storeu<ssemodesuffix><avxsizesuffix>,
+       <sse2_avx_avx512f>_loaddqu<mode><mask_name>,
+       <sse2_avx_avx512f>_storedqu<mode>, <sse3>_lddqu<avxsizesuffix>,
+       sse_vmrcpv4sf2, sse_vmrsqrtv4sf2, sse2_cvtdq2pd, sse_movhlps,
+       sse_movlhps, sse_storehps, sse_loadhps, sse_loadlps,
+       *vec_interleave_highv2df, *vec_interleave_lowv2df,
+       *vec_extractv2df_1_sse, sse2_movsd, sse4_1_<code>v8qiv8hi2,
+       sse4_1_<code>v4qiv4si2, sse4_1_<code>v4hiv4si2,
+       sse4_1_<code>v2qiv2di2, sse4_1_<code>v2hiv2di2,
+       sse4_1_<code>v2siv2di2, sse4_2_pcmpestr, *sse4_2_pcmpestr_unaligned,
+       sse4_2_pcmpestri, sse4_2_pcmpestrm, sse4_2_pcmpestr_cconly,
+       sse4_2_pcmpistr, *sse4_2_pcmpistr_unaligned, sse4_2_pcmpistri,
+       sse4_2_pcmpistrm, sse4_2_pcmpistr_cconly): Add ssememalign attribute.
+       * config/i386/i386.md (ssememalign): New define_attr.
+
 2013-12-04  Jakub Jelinek  <jakub@redhat.com>
 
        PR tree-optimization/59355
index 21963bb28b7132f571a93d1df4a303d68379953b..f9b06d13b89b5424f89a5ca7b3b5e0ae7ffab06f 100644 (file)
@@ -5733,6 +5733,17 @@ ix86_legitimate_combined_insn (rtx insn)
          bool win;
          int j;
 
+         /* For pre-AVX disallow unaligned loads/stores where the
+            instructions don't support it.  */
+         if (!TARGET_AVX
+             && VECTOR_MODE_P (GET_MODE (op))
+             && misaligned_operand (op, GET_MODE (op)))
+           {
+             int min_align = get_attr_ssememalign (insn);
+             if (min_align == 0)
+               return false;
+           }
+
          /* A unary operator may be accepted by the predicate, but it
             is irrelevant for matching constraints.  */
          if (UNARY_P (op))
@@ -32481,11 +32492,12 @@ ix86_expand_args_builtin (const struct builtin_description *d,
 
 static rtx
 ix86_expand_special_args_builtin (const struct builtin_description *d,
-                                   tree exp, rtx target)
+                                 tree exp, rtx target)
 {
   tree arg;
   rtx pat, op;
   unsigned int i, nargs, arg_adjust, memory;
+  bool aligned_mem = false;
   struct
     {
       rtx op;
@@ -32531,6 +32543,15 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
       nargs = 1;
       klass = load;
       memory = 0;
+      switch (icode)
+       {
+       case CODE_FOR_sse4_1_movntdqa:
+       case CODE_FOR_avx2_movntdqa:
+         aligned_mem = true;
+         break;
+       default:
+         break;
+       }
       break;
     case VOID_FTYPE_PV2SF_V4SF:
     case VOID_FTYPE_PV4DI_V4DI:
@@ -32548,6 +32569,26 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
       klass = store;
       /* Reserve memory operand for target.  */
       memory = ARRAY_SIZE (args);
+      switch (icode)
+       {
+       /* These builtins and instructions require the memory
+          to be properly aligned.  */
+       case CODE_FOR_avx_movntv4di:
+       case CODE_FOR_sse2_movntv2di:
+       case CODE_FOR_avx_movntv8sf:
+       case CODE_FOR_sse_movntv4sf:
+       case CODE_FOR_sse4a_vmmovntv4sf:
+       case CODE_FOR_avx_movntv4df:
+       case CODE_FOR_sse2_movntv2df:
+       case CODE_FOR_sse4a_vmmovntv2df:
+       case CODE_FOR_sse2_movntidi:
+       case CODE_FOR_sse_movntq:
+       case CODE_FOR_sse2_movntisi:
+         aligned_mem = true;
+         break;
+       default:
+         break;
+       }
       break;
     case V4SF_FTYPE_V4SF_PCV2SF:
     case V2DF_FTYPE_V2DF_PCDOUBLE:
@@ -32604,6 +32645,17 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
        {
          op = ix86_zero_extend_to_Pmode (op);
          target = gen_rtx_MEM (tmode, op);
+         /* target at this point has just BITS_PER_UNIT MEM_ALIGN
+            on it.  Try to improve it using get_pointer_alignment,
+            and if the special builtin is one that requires strict
+            mode alignment, also from it's GET_MODE_ALIGNMENT.
+            Failure to do so could leak to ix86_legitimate_combined_insn
+            rejecting all changes to such insns.  */
+         unsigned int align = get_pointer_alignment (arg);
+         if (aligned_mem && align < GET_MODE_ALIGNMENT (tmode))
+           align = GET_MODE_ALIGNMENT (tmode);
+         if (MEM_ALIGN (target) < align)
+           set_mem_align (target, align);
        }
       else
        target = force_reg (tmode, op);
@@ -32649,8 +32701,17 @@ ix86_expand_special_args_builtin (const struct builtin_description *d,
              /* This must be the memory operand.  */
              op = ix86_zero_extend_to_Pmode (op);
              op = gen_rtx_MEM (mode, op);
-             gcc_assert (GET_MODE (op) == mode
-                         || GET_MODE (op) == VOIDmode);
+             /* op at this point has just BITS_PER_UNIT MEM_ALIGN
+                on it.  Try to improve it using get_pointer_alignment,
+                and if the special builtin is one that requires strict
+                mode alignment, also from it's GET_MODE_ALIGNMENT.
+                Failure to do so could leak to ix86_legitimate_combined_insn
+                rejecting all changes to such insns.  */
+             unsigned int align = get_pointer_alignment (arg);
+             if (aligned_mem && align < GET_MODE_ALIGNMENT (mode))
+               align = GET_MODE_ALIGNMENT (mode);
+             if (MEM_ALIGN (op) < align)
+               set_mem_align (op, align);
            }
          else
            {
index 6976124d4a89ef77bb7b7f158be43b17f9ebbbe2..0c732c7689f62993faf9fe2fa9c433ba5a9d5302 100644 (file)
           (const_string "unknown")]
         (const_string "integer")))
 
+;; The minimum required alignment of vector mode memory operands of the SSE
+;; (non-VEX/EVEX) instruction in bits, if it is different from
+;; GET_MODE_ALIGNMENT of the operand, otherwise 0.  If an instruction has
+;; multiple alternatives, this should be conservative maximum of those minimum
+;; required alignments.
+(define_attr "ssememalign" "" (const_int 0))
+
 ;; The (bounding maximum) length of an instruction immediate.
 (define_attr "length_immediate" ""
   (cond [(eq_attr "type" "incdec,setcc,icmov,str,lea,other,multi,idiv,leave,
index 7a47f27e94ee71abf3b2ceb9febde8c812fd23c2..f4efeaa31226835ab22e98e45e3358233fd2dfea 100644 (file)
 }
   [(set_attr "type" "ssemov")
    (set_attr "movu" "1")
+   (set_attr "ssememalign" "8")
    (set_attr "prefix" "maybe_vex")
    (set (attr "mode")
        (cond [(match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL")
 }
   [(set_attr "type" "ssemov")
    (set_attr "movu" "1")
+   (set_attr "ssememalign" "8")
    (set_attr "prefix" "maybe_vex")
    (set (attr "mode")
        (cond [(ior (match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL")
 }
   [(set_attr "type" "ssemov")
    (set_attr "movu" "1")
+   (set_attr "ssememalign" "8")
    (set (attr "prefix_data16")
      (if_then_else
        (match_test "TARGET_AVX")
 }
   [(set_attr "type" "ssemov")
    (set_attr "movu" "1")
+   (set_attr "ssememalign" "8")
    (set (attr "prefix_data16")
      (if_then_else
        (match_test "TARGET_AVX")
   "%vlddqu\t{%1, %0|%0, %1}"
   [(set_attr "type" "ssemov")
    (set_attr "movu" "1")
+   (set_attr "ssememalign" "8")
    (set (attr "prefix_data16")
      (if_then_else
        (match_test "TARGET_AVX")
    vrcpss\t{%1, %2, %0|%0, %2, %k1}"
   [(set_attr "isa" "noavx,avx")
    (set_attr "type" "sse")
+   (set_attr "ssememalign" "32")
    (set_attr "atom_sse_attr" "rcp")
    (set_attr "btver2_sse_attr" "rcp")
    (set_attr "prefix" "orig,vex")
    vrsqrtss\t{%1, %2, %0|%0, %2, %k1}"
   [(set_attr "isa" "noavx,avx")
    (set_attr "type" "sse")
+   (set_attr "ssememalign" "32")
    (set_attr "prefix" "orig,vex")
    (set_attr "mode" "SF")])
 
   "%vcvtdq2pd\t{%1, %0|%0, %q1}"
   [(set_attr "type" "ssecvt")
    (set_attr "prefix" "maybe_vex")
+   (set_attr "ssememalign" "64")
    (set_attr "mode" "V2DF")])
 
 (define_insn "<mask_codefor>avx512f_cvtpd2dq512<mask_name>"
    %vmovhps\t{%2, %0|%q0, %2}"
   [(set_attr "isa" "noavx,avx,noavx,avx,*")
    (set_attr "type" "ssemov")
+   (set_attr "ssememalign" "64")
    (set_attr "prefix" "orig,vex,orig,vex,maybe_vex")
    (set_attr "mode" "V4SF,V4SF,V2SF,V2SF,V2SF")])
 
    %vmovlps\t{%2, %H0|%H0, %2}"
   [(set_attr "isa" "noavx,avx,noavx,avx,*")
    (set_attr "type" "ssemov")
+   (set_attr "ssememalign" "64")
    (set_attr "prefix" "orig,vex,orig,vex,maybe_vex")
    (set_attr "mode" "V4SF,V4SF,V2SF,V2SF,V2SF")])
 
    %vmovhlps\t{%1, %d0|%d0, %1}
    %vmovlps\t{%H1, %d0|%d0, %H1}"
   [(set_attr "type" "ssemov")
+   (set_attr "ssememalign" "64")
    (set_attr "prefix" "maybe_vex")
    (set_attr "mode" "V2SF,V4SF,V2SF")])
 
    %vmovlps\t{%2, %H0|%H0, %2}"
   [(set_attr "isa" "noavx,avx,noavx,avx,*")
    (set_attr "type" "ssemov")
+   (set_attr "ssememalign" "64")
    (set_attr "prefix" "orig,vex,orig,vex,maybe_vex")
    (set_attr "mode" "V2SF,V2SF,V4SF,V4SF,V2SF")])
 
    %vmovlps\t{%2, %0|%q0, %2}"
   [(set_attr "isa" "noavx,avx,noavx,avx,*")
    (set_attr "type" "sseshuf,sseshuf,ssemov,ssemov,ssemov")
+   (set_attr "ssememalign" "64")
    (set_attr "length_immediate" "1,1,*,*,*")
    (set_attr "prefix" "orig,vex,orig,vex,maybe_vex")
    (set_attr "mode" "V4SF,V4SF,V2SF,V2SF,V2SF")])
    vmovlpd\t{%H1, %2, %0|%0, %2, %H1}
    %vmovhpd\t{%1, %0|%q0, %1}"
   [(set_attr "isa" "noavx,avx,sse3,noavx,avx,*")
-  (set_attr "type" "sselog,sselog,sselog,ssemov,ssemov,ssemov")
+   (set_attr "type" "sselog,sselog,sselog,ssemov,ssemov,ssemov")
+   (set_attr "ssememalign" "64")
    (set_attr "prefix_data16" "*,*,*,1,*,1")
    (set_attr "prefix" "orig,vex,maybe_vex,orig,vex,maybe_vex")
    (set_attr "mode" "V2DF,V2DF,DF,V1DF,V1DF,V1DF")])
    %vmovlpd\t{%2, %H0|%H0, %2}"
   [(set_attr "isa" "noavx,avx,sse3,noavx,avx,*")
    (set_attr "type" "sselog,sselog,sselog,ssemov,ssemov,ssemov")
+   (set_attr "ssememalign" "64")
    (set_attr "prefix_data16" "*,*,*,1,*,1")
    (set_attr "prefix" "orig,vex,maybe_vex,orig,vex,maybe_vex")
    (set_attr "mode" "V2DF,V2DF,DF,V1DF,V1DF,V1DF")])
    movhlps\t{%1, %0|%0, %1}
    movlps\t{%H1, %0|%0, %H1}"
   [(set_attr "type" "ssemov")
+   (set_attr "ssememalign" "64")
    (set_attr "mode" "V2SF,V4SF,V2SF")])
 
 ;; Avoid combining registers from different units in a single alternative,
    #"
   [(set_attr "isa" "noavx,avx,noavx,avx,*,*,*")
    (set_attr "type" "ssemov,ssemov,sselog,sselog,ssemov,fmov,imov")
+   (set_attr "ssememalign" "64")
    (set_attr "prefix_data16" "1,*,*,*,*,*,*")
    (set_attr "prefix" "orig,vex,orig,vex,*,*,*")
    (set_attr "mode" "V1DF,V1DF,V2DF,V2DF,DF,DF,DF")])
              (const_string "imov")
           ]
           (const_string "ssemov")))
+   (set_attr "ssememalign" "64")
    (set_attr "prefix_data16" "*,1,*,*,*,*,1,*,*,*,*")
    (set_attr "length_immediate" "*,*,*,*,*,1,*,*,*,*,*")
    (set_attr "prefix" "maybe_vex,orig,vex,orig,vex,orig,orig,vex,*,*,*")
        (const_string "1")
        (const_string "*")))
    (set_attr "length_immediate" "*,*,*,*,*,1,*,*,*")
+   (set_attr "ssememalign" "64")
    (set_attr "prefix" "orig,vex,orig,vex,maybe_vex,orig,orig,vex,maybe_vex")
    (set_attr "mode" "DF,DF,V1DF,V1DF,V1DF,V2DF,V1DF,V1DF,V1DF")])
 
   "TARGET_SSE4_1"
   "%vpmov<extsuffix>bw\t{%1, %0|%0, %q1}"
   [(set_attr "type" "ssemov")
+   (set_attr "ssememalign" "64")
    (set_attr "prefix_extra" "1")
    (set_attr "prefix" "maybe_vex")
    (set_attr "mode" "TI")])
   "TARGET_SSE4_1"
   "%vpmov<extsuffix>bd\t{%1, %0|%0, %k1}"
   [(set_attr "type" "ssemov")
+   (set_attr "ssememalign" "32")
    (set_attr "prefix_extra" "1")
    (set_attr "prefix" "maybe_vex")
    (set_attr "mode" "TI")])
   "TARGET_SSE4_1"
   "%vpmov<extsuffix>wd\t{%1, %0|%0, %q1}"
   [(set_attr "type" "ssemov")
+   (set_attr "ssememalign" "64")
    (set_attr "prefix_extra" "1")
    (set_attr "prefix" "maybe_vex")
    (set_attr "mode" "TI")])
   "TARGET_SSE4_1"
   "%vpmov<extsuffix>bq\t{%1, %0|%0, %w1}"
   [(set_attr "type" "ssemov")
+   (set_attr "ssememalign" "16")
    (set_attr "prefix_extra" "1")
    (set_attr "prefix" "maybe_vex")
    (set_attr "mode" "TI")])
   "TARGET_SSE4_1"
   "%vpmov<extsuffix>wq\t{%1, %0|%0, %k1}"
   [(set_attr "type" "ssemov")
+   (set_attr "ssememalign" "32")
    (set_attr "prefix_extra" "1")
    (set_attr "prefix" "maybe_vex")
    (set_attr "mode" "TI")])
   "TARGET_SSE4_1"
   "%vpmov<extsuffix>dq\t{%1, %0|%0, %q1}"
   [(set_attr "type" "ssemov")
+   (set_attr "ssememalign" "64")
    (set_attr "prefix_extra" "1")
    (set_attr "prefix" "maybe_vex")
    (set_attr "mode" "TI")])
   [(set_attr "type" "sselog")
    (set_attr "prefix_data16" "1")
    (set_attr "prefix_extra" "1")
+   (set_attr "ssememalign" "8")
    (set_attr "length_immediate" "1")
    (set_attr "memory" "none,load")
    (set_attr "mode" "TI")])
   [(set_attr "type" "sselog")
    (set_attr "prefix_data16" "1")
    (set_attr "prefix_extra" "1")
+   (set_attr "ssememalign" "8")
    (set_attr "length_immediate" "1")
    (set_attr "memory" "load")
    (set_attr "mode" "TI")])
    (set_attr "prefix_data16" "1")
    (set_attr "prefix_extra" "1")
    (set_attr "prefix" "maybe_vex")
+   (set_attr "ssememalign" "8")
    (set_attr "length_immediate" "1")
    (set_attr "btver2_decode" "vector")
    (set_attr "memory" "none,load")
   [(set_attr "type" "sselog")
    (set_attr "prefix_data16" "1")
    (set_attr "prefix_extra" "1")
+   (set_attr "ssememalign" "8")
    (set_attr "length_immediate" "1")
    (set_attr "prefix" "maybe_vex")
    (set_attr "btver2_decode" "vector")
   [(set_attr "type" "sselog")
    (set_attr "prefix_data16" "1")
    (set_attr "prefix_extra" "1")
+   (set_attr "ssememalign" "8")
    (set_attr "length_immediate" "1")
    (set_attr "memory" "none,load,none,load")
    (set_attr "btver2_decode" "vector,vector,vector,vector") 
   [(set_attr "type" "sselog")
    (set_attr "prefix_data16" "1")
    (set_attr "prefix_extra" "1")
+   (set_attr "ssememalign" "8")
    (set_attr "length_immediate" "1")
    (set_attr "memory" "none,load")
    (set_attr "mode" "TI")])
   [(set_attr "type" "sselog")
    (set_attr "prefix_data16" "1")
    (set_attr "prefix_extra" "1")
+   (set_attr "ssememalign" "8")
    (set_attr "length_immediate" "1")
    (set_attr "memory" "load")
    (set_attr "mode" "TI")])
   [(set_attr "type" "sselog")
    (set_attr "prefix_data16" "1")
    (set_attr "prefix_extra" "1")
+   (set_attr "ssememalign" "8")
    (set_attr "length_immediate" "1")
    (set_attr "prefix" "maybe_vex")
    (set_attr "memory" "none,load")
   [(set_attr "type" "sselog")
    (set_attr "prefix_data16" "1")
    (set_attr "prefix_extra" "1")
+   (set_attr "ssememalign" "8")
    (set_attr "length_immediate" "1")
    (set_attr "prefix" "maybe_vex")
    (set_attr "memory" "none,load")
   [(set_attr "type" "sselog")
    (set_attr "prefix_data16" "1")
    (set_attr "prefix_extra" "1")
+   (set_attr "ssememalign" "8")
    (set_attr "length_immediate" "1")
    (set_attr "memory" "none,load,none,load")
    (set_attr "prefix" "maybe_vex")
index e35854179d2f7580d720bb4243e2ea90e196a49c..32b4ff41e3e27ab5f42fe991ebe61e8c3e106543 100644 (file)
@@ -1,5 +1,8 @@
 2013-12-04  Jakub Jelinek  <jakub@redhat.com>
 
+       PR target/59163
+       * g++.dg/torture/pr59163.C: New test.
+
        PR tree-optimization/59355
        * g++.dg/ipa/pr59355.C: New test.
 
diff --git a/gcc/testsuite/g++.dg/torture/pr59163.C b/gcc/testsuite/g++.dg/torture/pr59163.C
new file mode 100644 (file)
index 0000000..2f9a999
--- /dev/null
@@ -0,0 +1,30 @@
+// PR target/59163
+// { dg-do run }
+
+struct A { float a[4]; };
+struct B { int b; A a; };
+
+__attribute__((noinline, noclone)) void
+bar (A &a)
+{
+  if (a.a[0] != 36.0f || a.a[1] != 42.0f || a.a[2] != 48.0f || a.a[3] != 54.0f)
+    __builtin_abort ();
+}
+
+__attribute__((noinline, noclone)) void
+foo (A &a)
+{
+  int i;
+  A c = a;
+  for (i = 0; i < 4; i++)
+    c.a[i] *= 6.0f;
+  a = c;
+  bar (a);
+}
+
+int
+main ()
+{
+  B b = { 5, { 6, 7, 8, 9 } };
+  foo (b.a);
+}