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]

[PATCH,frv,installed] fix ifcvt error


The FR-V-specific ifcvt code attempts to leave alone insns introduced
while linearizing nested blocks that set a register to a constant,
because they don't have a conditional-execution form.  About a year
ago, I fixed one such error in which we'd let such an instruction in a
THEN block clobber a register the ELSE block needed.

What I didn't realize back then was that it was also possible for the
THEN block to clobber a register that an ELSE block should let through
to the JOIN block, if the previously-conditional block was before an
unconditional set of the register (such that it would look available
within the nested conditional blocks), and that the ELSE block
shouldn't clobber registers that the THEN block could set or let
through.  I've got a bug report from a customer that triggered one of
these cases, so I went ahead and fixed both.  Here's the patch that
I'm checking in, tested on x86_64-linux-x-frv-elf (with another GCC
patch and an assembler patch needed for it to build)

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

	* config/frv/frv.c (frv_ifcvt_modify_insn): Don't leave alone
	scratch insns that set a register live at the join point.

Index: gcc/config/frv/frv.c
===================================================================
RCS file: /cvs/uberbaum/gcc/config/frv/frv.c,v
retrieving revision 1.74
diff -u -p -r1.74 frv.c
--- gcc/config/frv/frv.c 9 Nov 2004 10:13:00 -0000 1.74
+++ gcc/config/frv/frv.c 26 Nov 2004 17:17:12 -0000
@@ -7418,10 +7418,28 @@ frv_ifcvt_modify_insn (ce_if_block_t *ce
       else if (frv_ifcvt.scratch_insns_bitmap
 	       && bitmap_bit_p (frv_ifcvt.scratch_insns_bitmap,
 				INSN_UID (insn))
-	       /* We must not unconditionally set a reg set used as
-		  scratch in the THEN branch if the same reg is live
-		  in the ELSE branch.  */
 	       && REG_P (SET_DEST (set))
+	       /* We must not unconditionally set a scratch reg chosen
+		  for a nested if-converted block if its incoming
+		  value from the TEST block (or the result of the THEN
+		  branch) could/should propagate to the JOIN block.
+		  It suffices to test whether the register is live at
+		  the JOIN point: if it's live there, we can infer
+		  that we set it in the former JOIN block of the
+		  nested if-converted block (otherwise it wouldn't
+		  have been available as a scratch register), and it
+		  is either propagated through or set in the other
+		  conditional block.  It's probably not worth trying
+		  to catch the latter case, and it could actually
+		  limit scheduling of the combined block quite
+		  severely.  */
+	       && ce_info->join_bb
+	       && ! (REGNO_REG_SET_P
+		     (ce_info->join_bb->global_live_at_start,
+		      REGNO (SET_DEST (set))))
+	       /* Similarly, we must not unconditionally set a reg
+		  used as scratch in the THEN branch if the same reg
+		  is live in the ELSE branch.  */
 	       && (! ce_info->else_bb
 		   || BLOCK_FOR_INSN (insn) == ce_info->else_bb
 		   || ! (REGNO_REG_SET_P
-- 
Alexandre Oliva             http://www.ic.unicamp.br/~oliva/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

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