optabs.c (add_equal_note): Do not create self-referencing REG_EQUAL notes.
authorSteven Bosscher <steven@gcc.gnu.org>
Sun, 2 Dec 2012 15:46:26 +0000 (15:46 +0000)
committerSteven Bosscher <steven@gcc.gnu.org>
Sun, 2 Dec 2012 15:46:26 +0000 (15:46 +0000)
* optabs.c (add_equal_note): Do not create self-referencing REG_EQUAL
notes.
* fwprop.c (forward_propagate_and_simplify): Likewise.

From-SVN: r194054

gcc/ChangeLog
gcc/fwprop.c
gcc/optabs.c

index 4b6c703b8488cd289db6d2169c57eb6eb8eec6ec..bada8f2acd19c8647c1538013438c41f0277b6fc 100644 (file)
@@ -1,3 +1,9 @@
+2012-12-02  Steven Bosscher  <steven@gcc.gnu.org>
+
+       * optabs.c (add_equal_note): Do not create self-referencing REG_EQUAL
+       notes.
+       * fwprop.c (forward_propagate_and_simplify): Likewise.
+
 2012-12-02  Steven Bosscher  <steven@gcc.gnu.org>
 
        * function.h (struct rtl_data): Remove epilogue_delay_list.
index 0f2ee49ac144772cba9a7b933feed63c43249d50..35c82d7ed7f1694ea5a5af74a9ee8c3a45c6ccf4 100644 (file)
@@ -1315,9 +1315,12 @@ forward_propagate_and_simplify (df_ref use, rtx def_insn, rtx def_set)
       /* Do not replace an existing REG_EQUAL note if the insn is not
         recognized.  Either we're already replacing in the note, or we'll
         separately try plugging the definition in the note and simplifying.
-        And only install a REQ_EQUAL note when the destination is a REG,
-        as the note would be invalid otherwise.  */
-      set_reg_equal = (note == NULL_RTX && REG_P (SET_DEST (use_set)));
+        And only install a REQ_EQUAL note when the destination is a REG
+        that isn't mentioned in USE_SET, as the note would be invalid
+        otherwise.  */
+      set_reg_equal = (note == NULL_RTX && REG_P (SET_DEST (use_set))
+                      && ! reg_mentioned_p (SET_DEST (use_set),
+                                            SET_SRC (use_set)));
     }
 
   if (GET_MODE (*loc) == VOIDmode)
index 353727f332488faad7d0ea29d374b1d92d36f590..d59a1eae3c199f74f81d3513618e1fe3382005e0 100644 (file)
@@ -170,14 +170,14 @@ optab_libfunc (optab optab, enum machine_mode mode)
 
    If the last insn does not set TARGET, don't do anything, but return 1.
 
-   If a previous insn sets TARGET and TARGET is one of OP0 or OP1,
-   don't add the REG_EQUAL note but return 0.  Our caller can then try
-   again, ensuring that TARGET is not one of the operands.  */
+   If the last insn or a previous insn sets TARGET and TARGET is one of OP0
+   or OP1, don't add the REG_EQUAL note but return 0.  Our caller can then
+   try again, ensuring that TARGET is not one of the operands.  */
 
 static int
 add_equal_note (rtx insns, rtx target, enum rtx_code code, rtx op0, rtx op1)
 {
-  rtx last_insn, insn, set;
+  rtx last_insn, set;
   rtx note;
 
   gcc_assert (insns && INSN_P (insns) && NEXT_INSN (insns));
@@ -192,6 +192,12 @@ add_equal_note (rtx insns, rtx target, enum rtx_code code, rtx op0, rtx op1)
   if (GET_CODE (target) == ZERO_EXTRACT)
     return 1;
 
+  /* If TARGET is in OP0 or OP1, punt.  We'd end up with a note referencing
+     a value changing in the insn, so the note would be invalid for CSE.  */
+  if (reg_overlap_mentioned_p (target, op0)
+      || (op1 && reg_overlap_mentioned_p (target, op1)))
+    return 0;
+
   for (last_insn = insns;
        NEXT_INSN (last_insn) != NULL_RTX;
        last_insn = NEXT_INSN (last_insn))
@@ -207,21 +213,6 @@ add_equal_note (rtx insns, rtx target, enum rtx_code code, rtx op0, rtx op1)
          || ! rtx_equal_p (XEXP (SET_DEST (set), 0), target)))
     return 1;
 
-  /* If TARGET is in OP0 or OP1, check if anything in SEQ sets TARGET
-     besides the last insn.  */
-  if (reg_overlap_mentioned_p (target, op0)
-      || (op1 && reg_overlap_mentioned_p (target, op1)))
-    {
-      insn = PREV_INSN (last_insn);
-      while (insn != NULL_RTX)
-       {
-         if (reg_set_p (target, insn))
-           return 0;
-
-         insn = PREV_INSN (insn);
-       }
-    }
-
   if (GET_RTX_CLASS (code) == RTX_UNARY)
     switch (code)
       {