OSDN Git Service

ABM popcount intrinsics.
[pf3gnuchains/gcc-fork.git] / gcc / config / i386 / predicates.md
index 4feb861..8f901cd 100644 (file)
                    && GET_MODE (op) == QImode
                    && REGNO (op) > BX_REG")))
 
+;; Similarly, but don't check mode of the operand.
+(define_predicate "ext_QIreg_nomode_operand"
+  (and (match_code "reg")
+       (match_test "TARGET_64BIT
+                   && REGNO (op) > BX_REG")))
+
 ;; Return true if op is not xmm0 register.
 (define_predicate "reg_not_xmm0_operand"
    (and (match_operand 0 "register_operand")
 (define_predicate "x86_64_szext_general_operand"
   (if_then_else (match_test "TARGET_64BIT")
     (ior (match_operand 0 "nonimmediate_operand")
-        (ior (match_operand 0 "x86_64_immediate_operand")
-             (match_operand 0 "x86_64_zext_immediate_operand")))
+        (match_operand 0 "x86_64_immediate_operand")
+        (match_operand 0 "x86_64_zext_immediate_operand"))
     (match_operand 0 "general_operand")))
 
 ;; Return nonzero if OP is nonmemory operand representable on x86_64.
 (define_predicate "x86_64_szext_nonmemory_operand"
   (if_then_else (match_test "TARGET_64BIT")
     (ior (match_operand 0 "register_operand")
-        (ior (match_operand 0 "x86_64_immediate_operand")
-             (match_operand 0 "x86_64_zext_immediate_operand")))
+        (match_operand 0 "x86_64_immediate_operand")
+        (match_operand 0 "x86_64_zext_immediate_operand"))
     (match_operand 0 "nonmemory_operand")))
 
 ;; Return true when operand is PIC expression that can be computed by lea
                        FIRST_PSEUDO_REGISTER, LAST_VIRTUAL_REGISTER));
 })
 
+;; P6 processors will jump to the address after the decrement when %esp
+;; is used as a call operand, so they will execute return address as a code.
+;; See Pentium Pro errata 70, Pentium 2 errata A33 and Pentium 3 errata E17.
+
+(define_predicate "call_register_no_elim_operand"
+  (match_operand 0 "register_operand")
+{
+  if (GET_CODE (op) == SUBREG)
+    op = SUBREG_REG (op);
+
+  if (!TARGET_64BIT && op == stack_pointer_rtx)
+    return 0;
+
+  return register_no_elim_operand (op, mode);
+})
+
 ;; Similarly, but include the stack pointer.  This is used to prevent esp
 ;; from being used as an index reg.
 (define_predicate "index_register_operand"
 ;; Test for a valid operand for a call instruction.
 (define_predicate "call_insn_operand"
   (ior (match_operand 0 "constant_call_address_operand")
-       (ior (match_operand 0 "register_no_elim_operand")
-           (match_operand 0 "memory_operand"))))
+       (match_operand 0 "call_register_no_elim_operand")
+       (match_operand 0 "memory_operand")))
 
 ;; Similarly, but for tail calls, in which we cannot allow memory references.
 (define_predicate "sibcall_insn_operand"
   (and (match_code "const_int")
        (match_test "INTVAL (op) == 128")))
 
-;; Match exactly -128.
-(define_predicate "constm128_operand"
-  (and (match_code "const_int")
-       (match_test "INTVAL (op) == -128")))
-
 ;; Match 2, 4, or 8.  Used for leal multiplicands.
 (define_predicate "const248_operand"
   (match_code "const_int")
 {
   unsigned n_elts;
   op = maybe_get_pool_constant (op);
-  if (!op)
-    return 0;
-  if (GET_CODE (op) != CONST_VECTOR)
+
+  if (!(op && GET_CODE (op) == CONST_VECTOR))
     return 0;
-  n_elts =
-    (GET_MODE_SIZE (GET_MODE (op)) /
-     GET_MODE_SIZE (GET_MODE_INNER (GET_MODE (op))));
+
+  n_elts = CONST_VECTOR_NUNITS (op);
+
   for (n_elts--; n_elts > 0; n_elts--)
     {
       rtx elt = CONST_VECTOR_ELT (op, n_elts);
 
   if (inmode == CCFPmode || inmode == CCFPUmode)
     {
-      enum rtx_code second_code, bypass_code;
-      ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code);
-      if (bypass_code != UNKNOWN || second_code != UNKNOWN)
+      if (!ix86_trivial_fp_comparison_operator (op, mode))
        return 0;
       code = ix86_fp_compare_code_to_integer (code);
     }
 (define_predicate "avx_comparison_float_operator"
   (match_code "ne,eq,ge,gt,le,lt,unordered,ordered,uneq,unge,ungt,unle,unlt,ltgt"))
 
-;; Return 1 if OP is a comparison operator that can be issued by sse predicate
-;; generation instructions
-(define_predicate "sse5_comparison_float_operator"
-  (and (match_test "TARGET_SSE5")
-       (match_code "ne,eq,ge,gt,le,lt,unordered,ordered,uneq,unge,ungt,unle,unlt,ltgt")))
-
 (define_predicate "ix86_comparison_int_operator"
   (match_code "ne,eq,ge,gt,le,lt"))
 
   enum rtx_code code = GET_CODE (op);
 
   if (inmode == CCFPmode || inmode == CCFPUmode)
-    {
-      enum rtx_code second_code, bypass_code;
-      ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code);
-      return (bypass_code == UNKNOWN && second_code == UNKNOWN);
-    }
+    return ix86_trivial_fp_comparison_operator (op, mode);
+
   switch (code)
     {
     case EQ: case NE:
   enum machine_mode inmode = GET_MODE (XEXP (op, 0));
   enum rtx_code code = GET_CODE (op);
 
-  if (!REG_P (XEXP (op, 0))
-      || REGNO (XEXP (op, 0)) != FLAGS_REG
-      || XEXP (op, 1) != const0_rtx)
-    return 0;
-
   if (inmode == CCFPmode || inmode == CCFPUmode)
     {
-      enum rtx_code second_code, bypass_code;
-      ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code);
-      if (bypass_code != UNKNOWN || second_code != UNKNOWN)
+      if (!ix86_trivial_fp_comparison_operator (op, mode))
        return 0;
       code = ix86_fp_compare_code_to_integer (code);
     }
   return code == LTU;
 })
 
+;; Return 1 if this comparison only requires testing one flag bit.
+(define_predicate "ix86_trivial_fp_comparison_operator"
+  (match_code "gt,ge,unlt,unle,uneq,ltgt,ordered,unordered"))
+
+;; Return 1 if we know how to do this comparison.  Others require
+;; testing more than one flag bit, and we let the generic middle-end
+;; code do that.
+(define_predicate "ix86_fp_comparison_operator"
+  (if_then_else (match_test "ix86_fp_comparison_strategy (GET_CODE (op))
+                             == IX86_FPCMP_ARITH")
+               (match_operand 0 "comparison_operator")
+               (match_operand 0 "ix86_trivial_fp_comparison_operator")))
+
 ;; Nearly general operand, but accept any const_double, since we wish
 ;; to be able to drop them into memory rather than have them get pulled
 ;; into registers.
        (and (match_code "mult")
            (match_test "TARGET_TUNE_PROMOTE_HIMODE_IMUL"))))
 
-;; To avoid problems when jump re-emits comparisons like testqi_ext_ccno_0,
-;; re-recognize the operand to avoid a copy_to_mode_reg that will fail.
-;;
-;; ??? It seems likely that this will only work because cmpsi is an
-;; expander, and no actual insns use this.
-
-(define_predicate "cmpsi_operand"
-  (ior (match_operand 0 "nonimmediate_operand")
-       (and (match_code "and")
-           (match_code "zero_extract" "0")
-           (match_code "const_int"    "1")
-           (match_code "const_int"    "01")
-           (match_code "const_int"    "02")
-           (match_test "INTVAL (XEXP (XEXP (op, 0), 1)) == 8")
-           (match_test "INTVAL (XEXP (XEXP (op, 0), 2)) == 8")
-       )))
-
 (define_predicate "compare_operator"
   (match_code "compare"))
 
   (and (match_code "mem")
        (match_test "MEM_ALIGN (op) < GET_MODE_ALIGNMENT (mode)")))
 
+;; Return 1 if OP is a emms operation, known to be a PARALLEL.
+(define_predicate "emms_operation"
+  (match_code "parallel")
+{
+  unsigned i;
+
+  if (XVECLEN (op, 0) != 17)
+    return 0;
+
+  for (i = 0; i < 8; i++)
+    {
+      rtx elt = XVECEXP (op, 0, i+1);
+
+      if (GET_CODE (elt) != CLOBBER
+         || GET_CODE (SET_DEST (elt)) != REG
+         || GET_MODE (SET_DEST (elt)) != XFmode
+         || REGNO (SET_DEST (elt)) != FIRST_STACK_REG + i)
+        return 0;
+
+      elt = XVECEXP (op, 0, i+9);
+
+      if (GET_CODE (elt) != CLOBBER
+         || GET_CODE (SET_DEST (elt)) != REG
+         || GET_MODE (SET_DEST (elt)) != DImode
+         || REGNO (SET_DEST (elt)) != FIRST_MMX_REG + i)
+       return 0;
+    }
+  return 1;
+})
+
 ;; Return 1 if OP is a vzeroall operation, known to be a PARALLEL.
 (define_predicate "vzeroall_operation"
   (match_code "parallel")
 {
-  int nregs = TARGET_64BIT ? 16 : 8;
+  unsigned i, nregs = TARGET_64BIT ? 16 : 8;
 
-  if (XVECLEN (op, 0) != nregs + 1)
+  if ((unsigned) XVECLEN (op, 0) != 1 + nregs)
     return 0;
 
+  for (i = 0; i < nregs; i++)
+    {
+      rtx elt = XVECEXP (op, 0, i+1);
+
+      if (GET_CODE (elt) != SET
+         || GET_CODE (SET_DEST (elt)) != REG
+         || GET_MODE (SET_DEST (elt)) != V8SImode
+         || REGNO (SET_DEST (elt)) != SSE_REGNO (i)
+         || SET_SRC (elt) != CONST0_RTX (V8SImode))
+       return 0;
+    }
   return 1;
 })
+
+;; Return 1 if OP is a vzeroupper operation, known to be a PARALLEL.
+(define_predicate "vzeroupper_operation"
+  (match_code "parallel")
+{
+  unsigned i, nregs = TARGET_64BIT ? 16 : 8;
+  if ((unsigned) XVECLEN (op, 0) != 1 + nregs)
+    return 0;
+
+  for (i = 0; i < nregs; i++)
+    {
+      rtx elt = XVECEXP (op, 0, i+1);
+
+      if (GET_CODE (elt) != CLOBBER
+         || GET_CODE (SET_DEST (elt)) != REG
+         || GET_MODE (SET_DEST (elt)) != V8SImode
+         || REGNO (SET_DEST (elt)) != SSE_REGNO (i))
+       return 0;
+    }
+  return 1;
+})
+
+;; Return 1 if OP is a parallel for a vpermilp[ds] permute.
+;; ??? It would be much easier if the PARALLEL for a VEC_SELECT
+;; had a mode, but it doesn't.  So we have 4 copies and install
+;; the mode by hand.
+
+(define_predicate "avx_vpermilp_v8sf_operand"
+  (and (match_code "parallel")
+       (match_test "avx_vpermilp_parallel (op, V8SFmode)")))
+
+(define_predicate "avx_vpermilp_v4df_operand"
+  (and (match_code "parallel")
+       (match_test "avx_vpermilp_parallel (op, V4DFmode)")))
+
+(define_predicate "avx_vpermilp_v4sf_operand"
+  (and (match_code "parallel")
+       (match_test "avx_vpermilp_parallel (op, V4SFmode)")))
+
+(define_predicate "avx_vpermilp_v2df_operand"
+  (and (match_code "parallel")
+       (match_test "avx_vpermilp_parallel (op, V2DFmode)")))
+
+;; Return 1 if OP is a parallel for a vperm2f128 permute.
+
+(define_predicate "avx_vperm2f128_v8sf_operand"
+  (and (match_code "parallel")
+       (match_test "avx_vperm2f128_parallel (op, V8SFmode)")))
+
+(define_predicate "avx_vperm2f128_v8si_operand"
+  (and (match_code "parallel")
+       (match_test "avx_vperm2f128_parallel (op, V8SImode)")))
+
+(define_predicate "avx_vperm2f128_v4df_operand"
+  (and (match_code "parallel")
+       (match_test "avx_vperm2f128_parallel (op, V4DFmode)")))
+
+;; Return 1 if OP is a parallel for a vbroadcast permute.
+
+(define_predicate "avx_vbroadcast_operand"
+  (and (match_code "parallel")
+       (match_code "const_int" "a"))
+{
+  rtx elt = XVECEXP (op, 0, 0);
+  int i, nelt = XVECLEN (op, 0);
+
+  /* Don't bother checking there are the right number of operands,
+     merely that they're all identical.  */
+  for (i = 1; i < nelt; ++i)
+    if (XVECEXP (op, 0, i) != elt)
+      return false;
+  return true;
+})