]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/postreload.c
[C++] Protect call to copy_attributes_to_builtin (PR91505)
[thirdparty/gcc.git] / gcc / postreload.c
index 6026e21295aab140c176776252d33e5590a5c043..728aa9b0ed5a18b67ea7f89bd217cd0696d85b7c 100644 (file)
@@ -1,5 +1,5 @@
 /* Perform simple optimizations to clean up the result of reload.
-   Copyright (C) 1987-2017 Free Software Foundation, Inc.
+   Copyright (C) 1987-2019 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -133,6 +133,8 @@ reload_cse_simplify (rtx_insn *insn, rtx testreg)
          for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
            {
              rtx part = XVECEXP (body, 0, i);
+             /* asms can only have full clobbers, not clobber_highs.  */
+             gcc_assert (GET_CODE (part) != CLOBBER_HIGH);
              if (GET_CODE (part) == CLOBBER && REG_P (XEXP (part, 0)))
                cselib_invalidate_rtx (XEXP (part, 0));
            }
@@ -156,6 +158,7 @@ reload_cse_simplify (rtx_insn *insn, rtx testreg)
                }
            }
          else if (GET_CODE (part) != CLOBBER
+                  && GET_CODE (part) != CLOBBER_HIGH
                   && GET_CODE (part) != USE)
            break;
        }
@@ -335,12 +338,8 @@ reload_cse_simplify_set (rtx set, rtx_insn *insn)
              && !REG_P (SET_SRC (set))))
        {
          if (extend_op != UNKNOWN
-#ifdef CANNOT_CHANGE_MODE_CLASS
-             && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SET_DEST (set)),
-                                           word_mode,
-                                           REGNO_REG_CLASS (REGNO (SET_DEST (set))))
-#endif
-             )
+             && REG_CAN_CHANGE_MODE_P (REGNO (SET_DEST (set)),
+                                       GET_MODE (SET_DEST (set)), word_mode))
            {
              rtx wide_dest = gen_rtx_REG (word_mode, REGNO (SET_DEST (set)));
              ORIGINAL_REGNO (wide_dest) = ORIGINAL_REGNO (SET_DEST (set));
@@ -437,15 +436,13 @@ reload_cse_simplify_operands (rtx_insn *insn, rtx testreg)
                   || GET_CODE (SET_SRC (set)) == ZERO_EXTEND
                   || GET_CODE (SET_SRC (set)) == SIGN_EXTEND)
            ; /* Continue ordinary processing.  */
-#ifdef CANNOT_CHANGE_MODE_CLASS
          /* If the register cannot change mode to word_mode, it follows that
             it cannot have been used in word_mode.  */
          else if (REG_P (SET_DEST (set))
-                  && CANNOT_CHANGE_MODE_CLASS (GET_MODE (SET_DEST (set)),
-                                               word_mode,
-                                               REGNO_REG_CLASS (REGNO (SET_DEST (set)))))
+                  && !REG_CAN_CHANGE_MODE_P (REGNO (SET_DEST (set)),
+                                             GET_MODE (SET_DEST (set)),
+                                             word_mode))
            ; /* Continue ordinary processing.  */
-#endif
          /* If this is a straight load, make the extension explicit.  */
          else if (REG_P (SET_DEST (set))
                   && recog_data.n_operands == 2
@@ -673,7 +670,8 @@ struct reg_use
    STORE_RUID is always meaningful if we only want to use a value in a
    register in a different place: it denotes the next insn in the insn
    stream (i.e. the last encountered) that sets or clobbers the register.
-   REAL_STORE_RUID is similar, but clobbers are ignored when updating it.  */
+   REAL_STORE_RUID is similar, but clobbers are ignored when updating it.
+   EXPR is the expression used when storing the register.  */
 static struct
   {
     struct reg_use reg_use[RELOAD_COMBINE_MAX_USES];
@@ -683,6 +681,7 @@ static struct
     int real_store_ruid;
     int use_ruid;
     bool all_offsets_match;
+    rtx expr;
   } reg_state[FIRST_PSEUDO_REGISTER];
 
 /* Reverse linear uid.  This is increased in reload_combine while scanning
@@ -842,7 +841,7 @@ fixup_debug_insns (rtx reg, rtx replacement, rtx_insn *from, rtx_insn *to)
     {
       rtx t;
 
-      if (!DEBUG_INSN_P (insn))
+      if (!DEBUG_BIND_INSN_P (insn))
        continue;
       
       t = INSN_VAR_LOCATION_LOC (insn);
@@ -1163,11 +1162,13 @@ reload_combine_recognize_pattern (rtx_insn *insn)
             value in PREV, the constant loading instruction.  */
          validate_change (prev, &SET_DEST (prev_set), index_reg, 1);
          if (reg_state[regno].offset != const0_rtx)
-           validate_change (prev,
-                            &SET_SRC (prev_set),
-                            GEN_INT (INTVAL (SET_SRC (prev_set))
-                                     + INTVAL (reg_state[regno].offset)),
-                            1);
+           {
+             HOST_WIDE_INT c
+               = trunc_int_for_mode (UINTVAL (SET_SRC (prev_set))
+                                     + UINTVAL (reg_state[regno].offset),
+                                     GET_MODE (index_reg));
+             validate_change (prev, &SET_SRC (prev_set), GEN_INT (c), 1);
+           }
 
          /* Now for every use of REG that we have recorded, replace REG
             with REG_SUM.  */
@@ -1345,6 +1346,10 @@ reload_combine (void)
            {
              rtx setuse = XEXP (link, 0);
              rtx usage_rtx = XEXP (setuse, 0);
+             /* We could support CLOBBER_HIGH and treat it in the same way as
+                HARD_REGNO_CALL_PART_CLOBBERED, but no port needs that yet.  */
+             gcc_assert (GET_CODE (setuse) != CLOBBER_HIGH);
+
              if ((GET_CODE (setuse) == USE || GET_CODE (setuse) == CLOBBER)
                  && REG_P (usage_rtx))
                {
@@ -1520,6 +1525,10 @@ reload_combine_note_use (rtx *xp, rtx_insn *insn, int ruid, rtx containing_mem)
        }
       break;
 
+    case CLOBBER_HIGH:
+      gcc_assert (REG_P (SET_DEST (x)));
+      return;
+
     case PLUS:
       /* We are interested in (plus (reg) (const_int)) .  */
       if (!REG_P (XEXP (x, 0))
@@ -1710,9 +1719,9 @@ move2add_valid_value_p (int regno, scalar_int_mode mode)
         mode after truncation only if (REG:mode regno) is the lowpart of
         (REG:reg_mode[regno] regno).  Now, for big endian, the starting
         regno of the lowpart might be different.  */
-      int s_off = subreg_lowpart_offset (mode, old_mode);
+      poly_int64 s_off = subreg_lowpart_offset (mode, old_mode);
       s_off = subreg_regno_offset (regno, old_mode, s_off, mode);
-      if (s_off != 0)
+      if (maybe_ne (s_off, 0))
        /* We could in principle adjust regno, check reg_mode[regno] to be
           BLKmode, and return s_off to the caller (vs. -1 for failure),
           but we currently have no callers that could make use of this
@@ -2139,6 +2148,9 @@ reload_cse_move2add (rtx_insn *first)
            {
              rtx setuse = XEXP (link, 0);
              rtx usage_rtx = XEXP (setuse, 0);
+             /* CALL_INSN_FUNCTION_USAGEs can only have full clobbers, not
+                clobber_highs.  */
+             gcc_assert (GET_CODE (setuse) != CLOBBER_HIGH);
              if (GET_CODE (setuse) == CLOBBER
                  && REG_P (usage_rtx))
                {
@@ -2301,6 +2313,13 @@ move2add_note_store (rtx dst, const_rtx set, void *data)
 
       move2add_record_mode (dst);
     }
+  else if (GET_CODE (set) == CLOBBER_HIGH)
+    {
+      /* Only invalidate if actually clobbered.  */
+      if (reg_mode[regno] == BLKmode
+         || reg_is_clobbered_by_clobber_high (regno, reg_mode[regno], dst))
+        goto invalidate;
+    }
   else
     {
     invalidate: