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 debug-insn sensitivity in RA


While doing some work on wide-int, I hit a bootstrap comparison failure that
was caused by the RA output depending on debug insns.  There was a register R
that was used normally by all "real" insns, but which was used in a paradoxical
subreg by one of the debug insns.  There was also a natural equivalence
between R and a memory.  The problem was that the paradoxical subreg in
the debug insn was stopping that equivalence from being used.

The problem seems to be split across IRA and LRA.  In IRA we have:

  FOR_EACH_BB (bb)
    FOR_BB_INSNS (bb, insn)
      {
	if (! INSN_P (insn))
	  continue;
	for_each_rtx (&insn, set_paradoxical_subreg, (void *)pdx_subregs);
      }

which sets pdx_subregs[R] if R is used in a paradoxical subreg, followed by:

	  /* Don't set reg (if pdx_subregs[regno] == true) equivalent to a mem.  */
	  if (MEM_P (src) && pdx_subregs[regno])
	    {
	      note_stores (set, no_equiv, NULL);
	      continue;
	    }

I think this should only happen when a paradoxical subreg is seen
in a nondebug insn.  If we use the equivalence when a debug insn has
a paradoxical subreg, the subreg will be replaced with a MEM that might
overlap surrounding data, but I think it's a valid transformation when
no run-time access will take place.  The data in the defined part of
the MEM should still be correct.

Then in LRA we keep track of the biggest mode that is used to refer to each
register (including references via paradoxical subregs).  This is done when
recording register references in an instruction:

static struct lra_insn_reg *
new_insn_reg (int regno, enum op_type type, enum machine_mode mode,
	      bool subreg_p, bool early_clobber, struct lra_insn_reg *next)
{
  struct lra_insn_reg *ir;

  ir = (struct lra_insn_reg *) pool_alloc (insn_reg_pool);
  ir->type = type;
  ir->biggest_mode = mode;
  if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (lra_reg_info[regno].biggest_mode))
    lra_reg_info[regno].biggest_mode = mode;

This then affects allocation decisions in several places.  Here too I think
we need to guard for nondebug insns, although we still need to record
register references for debug insns.

This of course means that when substituting the allocation into the debug
insns, we have to cope with paradoxical subregs that are wider than the
largest recorded mode.  I don't think that's a new requirement though,
since we needed the same thing for reload.  AFAIK the existing code
should already handle it.

The patch below fixes the wide-int problem for me.  Bootstrapped &
regression-tested on trunk for x86_64-linux-gnu.  OK to install?

Thanks,
Richard


gcc/
	* ira.c (update_equiv_regs): Only call set_paradoxical_subreg
	for non-debug insns.
	* lra.c (new_insn_reg): Take the containing insn as a parameter.
	Only modify lra_reg_info[].biggest_mode if it's non-debug insn.
	(collect_non_operand_hard_regs, add_regs_to_insn_regno_info): Update
	accordingly.

Index: gcc/ira.c
===================================================================
--- gcc/ira.c	2013-09-01 12:39:40.739835911 +0100
+++ gcc/ira.c	2013-09-07 09:42:34.993934881 +0100
@@ -2944,11 +2944,8 @@ update_equiv_regs (void)
      prevent access beyond allocated memory for paradoxical memory subreg.  */
   FOR_EACH_BB (bb)
     FOR_BB_INSNS (bb, insn)
-      {
-	if (! INSN_P (insn))
-	  continue;
-	for_each_rtx (&insn, set_paradoxical_subreg, (void *)pdx_subregs);
-      }
+      if (NONDEBUG_INSN_P (insn))
+	for_each_rtx (&insn, set_paradoxical_subreg, (void *) pdx_subregs);
 
   /* Scan the insns and find which registers have equivalences.  Do this
      in a separate scan of the insns because (due to -fcse-follow-jumps)
Index: gcc/lra.c
===================================================================
--- gcc/lra.c	2013-07-17 08:36:09.260013240 +0100
+++ gcc/lra.c	2013-09-07 09:42:35.004934955 +0100
@@ -480,13 +480,13 @@ init_insn_regs (void)
     = create_alloc_pool ("insn regs", sizeof (struct lra_insn_reg), 100);
 }
 
-/* Create LRA insn related info about referenced REGNO with TYPE
-   (in/out/inout), biggest reference mode MODE, flag that it is
+/* Create LRA insn related info about a reference to REGNO in INSN with
+   TYPE (in/out/inout), biggest reference mode MODE, flag that it is
    reference through subreg (SUBREG_P), flag that is early clobbered
    in the insn (EARLY_CLOBBER), and reference to the next insn reg
    info (NEXT).	 */
 static struct lra_insn_reg *
-new_insn_reg (int regno, enum op_type type, enum machine_mode mode,
+new_insn_reg (rtx insn, int regno, enum op_type type, enum machine_mode mode,
 	      bool subreg_p, bool early_clobber, struct lra_insn_reg *next)
 {
   struct lra_insn_reg *ir;
@@ -494,7 +494,8 @@ new_insn_reg (int regno, enum op_type ty
   ir = (struct lra_insn_reg *) pool_alloc (insn_reg_pool);
   ir->type = type;
   ir->biggest_mode = mode;
-  if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (lra_reg_info[regno].biggest_mode))
+  if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (lra_reg_info[regno].biggest_mode)
+      && NONDEBUG_INSN_P (insn))
     lra_reg_info[regno].biggest_mode = mode;
   ir->subreg_p = subreg_p;
   ir->early_clobber = early_clobber;
@@ -976,7 +977,7 @@ collect_non_operand_hard_regs (rtx *x, l
 		     && ! (FIRST_STACK_REG <= regno
 			   && regno <= LAST_STACK_REG));
 #endif
-		list = new_insn_reg (regno, type, mode, subreg_p,
+		list = new_insn_reg (data->insn, regno, type, mode, subreg_p,
 				     early_clobber, list);
 	      }
 	  }
@@ -1575,7 +1576,7 @@ add_regs_to_insn_regno_info (lra_insn_re
       expand_reg_info ();
       if (bitmap_set_bit (&lra_reg_info[regno].insn_bitmap, uid))
 	{
-	  data->regs = new_insn_reg (regno, type, mode, subreg_p,
+	  data->regs = new_insn_reg (data->insn, regno, type, mode, subreg_p,
 				     early_clobber, data->regs);
 	  return;
 	}
@@ -1587,8 +1588,9 @@ add_regs_to_insn_regno_info (lra_insn_re
 		if (curr->subreg_p != subreg_p || curr->biggest_mode != mode)
 		  /* The info can not be integrated into the found
 		     structure.  */
-		  data->regs = new_insn_reg (regno, type, mode, subreg_p,
-					     early_clobber, data->regs);
+		  data->regs = new_insn_reg (data->insn, regno, type, mode,
+					     subreg_p, early_clobber,
+					     data->regs);
 		else
 		  {
 		    if (curr->type != type)


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