register allocation bug (BUG ID #3777)

Jeffrey A Law law@cygnus.com
Mon Aug 2 01:20:00 GMT 1999


  In message <199907110215.WAA23195@harvey.cyclic.com>you write:
  > OK, this is a reproducible bug with a small test case but I feel
  > handicapped by not knowing the compiler well enough (yet :-)), so I'm
  > hoping this will be (comparatively) obvious to someone who isn't as
  > green as I.
  > 
  > Let's start with the environment: EGCS 1.1.2 (this test case doesn't
  > hit the problem with 2.96 but I would guess other test cases might).
  > Script enclosed.  Processor is x86, OS is Red Hat Linux (either 6.0 or
  > 5.0, as long as the compiler is EGCS 1.1.2).
  > 
  > Now, what I have found so far.  The problem is that insn 253
  > (enclosed) allocates both (pseudo)register 81 and (pseudo)register 36
  > to the same hard register (%ebx).  For what it is worth, register 36
  > dies after insn 253 and register 81 is born in insn 253.  Anyway, the
  > buggy code ends up looking like:
  > 
  > 	movl -12(%ebx),%ebx
  > 	movl -8(%ebx),%esi
  > 
  > when the correct code would be more like insn 151:
  > 
  > 	movl -12(%ebx),%esi
  > 	movl -8(%ebx),%edi
  > 
  > Can anyone tell me whether the RTL is correct?  Whether the machine
  > description (fix_truncsfdi2 in i386.md) correctly describes the
  > clobbers?  Whether global.c is intended to handle a clobber like
  > "(mem:SI (plus:SI (reg:SI 36) (const_int -4))))" (the plain "(clobber
  > (reg:DF 80))" seems to work much better)?  Any other hints?  I want to
  > be able to track down problems like this rather than throw myself on
  > the mercy of others but there are so many places to turn in trying to
  > figure out what is wrong here.
  > 
  > (insn/i 253 249 254 (parallel[ 
  > 	    (set (reg/v:DI 81)
  > 		(fix:DI (fix:DF (reg:DF 80))))
  > 	    (clobber (reg:DF 80))
  > 	    (clobber (mem:SI (plus:SI (reg:SI 36)
  > 			(const_int -4))))
  > 	    (clobber (mem:DI (plus:SI (reg:SI 36)
  > 			(const_int -12))))
  > 	    (clobber (scratch:SI))
  > 	] ) 119 {fix_truncsfdi2+2} (insn_list 249 (nil))
  >     (expr_list:REG_DEAD (reg:SI 36)
  > 	(expr_list:REG_UNUSED (reg:DF 80)
  > 	    (expr_list:REG_UNUSED (scratch:SI)
  > 		(expr_list:REG_EQUAL (fix:DI (const_double:DF (mem/u:DF (symbol
  > _ref/u:SI ("*.LC54"))) 0 0 1073659904))
  > 		    (nil))))))

The way to start working on this is to find out what part of register
allocation is causing problems.

The example, you can look at the .lreg dump to see what the register assignments
were after local register allocation to see if reg81 & reg36 are assigned to
the same pseudo.

Similarly you can examine the state after global register allocation, though it
is a little tougher.

set a breakpoint in reload

When it hits print reg_renumber[80] and reg_renumber[36]

That'll tell you what allocations the global allocator made.

Depending on what you find, you'll have to look at local, global or (my bet)
reload.  

If we assume things are OK after global, then you'll probably want to know what
the reloads for that insn are.  You can get them by placing a breakpoint in
emit_reload_insns conditional on insn->fld[0].rtint == 253

When it hits you can say "p debug_reload ()" to dump the reloads for that
insn in a symbolic manner.

jeff



More information about the Gcc-bugs mailing list