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;