This is the mail archive of the gcc@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: Live range splitting in new allocator


On Mon, Jan 29, 2001 at 01:17:21PM -0500, Daniel Berlin wrote:
> 
> So, i've implemented live range splitting in the new allocator (it takes
> up ~30 lines, thanks to the dataflow routines). However, cse keeps
> raping me.
> It works like this:
> For each definition of a register besides the first, generate a new
> pseudo, and replace all uses of *that* particular definition, with the new
> pseudo, and then replace the definition so it uses the right register.

Hmmm, I was about to dust off the old live range splitting code I had written
some time ago (considerably more than 30 lines), which unfortunately is
currently if'ed out in the current internal Red Hat compiler, due to dataflow
problems.

In addition to the dataflow problems, another problem that I haven't had time
to work on is how to inform the debugger of a variables location as it moves
betweent he stack and multiple registers.  The current compiler is broken in
this regard, but LRS makes it more visible, since things can be in multiple
registers for a longer time.

At the time I did the code (2-3 years ago), stabs was the preferred debug
format, and we added an extension to stabs that gdb knows about to trace this
movement.  Obviously with dwarf-2 this could be done via the locator fields
(which does break for VLIW machines).  One thing that I had thought about doing
for other debug formats, but couldn't get right when I was working on the code,
was to split the lexical blocks each time you have a variable cross LRS
boundaries.  For instance, if you have the program:

	void foo()
	{
	  int i;

	  /* ... */

	  for (i = 0; i < 10; i++)
	    {
		/* ... */
	    }

	  /* ... */

	  for (i = 0; i < 10; i++)
	    {
		/* ... */
	    }

	  /* ... */
	}

it would effectively rewrite the program as:

	void foo()
	{
	  int i;

	  /* ... */

	  {
	    int i;
	    for (i = 0; i < 10; i++)
	      {
		/* ... */
	      }
	  }

	  /* ... */

	  {
	    int i;
	    for (i = 0; i < 10; i++)
	      {
		/* ... */
	      }
	  }

	  /* ... */
	}

so that if you were in the middle of one of the loops, the debugger would think
that i was just a lexically scopped replacement for the outer i.

> This works perfectly.
> I then update *all* the info (because i've been trying to figure out why
> this problem occurrs, updating more and more info as i go along).
> This means, I reset the log_links and reg_notes, then do this:
> 
>   find_basic_blocks(get_insns(), max_reg_num(), rtl_dump_file);
>   max_regno = max_reg_num();
>   fprintf(stderr, "New max_regno:%d, max_reg_num():%d", max_regno, max_reg_num());
>   reg_scan(get_insns(), max_reg_num(), 1);
>   allocate_reg_info(max_regno, FALSE, TRUE);
>   update_equiv_regs();
>   cleanup_cfg (get_insns());
>   count_or_remove_death_notes(0,1);
>   update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES,
>                       PROP_FINAL);
>   regclass(get_insns(), max_reg_num(), rtl_dump_file);
>   schedule_insns(rtl_dump_file);
> 
> 
> We now properly allocate registers, including for the new pseudos.
> 
> After reload, but before reload_cse_regs, for one of the new pseudos, we
> have this:
> 
> (insn 41 34 281 (set (reg:SI 4 [151])
>         (const_int 0 [0x0])) 282 {*movsi_internal1} (nil)
>     (nil))
> 
> After reload_cse_regs starts processing, something up and changes this to:
> (insn 41 34 281 (set (reg:SI 805875168 [4])
>         (const_int 0 [0x0])) 282 {*movsi_internal1} (nil)
>     (nil))
> 
> It's already like that by the time it calls reload_cse_simplify on the
> insn.
> (gdb) c
> Continuing.
> 
> Breakpoint 6, reload_cse_regs_1 (first=0x300926a0) at
> ../../gcc/reload1.c:8134
> 8134            reload_cse_simplify (insn);
> (gdb) p debug_rtx(insn)
> 
> (jump_insn 23 22 24 (set (pc)
>         (label_ref 175)) 467 {jump} (insn_list:REG_DEP_ANTI 21 (insn_list
> 22 (nil)))
>     (nil))
> $29 = void
> (gdb) c
> Continuing.
> 
> Breakpoint 6, reload_cse_regs_1 (first=0x300926a0) at
> ../../gcc/reload1.c:8134
> 8134            reload_cse_simplify (insn);
> (gdb) p debug_rtx(insn)
> 
> (insn 41 34 281 (set (reg:SI 805875168 [4])
>         (const_int 0 [0x0])) 282 {*movsi_internal1} (nil)
>     (nil))
> $30 = void
> 
> 
> WTF is going on?
> 
> Something is turning the register numbers on the new pseudos to garbage.
> It's not a memory overwrite, or at least, electricfence doesn't catch it.
> If i remove the call to reload_cse_regs, something else turns it to the
> same exact garbage a little later, etc.
> 
> It's really annoying me.
> Am i generating the new pseudos wrong? I'm using gen_reg_rtx.

What is happening I believe is that there are these tables based on the
register number.  You have to extend these tables whenever you allocate
registers in the middle end.

-- 
Michael Meissner, Red Hat, Inc.  (GCC group)
PMB 198, 174 Littleton Road #3, Westford, Massachusetts 01886, USA
Work:	  meissner@redhat.com		phone: +1 978-486-9304
Non-work: meissner@spectacle-pond.org	fax:   +1 978-692-4482

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