This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[3.3-e500-branch] REG_EQUAL notes on cond_jumps


This patch fixes an incredibly nasty bug I found while running the
Perennial testsuite on powerpc-linux-gnuspe.  A CR is considered live
across function calls, and other code that clearly clobbers it.

I'm surprised this wasn't exhibited earlier through bootstraps, glibc
builds, and test runs.

Anywhooo... Committed to the 3.3-e500 branch.

2004-03-03  Aldy Hernandez  <aldyh@redhat.com>

	Backport:

	2003-05-20  Roger Sayle  <roger@eyesopen.com>
                    Kazu Hirata  <kazu@cs.umass.edu>
		    Joern Rennecke  <joern.rennecke@superh.com>
 
        * gcse.c (cprop_jump):  Make use of REG_EQUAL notes on both
        setcc and jump, if they exist.  If substituted instruction
        fails to validate, store current effort in a REG_EQUAL note.
        (cprop_insn): Don't attempt further substitutions if the
        current instruction has been deleted.
        (local_cprop_pass): Likewise.
 
        * jump.c (redirect_jump):  Also update REG_EQUAL note, if
        one is attached to the jump instruction.
        (invert_jump): Delete REG_EQUAL note on jump, if one exists.

Index: gcse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gcse.c,v
retrieving revision 1.223.2.4.2.1
diff -u -p -r1.223.2.4.2.1 gcse.c
--- gcse.c	4 Sep 2003 22:19:15 -0000	1.223.2.4.2.1
+++ gcse.c	3 Mar 2004 15:30:13 -0000
@@ -4063,28 +4063,42 @@ cprop_jump (bb, setcc, jump, from, src)
      rtx from;
      rtx src;
 {
-  rtx new, new_set;
+  rtx new, set_src, note_src;
   rtx set = pc_set (jump);
+  rtx note = find_reg_equal_equiv_note (jump);
 
-  /* First substitute in the INSN condition as the SET_SRC of the JUMP,
-     then substitute that given values in this expanded JUMP.  */
-  if (setcc != NULL
+  if (note)
+    {
+      note_src = XEXP (note, 0);
+      if (GET_CODE (note_src) == EXPR_LIST)
+	note_src = NULL_RTX;
+    }
+  else note_src = NULL_RTX;
+
+  /* Prefer REG_EQUAL notes except those containing EXPR_LISTs.  */
+  set_src = note_src ? note_src : SET_SRC (set);
+
+  /* First substitute the SETCC condition into the JUMP instruction,
+     then substitute that given values into this expanded JUMP.  */
+  if (setcc != NULL_RTX
       && !modified_between_p (from, setcc, jump)
       && !modified_between_p (src, setcc, jump))
     {
+      rtx setcc_src;
       rtx setcc_set = single_set (setcc);
-      new_set = simplify_replace_rtx (SET_SRC (set),
-				      SET_DEST (setcc_set),
-				      SET_SRC (setcc_set));
+      rtx setcc_note = find_reg_equal_equiv_note (setcc);
+      setcc_src = (setcc_note && GET_CODE (XEXP (setcc_note, 0)) != EXPR_LIST)
+		? XEXP (setcc_note, 0) : SET_SRC (setcc_set);
+      set_src = simplify_replace_rtx (set_src, SET_DEST (setcc_set),
+				      setcc_src);
     }
   else
-    new_set = set;
+    setcc = NULL_RTX;
 
-  new = simplify_replace_rtx (new_set, from, src);
+  new = simplify_replace_rtx (set_src, from, src);
 
-  /* If no simplification can be made, then try the next
-     register.  */
-  if (rtx_equal_p (new, new_set) || rtx_equal_p (new, SET_SRC (set)))
+  /* If no simplification can be made, then try the next register.  */
+  if (rtx_equal_p (new, SET_SRC (set)))
     return 0;
 
   /* If this is now a no-op delete it, otherwise this must be a valid insn.  */
@@ -4094,11 +4108,27 @@ cprop_jump (bb, setcc, jump, from, src)
     {
       /* Ensure the value computed inside the jump insn to be equivalent
          to one computed by setcc.  */
-      if (setcc 
-	  && modified_in_p (new, setcc))
+      if (setcc && modified_in_p (new, setcc))
 	return 0;
       if (! validate_change (jump, &SET_SRC (set), new, 0))
-	return 0;
+	{
+	  /* When (some) constants are not valid in a comparison, and there
+	     are two registers to be replaced by constants before the entire
+	     comparison can be folded into a constant, we need to keep
+	     intermediate information in REG_EQUAL notes.  For targets with
+	     separate compare insns, such notes are added by try_replace_reg.
+	     When we have a combined compare-and-branch instruction, however,
+	     we need to attach a note to the branch itself to make this
+	     optimization work.  */
+
+	  if (!rtx_equal_p (new, note_src))
+	    set_unique_reg_note (jump, REG_EQUAL, copy_rtx (new));
+	  return 0;
+	}
+
+      /* Remove REG_EQUAL note after simplification.  */
+      if (note_src)
+	remove_note (jump, note);
 
       /* If this has turned into an unconditional jump,
 	 then put a barrier after it so that the unreachable
@@ -4235,6 +4265,8 @@ cprop_insn (insn, alter_jumps)
 		  print_rtl (gcse_file, src);
 		  fprintf (gcse_file, "\n");
 		}
+	      if (INSN_DELETED_P (insn))
+		return 1;
 	    }
 	}
       else if (GET_CODE (src) == REG
@@ -4477,6 +4509,8 @@ local_cprop_pass (alter_jumps)
 		    changed = true;
 		    break;
 		  }
+	      if (INSN_DELETED_P (insn))
+		break;
 	    }
 	  while (reg_use_count);
 	}
Index: jump.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/jump.c,v
retrieving revision 1.214.2.5.2.1
diff -u -p -r1.214.2.5.2.1 jump.c
--- jump.c	4 Sep 2003 22:19:16 -0000	1.214.2.5.2.1
+++ jump.c	3 Mar 2004 15:30:14 -0000
@@ -2099,6 +2099,7 @@ redirect_jump (jump, nlabel, delete_unus
      int delete_unused;
 {
   rtx olabel = JUMP_LABEL (jump);
+  rtx note;
 
   if (nlabel == olabel)
     return 1;
@@ -2110,6 +2111,29 @@ redirect_jump (jump, nlabel, delete_unus
   if (nlabel)
     ++LABEL_NUSES (nlabel);
 
+  /* Update labels in any REG_EQUAL note.  */
+  if ((note = find_reg_note (jump, REG_EQUAL, NULL_RTX)) != NULL_RTX)
+    {
+      if (nlabel && olabel)
+	{
+	  rtx dest = XEXP (note, 0);
+
+	  if (GET_CODE (dest) == IF_THEN_ELSE)
+	    {
+	      if (GET_CODE (XEXP (dest, 1)) == LABEL_REF
+		  && XEXP (XEXP (dest, 1), 0) == olabel)
+		XEXP (XEXP (dest, 1), 0) = nlabel;
+	      if (GET_CODE (XEXP (dest, 2)) == LABEL_REF
+		  && XEXP (XEXP (dest, 2), 0) == olabel)
+		XEXP (XEXP (dest, 2), 0) = nlabel;
+	    }
+	  else
+	    remove_note (jump, note);
+	}
+      else
+        remove_note (jump, note);
+    }
+
   /* If we're eliding the jump over exception cleanups at the end of a
      function, move the function end note so that -Wreturn-type works.  */
   if (olabel && nlabel
@@ -2226,6 +2250,11 @@ invert_jump (jump, nlabel, delete_unused
 
   if (redirect_jump (jump, nlabel, delete_unused))
     {
+      /* Remove REG_EQUAL note if we have one.  */
+      rtx note = find_reg_note (jump, REG_EQUAL, NULL_RTX);
+      if (note)
+	remove_note (jump, note);
+
       invert_br_probabilities (jump);
 
       return 1;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]