update_equiv_regs fix

Jan Hubicka hubicka@atrey.karlin.mff.cuni.cz
Sat Dec 25 08:08:00 GMT 1999


Hi
It seems to me that update_equiv_regs contain bug that might result in
incorrect code.  It moves the insns with REG_EUIV note right before the user of
register.  I believe that when insn is parallel clobbering register it may
actually clobber live register. I don't have testcase, but I believe that the
problem is quite clear.  Thats why I've added ok_to_move_before_p function to
verify that insn don't contain any clobbers of non-scratchs and uses of
nonconstant stuff.

Pá prosinec 24 10:24:56 CET 1999  Jan Hubicka  <hubicka@freesoft.cz>
	* equiv.c (ok_to_move_before_p): New static function.
	(update_equiv_regs): Use it.

*** equiv.c.noequiv2	Fri Dec 24 08:46:03 1999
--- equiv.c	Fri Dec 24 10:12:27 1999
*************** static int equiv_mem_modified;
*** 56,65 ****
     Called via note_stores.  */
  static void validate_equiv_mem_from_store PROTO((rtx, rtx, void *));
  static int validate_equiv_mem	PROTO((rtx, rtx, rtx));
  static int contains_replace_regs PROTO((rtx));
  static int memref_referenced_p	PROTO((rtx, rtx));
  static int memref_used_between_p PROTO((rtx, rtx, rtx));
  static void no_equiv		PROTO((rtx, rtx, void *));
  
  
  static void
--- 53,63 ----
     Called via note_stores.  */
  static void validate_equiv_mem_from_store PROTO((rtx, rtx, void *));
  static int validate_equiv_mem	PROTO((rtx, rtx, rtx));
  static int contains_replace_regs PROTO((rtx));
  static int memref_referenced_p	PROTO((rtx, rtx));
  static int memref_used_between_p PROTO((rtx, rtx, rtx));
  static void no_equiv		PROTO((rtx, rtx, void *));
+ static int ok_to_move_before_p PROTO((rtx, rtx));
  
  
  static void
*************** function_invariant_p (x)
*** 284,289 ****
--- 313,347 ----
    return 0;
  }
  
+ /* Return 1 if it is OK to move single_set insn INSN before insn WHERE. 
+    We have to ensure, that insn don't contain any clobbers to live registers
+    or any uses of registers.  */
+ static int
+ ok_to_move_before_p (insn, where)
+      rtx insn;
+      rtx where ATTRIBUTE_UNUSED;
+ {
+   rtx pat = PATTERN (insn);
+   int i;
+   if (GET_CODE (pat) != PARALLEL)
+     return 1;
+   for (i = 0; i < XVECLEN (pat, 0); i++)
+   {
+     rtx x = XVECEXP (pat, 0, i);
+ 
+     /* We ought to verify that register didn't changed in the insn,
+        but it is probably not too important, since USES are rare.  */
+     if (GET_CODE (x) == USE && !function_invariant_p (XEXP (x, 0)))
+       return 0;
+ 
+     /* If it turns out to be important, we may check that given hard register
+        is dead and accept such insns.  */
+     if (GET_CODE (x) == CLOBBER && GET_CODE (XEXP (x, 0)) != SCRATCH)
+       return 0;
+   }
+   return 0;
+ }
+ 
  /* Find registers that are equivalent to a single value throughout the
     compilation (either because they can be referenced in memory or are set once
     from a single constant).  Lower their priority for a register.
*************** update_equiv_regs ()
*** 592,597 ****
--- 635,641 ----
  		 before INSN.  Update the flow information.  */
  	      else if (depth == 0
  		       && GET_CODE (equiv_insn) == INSN
+ 		       && ok_to_move_before_p (equiv_insn, insn)
  		       && GET_CODE (insn) == INSN
  		       && REG_BASIC_BLOCK (regno) < 0)
  		{


More information about the Gcc-patches mailing list