[patch] Fix LRA/reload issue with -fnon-call-exceptions

Eric Botcazou ebotcazou@adacore.com
Fri Feb 15 10:05:00 GMT 2019


Hi,

this is a regression present on all active branches since the controversial 
get_initial_register_offset stuff was added to rtlanal.c some time ago, and 
visible in the testsuite on PowerPC/Linux under the form of gnat.dg/opt73.adb 
timing out at run time.

The problem is that the compiler generates code that doesn't save the frame 
pointer before clobbering it, because rs6000_stack_info computes a wrong final 
(post-reload) stack layout.  The scenario is as follows: LRA decides to use 
the frame pointer, sets reload_completed to 1 at the end and then does:

  /* We've possibly turned single trapping insn into multiple ones.  */
  if (cfun->can_throw_non_call_exceptions)
    {
      auto_sbitmap blocks (last_basic_block_for_fn (cfun));
      bitmap_ones (blocks);
      find_many_sub_basic_blocks (blocks);
    }

But find_many_sub_basic_blocks calls control_flow_insn_p, which in turn can 
call rtx_addr_can_trap_p_1, which can call get_initial_register_offset, which 
uses INITIAL_ELIMINATION_OFFSET, IOW rs6000_initial_elimination_offset, which 
calls rs6000_stack_info.  But at this point the DF information hasn't been 
updated so the frame pointer isn't detected as live by df_regs_ever_live_p.

You may think that the fix is just to set reload_completed to 1 after the 
above code in lra, but that's not sufficient because the same issue can arise 
from the do_reload function:

  if (optimize)
    cleanup_cfg (CLEANUP_EXPENSIVE);

when checking is enabled, because cleanup_cfg can calls control_flow_insn_p 
and then eventually rtx_addr_can_trap_p_1.  In other words, we would need 
to set reload_completed to 1 only after the above code, which is very late.
As a matter of fact, that's not possible for old reload itself because of:

  /* We must set reload_completed now since the cleanup_subreg_operands call
     below will re-recognize each insn and reload may have generated insns
     which are only valid during and after reload.  */
  reload_completed = 1;

So, barring the removal of the get_initial_register_offset stuff, the only 
simple fix is probably to prevent it from calling into the back-end too early, 
for example with the attached fixlet.  Tested on x86-64 and PowerPC/Linux.

Thoughts?  Where do we want to fix this?


	* rtlanal.c (get_initial_register_offset): Fall back to the raw estimate
	as long as the epilogue isn't completed.

-- 
Eric Botcazou
-------------- next part --------------
A non-text attachment was scrubbed...
Name: p.diff
Type: text/x-patch
Size: 757 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/gcc-patches/attachments/20190215/191cc99c/attachment.bin>


More information about the Gcc-patches mailing list