REG_USERVAR_P and GCSE

Jeffrey A Law law@cygnus.com
Sun Oct 18 22:47:00 GMT 1998


  In message < 199810170757.RAA02250@geoffk.wattle.id.au >you write:
  > 
  > The attached test program, compiled with egcs 1.1b (and my previous
  > GCSE fix) under powerpc-linux, with 'gcc -O2 x.c -o x', abort()s in
  > f2, when it should not.
  > 
  > I'll save everyone the long discussion of what GCSE is doing to the
  > program (although this is a great example of how GCSE works).  The
  > problem is that GCSE is creating a new register, register 94 when I
  > run it, which does not have REG_USERVAR_P set:
You really should have explained this a little more.  I spent about an
hour starting at dumps to find out what was wrong.

At the least you should have indicated more clearly:

	* The code after gcse is correct

	* A bad transformation is made by loop

	* The path by which bad things happen.  ie, what path through the
	cfg needs to be taken for reg94 to have the wrong value.  This is
	critical for analyzing any kind of global optimization problem.

The path in question is block 0 -> block 3 -> block 4.

At the end of block 4 after global cse reg94 will have the value
(compare (reg83) (const_int 0)), which is correct.

After loop opts at the same location via the same path reg94 wiil have the
value (compare (reg82) (const_int 0)), which is incorrect.

REG_USERVAR_P should definitely not be set for reg94.  reg94 is a compiler
generated temporary.

  > and setting it in basic blocks 1, 3, and 9. (I don't know why it
  > doesn't create it in bb 0 instead of bb 1 and 3, it might be
  > worthwhile adding a little code to fix this).
PRE is doing the right thing.  It tries to minimize the number of computations
on every path through the cfg.  It does not try to do code hoisting into
dominator blocks (aka unification).  Do not change gcse to do this.


  > Then loop.c is assuming that all non-user registers are only used
  > in a loop after they are set, and this is not true in this case (it's
  > used in block 5 after being set in block 3).
But every path leading to block 5 has a set of reg 94.  And since reg94 is
not set in the loop, it is a loop invariant and can be moved.


  > My patch is attached.  Another possibility is to set REG_USERVAR_P in
  > GCSE when it creates new registers, in which case I strongly recommend
  > changing the name to something like REG_LONGLIFE_P.
Right now, I think your're just papering over the problem.  I also worry about
the performance impacts of that change.

I think the underlying problem lies with the insns in blocks 7, 8 & 9, which
are physically inside the loop, but which are not actually part of the loop
(once you start executing block 7, you must exit the loop).  Somehow loop is
mis-handling this.

jeff



More information about the Gcc-patches mailing list