We ran across problems with the regrename pass introducing invalid insns while working on support for new load/store multiple instructions on nios2. We're using an implementation similar to what ARM already does, with a match_parallel predicate testing for restrictions on the underlying machine instructions that can't be expressed using GCC register constraints. (E.g., the register numbers do not have to be sequential, but they do have to be ascending/descending and a combination that can be encoded in the machine instruction.)

The attached patch teaches regrename to validate insns affected by each register renaming before making the change. I can see at least two other ways to handle this -- earlier, by rejecting renamings that result in invalid instructions when it's searching for the best renaming; or later, by validating the entire set of renamings as a group instead of incrementally for each one -- but doing it all in regname_do_replace seems least disruptive and risky in terms of the existing code.

There are a couple of old bugzilla tickets for instruction-doesn't-satisfy-its-constraints ICEs in regrename that might or might not be related to this. The symptom we saw was not an ICE, just bad code being emitted that resulted in assembler errors.

I've bootstrapped and regression-tested this on x86_64-linux-gnu in addition to our testing with the pending nios2 patch set. OK to commit?

-Sandra

2015-06-17  Chung-Lin Tang <clt...@codesourcery.com>
	    Sandra Loosemore <san...@codesourcery.com>

	gcc/
	* regrename.c (regrename_do_replace): Re-validate the modified
	insns.
Index: gcc/regrename.c
===================================================================
--- gcc/regrename.c	(revision 224532)
+++ gcc/regrename.c	(working copy)
@@ -942,19 +942,22 @@ regrename_do_replace (struct du_head *he
       int reg_ptr = REG_POINTER (*chain->loc);
 
       if (DEBUG_INSN_P (chain->insn) && REGNO (*chain->loc) != base_regno)
-	INSN_VAR_LOCATION_LOC (chain->insn) = gen_rtx_UNKNOWN_VAR_LOC ();
+	validate_change (chain->insn, &(INSN_VAR_LOCATION_LOC (chain->insn)),
+			 gen_rtx_UNKNOWN_VAR_LOC (), true);
       else
 	{
-	  *chain->loc = gen_raw_REG (GET_MODE (*chain->loc), reg);
+	  validate_change (chain->insn, chain->loc, 
+			   gen_raw_REG (GET_MODE (*chain->loc), reg), true);
 	  if (regno >= FIRST_PSEUDO_REGISTER)
 	    ORIGINAL_REGNO (*chain->loc) = regno;
 	  REG_ATTRS (*chain->loc) = attr;
 	  REG_POINTER (*chain->loc) = reg_ptr;
 	}
-
-      df_insn_rescan (chain->insn);
     }
 
+  if (!apply_change_group ())
+    return;
+
   mode = GET_MODE (*head->first->loc);
   head->regno = reg;
   head->nregs = hard_regno_nregs[reg][mode];

Reply via email to