Patchwork [PR,debug/45656] Don't let BB-trailing debug insns break cc0 cse

login
register
mail settings
Submitter Alexandre Oliva
Date Oct. 1, 2010, 10:14 p.m.
Message ID <orzkux36i9.fsf@livre.localdomain>
Download mbox | patch
Permalink /patch/66526/
State New
Headers show

Comments

Alexandre Oliva - Oct. 1, 2010, 10:14 p.m.
The presence of debug insns at the end of a block may change
CC0-specific behavior of cse.  Also, debug insns should be skipped
between CC0 setter and user, rather than reset the cc0 status.  H-P
Nilsson confirms this patch fixes the problem he ran into, and doesn't
introduce regressions on cris-elf.

Also regstrapped (along with other patches) on x86_64-linux-gnu and
i686-pc-linux-gnu.  Useless, I know, no CC0 there ;-)

Ok to install?
Eric Botcazou - Oct. 2, 2010, 9:35 p.m.
> The presence of debug insns at the end of a block may change
> CC0-specific behavior of cse.  Also, debug insns should be skipped
> between CC0 setter and user, rather than reset the cc0 status.

The patch doesn't fully solve the first problem as far as I can see: if BB_END 
happens to be a debug insn, a dangling setter of cc0 in the previous insn 
will be deleted, whereas it might not be if the debug insn is not present.

In other words, why the "insn == BB_END (bb)" in the first condition?

Note that the first part of the second condition is redundant in any cases:

if (!DEBUG_INSN_P (insn) && insn != BB_END (bb))

If the insn isn't BB_END, it's necessarily !DEBUG_INSN_P.

Patch

for  gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	PR debug/45656
	* cse.c (cse_extended_basic_block): Preserve cc0 info across
	debug isnsn.  Skip them when searching for cc0 setter.
	(set_live_p): Skip debug insns when searching for cc0 user.

Index: gcc/cse.c
===================================================================
--- gcc/cse.c.orig	2010-09-21 06:53:10.268422325 -0300
+++ gcc/cse.c	2010-09-21 06:59:33.104422820 -0300
@@ -6348,29 +6348,30 @@  cse_extended_basic_block (struct cse_bas
 		recorded_label_ref = true;
 
 #ifdef HAVE_cc0
-	      /* If the previous insn set CC0 and this insn no longer
-		 references CC0, delete the previous insn.  Here we use
-		 fact that nothing expects CC0 to be valid over an insn,
-		 which is true until the final pass.  */
-	      {
-		rtx prev_insn, tem;
-
-		prev_insn = PREV_INSN (insn);
-		if (prev_insn && NONJUMP_INSN_P (prev_insn)
-		    && (tem = single_set (prev_insn)) != 0
-		    && SET_DEST (tem) == cc0_rtx
-		    && ! reg_mentioned_p (cc0_rtx, PATTERN (insn)))
-		  delete_insn (prev_insn);
-	      }
-
-	      /* If this insn is not the last insn in the basic block,
-		 it will be PREV_INSN(insn) in the next iteration.  If
-		 we recorded any CC0-related information for this insn,
-		 remember it.  */
-	      if (insn != BB_END (bb))
+	      if (!DEBUG_INSN_P (insn) || insn == BB_END (bb))
 		{
-		  prev_insn_cc0 = this_insn_cc0;
-		  prev_insn_cc0_mode = this_insn_cc0_mode;
+		  /* If the previous insn set CC0 and this insn no longer
+		     references CC0, delete the previous insn.  Here we use
+		     fact that nothing expects CC0 to be valid over an insn,
+		     which is true until the final pass.  */
+		  rtx prev_insn, tem;
+
+		  prev_insn = prev_nonnote_nondebug_insn (insn);
+		  if (prev_insn && NONJUMP_INSN_P (prev_insn)
+		      && (tem = single_set (prev_insn)) != NULL_RTX
+		      && SET_DEST (tem) == cc0_rtx
+		      && ! reg_mentioned_p (cc0_rtx, PATTERN (insn)))
+		    delete_insn (prev_insn);
+
+		  /* If this insn is not the last insn in the basic block,
+		     it will be PREV_INSN(insn) in the next iteration.  If
+		     we recorded any CC0-related information for this insn,
+		     remember it.  */
+		  if (!DEBUG_INSN_P (insn) && insn != BB_END (bb))
+		    {
+		      prev_insn_cc0 = this_insn_cc0;
+		      prev_insn_cc0_mode = this_insn_cc0_mode;
+		    }
 		}
 #endif
 	    }
@@ -6713,7 +6714,7 @@  set_live_p (rtx set, rtx insn ATTRIBUTE_
 #ifdef HAVE_cc0
   else if (GET_CODE (SET_DEST (set)) == CC0
 	   && !side_effects_p (SET_SRC (set))
-	   && ((tem = next_nonnote_insn (insn)) == 0
+	   && ((tem = next_nonnote_nondebug_insn (insn)) == NULL_RTX
 	       || !INSN_P (tem)
 	       || !reg_referenced_p (cc0_rtx, PATTERN (tem))))
     return false;