On Thu, Apr 21, 2016 at 10:58 PM, H.J. Lu <hjl.to...@gmail.com> wrote:

> Here is the updated patch with my standard_sse_constant_p change and
> your SSE/AVX pattern change.  I didn't include your
> standard_sse_constant_opcode since it didn't compile nor is needed
> for this purpose.

H.J.,

please test the attached patch that finally rewrites and improves SSE
constants handling.

This is what I want to commit, a follow-up patch will further clean
standard_sse_constant_opcode wrt TARGET_AVX512VL.

Bootstrapped and regtested with i386.exp, full regtest in progress.

Uros.
diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
index afdc546..c02c321 100644
--- a/gcc/config/i386/constraints.md
+++ b/gcc/config/i386/constraints.md
@@ -186,7 +186,9 @@
 
 (define_constraint "BC"
   "@internal SSE constant operand."
-  (match_test "standard_sse_constant_p (op)"))
+  (and (match_test "TARGET_SSE")
+       (ior (match_operand 0 "const0_operand")
+           (match_operand 0 "all_ones_operand"))))
 
 ;; Integer constant constraints.
 (define_constraint "I"
@@ -239,7 +241,8 @@
 ;; This can theoretically be any mode's CONST0_RTX.
 (define_constraint "C"
   "SSE constant zero operand."
-  (match_test "standard_sse_constant_p (op) == 1"))
+  (and (match_test "TARGET_SSE")
+       (match_operand 0 "const0_operand")))
 
 ;; Constant-or-symbol-reference constraints.
 
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index ff47bc1..93b5e1e 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -50,7 +50,7 @@ extern bool ix86_using_red_zone (void);
 extern int standard_80387_constant_p (rtx);
 extern const char *standard_80387_constant_opcode (rtx);
 extern rtx standard_80387_constant_rtx (int);
-extern int standard_sse_constant_p (rtx);
+extern int standard_sse_constant_p (rtx, machine_mode);
 extern const char *standard_sse_constant_opcode (rtx_insn *, rtx);
 extern bool symbolic_reference_mentioned_p (rtx);
 extern bool extended_reg_mentioned_p (rtx);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 6379313..874f837 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -10762,42 +10762,44 @@ standard_80387_constant_rtx (int idx)
                                       XFmode);
 }
 
-/* Return 1 if X is all 0s and 2 if x is all 1s
+/* Return 1 if X is all bits 0 and 2 if X is all bits 1
    in supported SSE/AVX vector mode.  */
 
 int
-standard_sse_constant_p (rtx x)
+standard_sse_constant_p (rtx x, machine_mode pred_mode)
 {
   machine_mode mode;
 
   if (!TARGET_SSE)
     return 0;
 
-  mode = GET_MODE (x);
-  
-  if (x == const0_rtx || x == CONST0_RTX (mode))
+  if (const0_operand (x, VOIDmode))
     return 1;
-  if (vector_all_ones_operand (x, mode))
-    switch (mode)
+
+  mode = GET_MODE (x);
+
+  /* VOIDmode integer constant, infer mode from the predicate.  */
+  if (mode == VOIDmode)
+    mode = pred_mode;
+
+  else if (all_ones_operand (x, VOIDmode))
+    switch (GET_MODE_SIZE (mode))
       {
-      case V16QImode:
-      case V8HImode:
-      case V4SImode:
-      case V2DImode:
-       if (TARGET_SSE2)
+      case 64:
+       if (TARGET_AVX512F)
          return 2;
-      case V32QImode:
-      case V16HImode:
-      case V8SImode:
-      case V4DImode:
+       break;
+      case 32:
        if (TARGET_AVX2)
          return 2;
-      case V64QImode:
-      case V32HImode:
-      case V16SImode:
-      case V8DImode:
-       if (TARGET_AVX512F)
+       break;
+      case 16:
+       if (TARGET_SSE2)
          return 2;
+       break;
+      case 0:
+       /* VOIDmode */
+       gcc_unreachable ();
       default:
        break;
       }
@@ -10811,53 +10813,81 @@ standard_sse_constant_p (rtx x)
 const char *
 standard_sse_constant_opcode (rtx_insn *insn, rtx x)
 {
-  switch (standard_sse_constant_p (x))
+  gcc_assert (TARGET_SSE);
+
+  if (const0_operand (x, VOIDmode))
     {
-    case 1:
       switch (get_attr_mode (insn))
        {
        case MODE_XI:
          return "vpxord\t%g0, %g0, %g0";
-       case MODE_V16SF:
-         return TARGET_AVX512DQ ? "vxorps\t%g0, %g0, %g0"
-                                : "vpxord\t%g0, %g0, %g0";
-       case MODE_V8DF:
-         return TARGET_AVX512DQ ? "vxorpd\t%g0, %g0, %g0"
-                                : "vpxorq\t%g0, %g0, %g0";
+       case MODE_OI:
+         return (TARGET_AVX512VL
+                 ? "vpxord\t%x0, %x0, %x0"
+                 : "vpxor\t%x0, %x0, %x0");
        case MODE_TI:
-         return TARGET_AVX512VL ? "vpxord\t%t0, %t0, %t0"
-                                : "%vpxor\t%0, %d0";
+         return (TARGET_AVX512VL
+                 ? "vpxord\t%t0, %t0, %t0"
+                 : "%vpxor\t%0, %d0");
+
+       case MODE_V8DF:
+         return (TARGET_AVX512DQ
+                 ? "vxorpd\t%g0, %g0, %g0"
+                 : "vpxorq\t%g0, %g0, %g0");
+       case MODE_V4DF:
+         return "vxorpd\t%x0, %x0, %x0";
        case MODE_V2DF:
          return "%vxorpd\t%0, %d0";
+
+       case MODE_V16SF:
+         return (TARGET_AVX512DQ
+                 ? "vxorps\t%g0, %g0, %g0"
+                 : "vpxord\t%g0, %g0, %g0");
+       case MODE_V8SF:
+         return "vxorps\t%x0, %x0, %x0";
        case MODE_V4SF:
          return "%vxorps\t%0, %d0";
 
+       default:
+         gcc_unreachable ();
+       }
+    }
+  else if (all_ones_operand (x, VOIDmode))
+    {
+      enum attr_mode insn_mode = get_attr_mode (insn);
+      
+      switch (insn_mode)
+       {
+       case MODE_XI:
+       case MODE_V8DF:
+       case MODE_V16SF:
+         gcc_assert (TARGET_AVX512F);
+         break;
        case MODE_OI:
-         return TARGET_AVX512VL ? "vpxord\t%x0, %x0, %x0"
-                                : "vpxor\t%x0, %x0, %x0";
        case MODE_V4DF:
-         return "vxorpd\t%x0, %x0, %x0";
        case MODE_V8SF:
-         return "vxorps\t%x0, %x0, %x0";
-
-       default:
+         gcc_assert (TARGET_AVX2);
+         break;
+       case MODE_TI:
+       case MODE_V2DF:
+       case MODE_V4SF:
+         gcc_assert (TARGET_SSE2);
          break;
+       default:
+         gcc_unreachable ();
        }
 
-    case 2:
       if (TARGET_AVX512VL
-         || get_attr_mode (insn) == MODE_XI
-         || get_attr_mode (insn) == MODE_V8DF
-         || get_attr_mode (insn) == MODE_V16SF)
+         || insn_mode == MODE_XI
+         || insn_mode == MODE_V8DF
+         || insn_mode == MODE_V16SF)
        return "vpternlogd\t{$0xFF, %g0, %g0, %g0|%g0, %g0, %g0, 0xFF}";
-      if (TARGET_AVX)
+      else if (TARGET_AVX)
        return "vpcmpeqd\t%0, %0, %0";
       else
        return "pcmpeqd\t%0, %0";
+   }
 
-    default:
-      break;
-    }
   gcc_unreachable ();
 }
 
@@ -14360,7 +14390,7 @@ darwin_local_data_pic (rtx disp)
    satisfies CONSTANT_P.  */
 
 static bool
-ix86_legitimate_constant_p (machine_mode, rtx x)
+ix86_legitimate_constant_p (machine_mode mode, rtx x)
 {
   /* Pointer bounds constants are not valid.  */
   if (POINTER_BOUNDS_MODE_P (GET_MODE (x)))
@@ -14427,12 +14457,12 @@ ix86_legitimate_constant_p (machine_mode, rtx x)
       break;
 
     case CONST_WIDE_INT:
-      if (!TARGET_64BIT && !standard_sse_constant_p (x))
+      if (!TARGET_64BIT && !standard_sse_constant_p (x, mode))
        return false;
       break;
 
     case CONST_VECTOR:
-      if (!standard_sse_constant_p (x))
+      if (!standard_sse_constant_p (x, mode))
        return false;
 
     default:
@@ -18758,7 +18788,7 @@ ix86_expand_vector_move (machine_mode mode, rtx 
operands[])
       && (CONSTANT_P (op1)
          || (SUBREG_P (op1)
              && CONSTANT_P (SUBREG_REG (op1))))
-      && !standard_sse_constant_p (op1))
+      && !standard_sse_constant_p (op1, mode))
     op1 = validize_mem (force_const_mem (mode, op1));
 
   /* We need to check memory alignment for SSE mode since attribute
@@ -22619,7 +22649,7 @@ ix86_expand_sse_movcc (rtx dest, rtx cmp, rtx op_true, 
rtx op_false)
       cmp = gen_rtx_SUBREG (mode, cmp, 0);
     }
 
-  if (vector_all_ones_operand (op_true, mode)
+  if (all_ones_operand (op_true, mode)
       && rtx_equal_p (op_false, CONST0_RTX (mode))
       && !maskcmp)
     {
@@ -23243,7 +23273,7 @@ ix86_expand_int_vcond (rtx operands[])
          return true;
        }
       else if (GET_MODE_INNER (data_mode) != DImode
-              && vector_all_ones_operand (negop, data_mode))
+              && all_ones_operand (negop, data_mode))
        {
          rtx res = expand_simple_binop (mode, ASHIFTRT, cop0, GEN_INT (shift),
                                         operands[0], 0, OPTAB_DIRECT);
@@ -43679,8 +43709,8 @@ ix86_rtx_costs (rtx x, machine_mode mode, int 
outer_code_i, int opno,
        }
       if (SSE_FLOAT_MODE_P (mode))
        {
-    case CONST_VECTOR:
-         switch (standard_sse_constant_p (x))
+       case CONST_VECTOR:
+         switch (standard_sse_constant_p (x, mode))
            {
            case 0:
              break;
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index babd0a4..25be5ca 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -1970,9 +1970,11 @@
    (set_attr "length_immediate" "1")])
 
 (define_insn "*movxi_internal_avx512f"
-  [(set (match_operand:XI 0 "nonimmediate_operand" "=v,v ,m")
-       (match_operand:XI 1 "vector_move_operand"  "C ,vm,v"))]
-  "TARGET_AVX512F && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+  [(set (match_operand:XI 0 "nonimmediate_operand"             "=v,v ,m")
+       (match_operand:XI 1 "nonimmediate_or_sse_const_operand" "BC,vm,v"))]
+  "TARGET_AVX512F
+   && (register_operand (operands[0], XImode)
+       || register_operand (operands[1], XImode))"
 {
   switch (which_alternative)
     {
@@ -1994,9 +1996,11 @@
    (set_attr "mode" "XI")])
 
 (define_insn "*movoi_internal_avx"
-  [(set (match_operand:OI 0 "nonimmediate_operand" "=v,v ,m")
-       (match_operand:OI 1 "vector_move_operand"  "C ,vm,v"))]
-  "TARGET_AVX && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+  [(set (match_operand:OI 0 "nonimmediate_operand"             "=v,v,v ,m")
+       (match_operand:OI 1 "nonimmediate_or_sse_const_operand" "BC,C,vm,v"))]
+  "TARGET_AVX
+   && (register_operand (operands[0], OImode)
+       || register_operand (operands[1], OImode))"
 {
   switch (get_attr_type (insn))
     {
@@ -2028,7 +2032,8 @@
       gcc_unreachable ();
     }
 }
-  [(set_attr "type" "sselog1,ssemov,ssemov")
+  [(set_attr "isa" "avx2,*,*,*")
+   (set_attr "type" "sselog1,sselog1,ssemov,ssemov")
    (set_attr "prefix" "vex")
    (set (attr "mode")
        (cond [(ior (match_operand 0 "ext_sse_reg_operand")
@@ -2036,17 +2041,21 @@
                 (const_string "XI")
               (match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL")
                 (const_string "V8SF")
-              (and (eq_attr "alternative" "2")
+              (and (eq_attr "alternative" "3")
                    (match_test "TARGET_SSE_TYPELESS_STORES"))
                 (const_string "V8SF")
              ]
              (const_string "OI")))])
 
 (define_insn "*movti_internal"
-  [(set (match_operand:TI 0 "nonimmediate_operand" "=!r ,o ,v,v ,m")
-       (match_operand:TI 1 "general_operand"      "riFo,re,C,vm,v"))]
-  "(TARGET_64BIT || TARGET_SSE)
-   && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+  [(set (match_operand:TI 0 "nonimmediate_operand" "=!r ,o ,v ,v,v ,m")
+       (match_operand:TI 1 "general_operand"      "riFo,re,BC,C,vm,v"))]
+  "(TARGET_64BIT
+    && !(MEM_P (operands[0]) && MEM_P (operands[1])))
+   || (TARGET_SSE
+       && nonimmediate_or_sse_const_operand (operands[1], TImode)
+       && (register_operand (operands[0], TImode)
+          || register_operand (operands[1], TImode)))"
 {
   switch (get_attr_type (insn))
     {
@@ -2083,8 +2092,8 @@
       gcc_unreachable ();
     }
 }
-  [(set_attr "isa" "x64,x64,*,*,*")
-   (set_attr "type" "multi,multi,sselog1,ssemov,ssemov")
+  [(set_attr "isa" "x64,x64,sse2,*,*,*")
+   (set_attr "type" "multi,multi,sselog1,sselog1,ssemov,ssemov")
    (set (attr "prefix")
      (if_then_else (eq_attr "type" "sselog1,ssemov")
        (const_string "maybe_vex")
@@ -2098,7 +2107,7 @@
               (ior (not (match_test "TARGET_SSE2"))
                    (match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL"))
                 (const_string "V4SF")
-              (and (eq_attr "alternative" "4")
+              (and (eq_attr "alternative" "5")
                    (match_test "TARGET_SSE_TYPELESS_STORES"))
                 (const_string "V4SF")
               (match_test "TARGET_AVX")
@@ -3086,7 +3095,7 @@
        || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
        || !CONST_DOUBLE_P (operands[1])
        || (optimize_function_for_size_p (cfun)
-          && standard_sse_constant_p (operands[1])
+          && standard_sse_constant_p (operands[1], TFmode) == 1
           && !memory_operand (operands[0], TFmode))
        || (!TARGET_MEMORY_MISMATCH_STALL
           && memory_operand (operands[0], TFmode)))"
@@ -3240,7 +3249,7 @@
           && ((!(TARGET_SSE2 && TARGET_SSE_MATH)
                && standard_80387_constant_p (operands[1]) > 0)
               || (TARGET_SSE2 && TARGET_SSE_MATH
-                  && standard_sse_constant_p (operands[1])))
+                  && standard_sse_constant_p (operands[1], DFmode) == 1))
           && !memory_operand (operands[0], DFmode))
        || ((TARGET_64BIT || !TARGET_MEMORY_MISMATCH_STALL)
           && memory_operand (operands[0], DFmode))
@@ -3442,7 +3451,7 @@
           && ((!TARGET_SSE_MATH
                && standard_80387_constant_p (operands[1]) > 0)
               || (TARGET_SSE_MATH
-                  && standard_sse_constant_p (operands[1]))))
+                  && standard_sse_constant_p (operands[1], SFmode) == 1)))
        || memory_operand (operands[0], SFmode)
        || !TARGET_HARD_SF_REGS)"
 {
@@ -3579,7 +3588,8 @@
 
   if (operands[2] == NULL_RTX
       || (SSE_REGNO_P (REGNO (operands[0]))
-         && !standard_sse_constant_p (operands[2]))
+         && standard_sse_constant_p (operands[2],
+                                     GET_MODE (operands[0])) != 1)
       || (STACK_REGNO_P (REGNO (operands[0]))
           && standard_80387_constant_p (operands[2]) < 1))
     FAIL;
@@ -3598,7 +3608,8 @@
 
   if (operands[2] == NULL_RTX
       || (SSE_REGNO_P (REGNO (operands[0]))
-         && !standard_sse_constant_p (operands[2]))
+         && standard_sse_constant_p (operands[2],
+                                     GET_MODE (operands[0])) != 1)
       || (STACK_REGNO_P (REGNO (operands[0]))
           && standard_80387_constant_p (operands[2]) < 1))
     FAIL;
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 93dda7b..fd2737c 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -661,29 +661,37 @@
 (define_predicate "const0_operand"
   (match_code "const_int,const_wide_int,const_double,const_vector")
 {
+  if (op == const0_rtx)
+    return true;
+
   if (mode == VOIDmode)
     mode = GET_MODE (op);
   return op == CONST0_RTX (mode);
 })
 
-;; Match -1.
-(define_predicate "constm1_operand"
-  (match_code "const_int,const_wide_int,const_double,const_vector")
+;; Match one or vector with all elements equal to one.
+(define_predicate "const1_operand"
+  (match_code "const_int,const_wide_int,const_vector")
 {
+  if (op == const1_rtx)
+    return true;
+
   if (mode == VOIDmode)
     mode = GET_MODE (op);
-  return op == CONSTM1_RTX (mode);
+  return op == CONST1_RTX (mode);
 })
 
-;; Match one or vector filled with ones.
-(define_predicate "const1_operand"
-  (match_code "const_int,const_wide_int,const_double,const_vector")
+;; Return true if operand is a (vector) constant with all bits set.
+(define_predicate "all_ones_operand"
+  (match_code "const_int,const_wide_int,const_vector")
 {
+  if (op == constm1_rtx)
+    return true;
+
   if (mode == VOIDmode)
     mode = GET_MODE (op);
-  return op == CONST1_RTX (mode);
+  return op == CONSTM1_RTX (mode);
 })
-
 ;; Match exactly eight.
 (define_predicate "const8_operand"
   (and (match_code "const_int")
@@ -945,12 +953,6 @@
   return true;
 })
 
-/* Return true if operand is a vector constant that is all ones. */
-(define_predicate "vector_all_ones_operand"
-  (and (match_code "const_vector")
-       (match_test "INTEGRAL_MODE_P (GET_MODE (op))")
-       (match_test "op == CONSTM1_RTX (GET_MODE (op))")))
-
 ; Return true when OP is operand acceptable for vector memory operand.
 ; Only AVX can have misaligned memory operand.
 (define_predicate "vector_memory_operand"
@@ -976,14 +978,8 @@
 
 ;; Return true when OP is nonimmediate or standard SSE constant.
 (define_predicate "nonimmediate_or_sse_const_operand"
-  (match_operand 0 "general_operand")
-{
-  if (nonimmediate_operand (op, mode))
-    return true;
-  if (standard_sse_constant_p (op) > 0)
-    return true;
-  return false;
-})
+  (ior (match_operand 0 "nonimmediate_operand")
+       (match_test "standard_sse_constant_p (op, mode)")))
 
 ;; Return true if OP is a register or a zero.
 (define_predicate "reg_or_0_operand"
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index 48a7abb..a31501b 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -5097,7 +5097,7 @@
 (define_insn "*<avx512>_cvtmask2<ssemodesuffix><mode>"
   [(set (match_operand:VI12_AVX512VL 0 "register_operand" "=v")
        (vec_merge:VI12_AVX512VL
-         (match_operand:VI12_AVX512VL 2 "constm1_operand")
+         (match_operand:VI12_AVX512VL 2 "all_ones_operand")
          (match_operand:VI12_AVX512VL 3 "const0_operand")
          (match_operand:<avx512fmaskmode> 1 "register_operand" "Yk")))]
   "TARGET_AVX512BW"
@@ -5120,7 +5120,7 @@
 (define_insn "*<avx512>_cvtmask2<ssemodesuffix><mode>"
   [(set (match_operand:VI48_AVX512VL 0 "register_operand" "=v")
        (vec_merge:VI48_AVX512VL
-         (match_operand:VI48_AVX512VL 2 "constm1_operand")
+         (match_operand:VI48_AVX512VL 2 "all_ones_operand")
          (match_operand:VI48_AVX512VL 3 "const0_operand")
          (match_operand:<avx512fmaskmode> 1 "register_operand" "Yk")))]
   "TARGET_AVX512DQ"

Reply via email to