Hi,
we have run into optimization regressions in Ada caused by the interaction
between the GIMPLE clobbers and SRA: on the one hand GIMPLE clobbers create
artificial EH handlers for aggregate variables, on the other hand SRA refuses
to scalarize objects that appear in a statement that can throw internally.
The result is that GIMPLE clobbers block the scalarization of variables that
used to be possible up to the 4.6 series. Testcase attached, compile p.adb on
x86-64 with -O2 -fdump-tree-ealias -fdump-tree-esra.
This can be solved by moving the ehcleanup pass to before early SRA in
the pipeline. It has a small but measurable positive effect on some of our
benchmarks (with a 4.7-based compiler). Tested on x86-64/Linux.
Thoughts?
2014-01-15 Eric Botcazou <ebotca...@adacore.com>
* passes.def (pass_early_local_passes): Run first EH cleanup pass early.
--
Eric Botcazou
Index: passes.def
===================================================================
--- passes.def (revision 206563)
+++ passes.def (working copy)
@@ -71,6 +71,10 @@ along with GCC; see the file COPYING3.
/* pass_build_ealias is a dummy pass that ensures that we
execute TODO_rebuild_alias at this point. */
NEXT_PASS (pass_build_ealias);
+ /* SRA refuses to scalarize objects that appear in a statement
+ that can throw internally so we need to cleanup the EH tree
+ early to remove handlers that contain only clobbers. */
+ NEXT_PASS (pass_cleanup_eh);
NEXT_PASS (pass_sra_early);
NEXT_PASS (pass_fre);
NEXT_PASS (pass_copy_prop);
@@ -79,7 +83,6 @@ along with GCC; see the file COPYING3.
NEXT_PASS (pass_early_ipa_sra);
NEXT_PASS (pass_tail_recursion);
NEXT_PASS (pass_convert_switch);
- NEXT_PASS (pass_cleanup_eh);
NEXT_PASS (pass_profile);
NEXT_PASS (pass_local_pure_const);
/* Split functions creates parts that are not run through
with Decls_Pack_2; use Decls_Pack_2;
with Decls_Support; use Decls_Support;
with Support; use Support;
procedure P is
package Decls_Pack_Private is new Decls_Pack_Private_G;
use Decls_Pack_Private;
begin
Assert (Get_Integer (Decls_Pack_Private.Local_Fun (Get_Private (1))) = 100);
end;
package body Decls_Pack_2 is
procedure Local_Swap (V1, V2 : in out Access_Integer) is
Tmp : Access_Integer := V1;
begin
V1 := V2;
V2 := Tmp;
end Local_Swap;
function Local_Fun (I : Integer) return Access_Const_Integer is
Result : Access_Const_Integer := new Integer'(I);
begin
if I < 0 then
Result := null;
end if;
return Result;
end Local_Fun;
package body Decls_Pack_Derived_Records_G is
procedure Local_Swap (V1, V2 : in out Derived_Coordinate) is
Tmp : Derived_Coordinate;
begin
if V1 /= V2 then
Tmp := V1;
V1 := V2;
V2 := Tmp;
end if;
end Local_Swap;
function Local_Fun (C1, C2 : Float) return Derived_Coordinate is
Result : Derived_Coordinate;
begin
if C1 > 0.0 and then C2 > 0.0 then
Result.X := C1;
Result.Y := C2;
end if;
return Result;
end Local_Fun;
end Decls_Pack_Derived_Records_G;
package body Decls_Pack_Private_G is
procedure Local_Swap (V1, V2 : in out T_Private) is
Tmp : T_Private := V1;
begin
V1 := V2;
V2 := Tmp;
end Local_Swap;
function Local_Fun (Arg : T_Private) return T_Private is
Result : T_Private;
begin
case Get_Integer (Arg) is
when 1 =>
Result := Get_Private (100);
when 2 =>
Result := T_Private_Zero;
when others =>
null;
end case;
return Result;
end Local_Fun;
end Decls_Pack_Private_G;
end Decls_Pack_2;
with Decls_Support; use Decls_Support;
with Support; use Support;
package Decls_Pack_2 is
Access_All_Integer_Var : Access_All_Integer := Integer_Var'Access;
I : Integer := Identity (1);
procedure Local_Swap (V1, V2 : in out Access_Integer);
function Local_Fun (I : Integer) return Access_Const_Integer;
generic
package Decls_Pack_Derived_Records_G is
Derived_Discrete_Coordinate_V : Derived_Discrete_Coordinate;
procedure Local_Swap (V1, V2 : in out Derived_Coordinate);
function Local_Fun (C1, C2 : Float) return Derived_Coordinate;
end Decls_Pack_Derived_Records_G;
generic
package Decls_Pack_Private_G is
T_Private_C : constant T_Private := T_Private_Zero;
procedure Local_Swap (V1, V2 : in out T_Private);
function Local_Fun (Arg : T_Private) return T_Private;
end Decls_Pack_Private_G;
end Decls_Pack_2;
with Support; use Support;
package Decls_Support is
type Week_Day is (Mon, Tue, Wen, Thu, Fri, Sat, Sun);
subtype Index is Natural range 0 .. 100;
type Var_String (Len : Index := 0) is record
Data : String (1 .. Len);
end record;
type Coordinate is record
X, Y : Float := 0.0;
end record;
Coordinate_Zero : constant Coordinate := (X => 0.0, Y => 0.0);
type Discrete_Coordinate is record
X : Integer := Identity (0);
Y : Integer := Identity (0);
end record;
type Vector is array (Integer range <>) of Integer;
type Matrix is array (Integer range <>, Integer range <>) of Integer;
subtype Small_Matrix is Matrix (1 .. 2, 1 .. 2);
type T_Private is private;
T_Private_Zero : constant T_Private;
function Get_Private (I : Integer) return T_Private;
function Get_Integer (X : T_Private) return Integer;
type Access_Integer is access Integer;
type Access_All_Integer is access all Integer;
type Access_Const_Integer is access constant Integer;
type Access_Coordinate is access Coordinate;
type Derived_Discrete_Coordinate is new Discrete_Coordinate;
type Derived_Coordinate is new Coordinate;
Integer_Var : aliased Integer := 1;
private
type T_Private is record
I : Integer := 0;
end record;
T_Private_Zero : constant T_Private := (I => 0);
end Decls_Support;
package Support is
procedure Assert (Cond : Boolean);
function Identity (X : Integer) return Integer;
function Identity (B : Boolean) return Boolean;
function Value (X : Integer) return Integer renames Identity;
function Value (B : Boolean) return Boolean renames Identity;
end;