summaryrefslogtreecommitdiff
path: root/gcc/config/rs6000/predicates.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/rs6000/predicates.md')
-rw-r--r--gcc/config/rs6000/predicates.md110
1 files changed, 68 insertions, 42 deletions
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index 71fac765e2..41694a51f1 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -572,6 +572,38 @@
}
})
+;; Return 1 if the operand is a CONST_VECTOR or VEC_DUPLICATE of a constant
+;; that can loaded with a XXSPLTIB instruction and then a VUPKHSB, VECSB2W or
+;; VECSB2D instruction.
+
+(define_predicate "xxspltib_constant_split"
+ (match_code "const_vector,vec_duplicate,const_int")
+{
+ int value = 256;
+ int num_insns = -1;
+
+ if (!xxspltib_constant_p (op, mode, &num_insns, &value))
+ return false;
+
+ return num_insns > 1;
+})
+
+
+;; Return 1 if the operand is a CONST_VECTOR that can loaded directly with a
+;; XXSPLTIB instruction.
+
+(define_predicate "xxspltib_constant_nosplit"
+ (match_code "const_vector,vec_duplicate,const_int")
+{
+ int value = 256;
+ int num_insns = -1;
+
+ if (!xxspltib_constant_p (op, mode, &num_insns, &value))
+ return false;
+
+ return num_insns == 1;
+})
+
;; Return 1 if the operand is a CONST_VECTOR and can be loaded into a
;; vector register without using memory.
(define_predicate "easy_vector_constant"
@@ -590,7 +622,14 @@
if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode))
{
- if (zero_constant (op, mode))
+ int value = 256;
+ int num_insns = -1;
+
+ if (zero_constant (op, mode) || all_ones_constant (op, mode))
+ return true;
+
+ if (TARGET_P9_VECTOR
+ && xxspltib_constant_p (op, mode, &num_insns, &value))
return true;
return easy_altivec_constant (op, mode);
@@ -669,6 +708,11 @@
(and (match_code "const_int,const_double,const_wide_int,const_vector")
(match_test "op == CONST0_RTX (mode)")))
+;; Return 1 if operand is constant -1 (scalars and vectors).
+(define_predicate "all_ones_constant"
+ (and (match_code "const_int,const_double,const_wide_int,const_vector")
+ (match_test "op == CONSTM1_RTX (mode) && !FLOAT_MODE_P (mode)")))
+
;; Return 1 if operand is 0.0.
(define_predicate "zero_fp_constant"
(and (match_code "const_double")
@@ -698,48 +742,25 @@
(define_predicate "quad_memory_operand"
(match_code "mem")
{
- rtx addr, op0, op1;
- int ret;
-
if (!TARGET_QUAD_MEMORY && !TARGET_SYNC_TI)
- ret = 0;
-
- else if (!memory_operand (op, mode))
- ret = 0;
-
- else if (GET_MODE_SIZE (GET_MODE (op)) != 16)
- ret = 0;
-
- else if (MEM_ALIGN (op) < 128)
- ret = 0;
-
- else
- {
- addr = XEXP (op, 0);
- if (int_reg_operand (addr, Pmode))
- ret = 1;
+ return false;
- else if (GET_CODE (addr) != PLUS)
- ret = 0;
+ if (GET_MODE_SIZE (mode) != 16 || !MEM_P (op) || MEM_ALIGN (op) < 128)
+ return false;
- else
- {
- op0 = XEXP (addr, 0);
- op1 = XEXP (addr, 1);
- ret = (int_reg_operand (op0, Pmode)
- && GET_CODE (op1) == CONST_INT
- && IN_RANGE (INTVAL (op1), -32768, 32767)
- && (INTVAL (op1) & 15) == 0);
- }
- }
+ return quad_address_p (XEXP (op, 0), mode, false);
+})
- if (TARGET_DEBUG_ADDR)
- {
- fprintf (stderr, "\nquad_memory_operand, ret = %s\n", ret ? "true" : "false");
- debug_rtx (op);
- }
+;; Return 1 if the operand is suitable for load/store to vector registers with
+;; d-form addressing (register+offset), which was added in ISA 3.0.
+;; Unlike quad_memory_operand, we do not have to check for alignment.
+(define_predicate "vsx_quad_dform_memory_operand"
+ (match_code "mem")
+{
+ if (!TARGET_P9_DFORM_VECTOR || !MEM_P (op) || GET_MODE_SIZE (mode) != 16)
+ return false;
- return ret;
+ return quad_address_p (XEXP (op, 0), mode, false);
})
;; Return 1 if the operand is an indexed or indirect memory operand.
@@ -1054,6 +1075,10 @@
mode = V2DFmode;
else if (mode == DImode)
mode = V2DImode;
+ else if (mode == SImode && TARGET_P9_VECTOR)
+ mode = V4SImode;
+ else if (mode == SFmode && TARGET_P9_VECTOR)
+ mode = V4SFmode;
else
gcc_unreachable ();
return memory_address_addr_space_p (mode, XEXP (op, 0),
@@ -1091,10 +1116,6 @@
(define_special_predicate "equality_operator"
(match_code "eq,ne"))
-;; Return true if operand is MIN or MAX operator.
-(define_predicate "min_max_operator"
- (match_code "smin,smax,umin,umax"))
-
;; Return 1 if OP is a comparison operation that is valid for a branch
;; instruction. We check the opcode against the mode of the CC value.
;; validate_condition_mode is an assertion.
@@ -1137,6 +1158,11 @@
(and (match_operand 0 "branch_comparison_operator")
(match_code "ne,le,ge,leu,geu,ordered")))
+;; Return 1 if OP is a comparison operator suitable for vector/scalar
+;; comparisons that generate a -1/0 mask.
+(define_predicate "fpmask_comparison_operator"
+ (match_code "eq,gt,ge"))
+
;; Return 1 if OP is a comparison operation that is valid for a branch
;; insn, which is true if the corresponding bit in the CC register is set.
(define_predicate "branch_positive_comparison_operator"