| Index: gcc/gcc/config/rs6000/predicates.md
|
| diff --git a/gcc/gcc/config/rs6000/predicates.md b/gcc/gcc/config/rs6000/predicates.md
|
| index af80ef46b6f0a8ddc8933c44d23fe0af29264505..2d8a2a8d5d1bc619d846d7c24f574d4964216abd 100644
|
| --- a/gcc/gcc/config/rs6000/predicates.md
|
| +++ b/gcc/gcc/config/rs6000/predicates.md
|
| @@ -1,5 +1,5 @@
|
| ;; Predicate definitions for POWER and PowerPC.
|
| -;; Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
| +;; Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
|
| ;;
|
| ;; This file is part of GCC.
|
| ;;
|
| @@ -38,6 +38,37 @@
|
| || ALTIVEC_REGNO_P (REGNO (op))
|
| || REGNO (op) > LAST_VIRTUAL_REGISTER")))
|
|
|
| +;; Return 1 if op is a VSX register.
|
| +(define_predicate "vsx_register_operand"
|
| + (and (match_operand 0 "register_operand")
|
| + (match_test "GET_CODE (op) != REG
|
| + || VSX_REGNO_P (REGNO (op))
|
| + || REGNO (op) > LAST_VIRTUAL_REGISTER")))
|
| +
|
| +;; Return 1 if op is a vector register that operates on floating point vectors
|
| +;; (either altivec or VSX).
|
| +(define_predicate "vfloat_operand"
|
| + (and (match_operand 0 "register_operand")
|
| + (match_test "GET_CODE (op) != REG
|
| + || VFLOAT_REGNO_P (REGNO (op))
|
| + || REGNO (op) > LAST_VIRTUAL_REGISTER")))
|
| +
|
| +;; Return 1 if op is a vector register that operates on integer vectors
|
| +;; (only altivec, VSX doesn't support integer vectors)
|
| +(define_predicate "vint_operand"
|
| + (and (match_operand 0 "register_operand")
|
| + (match_test "GET_CODE (op) != REG
|
| + || VINT_REGNO_P (REGNO (op))
|
| + || REGNO (op) > LAST_VIRTUAL_REGISTER")))
|
| +
|
| +;; Return 1 if op is a vector register to do logical operations on (and, or,
|
| +;; xor, etc.)
|
| +(define_predicate "vlogical_operand"
|
| + (and (match_operand 0 "register_operand")
|
| + (match_test "GET_CODE (op) != REG
|
| + || VLOGICAL_REGNO_P (REGNO (op))
|
| + || REGNO (op) > LAST_VIRTUAL_REGISTER")))
|
| +
|
| ;; Return 1 if op is XER register.
|
| (define_predicate "xer_operand"
|
| (and (match_code "reg")
|
| @@ -234,6 +265,10 @@
|
| && num_insns_constant_wide ((HOST_WIDE_INT) k[3]) == 1);
|
|
|
| case DFmode:
|
| + /* The constant 0.f is easy under VSX. */
|
| + if (op == CONST0_RTX (DFmode) && VECTOR_UNIT_VSX_P (DFmode))
|
| + return 1;
|
| +
|
| /* Force constants to memory before reload to utilize
|
| compress_float_constant.
|
| Avoid this when flag_unsafe_math_optimizations is enabled
|
| @@ -292,6 +327,9 @@
|
| if (TARGET_PAIRED_FLOAT)
|
| return false;
|
|
|
| + if ((VSX_VECTOR_MODE (mode) || mode == TImode) && zero_constant (op, mode))
|
| + return true;
|
| +
|
| if (ALTIVEC_VECTOR_MODE (mode))
|
| {
|
| if (zero_constant (op, mode))
|
| @@ -339,6 +377,16 @@
|
| return EASY_VECTOR_15_ADD_SELF (val);
|
| })
|
|
|
| +;; Same as easy_vector_constant but only for EASY_VECTOR_MSB.
|
| +(define_predicate "easy_vector_constant_msb"
|
| + (and (match_code "const_vector")
|
| + (and (match_test "TARGET_ALTIVEC")
|
| + (match_test "easy_altivec_constant (op, mode)")))
|
| +{
|
| + HOST_WIDE_INT val = const_vector_elt_as_int (op, GET_MODE_NUNITS (mode) - 1);
|
| + return EASY_VECTOR_MSB (val, GET_MODE_INNER (mode));
|
| +})
|
| +
|
| ;; Return 1 if operand is constant zero (scalars and vectors).
|
| (define_predicate "zero_constant"
|
| (and (match_code "const_int,const_double,const_vector")
|
| @@ -367,9 +415,7 @@
|
| ;; Return 1 if the operand is an offsettable memory operand.
|
| (define_predicate "offsettable_mem_operand"
|
| (and (match_operand 0 "memory_operand")
|
| - (match_test "GET_CODE (XEXP (op, 0)) != PRE_INC
|
| - && GET_CODE (XEXP (op, 0)) != PRE_DEC
|
| - && GET_CODE (XEXP (op, 0)) != PRE_MODIFY")))
|
| + (match_test "offsettable_nonstrict_memref_p (op)")))
|
|
|
| ;; Return 1 if the operand is a memory operand with an address divisible by 4
|
| (define_predicate "word_offset_memref_operand"
|
| @@ -396,8 +442,7 @@
|
| (match_code "mem")
|
| {
|
| op = XEXP (op, 0);
|
| - if (TARGET_ALTIVEC
|
| - && ALTIVEC_VECTOR_MODE (mode)
|
| + if (VECTOR_MEM_ALTIVEC_P (mode)
|
| && GET_CODE (op) == AND
|
| && GET_CODE (XEXP (op, 1)) == CONST_INT
|
| && INTVAL (XEXP (op, 1)) == -16)
|
| @@ -406,6 +451,23 @@
|
| return indexed_or_indirect_address (op, mode);
|
| })
|
|
|
| +;; Return 1 if the operand is an indexed or indirect memory operand with an
|
| +;; AND -16 in it, used to recognize when we need to switch to Altivec loads
|
| +;; to realign loops instead of VSX (altivec silently ignores the bottom bits,
|
| +;; while VSX uses the full address and traps)
|
| +(define_predicate "altivec_indexed_or_indirect_operand"
|
| + (match_code "mem")
|
| +{
|
| + op = XEXP (op, 0);
|
| + if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode)
|
| + && GET_CODE (op) == AND
|
| + && GET_CODE (XEXP (op, 1)) == CONST_INT
|
| + && INTVAL (XEXP (op, 1)) == -16)
|
| + return indexed_or_indirect_address (XEXP (op, 0), mode);
|
| +
|
| + return 0;
|
| +})
|
| +
|
| ;; Return 1 if the operand is an indexed or indirect address.
|
| (define_special_predicate "indexed_or_indirect_address"
|
| (and (match_test "REG_P (op)
|
| @@ -830,6 +892,11 @@
|
| GET_MODE (XEXP (op, 0))),
|
| 1"))))
|
|
|
| +(define_predicate "rs6000_cbranch_operator"
|
| + (if_then_else (match_test "TARGET_HARD_FLOAT && !TARGET_FPRS")
|
| + (match_operand 0 "ordered_comparison_operator")
|
| + (match_operand 0 "comparison_operator")))
|
| +
|
| ;; Return 1 if OP is a comparison operation that is valid for an SCC insn --
|
| ;; it must be a positive comparison.
|
| (define_predicate "scc_comparison_operator"
|
| @@ -842,11 +909,6 @@
|
| (and (match_operand 0 "branch_comparison_operator")
|
| (match_code "eq,lt,gt,ltu,gtu,unordered")))
|
|
|
| -;; Return 1 is OP is a comparison operation that is valid for a trap insn.
|
| -(define_predicate "trap_comparison_operator"
|
| - (and (match_operand 0 "comparison_operator")
|
| - (match_code "eq,ne,le,lt,ge,gt,leu,ltu,geu,gtu")))
|
| -
|
| ;; Return 1 if OP is a load multiple operation, known to be a PARALLEL.
|
| (define_predicate "load_multiple_operation"
|
| (match_code "parallel")
|
|
|