diff mbox

Fix ICE in RTL PRE on abnormal edges

Message ID 4301892.PSeepinNW0@arcturus.home
State New
Headers show

Commit Message

Eric Botcazou Aug. 30, 2016, 10:14 a.m. UTC
We ran into an ICE at -O3 on x86-64/Darwin for the attached testcase with our 
GCC 6 compiler:

+===========================GNAT BUG DETECTED==============================+
| Pro 17.0w (20160830-62) (x86_64-apple-darwin14.5.0) GCC error:           |
| in rtl_split_edge, at cfgrtl.c:1887                                      |
| Error detected around p.adb:87:7    

It doesn't reproduce with mainline, but the issue is latent.

postreload-gcse.c:eliminate_partially_redundant_loads uses an ad-hoc predicate 
to detect problematic patterns and consequently punt:

      /* Don't try anything on basic blocks with strange predecessors.  */
      if (! bb_has_well_behaved_predecessors (bb))
	continue;

This predicate has for abnormal edges:

      if ((pred->flags & EDGE_ABNORMAL) && EDGE_CRITICAL_P (pred))
	return false;

which makes sense since rtl_split_edge aborts on abnormal edges (it's the ICE) 
so any abnormal critical edge cannot be used to create a full redundancy by 
PRE.  Now PRE actually uses commit_edge_insertions to insert intructions on 
edges and commit_one_edge_insertion has an additional restriction:

  /* If the source has one successor and the edge is not abnormal,
     insert there.  Except for the entry block.
     Don't do this if the predecessor ends in a jump other than
     unconditional simple jump.  E.g. for asm goto that points all
     its labels at the fallthru basic block, we can't insert instructions
     before the asm goto, as the asm goto can have various of side effects,
     and can't emit instructions after the asm goto, as it must end
     the basic block.  */
  else if ((e->flags & EDGE_ABNORMAL) == 0
	   && single_succ_p (e->src)

That is to say, even an abnormal edge whose source has a single successor is 
rejected here and leads to the tentative splitting and the ICE.  So the patch 
makes bb_has_well_behaved_predecessors match what commit_one_edge_insertion 
supports for abnormal edges with an explicit reference in the comment.

Tested on x86_64-suse-linux, applied on the mainline.


2016-08-30  Eric Botcazou  <ebotcazou@adacore.com>

	* postreload-gcse.c (bb_has_well_behaved_predecessors): Tweak
	criterion used for abnormal egdes.


2016-08-30  Eric Botcazou  <ebotcazou@adacore.com>

	* gnat.dg/opt57.ad[sb]: New test.
	* gnat.dg/opt57_pkg.ads: New helper.
diff mbox

Patch

commit 5a1da5d39381c87a5a680cc886ea2f6c0cadf306
Author: Eric Botcazou <ebotcazou@adacore.com>
Date:   Tue Jul 26 00:05:15 2016 +0200

    Fix for P725-013 (build failure of CodePeer on x86-64/Darwin with GCC 6).

diff --git a/gcc/postreload-gcse.c b/gcc/postreload-gcse.c
index 566e875..da04fb7 100644
--- a/gcc/postreload-gcse.c
+++ b/gcc/postreload-gcse.c
@@ -962,7 +962,9 @@  bb_has_well_behaved_predecessors (basic_block bb)
 
   FOR_EACH_EDGE (pred, ei, bb->preds)
     {
-      if ((pred->flags & EDGE_ABNORMAL) && EDGE_CRITICAL_P (pred))
+      /* commit_one_edge_insertion refuses to insert on abnormal edges even if
+	 the source has only one successor so EDGE_CRITICAL_P is too weak.  */
+      if ((pred->flags & EDGE_ABNORMAL) && !single_pred_p (pred->dest))
 	return false;
 
       if ((pred->flags & EDGE_ABNORMAL_CALL) && cfun->has_nonlocal_label)