This is the mail archive of the gcc-bugs@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]

Re: conditional exec verify_live problem after scheduling


> 
> rearnsha@arm.com said:
> > I've come across the following problem which I think is probably
> > related  to your recent conditional-execution scheduling changes
> > (though it may be  just uncovering an underlying problem from before).
> >  The problem is in  newlib/libm/common/s_modf.c when compiling arm-elf
> > and -mhard-float. 
> 
> 
> I've finally had chance to look into this.  It isn't the cond_exec 
> scheduling changes per-say, but revealing a latent bug in mark_set_1.  The 
> problem is that the variable not_dead is calculated as the OR of the 
> result of all the calls to mark_regno_cond_dead for each real reg of a 
> multi-reg value.  Why does this make a difference?  Well, before 
> scheduling we have
> 
> (insn 96 94 104 (cond_exec (eq (reg:CC_NOOV 24 cc)
>             (const_int 0 [0x0]))
>         (set (reg:DF 3 r3 [54])
>             (reg/v:DF 16 f0 [32]))) 604 {ffssi2+104} (nil)
>     (nil))
> ...
> (insn 136 142 138 (cond_exec (ne (reg:CC_NOOV 24 cc)
>             (const_int 0 [0x0]))
>         (set (reg:SI 4 r4 [58])
>             (and:SI (not:SI (reg/v:SI 3 r3 [37]))
>                 (reg/v:SI 12 ip [34])))) 544 {ffssi2+44} (nil)
>     (expr_list:REG_DEAD (reg/v:SI 3 r3 [37])
>         (expr_list:REG_DEAD (reg/v:SI 12 ip [34])
>             (nil))))
> 
> and since at the point of processing insn 96 the hard reg r3 is not dead, 
> not_dead is set to 1 even though hard reg r4 (the upper half of (reg:DI 
> r3)) is really dead at this point.  This means that we erroneously leave 
> r4 live at the start of the block.  After scheduling the order of these 
> two insns is reversed, so the liveness of r4 is calculated from a single 
> call to mark_regno_cond_dead which this time tells us that the register is 
> dead.  Hence we get different liveness information at the start of the 
> block.

I believe the following patch should fix this problem.  By treating 
not_dead as a bitmask of the registers that don't die we can correctly 
handle partial deaths of registers that live in multi hard regs.

Bootstrapped on arm-netbsd and confirmed that it can now build the newlib 
cases that previously failed.


<date>  Richard Earnshaw (rearnsha@arm.com)

	* flow.c (mark_set_1): Make not_dead unsigned long.  For
	non-pseudos, use it as a bitmask of the hard regs that 
	don't die.


Index: flow.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/flow.c,v
retrieving revision 1.374
diff -p -r1.374 flow.c
*** flow.c	2001/02/04 22:43:59	1.374
--- flow.c	2001/02/07 15:16:45
*************** mark_set_1 (pbi, code, reg, cond, insn, 
*** 4655,4661 ****
       int flags;
  {
    int regno_first = -1, regno_last = -1;
!   int not_dead = 0;
    int i;
  
    /* Modifying just one hardware register of a multi-reg value or just a
--- 4655,4661 ----
       int flags;
  {
    int regno_first = -1, regno_last = -1;
!   unsigned long not_dead = 0;
    int i;
  
    /* Modifying just one hardware register of a multi-reg value or just a
*************** mark_set_1 (pbi, code, reg, cond, insn, 
*** 4830,4836 ****
  	{
  	  for (i = regno_first; i <= regno_last; ++i)
  	    if (! mark_regno_cond_dead (pbi, i, cond))
! 	      not_dead = 1;
  	}
  #endif
  
--- 4830,4836 ----
  	{
  	  for (i = regno_first; i <= regno_last; ++i)
  	    if (! mark_regno_cond_dead (pbi, i, cond))
! 	      not_dead |= 1 << (i - regno_first);
  	}
  #endif
  
*************** mark_set_1 (pbi, code, reg, cond, insn, 
*** 4943,4949 ****
  
        /* Mark the register as being dead.  */
        if (some_was_live
- 	  && ! not_dead
  	  /* The stack pointer is never dead.  Well, not strictly true,
  	     but it's very difficult to tell from here.  Hopefully
  	     combine_stack_adjustments will fix up the most egregious
--- 4943,4948 ----
*************** mark_set_1 (pbi, code, reg, cond, insn, 
*** 4951,4957 ****
  	  && regno_first != STACK_POINTER_REGNUM)
  	{
  	  for (i = regno_first; i <= regno_last; ++i)
! 	    CLEAR_REGNO_REG_SET (pbi->reg_live, i);
  	}
      }
    else if (GET_CODE (reg) == REG)
--- 4950,4957 ----
  	  && regno_first != STACK_POINTER_REGNUM)
  	{
  	  for (i = regno_first; i <= regno_last; ++i)
! 	    if (!(not_dead & (1 << (i - regno_first))))
! 	      CLEAR_REGNO_REG_SET (pbi->reg_live, i);
  	}
      }
    else if (GET_CODE (reg) == REG)

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