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]

RFA: fix execute/20010119-1.c failures on sh-elf


-- 
--------------------------
SuperH (UK) Ltd.
2410 Aztec West / Almondsbury / BRISTOL / BS32 4QX
T:+44 1454 465658
reg/v:SI 159 is an inline-function argument that is set to the
constant 10.  __builtin_constant_p on it is evaluated to 1 by
gcse, yet a comparison of it against 20000 is not evaluated.

cprop_jump considers only one constant at a time, but the instruction
that sets the condition is:

(insn 29 28 30 2 0x401d58f0 (set (reg:SI 147 t)
        (gt:SI (reg/v:SI 159 [ a ])
            (reg:SI 164))) 2 {cmpgtsi_t} (nil)
    (expr_list:REG_EQUAL (gt:SI (reg/v:SI 159 [ a ])
            (const_int 20000 [0x4e20]))
        (nil)))

By substituting only one constant at a time into the instruction
pattern, we always end up with one remaining register, and the
substitution fails - this is not even dependent on whether we
would accept constants in the comparison pattern during gcse,
as the modified_in_p test fails when it sees PC.

By trying a REG_EQUAL note too if the substitution failed with the
pattern of setcc, we succeed when replacing reg/v:SI 159.

Because the indentation changes make it hard to see what I've actually
changed, I've appended a diff -puw as well as the ordinary diff -p.

2003-05-16  J"orn Rennecke <joern.rennecke@superh.com>

	* gcse.c (cprop_jump): If substitution fails using the pattern
	of SETCC, try to use a REG_EQUAL / REG_EQUIV note.

Index: gcse.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/gcse.c,v
retrieving revision 1.248
diff -p -r1.248 gcse.c
*** gcse.c	25 Apr 2003 00:58:27 -0000	1.248
--- gcse.c	16 May 2003 15:41:18 -0000
*************** cprop_jump (bb, setcc, jump, from, src)
*** 4090,4096 ****
--- 4090,4098 ----
       rtx src;
  {
    rtx new, new_set;
+   rtx new_set2 = 0;
    rtx set = pc_set (jump);
+   rtx setcc_set;
  
    /* First substitute in the INSN condition as the SET_SRC of the JUMP,
       then substitute that given values in this expanded JUMP.  */
*************** cprop_jump (bb, setcc, jump, from, src)
*** 4098,4158 ****
        && !modified_between_p (from, setcc, jump)
        && !modified_between_p (src, setcc, jump))
      {
!       rtx setcc_set = single_set (setcc);
        new_set = simplify_replace_rtx (SET_SRC (set),
  				      SET_DEST (setcc_set),
  				      SET_SRC (setcc_set));
      }
    else
      new_set = set;
  
!   new = simplify_replace_rtx (new_set, 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)))
!     return 0;
! 
!   /* If this is now a no-op delete it, otherwise this must be a valid insn.  */
!   if (new == pc_rtx)
!     delete_insn (jump);
!   else
      {
!       /* Ensure the value computed inside the jump insn to be equivalent
!          to one computed by setcc.  */
!       if (setcc 
! 	  && modified_in_p (new, setcc))
! 	return 0;
!       if (! validate_change (jump, &SET_SRC (set), new, 0))
! 	return 0;
! 
!       /* If this has turned into an unconditional jump,
! 	 then put a barrier after it so that the unreachable
! 	 code will be deleted.  */
!       if (GET_CODE (SET_SRC (set)) == LABEL_REF)
! 	emit_barrier_after (jump);
!      }
  
  #ifdef HAVE_cc0
!   /* Delete the cc0 setter.  */
!   if (setcc != NULL && CC0_P (SET_DEST (single_set (setcc))))
!     delete_insn (setcc);
  #endif
  
!   run_jump_opt_after_gcse = 1;
! 
!   const_prop_count++;
!   if (gcse_file != NULL)
!     {
!       fprintf (gcse_file,
! 	       "CONST-PROP: Replacing reg %d in jump_insn %d with constant ",
! 	       REGNO (from), INSN_UID (jump));
!       print_rtl (gcse_file, src);
!       fprintf (gcse_file, "\n");
!     }
!   purge_dead_edges (bb);
  
!   return 1;
  }
  
  static bool
--- 4100,4178 ----
        && !modified_between_p (from, setcc, jump)
        && !modified_between_p (src, setcc, jump))
      {
!       rtx note;
!       setcc_set = single_set (setcc);
        new_set = simplify_replace_rtx (SET_SRC (set),
  				      SET_DEST (setcc_set),
  				      SET_SRC (setcc_set));
+       note = find_reg_equal_equiv_note (setcc);
+       if (note != 0)
+ 	{
+ 	  new_set2 = simplify_replace_rtx (SET_SRC (set),
+ 					   SET_DEST (setcc_set),
+ 					   XEXP (note, 0));
+ 	  if (rtx_equal_p (new_set2, new_set))
+ 	    new_set2 = 0;
+ 	}
      }
    else
      new_set = set;
  
!   /* First, try to use a substitution based on the pattern of SETCC_SET,
!      i.e. using NEW_SET.  If that fails, try a substitution based on
!      a reg note of setcc, i.e. using NEW_SET2.  */
!   do
      {
!       new = simplify_replace_rtx (new_set, 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)))
! 	continue;
! 
!       /* If this is now a no-op delete it, otherwise this must be a valid
!          insn.  */
!       if (new == pc_rtx)
! 	delete_insn (jump);
!       else
! 	{
! 	  /* Ensure the value computed inside the jump insn to be equivalent
! 	     to one computed by setcc.  */
! 	  if (setcc 
! 	      && modified_in_p (new, setcc))
! 	    continue;
! 	  if (! validate_change (jump, &SET_SRC (set), new, 0))
! 	    continue;
! 
! 	  /* If this has turned into an unconditional jump,
! 	     then put a barrier after it so that the unreachable
! 	     code will be deleted.  */
! 	  if (GET_CODE (SET_SRC (set)) == LABEL_REF)
! 	    emit_barrier_after (jump);
! 	 }
  
  #ifdef HAVE_cc0
!       /* Delete the cc0 setter.  */
!       if (setcc != NULL && CC0_P (SET_DEST (single_set (setcc))))
! 	delete_insn (setcc);
  #endif
  
!       run_jump_opt_after_gcse = 1;
  
!       const_prop_count++;
!       if (gcse_file != NULL)
! 	{
! 	  fprintf (gcse_file,
! 		   "CONST-PROP: Replacing reg %d in jump_insn %d with constant ",
! 		   REGNO (from), INSN_UID (jump));
! 	  print_rtl (gcse_file, src);
! 	  fprintf (gcse_file, "\n");
! 	}
!       purge_dead_edges (bb);
! 
!       return 1;
!     } while (new_set != new_set2 && (new_set = new_set2));
!   return 0;
  }
  
  static bool
Index: gcse.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/gcse.c,v
retrieving revision 1.248
diff -p -u -w -r1.248 gcse.c
--- gcse.c	25 Apr 2003 00:58:27 -0000	1.248
+++ gcse.c	16 May 2003 15:48:59 -0000
@@ -4090,7 +4090,9 @@ cprop_jump (bb, setcc, jump, from, src)
      rtx src;
 {
   rtx new, new_set;
+  rtx new_set2 = 0;
   rtx set = pc_set (jump);
+  rtx setcc_set;
 
   /* First substitute in the INSN condition as the SET_SRC of the JUMP,
      then substitute that given values in this expanded JUMP.  */
@@ -4098,22 +4100,38 @@ cprop_jump (bb, setcc, jump, from, src)
       && !modified_between_p (from, setcc, jump)
       && !modified_between_p (src, setcc, jump))
     {
-      rtx setcc_set = single_set (setcc);
+      rtx note;
+      setcc_set = single_set (setcc);
       new_set = simplify_replace_rtx (SET_SRC (set),
 				      SET_DEST (setcc_set),
 				      SET_SRC (setcc_set));
+      note = find_reg_equal_equiv_note (setcc);
+      if (note != 0)
+	{
+	  new_set2 = simplify_replace_rtx (SET_SRC (set),
+					   SET_DEST (setcc_set),
+					   XEXP (note, 0));
+	  if (rtx_equal_p (new_set2, new_set))
+	    new_set2 = 0;
+	}
     }
   else
     new_set = set;
 
+  /* First, try to use a substitution based on the pattern of SETCC_SET,
+     i.e. using NEW_SET.  If that fails, try a substitution based on
+     a reg note of setcc, i.e. using NEW_SET2.  */
+  do
+    {
   new = simplify_replace_rtx (new_set, 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)))
-    return 0;
+	continue;
 
-  /* If this is now a no-op delete it, otherwise this must be a valid insn.  */
+      /* If this is now a no-op delete it, otherwise this must be a valid
+         insn.  */
   if (new == pc_rtx)
     delete_insn (jump);
   else
@@ -4122,9 +4140,9 @@ cprop_jump (bb, setcc, jump, from, src)
          to one computed by setcc.  */
       if (setcc 
 	  && modified_in_p (new, setcc))
-	return 0;
+	    continue;
       if (! validate_change (jump, &SET_SRC (set), new, 0))
-	return 0;
+	    continue;
 
       /* If this has turned into an unconditional jump,
 	 then put a barrier after it so that the unreachable
@@ -4153,6 +4171,8 @@ cprop_jump (bb, setcc, jump, from, src)
   purge_dead_edges (bb);
 
   return 1;
+    } while (new_set != new_set2 && (new_set = new_set2));
+  return 0;
 }
 
 static bool

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