diff mbox series

The upper bits of FIXUPIMMS{S, D} should come from src1 not dest.

Message ID 20210629045543.24220-1-hongtao.liu@intel.com
State New
Headers show
Series The upper bits of FIXUPIMMS{S, D} should come from src1 not dest. | expand

Commit Message

Liu, Hongtao June 29, 2021, 4:55 a.m. UTC
Hi:
  Currently patterns of vfixupimm{s,d} keep the upper bits of dest unchanged which
is wrong, the upper bits of the dest should comes from src1(operands[2] in the pattern).

  Bootstrapped and regtested on x86_64-linux-gnu{-m32,}.

gcc/ChangeLog:

	PR target/101248
	* config/i386/sse.md
	(avx512f_sfixupimm<mode><sd_maskz_name><round_saeonly_name>):
	Refined.
	(avx512f_sfixupimm<mode><maskz_scalar_name><round_saeonly_name>):
	Ditto.
	* config/i386/subst.md (maskz_scalar): New define_subst.
	(maskz_scalar_name): New subst_attr.
	(maskz_scalar_op5): Ditto.
	(round_saeonly_maskz_scalar_op5): Ditto.
	(round_saeonly_maskz_scalar_operand5): Ditto.

gcc/testsuite/ChangeLog

	PR target/101248
	* gcc.target/i386/pr101248.c: New test.
---
 gcc/config/i386/sse.md                   |   8 +-
 gcc/config/i386/subst.md                 |  21 ++++
 gcc/testsuite/gcc.target/i386/pr101248.c | 123 +++++++++++++++++++++++
 3 files changed, 148 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr101248.c
diff mbox series

Patch

diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index ffcc0c81964..d3f5a74f763 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -9942,7 +9942,7 @@ 
   DONE;
 })
 
-(define_insn "avx512f_sfixupimm<mode><sd_maskz_name><round_saeonly_name>"
+(define_insn "avx512f_sfixupimm<mode><maskz_scalar_name><round_saeonly_name>"
   [(set (match_operand:VF_128 0 "register_operand" "=v")
 	(vec_merge:VF_128
           (unspec:VF_128
@@ -9951,10 +9951,10 @@ 
 	     (match_operand:<sseintvecmode> 3 "<round_saeonly_nimm_scalar_predicate>" "<round_saeonly_constraint>")
 	     (match_operand:SI 4 "const_0_to_255_operand")]
 	    UNSPEC_FIXUPIMM)
-	  (match_dup 1)
+	  (match_dup 2)
 	  (const_int 1)))]
    "TARGET_AVX512F"
-   "vfixupimm<ssescalarmodesuffix>\t{%4, <round_saeonly_sd_mask_op5>%3, %2, %0<sd_mask_op5>|%0<sd_mask_op5>, %2, %<iptr>3<round_saeonly_sd_mask_op5>, %4}";
+   "vfixupimm<ssescalarmodesuffix>\t{%4, <round_saeonly_maskz_scalar_op5>%3, %2, %0<maskz_scalar_op5>|%0<maskz_scalar_op5>, %2, %<iptr>3<round_saeonly_maskz_scalar_op5>, %4}";
    [(set_attr "prefix" "evex")
    (set_attr "mode" "<ssescalarmode>")])
 
@@ -9968,7 +9968,7 @@ 
 		(match_operand:<sseintvecmode> 3 "<round_saeonly_nimm_scalar_predicate>" "<round_saeonly_constraint>")
 		(match_operand:SI 4 "const_0_to_255_operand")]
 	       UNSPEC_FIXUPIMM)
-	    (match_dup 1)
+	    (match_dup 2)
 	    (const_int 1))
 	  (match_dup 1)
 	  (match_operand:<avx512fmaskmode> 5 "register_operand" "Yk")))]
diff --git a/gcc/config/i386/subst.md b/gcc/config/i386/subst.md
index 477a89803fa..6614e044857 100644
--- a/gcc/config/i386/subst.md
+++ b/gcc/config/i386/subst.md
@@ -117,6 +117,25 @@ 
 	 (match_operand:<avx512fmaskmode> 3 "register_operand" "Yk")))
 ])
 
+(define_subst_attr "maskz_scalar_name" "maskz_scalar" "" "_maskz_1")
+(define_subst_attr "maskz_scalar_op5" "maskz_scalar" "" "%{%6%}%N5")
+
+(define_subst "maskz_scalar"
+  [(set (match_operand:SUBST_V 0)
+	(vec_merge:SUBST_V
+	  (match_operand:SUBST_V 1)
+	  (match_operand:SUBST_V 2)
+	  (const_int 1)))]
+  "TARGET_AVX512F"
+  [(set (match_dup 0)
+	(vec_merge:SUBST_V
+	  (vec_merge:SUBST_V
+	    (match_dup 1)
+	    (match_operand:SUBST_V 3 "const0_operand" "C")
+	    (match_operand:<avx512fmaskmode> 4 "register_operand" "Yk"))
+	  (match_dup 2)
+	  (const_int 1)))])
+
 (define_subst_attr "round_name" "round" "" "_round")
 (define_subst_attr "round_mask_operand2" "mask" "%R2" "%R4")
 (define_subst_attr "round_mask_operand3" "mask" "%R3" "%R5")
@@ -163,6 +182,7 @@ 
 (define_subst_attr "round_saeonly_mask_operand3" "mask" "%r3" "%r5")
 (define_subst_attr "round_saeonly_mask_operand4" "mask" "%r4" "%r6")
 (define_subst_attr "round_saeonly_mask_scalar_merge_operand4" "mask_scalar_merge" "%r4" "%r5")
+(define_subst_attr "round_saeonly_maskz_scalar_operand5" "maskz_scalar" "%r5" "%r7")
 (define_subst_attr "round_saeonly_sd_mask_operand5" "sd" "%r5" "%r7")
 (define_subst_attr "round_saeonly_op2" "round_saeonly" "" "%r2")
 (define_subst_attr "round_saeonly_op3" "round_saeonly" "" "%r3")
@@ -175,6 +195,7 @@ 
 (define_subst_attr "round_saeonly_mask_op4" "round_saeonly" "" "<round_saeonly_mask_operand4>")
 (define_subst_attr "round_saeonly_mask_scalar_merge_op4" "round_saeonly" "" "<round_saeonly_mask_scalar_merge_operand4>")
 (define_subst_attr "round_saeonly_sd_mask_op5" "round_saeonly" "" "<round_saeonly_sd_mask_operand5>")
+(define_subst_attr "round_saeonly_maskz_scalar_op5" "round_saeonly" "" "<round_saeonly_maskz_scalar_operand5>")
 (define_subst_attr "round_saeonly_mask_arg3" "round_saeonly" "" ", operands[<mask_expand_op3>]")
 (define_subst_attr "round_saeonly_constraint" "round_saeonly" "vm" "v")
 (define_subst_attr "round_saeonly_constraint2" "round_saeonly" "m" "v")
diff --git a/gcc/testsuite/gcc.target/i386/pr101248.c b/gcc/testsuite/gcc.target/i386/pr101248.c
new file mode 100644
index 00000000000..f5ac94f5769
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr101248.c
@@ -0,0 +1,123 @@ 
+/* PR target/101248  */
+/* { dg-do run } */
+/* { dg-options "-O2 -mavx512vl -std=gnu99" } */
+/* { dg-require-effective-target avx512vl } */
+/* { dg-require-effective-target c99_runtime } */
+
+#define AVX512VL
+#define AVX512F_LEN 128
+#define AVX512F_LEN_HALF 128
+
+#include "avx512f-helper.h"
+
+#define SIZE (AVX512F_LEN / 64)
+#include "avx512f-mask-type.h"
+#include "math_m_pi.h"
+#include "float.h"
+
+
+static void
+CALC (double *r, double dest, double src, long long tbl)
+{
+  switch (tbl & 0xf)
+    {
+    case 0:
+      *r = dest;
+      break;
+    case 1:
+      *r = src;
+      break;
+    case 2:
+      *r = signbit (src) ? -NAN : NAN;
+      break;
+    case 3:
+      *r = -NAN;
+      break;
+    case 4:
+      *r = -INFINITY;
+      break;
+    case 5:
+      *r = INFINITY;
+      break;
+    case 6:
+      *r = signbit (src) ? -INFINITY : INFINITY;
+      break;
+    case 7:
+      *r = 1.0 / -INFINITY;
+      break;
+    case 8:
+      *r = 0.0;
+      break;
+    case 9:
+      *r = -1.0;
+      break;
+    case 10:
+      *r = 1.0;
+      break;
+    case 11:
+      *r = 1.0 / 2.0;
+      break;
+    case 12:
+      *r = 90.0;
+      break;
+    case 13:
+      *r = M_PI_2;
+      break;
+    case 14:
+      *r = DBL_MAX;
+      break;
+    case 15:
+      *r = -DBL_MAX;
+      break;
+    default:
+      abort ();
+    }
+}
+
+void
+TEST (void)
+{
+  int i, j;
+  UNION_TYPE (AVX512F_LEN, d) res1, res2, res3, s1;
+  UNION_TYPE (AVX512F_LEN, i_q) s2;
+  double res_ref[SIZE];
+
+
+  float vals[2] = { -10, 10 };
+  int controls[8] = {0, 0x11111111, 0x77777777, 0x88888888,
+    0x99999999, 0xaaaaaaaa, 0xbbbbbbbb, 0xcccccccc};
+
+  MASK_TYPE mask = 1;
+
+  for (i = 0; i < 2; i++)
+    {
+      for (j = 0; j < SIZE; j++)
+	{
+	  s1.a[j] = vals[i];
+	  s2.a[j] = controls[j];
+	  res1.a[j] = DEFAULT_VALUE;
+	  res2.a[j] = DEFAULT_VALUE;
+	  res3.a[j] = DEFAULT_VALUE;
+
+	  CALC (&res_ref[j], res1.a[j], s1.a[j], s2.a[j]);
+	}
+
+      res1.x = INTRINSIC (_fixupimm_pd) (res1.x, s1.x, s2.x, 0);
+      res2.x = INTRINSIC (_mask_fixupimm_pd) (res2.x, mask, s1.x, s2.x, 0);
+      res3.x = INTRINSIC (_maskz_fixupimm_pd) (mask, res3.x, s1.x, s2.x, 0);
+
+      if (UNION_CHECK (AVX512F_LEN, d) (res1, res_ref))
+	abort ();
+
+      MASK_MERGE(d) (res_ref, mask, SIZE);
+      if (UNION_CHECK (AVX512F_LEN, d) (res2, res_ref))
+	abort ();
+      MASK_ZERO(d) (res_ref, mask, SIZE);
+      if (UNION_CHECK (AVX512F_LEN, d) (res3, res_ref))
+	abort ();
+    }
+}
+
+void
+test_256 (void)
+{}