]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/config/s390/predicates.md
Update copyright years.
[thirdparty/gcc.git] / gcc / config / s390 / predicates.md
index bbff8d856c23bc0101beb80a73c3ab3d5a4ed3b1..8b8043daa5140e2e707193609bcfce794398df6f 100644 (file)
@@ -1,5 +1,5 @@
 ;; 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")))