re PR target/80206 (ICE in extract_insn, at recog.c:2327)
authorJakub Jelinek <jakub@redhat.com>
Thu, 30 Mar 2017 13:29:28 +0000 (15:29 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Thu, 30 Mar 2017 13:29:28 +0000 (15:29 +0200)
PR target/80206
* config/i386/sse.md
(<extract_type>_vextract<shuffletype><extract_suf>_mask): Use
register as dest whenever it is a MEM not rtx_equal_p to the
corresponding dup operand, and when forcing into reg move the
reg into the memory afterwards.
(<extract_type_2>_vextract<shuffletype><extract_suf_2>_mask):
Likewise.  Use <ssehalfvecmode> instead of <ssequartermode>
for the force_reg mode.
(avx512vl_vextractf128<mode>): Use register as dest either
always when a MEM, or when it is a MEM not rtx_equal_p to the
corresponding dup operand, or even not when it is a CONST_VECTOR
depending on the mode and lo vs. hi.
(avx512dq_vextract<shuffletype>64x2_1_maskm): Remove extraneous
parens.
(avx512f_vextract<shuffletype>32x4_1_maskm): Likewise.
(<mask_codefor>avx512dq_vextract<shuffletype>64x2_1<mask_name>):
Likewise.  Require that operands[2] is even.
(<mask_codefor>avx512f_vextract<shuffletype>32x4_1<mask_name>):
Remove extraneous parens.  Require that operands[2] is a multiple
of 4.
(vec_extract_lo_<mode><mask_name>): Don't bother testing if
operands[0] is a MEM if <mask_applied>, the predicates/constraints
disallow memory then.

* gcc.target/i386/pr80206.c: New test.

From-SVN: r246588

gcc/ChangeLog
gcc/config/i386/sse.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr80206.c [new file with mode: 0644]

index 3333bfd146852e0cece9066459f02cdb35deccb7..99256af1cff2f597cf3cf41d04a96ed812f3fadd 100644 (file)
@@ -1,3 +1,30 @@
+2017-03-30  Jakub Jelinek  <jakub@redhat.com>
+
+       PR target/80206
+       * config/i386/sse.md
+       (<extract_type>_vextract<shuffletype><extract_suf>_mask): Use
+       register as dest whenever it is a MEM not rtx_equal_p to the
+       corresponding dup operand, and when forcing into reg move the
+       reg into the memory afterwards.
+       (<extract_type_2>_vextract<shuffletype><extract_suf_2>_mask):
+       Likewise.  Use <ssehalfvecmode> instead of <ssequartermode>
+       for the force_reg mode.
+       (avx512vl_vextractf128<mode>): Use register as dest either
+       always when a MEM, or when it is a MEM not rtx_equal_p to the
+       corresponding dup operand, or even not when it is a CONST_VECTOR
+       depending on the mode and lo vs. hi.
+       (avx512dq_vextract<shuffletype>64x2_1_maskm): Remove extraneous
+       parens.
+       (avx512f_vextract<shuffletype>32x4_1_maskm): Likewise.
+       (<mask_codefor>avx512dq_vextract<shuffletype>64x2_1<mask_name>):
+       Likewise.  Require that operands[2] is even.
+       (<mask_codefor>avx512f_vextract<shuffletype>32x4_1<mask_name>):
+       Remove extraneous parens.  Require that operands[2] is a multiple
+       of 4.
+       (vec_extract_lo_<mode><mask_name>): Don't bother testing if
+       operands[0] is a MEM if <mask_applied>, the predicates/constraints
+       disallow memory then.
+
 2017-03-30  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/77498
index 5cca4f1d4fd942cbcdabcbe5faa1182d3371ca0e..0ea06c5aa533894a3589089d4d4b52f739837935 100644 (file)
 {
   int mask;
   mask = INTVAL (operands[2]);
+  rtx dest = operands[0];
 
-  if (MEM_P (operands[0]) && GET_CODE (operands[3]) == CONST_VECTOR)
-    operands[0] = force_reg (<ssequartermode>mode, operands[0]);
+  if (MEM_P (operands[0]) && !rtx_equal_p (operands[0], operands[3]))
+    dest = gen_reg_rtx (<ssequartermode>mode);
 
   if (<MODE>mode == V16SImode || <MODE>mode == V16SFmode)
-    emit_insn (gen_avx512f_vextract<shuffletype>32x4_1_mask (operands[0],
+    emit_insn (gen_avx512f_vextract<shuffletype>32x4_1_mask (dest,
         operands[1], GEN_INT (mask * 4), GEN_INT (mask * 4 + 1),
        GEN_INT (mask * 4 + 2), GEN_INT (mask * 4 + 3), operands[3],
        operands[4]));
   else
-    emit_insn (gen_avx512dq_vextract<shuffletype>64x2_1_mask (operands[0],
+    emit_insn (gen_avx512dq_vextract<shuffletype>64x2_1_mask (dest,
         operands[1], GEN_INT (mask * 2), GEN_INT (mask * 2 + 1), operands[3],
        operands[4]));
+  if (dest != operands[0])
+    emit_move_insn (operands[0], dest);
   DONE;
 })
 
          (match_operand:<ssequartermode> 4 "memory_operand" "0")
          (match_operand:QI 5 "register_operand" "Yk")))]
   "TARGET_AVX512DQ
-   && (INTVAL (operands[2]) % 2 == 0)
-   && (INTVAL (operands[2]) == INTVAL (operands[3]) - 1)
+   && INTVAL (operands[2]) % 2 == 0
+   && INTVAL (operands[2]) == INTVAL (operands[3]) - 1
    && rtx_equal_p (operands[4], operands[0])"
 {
   operands[2] = GEN_INT ((INTVAL (operands[2])) >> 1);
          (match_operand:<ssequartermode> 6 "memory_operand" "0")
          (match_operand:QI 7 "register_operand" "Yk")))]
   "TARGET_AVX512F
-   && ((INTVAL (operands[2]) % 4 == 0)
-       && INTVAL (operands[2]) == (INTVAL (operands[3]) - 1)
-       && INTVAL (operands[3]) == (INTVAL (operands[4]) - 1)
-       && INTVAL (operands[4]) == (INTVAL (operands[5]) - 1))
+   && INTVAL (operands[2]) % 4 == 0
+   && INTVAL (operands[2]) == INTVAL (operands[3]) - 1
+   && INTVAL (operands[3]) == INTVAL (operands[4]) - 1
+   && INTVAL (operands[4]) == INTVAL (operands[5]) - 1
    && rtx_equal_p (operands[6], operands[0])"
 {
-  operands[2] = GEN_INT ((INTVAL (operands[2])) >> 2);
+  operands[2] = GEN_INT (INTVAL (operands[2]) >> 2);
   return "vextract<shuffletype>32x4\t{%2, %1, %0%{%7%}|%0%{%7%}, %1, %2}";
 }
   [(set_attr "type" "sselog")
          (match_operand:V8FI 1 "register_operand" "v")
          (parallel [(match_operand 2  "const_0_to_7_operand")
             (match_operand 3  "const_0_to_7_operand")])))]
-  "TARGET_AVX512DQ && (INTVAL (operands[2]) == INTVAL (operands[3]) - 1)"
+  "TARGET_AVX512DQ
+   && INTVAL (operands[2]) % 2 == 0
+   && INTVAL (operands[2]) == INTVAL (operands[3]) - 1"
 {
-  operands[2] = GEN_INT ((INTVAL (operands[2])) >> 1);
+  operands[2] = GEN_INT (INTVAL (operands[2]) >> 1);
   return "vextract<shuffletype>64x2\t{%2, %1, %0<mask_operand4>|%0<mask_operand4>, %1, %2}";
 }
   [(set_attr "type" "sselog1")
             (match_operand 4  "const_0_to_15_operand")
             (match_operand 5  "const_0_to_15_operand")])))]
   "TARGET_AVX512F
-   && (INTVAL (operands[2]) == (INTVAL (operands[3]) - 1)
-       && INTVAL (operands[3]) == (INTVAL (operands[4]) - 1)
-       && INTVAL (operands[4]) == (INTVAL (operands[5]) - 1))"
+   && INTVAL (operands[2]) % 4 == 0
+   && INTVAL (operands[2]) == INTVAL (operands[3]) - 1
+   && INTVAL (operands[3]) == INTVAL (operands[4]) - 1
+   && INTVAL (operands[4]) == INTVAL (operands[5]) - 1"
 {
-  operands[2] = GEN_INT ((INTVAL (operands[2])) >> 2);
+  operands[2] = GEN_INT (INTVAL (operands[2]) >> 2);
   return "vextract<shuffletype>32x4\t{%2, %1, %0<mask_operand6>|%0<mask_operand6>, %1, %2}";
 }
   [(set_attr "type" "sselog1")
   "TARGET_AVX512F"
 {
   rtx (*insn)(rtx, rtx, rtx, rtx);
+  rtx dest = operands[0];
 
-  if (MEM_P (operands[0]) && GET_CODE (operands[3]) == CONST_VECTOR)
-    operands[0] = force_reg (<ssequartermode>mode, operands[0]);
+  if (MEM_P (dest) && !rtx_equal_p (dest, operands[3]))
+    dest = gen_reg_rtx (<ssehalfvecmode>mode);
 
   switch (INTVAL (operands[2]))
     {
       gcc_unreachable ();
     }
 
-  emit_insn (insn (operands[0], operands[1], operands[3], operands[4]));
+  emit_insn (insn (dest, operands[1], operands[3], operands[4]));
+  if (dest != operands[0])
+    emit_move_insn (operands[0], dest);
   DONE;
 })
 
          (match_operand:V8FI 1 "nonimmediate_operand" "v,m")
          (parallel [(const_int 0) (const_int 1)
             (const_int 2) (const_int 3)])))]
-  "TARGET_AVX512F && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+  "TARGET_AVX512F
+   && (<mask_applied> || !(MEM_P (operands[0]) && MEM_P (operands[1])))"
 {
   if (<mask_applied> || !TARGET_AVX512VL)
     return "vextract<shuffletype>64x4\t{$0x0, %1, %0<mask_operand2>|%0<mask_operand2>, %1, 0x0}";
   "TARGET_AVX512DQ && TARGET_AVX512VL"
 {
   rtx (*insn)(rtx, rtx, rtx, rtx);
-
-  if (MEM_P (operands[0]) && GET_CODE (operands[3]) == CONST_VECTOR)
-    operands[0] = force_reg (<ssehalfvecmode>mode, operands[0]);
-
+  rtx dest = operands[0];
+
+  if (MEM_P (dest)
+      && (GET_MODE_SIZE (GET_MODE_INNER (<MODE>mode)) == 4
+         /* For V8S[IF]mode there are maskm insns with =m and 0
+            constraints.  */
+         ? !rtx_equal_p (dest, operands[3])
+         /* For V4D[IF]mode, hi insns don't allow memory, and
+            lo insns have =m and 0C constraints.  */
+         : (operands[2] != const0_rtx
+            || (!rtx_equal_p (dest, operands[3])
+                && GET_CODE (operands[3]) != CONST_VECTOR))))
+    dest = gen_reg_rtx (<ssehalfvecmode>mode);
   switch (INTVAL (operands[2]))
     {
     case 0:
       gcc_unreachable ();
     }
 
-  emit_insn (insn (operands[0], operands[1], operands[3], operands[4]));
+  emit_insn (insn (dest, operands[1], operands[3], operands[4]));
+  if (dest != operands[0])
+    emit_move_insn (operands[0], dest);
   DONE;
 })
 
index 5d33ce78b67a1384d1cf97e218d7ee7f4110bcd0..c1b6566033a00eb0531f068c30b0074d1d07ca0c 100644 (file)
@@ -1,3 +1,8 @@
+2017-03-30  Jakub Jelinek  <jakub@redhat.com>
+
+       PR target/80206
+       * gcc.target/i386/pr80206.c: New test.
+
 2017-03-30  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/77498
diff --git a/gcc/testsuite/gcc.target/i386/pr80206.c b/gcc/testsuite/gcc.target/i386/pr80206.c
new file mode 100644 (file)
index 0000000..dafa9a6
--- /dev/null
@@ -0,0 +1,14 @@
+/* PR target/80206 */
+/* { dg-do compile } */
+/* { dg-options "-mavx512f -ffloat-store" } */
+
+#include <immintrin.h>
+
+__m512d a;
+__m256d b;
+
+void
+foo (__m256d *p)
+{
+  *p = _mm512_mask_extractf64x4_pd (b, 1, a, 1);
+}