Fix PR44281 (bad RA with global regs)

Dominik Vogt vogt@linux.vnet.ibm.com
Wed Jul 13 15:30:00 GMT 2016


On Fri, Feb 19, 2016 at 11:03:02PM +0100, Bernd Schmidt wrote:
> In this PR, we generate unnecessarily bad code for code that
> declares a global register var. Since global regs get added to
> fixed_regs, IRA never considers them as candidates. However, we do
> seem to have proper data flow information for them. In the testcase,
> the global reg dies, some operations are done on temporary results,
> and the final result stored back in the global reg. We can achieve
> the desired code generation by reusing the global reg for those
> temporaries.
> 
> Bootstrapped and tested on x86_64-linux. Ok? An argument could be
> made not to use this for gcc-6 since global register vars are both
> not very important and not very well represented in the testsuite.

> 	PR rtl-optimization/44281
> 	* hard-reg-set.h (struct target_hard_regs): New field
> 	x_fixed_nonglobal_reg_set.
> 	(fixed_nonglobal_reg_set): New macro.
> 	* reginfo.c (init_reg_sets_1): Initialize it.
> 	* ira.c (setup_alloc_regs): Use fixed_nonglobal_reg_set instead
> 	of fixed_reg_set.
> 
> 	PR rtl-optimization/44281
> 	* gcc.target/i386/pr44281.c: New test.

Unfortunately this patch (or whatever got actually committed) has
broken the gcc.target/s390/pr679443.c test case, which is a bit
fishy (see code snippet below).  I assign most registers to global
variables and then use some complicated arithmetics with the goal
that the pointer stored in the first argument gets saved on the
stack and reloaded to a different register.  Before this patch the
test case just needed three registers to do its work (r2, r3, r4).
With the patch it currently causes an error in the reload pass

  error: unable to find a register to spill

-- snip --
/* Block all registers except the first three argument registers.  */
register long r0 asm ("r0");
register long r1 asm ("r1");
register long r5 asm ("r5");
register long r6 asm ("r6");
register long r7 asm ("r7");
register long r8 asm ("r8");
register long r9 asm ("r9");
register long r10 asm ("r10");
register long r11 asm ("r11");

...

void foo (struct s_t *ps, int c, int i)
{
  /* Uses r2 as address register.  */
  ps->f1 = c;
  /* The calculation of the value is so expensive that it's cheaper to spill ps
     to the stack and reload it later (into a different register).
     ==> Uses r4 as address register.*/
  ps->f2 = i + i % 3;
  /* If dead store elimination fails to detect that the address in r2 during
     the first assignment is an alias of the address in r4 during the second
     assignment, it eliminates the first assignment and the f1 field is not
     written (bug).  */
}
-- snip --

If a fourth register is available, the ICE goes away, but the
pointer remains in r2, rendering the test case useless.

So, what should be done about this?

Ciao

Dominik ^_^  ^_^

-- 

Dominik Vogt
IBM Germany



More information about the Gcc-patches mailing list