With this change, the compiler now supports the -gnatn[d] switch, where 'd' is a digit and can only be '1' or '2' for the time being, to let the user specify the level of inlining across modules. If the old form `-gnatn' is used, the compiler will pick the inlining level based on the optimization level.
Tested on x86_64-pc-linux-gnu, committed on trunk 2012-06-12 Eric Botcazou <ebotca...@adacore.com> * opt.ads (Inline_Level): New variable. * gnat1drv.adb (Adjust_Global_Switches): Set it based on optimization level if it has not been set by the user. * switch-c.adb (Scan_Front_End_Switches): Accept -gnatn1 and -gnatn2 and set Inline_Level accordingly. * inline.adb (Add_Inlined_Body): Declate new Inline_Level_Type type. (Must_Inline): Return Inline_Level_T instead of Boolean to indicate whether the package of the inlined subprogram must be compiled. If Inline_Level is set to 1, only compile packages of subprograms directly called from the main unit. * usage.adb (Usage): Adjust line for -gnatn switch. * gnat_ugn.texi (Switches for gcc): Document -gnatn1 and -gnatn2.
Index: switch-c.adb =================================================================== --- switch-c.adb (revision 188428) +++ switch-c.adb (working copy) @@ -732,6 +732,16 @@ Ptr := Ptr + 1; Inline_Active := True; + -- There may be a digit appended to the switch + + if Ptr <= Max then + C := Switch_Chars (Ptr); + if C = '1' or C = '2' then + Ptr := Ptr + 1; + Inline_Level := Character'Pos (C) - Character'Pos ('0'); + end if; + end if; + -- Processing for N switch when 'N' => Index: inline.adb =================================================================== --- inline.adb (revision 188428) +++ inline.adb (working copy) @@ -229,7 +229,13 @@ procedure Add_Inlined_Body (E : Entity_Id) is - function Must_Inline return Boolean; + type Inline_Level_Type is (Dont_Inline, Inline_Call, Inline_Package); + -- Level of inlining for the call: Dont_Inline means no inlining, + -- Inline_Call means that only the call is considered for inlining, + -- Inline_Package means that the call is considered for inlining and + -- its package compiled and scanned for more inlining opportunities. + + function Must_Inline return Inline_Level_Type; -- Inlining is only done if the call statement N is in the main unit, -- or within the body of another inlined subprogram. @@ -237,7 +243,7 @@ -- Must_Inline -- ----------------- - function Must_Inline return Boolean is + function Must_Inline return Inline_Level_Type is Scop : Entity_Id; Comp : Node_Id; @@ -251,7 +257,7 @@ -- trouble to try to inline at this level. if Scop = Standard_Standard then - return False; + return Dont_Inline; end if; -- Otherwise lookup scope stack to outer scope @@ -267,14 +273,19 @@ Comp := Parent (Comp); end loop; + -- If the call is in the main unit, inline the call and compile the + -- package of the subprogram to find more calls to be inlined. + if Comp = Cunit (Main_Unit) or else Comp = Library_Unit (Cunit (Main_Unit)) then Add_Call (E); - return True; + return Inline_Package; end if; - -- Call is not in main unit. See if it's in some inlined subprogram + -- The call is not in the main unit. See if it is in some inlined + -- subprogram. If so, inline the call and, if the inlining level is + -- set to 1, stop there; otherwise also compile the package as above. Scop := Current_Scope; while Scope (Scop) /= Standard_Standard @@ -284,15 +295,21 @@ and then Is_Inlined (Scop) then Add_Call (E, Scop); - return True; + if Inline_Level = 1 then + return Inline_Call; + else + return Inline_Package; + end if; end if; Scop := Scope (Scop); end loop; - return False; + return Dont_Inline; end Must_Inline; + Level : Inline_Level_Type; + -- Start of processing for Add_Inlined_Body begin @@ -309,11 +326,15 @@ -- no enclosing package to retrieve. In this case, it is the body of -- the function that will have to be loaded. - if not Is_Abstract_Subprogram (E) - and then not Is_Nested (E) - and then Convention (E) /= Convention_Protected - and then Must_Inline + if Is_Abstract_Subprogram (E) + or else Is_Nested (E) + or else Convention (E) = Convention_Protected then + return; + end if; + + Level := Must_Inline; + if Level /= Dont_Inline then declare Pack : constant Entity_Id := Get_Code_Unit_Entity (E); @@ -339,7 +360,8 @@ -- declares the type, and that body is visible to the back end. -- Do not inline it either if it is in the main unit. - elsif not Is_Inlined (Pack) + elsif Level = Inline_Package + and then not Is_Inlined (Pack) and then Comes_From_Source (E) and then not In_Main_Unit_Or_Subunit (Pack) then Index: usage.adb =================================================================== --- usage.adb (revision 188428) +++ usage.adb (working copy) @@ -298,7 +298,7 @@ -- Line for -gnatn switch - Write_Switch_Char ("n"); + Write_Switch_Char ("n[d]"); Write_Line ("Enable pragma Inline (both within and across units)"); -- Line for -gnatN switch Index: gnat_ugn.texi =================================================================== --- gnat_ugn.texi (revision 188441) +++ gnat_ugn.texi (working copy) @@ -4302,11 +4302,15 @@ is abandoned. The equal sign here is optional. A value of zero means that no limit applies. -@item -gnatn +@item -gnatn[12] @cindex @option{-gnatn} (@command{gcc}) -Activate inlining for subprograms for which -pragma @code{Inline} is specified. This inlining is performed -by the GCC back-end. +Activate inlining for subprograms for which pragma @code{Inline} is +specified. This inlining is performed by the GCC back-end. An optional +digit sets the inlining level: 1 for moderate inlining across modules, +which is a good compromise between compilation times and performances +at run time, and 2 for full inlining across modules, which may bring +about longer compilation times. If no inlining level is specified, +the compiler will pick it based on the optimization level. @item -gnatN @cindex @option{-gnatN} (@command{gcc}) Index: gnat1drv.adb =================================================================== --- gnat1drv.adb (revision 188449) +++ gnat1drv.adb (working copy) @@ -505,6 +505,17 @@ Tagged_Type_Expansion := False; end if; + + -- If the inlining level has not been set by the user, compute it from + -- the optimization level: 1 at -O1/-O2 (and -Os), 2 at -O3 and above. + + if Inline_Level = 0 then + if Optimization_Level < 3 then + Inline_Level := 1; + else + Inline_Level := 2; + end if; + end if; end Adjust_Global_Switches; -------------------- Index: opt.ads =================================================================== --- opt.ads (revision 188428) +++ opt.ads (working copy) @@ -733,6 +733,12 @@ -- Set True to activate pragma Inline processing across modules. Default -- for now is not to inline across module boundaries. + Inline_Level : Nat := 0; + -- GNAT + -- Set to indicate the inlining level: 0 means that an appropriate value + -- is to be computed by the compiler, 1 is for moderate inlining across + -- modules and 2 for full inlining across modules. + Interface_Library_Unit : Boolean := False; -- GNATBIND -- Set to True to indicate that at least one ALI file is an interface ALI: