;; Predicate definitions for S/390 and zSeries.
-;; Copyright (C) 2005-2016 Free Software Foundation, Inc.
+;; Copyright (C) 2005-2020 Free Software Foundation, Inc.
;; Contributed by Hartmut Penner (hpenner@de.ibm.com) and
;; Ulrich Weigand (uweigand@de.ibm.com).
;;
(and (match_code "symbol_ref, label_ref, const, const_int, const_wide_int, const_double, const_vector")
(match_test "CONSTANT_P (op)")))
+; An operand used as vector permutation pattern
+
+; This in particular accepts constants which would otherwise be
+; rejected. These constants require special post reload handling
+
+(define_special_predicate "permute_pattern_operand"
+ (and (match_code "const_vector,mem,reg,subreg")
+ (match_test "GET_MODE (op) == V16QImode")
+ (match_test "!MEM_P (op) || s390_mem_constraint (\"R\", op)")))
+
;; Return true if OP is a valid S-type operand.
(define_predicate "s_operand"
return true;
})
+;; Return true of the address of the mem operand plus 16 is still a
+;; valid Q constraint address.
+
+(define_predicate "plus16_Q_operand"
+ (and (match_code "mem")
+ (match_operand 0 "general_operand"))
+{
+ rtx addr = XEXP (op, 0);
+ if (REG_P (addr))
+ return true;
+
+ if (GET_CODE (addr) != PLUS
+ || !REG_P (XEXP (addr, 0))
+ || !CONST_INT_P (XEXP (addr, 1)))
+ return false;
+
+ return SHORT_DISP_IN_RANGE (INTVAL (XEXP (addr, 1)) + 16);
+})
+
;; Return true if OP is a valid operand for the BRAS instruction.
;; Allow SYMBOL_REFs and @PLT stubs.
/* Allow labels and local symbols. */
if (GET_CODE (op) == LABEL_REF)
return true;
- if (GET_CODE (op) == SYMBOL_REF)
+ if (SYMBOL_REF_P (op))
return (!SYMBOL_FLAG_NOTALIGN2_P (op)
&& SYMBOL_REF_TLS_MODEL (op) == 0
- && (!flag_pic || SYMBOL_REF_LOCAL_P (op)));
+ && s390_rel_address_ok_p (op));
/* Everything else must have a CONST, so strip it. */
if (GET_CODE (op) != CONST)
if (GET_CODE (XEXP (op, 1)) != CONST_INT
|| (INTVAL (XEXP (op, 1)) & 1) != 0)
return false;
- if (INTVAL (XEXP (op, 1)) >= (HOST_WIDE_INT)1 << 31
- || INTVAL (XEXP (op, 1)) < -((HOST_WIDE_INT)1 << 31))
+ if (INTVAL (XEXP (op, 1)) >= HOST_WIDE_INT_1 << 31
+ || INTVAL (XEXP (op, 1)) < -(HOST_WIDE_INT_1 << 31))
return false;
op = XEXP (op, 0);
}
/* Labels and local symbols allowed here as well. */
if (GET_CODE (op) == LABEL_REF)
return true;
- if (GET_CODE (op) == SYMBOL_REF)
+ if (SYMBOL_REF_P (op))
return (!SYMBOL_FLAG_NOTALIGN2_P (op)
&& SYMBOL_REF_TLS_MODEL (op) == 0
- && (!flag_pic || SYMBOL_REF_LOCAL_P (op)));
+ && s390_rel_address_ok_p (op));
+
/* Now we must have a @GOTENT offset or @PLT stub
or an @INDNTPOFF TLS offset. */
(INTVAL (op), false, GET_MODE_BITSIZE (mode), NULL, NULL);
})
-;; Return true if OP is ligitimate for any LOC instruction.
+;; Return true if OP is legitimate for any LOC instruction.
(define_predicate "loc_operand"
(ior (match_operand 0 "nonimmediate_operand")
(and (match_code "const_int")
(match_test "INTVAL (op) <= 32767 && INTVAL (op) >= -32768"))))
+(define_predicate "reload_const_wide_int_operand"
+ (and (match_code "const_wide_int")
+ (match_test "legitimate_reload_constant_p (op)")))
+
+
;; operators --------------------------------------------------------------
;; Return nonzero if OP is a valid comparison operator
switch (GET_MODE (XEXP (op, 0)))
{
- case CCL1mode:
+ case E_CCL1mode:
return GET_CODE (op) == LTU;
- case CCL2mode:
+ case E_CCL2mode:
return GET_CODE (op) == LEU;
- case CCL3mode:
+ case E_CCL3mode:
return GET_CODE (op) == GEU;
- case CCUmode:
+ case E_CCUmode:
return GET_CODE (op) == GTU;
- case CCURmode:
+ case E_CCURmode:
return GET_CODE (op) == LTU;
- case CCSmode:
+ case E_CCSmode:
return GET_CODE (op) == UNGT;
- case CCSRmode:
+ case E_CCSRmode:
return GET_CODE (op) == UNLT;
default:
switch (GET_MODE (XEXP (op, 0)))
{
- case CCL1mode:
+ case E_CCL1mode:
return GET_CODE (op) == GEU;
- case CCL2mode:
+ case E_CCL2mode:
return GET_CODE (op) == GTU;
- case CCL3mode:
+ case E_CCL3mode:
return GET_CODE (op) == LTU;
- case CCUmode:
+ case E_CCUmode:
return GET_CODE (op) == LEU;
- case CCURmode:
+ case E_CCURmode:
return GET_CODE (op) == GEU;
- case CCSmode:
+ case E_CCSmode:
return GET_CODE (op) == LE;
- case CCSRmode:
+ case E_CCSRmode:
return GET_CODE (op) == GE;
default:
}
return true;
})
+
+(define_predicate "const_shift_by_byte_operand"
+ (match_code "const_int")
+{
+ unsigned HOST_WIDE_INT val = INTVAL (op);
+ return val <= 128 && val % 8 == 0;
+})
+
+;; Certain operations (e.g. CS) cannot access SYMBOL_REF directly, it needs to
+;; be loaded into some register first. In theory, if we put a SYMBOL_REF into
+;; a corresponding insn anyway, reload will generate a load for it, but, when
+;; coupled with constant propagation, this will lead to an inefficient code
+;; (see PR 80080).
+
+(define_predicate "nonsym_memory_operand"
+ (match_code "mem")
+{
+ return memory_operand (op, mode) && !contains_symbol_ref_p (op);
+})
+
+;; Check for a valid shift count operand with an implicit
+;; shift truncation mask of 63.
+
+(define_predicate "shift_count_operand"
+ (and (match_code "reg, subreg, and, plus, const_int")
+ (match_test "CONST_INT_P (op) || GET_MODE (op) == E_QImode"))
+{
+ return s390_valid_shift_count (op, 63);
+}
+)
+
+;; This is used as operand predicate. As we do not know
+;; the mode of the first operand here and the shift truncation
+;; mask depends on the mode, we cannot check the mask.
+;; This is supposed to happen in the insn condition which
+;; calls s390_valid_shift_count with the proper mode size.
+;; We need two separate predicates for non-vector and vector
+;; shifts since the (less restrictive) insn condition is checked
+;; after the more restrictive operand predicate which will
+;; disallow the operand before we can check the condition.
+
+(define_predicate "shift_count_operand_vec"
+ (and (match_code "reg, subreg, and, plus, const_int")
+ (match_test "CONST_INT_P (op) || GET_MODE (op) == E_QImode"))
+{
+ return s390_valid_shift_count (op, 0);
+}
+)
+
+; An integer constant which can be used in a signed add with overflow
+; pattern without being reloaded.
+(define_predicate "addv_const_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) >= -32768 && INTVAL (op) <= 32767")))