]> 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 af9ad82dab12f9852e14e1aa305fc35869fdd80b..728aa9b0ed5a18b67ea7f89bd217cd0696d85b7c 100644 (file)
@@ -1,5 +1,5 @@
 /* Perform simple optimizations to clean up the result of reload.
-   Copyright (C) 1987-2018 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;
        }
@@ -667,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];
@@ -677,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
@@ -1157,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.  */
@@ -1339,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))
                {
@@ -1514,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))
@@ -2133,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))
                {
@@ -2295,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: