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  <ebotca...@adacore.com>

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


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

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

-- 
Eric Botcazou
commit 5a1da5d39381c87a5a680cc886ea2f6c0cadf306
Author: Eric Botcazou <ebotca...@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)
package body Opt57 is

   type Phase_Enum is (None_Phase, FE_Init_Phase, FE_Phase);

   type Message_State is (No_Messages, Some_Messages);

   type Module_List_Array is array (Phase_Enum, Message_State) of List;

   type Private_Module_Factory is limited record
      Module_Lists : Module_List_Array;
   end record;

   type Element_Array is array (Positive range <>) of Module_Factory_Ptr;

   type Hash_Table is array (Positive range <>) of aliased Module_Factory_Ptr;

   type Heap_Data_Rec (Table_Last : Positive) is limited record
      Number_Of_Elements : Positive;
      Table              : Hash_Table (1 .. Table_Last);
   end record;

   type Heap_Data_Ptr is access Heap_Data_Rec;

   type Table is limited record
      Data : Heap_Data_Ptr;
   end record;

   function All_Elements (M : Table) return Element_Array is
      Result : Element_Array (1 .. Natural (M.Data.Number_Of_Elements));
      Last   : Natural := 0;
   begin
      for H in M.Data.Table'Range loop
         Last := Last + 1;
         Result (Last) := M.Data.Table(H);
      end loop;
      return Result;
   end;

   The_Factories : Table;

   subtype Language_Array is Element_Array;
   type Language_Array_Ptr is access Language_Array;
   All_Languages : Language_Array_Ptr := null;

   procedure Init is
   begin
      if All_Languages = null then
         All_Languages := new Language_Array'(All_Elements (The_Factories));
      end if;
   end;

   function Is_Empty (L : List) return Boolean is
   begin
      return Link_Constant (L.Next) = L'Unchecked_Access;
   end;

   function First (L : List) return Linkable_Ptr is
   begin
      return Links_Type (L.Next.all).Container.all'Access;
   end;

   procedure Update is
      Check_New_Dependences : Boolean := False;
   begin
      loop
         for Lang_Index in All_Languages'Range loop
            for Has_Messages in Message_State loop
               declare
                  L : List renames
                    All_Languages (Lang_Index).Priv.Module_Lists
                      (FE_Init_Phase, Has_Messages);
               begin
                  while not Is_Empty (L) loop
                     declare
                        Module_In_Init_State : constant Module_Ptr :=
                          Module_Ptr (First (L));
                        Pin_Dependence : Pinned (Module_In_Init_State);
                     begin
                        Check_New_Dependences := True;
                     end;
                  end loop;
               end;
            end loop;
         end loop;
         exit when not Check_New_Dependences;
      end loop;
   end;

end Opt57;
-- { dg-do compile }
-- { dg-options "-O3" }

with Ada.Finalization; use Ada.Finalization;
with Opt57_Pkg; use Opt57_Pkg;

package Opt57 is

   procedure Update;

   procedure Init;

   type Module_Factory is abstract new Limited_Controlled with private;

   type Root_Module_Rec (Language : access Module_Factory'Class)
   is abstract new GC_Pool with null record;

   type List is tagged limited private;
   type Linkable is abstract new Root_Module_Rec with private;
   type Linkable_Ptr is access all Linkable'Class;

private

   type Link is access all List'Class;
   type Link_Constant is access constant List'Class;
   type List is tagged limited record
      Next : Link;
   end record;

   type Links_Type (Container : access Linkable) is new List with null record;

   type Linkable is abstract new Root_Module_Rec with record
      On_List : Link_Constant;
      Links   : aliased Links_Type (Linkable'Access);
   end record;

   type Module_Rec (Language : access Module_Factory'Class)
   is abstract new Linkable (Language) with null record;
   type Module_Ptr is access all Module_Rec'Class;

   type Private_Module_Factory;
   type Private_Module_Factory_Ptr is access Private_Module_Factory;

   type Module_Factory is abstract new Limited_Controlled with record
      Priv : Private_Module_Factory_Ptr;
   end record;

   type Module_Factory_Ptr is access all Module_Factory'Class;

end Opt57;
with System.Storage_Pools; use System.Storage_Pools;

with Ada.Finalization; use Ada.Finalization;

package Opt57_Pkg is

   type GC_Pool is abstract new Root_Storage_Pool with null record;

   type Pinned (Pool : access GC_Pool'Class) is new Controlled with null record;

   procedure Finalize (X : in out Pinned);

end Opt57_Pkg;

Reply via email to