diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2019-08-14 09:52:15 +0000 |
---|---|---|
committer | Pierre-Marie de Rodat <pmderodat@gcc.gnu.org> | 2019-08-14 09:52:15 +0000 |
commit | 4b96d3861e74b8df1032f4317230408248e4bf09 (patch) | |
tree | fbcdc10f2092f73da537788d02b6fc5d18e05425 /gcc/ada/sem_ch12.adb | |
parent | 72e324b6d8cb43b07eb3927f7d150b93105d1add (diff) | |
download | gcc-4b96d3861e74b8df1032f4317230408248e4bf09.zip gcc-4b96d3861e74b8df1032f4317230408248e4bf09.tar.gz gcc-4b96d3861e74b8df1032f4317230408248e4bf09.tar.bz2 |
[Ada] Compiler speedup with inlining across units
This change is aimed at speeding up the inlining across units done by
the Ada compiler when -gnatn is specified and in the presence of units
instantiating a lot of generic packages.
The current implementation is as follows: when a generic package is
being instantiated, the compiler scans its spec for the presence of
subprograms with an aspect/pragma Inline and, upon finding one,
schedules the instantiation of its body. That's not very efficient
because the compiler doesn't know yet if one of those inlined
subprograms will eventually be called from the main unit.
The new implementation arranges for the compiler to instantiate the body
on demand, i.e. when it encounters a call to one of the inlined
subprograms. That's still not optimal because, at this point, the
compiler has not yet computed whether the call itself is reachable from
the main unit (it will do this computation at the very end of the
processing, just before sending the inlined units to the code generator)
but that's nevertheless a net progress.
The patch also enhances the -gnatd.j option to make it output the list
of instances "inlined" this way. The following package is a simple
example:
with Q;
procedure P is
begin
Q.Proc;
end;
package Q is
procedure Proc;
pragma Inline (Proc);
end Q;
with G;
package body Q is
package My_G is new G (1);
procedure Proc is
Val : constant Integer := My_G.Func;
begin
if Val /= 1 then
raise Program_Error;
end if;
end;
end Q;
generic
Value : Integer;
package G is
function Func return Integer;
pragma Inline (Func);
end G;
package body G is
function Func return Integer is
begin
return Value;
end;
end G;
2019-08-14 Eric Botcazou <ebotcazou@adacore.com>
gcc/ada/
* einfo.ads (Is_Called): Document new usage on E_Package
entities.
* einfo.adb (Is_Called): Accept E_Package entities.
(Set_Is_Called): Likewise.
* exp_ch6.adb (Expand_Call_Helper): Move code dealing with
instances for back-end inlining to Add_Inlined_Body.
* inline.ads: Remove with clauses for Alloc and Table.
(Pending_Instantiations): Move to...
* inline.adb: Add with clauses for Alloc, Uintp, Table and
GNAT.HTable.
(Backend_Instances): New variable.
(Pending_Instantiations): ...here.
(Called_Pending_Instantiations): New table.
(Node_Table_Size): New constant.
(Node_Header_Num): New subtype.
(Node_Hash): New function.
(To_Pending_Instantiations): New hash table.
(Add_Inlined_Body): Bail out early for subprograms in the main
unit or subunit. Likewise if the Is_Called flag is set. If the
subprogram is an instance, invoke Add_Inlined_Instance. Call
Set_Is_Called earlier. If the subrogram is within an instance,
invoke Add_Inlined_Instance. Also deal with the case where the
call itself is within an instance.
(Add_Inlined_Instance): New procedure.
(Add_Inlined_Subprogram): Remove conditions always fulfilled.
(Add_Pending_Instantiation): Move the defence against ludicruous
number of instantiations to here. When back-end inlining is
enabled, associate an instantiation with its index in table and
mark a few selected kinds of instantiations as always needed.
(Initialize): Set Backend_Instances to No_Elist.
(Instantiate_Body): New procedure doing the work extracted
from...
(Instantiate_Bodies): ...here. When back-end inlining is
enabled, loop over Called_Pending_Instantiations instead of
Pending_Instantiations.
(Is_Nested): Minor tweak.
(List_Inlining_Info): Also list the contents of
Backend_Instances.
* sem_ch12.adb (Might_Inline_Subp): Return early if Is_Inlined
is set and otherwise set it before returning true.
(Analyze_Package_Instantiation): Remove the defence against
ludicruous number of instantiations. Invoke
Remove_Dead_Instance instead of doing the removal manually if
there is a guaranteed ABE.
From-SVN: r274465
Diffstat (limited to 'gcc/ada/sem_ch12.adb')
-rw-r--r-- | gcc/ada/sem_ch12.adb | 21 |
1 files changed, 8 insertions, 13 deletions
diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb index 06afd2a..dffec14 100644 --- a/gcc/ada/sem_ch12.adb +++ b/gcc/ada/sem_ch12.adb @@ -3861,6 +3861,12 @@ package body Sem_Ch12 is begin if Inline_Processing_Required then + -- No need to recompute the answer if we know it is positive + + if Is_Inlined (Gen_Unit) then + return True; + end if; + E := First_Entity (Gen_Unit); while Present (E) loop if Is_Subprogram (E) and then Is_Inlined (E) then @@ -3870,6 +3876,7 @@ package body Sem_Ch12 is Has_Inline_Always := True; end if; + Set_Is_Inlined (Gen_Unit); return True; end if; @@ -4425,17 +4432,6 @@ package body Sem_Ch12 is end if; if Needs_Body then - - -- Here is a defence against a ludicrous number of instantiations - -- caused by a circular set of instantiation attempts. - - if Pending_Instantiations.Last > Maximum_Instantiations then - Error_Msg_Uint_1 := UI_From_Int (Maximum_Instantiations); - Error_Msg_N ("too many instantiations, exceeds max of^", N); - Error_Msg_N ("\limit can be changed using -gnateinn switch", N); - raise Unrecoverable_Error; - end if; - -- Indicate that the enclosing scopes contain an instantiation, -- and that cleanup actions should be delayed until after the -- instance body is expanded. @@ -4633,11 +4629,10 @@ package body Sem_Ch12 is -- The instantiation results in a guaranteed ABE if Is_Known_Guaranteed_ABE (N) and then Needs_Body then - -- Do not instantiate the corresponding body because gigi cannot -- handle certain types of premature instantiations. - Pending_Instantiations.Decrement_Last; + Remove_Dead_Instance (N); -- Create completing bodies for all subprogram declarations since -- their real bodies will not be instantiated. |