fix for linux network hang

Jeffrey A Law law@upchuck.cygnus.com
Sat Mar 27 15:17:00 GMT 1999


This patch fixes the linux network hang when compiling a 2.2.x kernel with
the mainline egcs sources.

In short we had something like this

  a->b = 0;
  volatile asm which accepted "a" as an input and referenced a->b.
  a->b = new value


The dead store elimination code did not consider the volatile asm as
referencing memory, as a result the assignment a->b = 0 was considered
dead and was incorrectly deleted.

This bug has actually been around for a long time, but our dead store
elimination code has been so lame that nobody noticed.  Christian's
improvements to dead store elimination made this bug much more likely to
trigger.



	* flow.c (mark_used_regs): Improve handling of ASMs.

Index: flow.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/flow.c,v
retrieving revision 1.108
diff -c -3 -p -r1.108 flow.c
*** flow.c	1999/03/21 12:14:06	1.108
--- flow.c	1999/03/27 22:34:03
*************** static int loop_depth;
*** 242,249 ****
  static int cc0_live;
  
  /* During propagate_block, this contains a list of all the MEMs we are
!    tracking for dead store elimination.  */
  
  static rtx mem_set_list;
  
  /* Set of registers that may be eliminable.  These are handled specially
--- 242,254 ----
  static int cc0_live;
  
  /* During propagate_block, this contains a list of all the MEMs we are
!    tracking for dead store elimination. 
  
+    ?!? Note we leak memory by not free-ing items on this list.  We need to
+    write some generic routines to operate on memory lists since cse, gcse,
+    loop, sched, flow and possibly other passes all need to do basically the
+    same operations on these lists.  */
+ 
  static rtx mem_set_list;
  
  /* Set of registers that may be eliminable.  These are handled specially
*************** mark_used_regs (needed, live, x, final, 
*** 3593,3599 ****
      case PC:
      case ADDR_VEC:
      case ADDR_DIFF_VEC:
-     case ASM_INPUT:
        return;
  
  #ifdef HAVE_cc0
--- 3598,3603 ----
*************** mark_used_regs (needed, live, x, final, 
*** 3907,3912 ****
--- 3911,3954 ----
  	    )
  	  SET_REGNO_REG_SET (live, i);
        break;
+ 
+     case ASM_OPERANDS:
+     case UNSPEC_VOLATILE:
+     case TRAP_IF:
+     case ASM_INPUT:
+       {
+ 	/* Traditional and volatile asm instructions must be considered to use
+ 	   and clobber all hard registers, all pseudo-registers and all of
+ 	   memory.  So must TRAP_IF and UNSPEC_VOLATILE operations.
+ 
+ 	   Consider for instance a volatile asm that changes the fpu rounding
+ 	   mode.  An insn should not be moved across this even if it only uses
+ 	   pseudo-regs because it might give an incorrectly rounded result. 
+ 
+ 	   ?!? Unfortunately, marking all hard registers as live causes massive
+ 	   problems for the register allocator and marking all pseudos as live
+ 	   creates mountains of uninitialized variable warnings.
+ 
+ 	   So for now, just clear the memory set list and mark any regs
+ 	   we can find in ASM_OPERANDS as used.  */
+ 	if (code != ASM_OPERANDS || MEM_VOLATILE_P (x))
+ 	  mem_set_list = NULL_RTX;
+ 
+         /* For all ASM_OPERANDS, we must traverse the vector of input operands.
+ 	   We can not just fall through here since then we would be confused
+ 	   by the ASM_INPUT rtx inside ASM_OPERANDS, which do not indicate
+ 	   traditional asms unlike their normal usage.  */
+ 	if (code == ASM_OPERANDS)
+ 	  {
+ 	    int j;
+ 
+ 	    for (j = 0; j < ASM_OPERANDS_INPUT_LENGTH (x); j++)
+ 	      mark_used_regs (needed, live, ASM_OPERANDS_INPUT (x, j),
+ 			      final, insn);
+ 	  }
+ 	break;
+       }
+ 
  
      default:
        break;









More information about the Gcc-patches mailing list