;; Predicate definitions for IA-32 and x86-64.
-;; Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+;; Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009
+;; Free Software Foundation, Inc.
;;
;; This file is part of GCC.
;;
;; GCC is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
+;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
;;
;; GCC is distributed in the hope that it will be useful,
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
+;; along with GCC; see the file COPYING3. If not see
+;; <http://www.gnu.org/licenses/>.
;; Return nonzero if OP is either a i387 or SSE fp register.
(define_predicate "any_fp_register_operand"
return ANY_QI_REG_P (op);
})
-;; Return true if op is a NON_Q_REGS class register.
-(define_predicate "non_q_regs_operand"
- (match_operand 0 "register_operand")
-{
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- return NON_QI_REG_P (op);
-})
-
;; Match an SI or HImode register for a zero_extract.
(define_special_predicate "ext_register_operand"
(match_operand 0 "register_operand")
(and (match_code "reg")
(match_test "REGNO (op) == FLAGS_REG")))
+;; Return true if op is a QImode register operand other than
+;; %[abcd][hl].
+(define_predicate "ext_QIreg_operand"
+ (and (match_code "reg")
+ (match_test "TARGET_64BIT
+ && 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")
+ (match_test "!REG_P (op)
+ || REGNO (op) != FIRST_SSE_REG")))
+
+;; As above, but allow nonimmediate operands.
+(define_predicate "nonimm_not_xmm0_operand"
+ (and (match_operand 0 "nonimmediate_operand")
+ (match_test "!REG_P (op)
+ || REGNO (op) != FIRST_SSE_REG")))
+
;; Return 1 if VALUE can be stored in a sign extended immediate field.
(define_predicate "x86_64_immediate_operand"
(match_code "const_int,symbol_ref,label_ref,const")
if (ix86_cmodel == CM_LARGE)
return 0;
- if (GET_CODE (op2) != CONST_INT)
+ if (!CONST_INT_P (op2))
return 0;
offset = trunc_int_for_mode (INTVAL (op2), DImode);
switch (GET_CODE (op1))
if ((ix86_cmodel == CM_SMALL
|| (ix86_cmodel == CM_MEDIUM
&& !SYMBOL_REF_FAR_ADDR_P (op1)))
- && GET_CODE (op2) == CONST_INT
+ && CONST_INT_P (op2)
&& trunc_int_for_mode (INTVAL (op2), DImode) > -0x10000
&& trunc_int_for_mode (INTVAL (op2), SImode) == INTVAL (op2))
return 1;
/* These conditions are similar to SYMBOL_REF ones, just the
constraints for code models differ. */
if ((ix86_cmodel == CM_SMALL || ix86_cmodel == CM_MEDIUM)
- && GET_CODE (op2) == CONST_INT
+ && CONST_INT_P (op2)
&& trunc_int_for_mode (INTVAL (op2), DImode) > -0x10000
&& trunc_int_for_mode (INTVAL (op2), SImode) == INTVAL (op2))
return 1;
(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
if (TARGET_64BIT && GET_CODE (op) == CONST)
{
op = XEXP (op, 0);
- if (GET_CODE (op) == PLUS && GET_CODE (XEXP (op, 1)) == CONST_INT)
+ if (GET_CODE (op) == PLUS && CONST_INT_P (XEXP (op, 1)))
op = XEXP (op, 0);
if (GET_CODE (op) == UNSPEC
&& (XINT (op, 1) == UNSPEC_GOTOFF
|| XINT (op, 1) == UNSPEC_GOTPCREL)))
return 1;
if (GET_CODE (op) != PLUS
- || GET_CODE (XEXP (op, 1)) != CONST_INT)
+ || !CONST_INT_P (XEXP (op, 1)))
return 0;
op = XEXP (op, 0);
if (GET_CODE (op) == UNSPEC)
return 1;
if (GET_CODE (op) != PLUS
- || GET_CODE (XEXP (op, 1)) != CONST_INT)
+ || !CONST_INT_P (XEXP (op, 1)))
return 0;
op = XEXP (op, 0);
- if (GET_CODE (op) == UNSPEC)
+ if (GET_CODE (op) == UNSPEC
+ && XINT (op, 1) != UNSPEC_MACHOPIC_OFFSET)
return 1;
}
return 0;
{
if (GET_CODE (op) == CONST
&& GET_CODE (XEXP (op, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
+ && CONST_INT_P (XEXP (XEXP (op, 0), 1)))
op = XEXP (XEXP (op, 0), 0);
if (GET_CODE (op) == LABEL_REF)
if (GET_CODE (op) != SYMBOL_REF)
return 0;
+ if (SYMBOL_REF_TLS_MODEL (op) != 0)
+ return 0;
+
if (SYMBOL_REF_LOCAL_P (op))
return 1;
return 0;
})
+;; Test for a legitimate @GOTOFF operand.
+;;
+;; VxWorks does not impose a fixed gap between segments; the run-time
+;; gap can be different from the object-file gap. We therefore can't
+;; use @GOTOFF unless we are absolutely sure that the symbol is in the
+;; same segment as the GOT. Unfortunately, the flexibility of linker
+;; scripts means that we can't be sure of that in general, so assume
+;; that @GOTOFF is never valid on VxWorks.
+(define_predicate "gotoff_operand"
+ (and (match_test "!TARGET_VXWORKS_RTP")
+ (match_operand 0 "local_symbolic_operand")))
+
;; Test for various thread-local symbols.
(define_predicate "tls_symbolic_operand"
(and (match_code "symbol_ref")
;; Test for a pc-relative call operand
(define_predicate "constant_call_address_operand"
- (ior (match_code "symbol_ref")
- (match_operand 0 "local_symbolic_operand")))
+ (match_code "symbol_ref")
+{
+ if (ix86_cmodel == CM_LARGE || ix86_cmodel == CM_LARGE_PIC)
+ return false;
+ if (TARGET_DLLIMPORT_DECL_ATTRIBUTES && SYMBOL_REF_DLLIMPORT_P (op))
+ return false;
+ return true;
+})
;; True for any non-virtual or eliminable register. Used in places where
;; instantiation of such a register may cause the pattern to not be recognized.
op = SUBREG_REG (op);
return !(op == arg_pointer_rtx
|| op == frame_pointer_rtx
- || (REGNO (op) >= FIRST_PSEUDO_REGISTER
- && REGNO (op) <= LAST_VIRTUAL_REGISTER));
+ || IN_RANGE (REGNO (op),
+ 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
;; 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) == 8")))
+;; Match exactly 128.
+(define_predicate "const128_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")
;; Match 0 to 3.
(define_predicate "const_0_to_3_operand"
(and (match_code "const_int")
- (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 3")))
+ (match_test "IN_RANGE (INTVAL (op), 0, 3)")))
;; Match 0 to 7.
(define_predicate "const_0_to_7_operand"
(and (match_code "const_int")
- (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 7")))
+ (match_test "IN_RANGE (INTVAL (op), 0, 7)")))
;; Match 0 to 15.
(define_predicate "const_0_to_15_operand"
(and (match_code "const_int")
- (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 15")))
+ (match_test "IN_RANGE (INTVAL (op), 0, 15)")))
+
+;; Match 0 to 31.
+(define_predicate "const_0_to_31_operand"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (INTVAL (op), 0, 31)")))
;; Match 0 to 63.
(define_predicate "const_0_to_63_operand"
(and (match_code "const_int")
- (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 63")))
+ (match_test "IN_RANGE (INTVAL (op), 0, 63)")))
;; Match 0 to 255.
(define_predicate "const_0_to_255_operand"
(and (match_code "const_int")
- (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 255")))
+ (match_test "IN_RANGE (INTVAL (op), 0, 255)")))
;; Match (0 to 255) * 8
(define_predicate "const_0_to_255_mul_8_operand"
;; for shift & compare patterns, as shifting by 0 does not change flags).
(define_predicate "const_1_to_31_operand"
(and (match_code "const_int")
- (match_test "INTVAL (op) >= 1 && INTVAL (op) <= 31")))
+ (match_test "IN_RANGE (INTVAL (op), 1, 31)")))
+
+;; Return nonzero if OP is CONST_INT >= 1 and <= 63 (a valid operand
+;; for 64bit shift & compare patterns, as shifting by 0 does not change flags).
+(define_predicate "const_1_to_63_operand"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (INTVAL (op), 1, 63)")))
;; Match 2 or 3.
(define_predicate "const_2_to_3_operand"
(and (match_code "const_int")
- (match_test "INTVAL (op) == 2 || INTVAL (op) == 3")))
+ (match_test "IN_RANGE (INTVAL (op), 2, 3)")))
+
+;; Match 4 to 5.
+(define_predicate "const_4_to_5_operand"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (INTVAL (op), 4, 5)")))
;; Match 4 to 7.
(define_predicate "const_4_to_7_operand"
(and (match_code "const_int")
- (match_test "INTVAL (op) >= 4 && INTVAL (op) <= 7")))
+ (match_test "IN_RANGE (INTVAL (op), 4, 7)")))
+
+;; Match 6 to 7.
+(define_predicate "const_6_to_7_operand"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (INTVAL (op), 6, 7)")))
+
+;; Match 8 to 11.
+(define_predicate "const_8_to_11_operand"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (INTVAL (op), 8, 11)")))
+
+;; Match 12 to 15.
+(define_predicate "const_12_to_15_operand"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (INTVAL (op), 12, 15)")))
+
+;; Match exactly one bit in 2-bit mask.
+(define_predicate "const_pow2_1_to_2_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) == 1 || INTVAL (op) == 2")))
;; Match exactly one bit in 4-bit mask.
(define_predicate "const_pow2_1_to_8_operand"
return log <= 7;
})
+;; Match exactly one bit in 16-bit mask.
+(define_predicate "const_pow2_1_to_32768_operand"
+ (match_code "const_int")
+{
+ unsigned int log = exact_log2 (INTVAL (op));
+ return log <= 15;
+})
+
;; True if this is a constant appropriate for an increment or decrement.
(define_predicate "incdec_operand"
(match_code "const_int")
{
/* On Pentium4, the inc and dec operations causes extra dependency on flag
registers, since carry flag is not set. */
- if (!TARGET_USE_INCDEC && !optimize_size)
+ if (!TARGET_USE_INCDEC && !optimize_insn_for_size_p ())
return 0;
return op == const1_rtx || op == constm1_rtx;
})
{
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);
int ok;
/* Registers and immediate operands are always "aligned". */
- if (GET_CODE (op) != MEM)
+ if (!MEM_P (op))
return 1;
/* All patterns using aligned_operand on memory operands ends up
in promoting memory operand to 64bit and thus causing memory mismatch. */
- if (TARGET_MEMORY_MISMATCH_STALL && !optimize_size)
+ if (TARGET_MEMORY_MISMATCH_STALL && !optimize_insn_for_size_p ())
return 0;
/* Don't even try to do any aligned optimizations with volatiles. */
}
if (parts.disp)
{
- if (GET_CODE (parts.disp) != CONST_INT
+ if (!CONST_INT_P (parts.disp)
|| (INTVAL (parts.disp) & 3) != 0)
return 0;
}
struct ix86_address parts;
int ok;
+ if (TARGET_64BIT)
+ return 0;
+
ok = ix86_decompose_address (XEXP (op, 0), &parts);
gcc_assert (ok);
return parts.disp != NULL_RTX;
})
+;; Returns 1 if OP is memory operand which will need zero or
+;; one register at most, not counting stack pointer or frame pointer.
+(define_predicate "cmpxchg8b_pic_memory_operand"
+ (match_operand 0 "memory_operand")
+{
+ struct ix86_address parts;
+ int ok;
+
+ ok = ix86_decompose_address (XEXP (op, 0), &parts);
+ gcc_assert (ok);
+ if (parts.base == NULL_RTX
+ || parts.base == arg_pointer_rtx
+ || parts.base == frame_pointer_rtx
+ || parts.base == hard_frame_pointer_rtx
+ || parts.base == stack_pointer_rtx)
+ return 1;
+
+ if (parts.index == NULL_RTX
+ || parts.index == arg_pointer_rtx
+ || parts.index == frame_pointer_rtx
+ || parts.index == hard_frame_pointer_rtx
+ || parts.index == stack_pointer_rtx)
+ return 1;
+
+ return 0;
+})
+
+
;; Returns 1 if OP is memory operand that cannot be represented
;; by the modRM array.
(define_predicate "long_memory_operand"
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);
}
switch (code)
{
case LTU: case GTU: case LEU: case GEU:
- if (inmode == CCmode || inmode == CCFPmode || inmode == CCFPUmode)
+ if (inmode == CCmode || inmode == CCFPmode || inmode == CCFPUmode
+ || inmode == CCCmode)
return 1;
return 0;
case ORDERED: case UNORDERED:
(define_special_predicate "sse_comparison_operator"
(match_code "eq,lt,le,unordered,ne,unge,ungt,ordered"))
+;; Return 1 if OP is a comparison operator that can be issued by
+;; avx predicate generation instructions
+(define_predicate "avx_comparison_float_operator"
+ (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"))
+
+(define_predicate "ix86_comparison_uns_operator"
+ (match_code "ne,eq,geu,gtu,leu,ltu"))
+
+(define_predicate "bt_comparison_operator"
+ (match_code "ne,eq"))
+
;; Return 1 if OP is a valid comparison operator in valid mode.
(define_predicate "ix86_comparison_operator"
(match_operand 0 "comparison_operator")
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:
|| inmode == CCGOCmode || inmode == CCNOmode)
return 1;
return 0;
- case LTU: case GTU: case LEU: case ORDERED: case UNORDERED: case GEU:
+ case LTU: case GTU: case LEU: case GEU:
+ if (inmode == CCmode || inmode == CCCmode)
+ return 1;
+ return 0;
+ case ORDERED: case UNORDERED:
if (inmode == CCmode)
return 1;
return 0;
;; Return 1 if OP is a valid comparison operator testing carry flag to be set.
(define_predicate "ix86_carry_flag_operator"
- (match_code "ltu,lt,unlt,gt,ungt,le,unle,ge,unge,ltgt,uneq")
+ (match_code "ltu,lt,unlt,gtu,gt,ungt,le,unle,ge,unge,ltgt,uneq")
{
enum machine_mode inmode = GET_MODE (XEXP (op, 0));
enum rtx_code code = GET_CODE (op);
- if (GET_CODE (XEXP (op, 0)) != REG
- || 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);
}
+ else if (inmode == CCCmode)
+ return code == LTU || code == GTU;
else if (inmode != CCmode)
return 0;
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.
(match_code "plus,mult,and,ior,xor,smin,smax,umin,umax,compare,minus,div,
mod,udiv,umod,ashift,rotate,ashiftrt,lshiftrt,rotatert"))
+;; Return true for COMMUTATIVE_P.
+(define_predicate "commutative_operator"
+ (match_code "plus,mult,and,ior,xor,smin,smax,umin,umax"))
+
;; Return 1 if OP is a binary operator that can be promoted to wider mode.
-;; Modern CPUs have same latency for HImode and SImode multiply,
-;; but 386 and 486 do HImode multiply faster. */
(define_predicate "promotable_binary_operator"
(ior (match_code "plus,and,ior,xor,ashift")
(and (match_code "mult")
- (match_test "ix86_tune > PROCESSOR_I486"))))
-
-;; 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")
- )))
+ (match_test "TARGET_TUNE_PROMOTE_HIMODE_IMUL"))))
(define_predicate "compare_operator"
(match_code "compare"))
(define_predicate "absneg_operator"
(match_code "abs,neg"))
+
+;; Return 1 if OP is misaligned memory operand
+(define_predicate "misaligned_operand"
+ (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")
+{
+ 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) != 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;
+})