;; Predicate definitions for S/390 and zSeries.
-;; Copyright (C) 2005-2017 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.
(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")
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")))