]> 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 4d3fd97a1e241df6ef407fe89eb4fca11e34732d..8b8043daa5140e2e707193609bcfce794398df6f 100644 (file)
@@ -1,5 +1,5 @@
 ;; Predicate definitions for S/390 and zSeries.
-;; Copyright (C) 2005-2015 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).
 ;;
 
 ;; operands --------------------------------------------------------------
 
-;; Return true if OP a (const_int 0) operand.
-
+;; Return true if OP a const 0 operand (int/float/vector).
 (define_predicate "const0_operand"
-  (and (match_code "const_int, const_double")
+  (and (match_code "const_int,const_wide_int,const_double,const_vector")
        (match_test "op == CONST0_RTX (mode)")))
 
+;; Return true if OP an all ones operand (int/vector).
+(define_predicate "all_ones_operand"
+  (and (match_code "const_int, const_wide_int, const_vector")
+       (match_test "INTEGRAL_MODE_P (GET_MODE (op))")
+       (match_test "op == CONSTM1_RTX (mode)")))
+
+;; Return true if OP is a 4 bit mask operand
+(define_predicate "const_mask_operand"
+  (and (match_code "const_int")
+       (match_test "UINTVAL (op) < 16")))
+
 ;; Return true if OP is constant.
 
 (define_special_predicate "consttable_operand"
-  (and (match_code "symbol_ref, label_ref, const, const_int, const_double")
+  (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.
 
        (and (match_test "mode == Pmode")
            (match_test "!legitimate_la_operand_p (op)"))))
 
-;; Return true if OP is a valid operand as shift count or setmem.
+;; Return true if OP is a valid operand as scalar shift count or setmem.
 
-(define_predicate "shift_count_or_setmem_operand"
+(define_predicate "setmem_operand"
   (match_code "reg, subreg, plus, const_int")
 {
   HOST_WIDE_INT offset;
   rtx base;
 
+  if (GET_MODE (op) != VOIDmode
+      && GET_MODE_CLASS (GET_MODE (op)) != MODE_INT)
+    return false;
+
   /* Extract base register and offset.  */
-  if (!s390_decompose_shift_count (op, &base, &offset))
+  if (!s390_decompose_addrstyle_without_index (op, &base, &offset))
     return false;
 
   /* Don't allow any non-base hard registers.  Doing so without
   return true;
 })
 
+; An integer operand with the lowest order 6 bits all ones.
+(define_predicate "const_int_6bitset_operand"
+ (and (match_code "const_int")
+      (match_test "(INTVAL (op) & 63) == 63")))
 (define_predicate "nonzero_shift_count_operand"
   (and (match_code "const_int")
        (match_test "IN_RANGE (INTVAL (op), 1, GET_MODE_BITSIZE (mode) - 1)")))
 ;;  Return true if OP a valid operand for the LARL instruction.
 
 (define_predicate "larl_operand"
-  (match_code "label_ref, symbol_ref, const, const_int, const_double")
+  (match_code "label_ref, symbol_ref, const")
 {
   /* Allow labels and local symbols.  */
   if (GET_CODE (op) == LABEL_REF)
     return true;
-  if (GET_CODE (op) == SYMBOL_REF)
-    return (!SYMBOL_REF_ALIGN1_P (op)
+  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)
-    return ((SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_ALIGN1) == 0
+  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.  */
   return false;
 })
 
+; Predicate that always allows wraparound of the one-bit range.
 (define_predicate "contiguous_bitmask_operand"
   (match_code "const_int")
 {
-  return s390_contiguous_bitmask_p (INTVAL (op), GET_MODE_BITSIZE (mode), NULL, NULL);
+  return s390_contiguous_bitmask_p (INTVAL (op), true,
+                                    GET_MODE_BITSIZE (mode), NULL, NULL);
 })
 
+; Same without wraparound.
+(define_predicate "contiguous_bitmask_nowrap_operand"
+  (match_code "const_int")
+{
+  return s390_contiguous_bitmask_p
+    (INTVAL (op), false, GET_MODE_BITSIZE (mode), NULL, NULL);
+})
+
+;; 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")))