From patchwork Tue Aug 2 15:04:57 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnaud Charlet X-Patchwork-Id: 107942 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id B2D16B71C5 for ; Wed, 3 Aug 2011 01:05:31 +1000 (EST) Received: (qmail 28029 invoked by alias); 2 Aug 2011 15:05:29 -0000 Received: (qmail 28018 invoked by uid 22791); 2 Aug 2011 15:05:25 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL,BAYES_00 X-Spam-Check-By: sourceware.org Received: from rock.gnat.com (HELO rock.gnat.com) (205.232.38.15) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 02 Aug 2011 15:05:03 +0000 Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id AB3F02BB14C; Tue, 2 Aug 2011 11:04:57 -0400 (EDT) Received: from rock.gnat.com ([127.0.0.1]) by localhost (rock.gnat.com [127.0.0.1]) (amavisd-new, port 10024) with LMTP id 8j6gZQjNa1Ik; Tue, 2 Aug 2011 11:04:57 -0400 (EDT) Received: from kwai.gnat.com (kwai.gnat.com [205.232.38.4]) by rock.gnat.com (Postfix) with ESMTP id 97E082BB049; Tue, 2 Aug 2011 11:04:57 -0400 (EDT) Received: by kwai.gnat.com (Postfix, from userid 4192) id 8A13D3FEE8; Tue, 2 Aug 2011 11:04:57 -0400 (EDT) Date: Tue, 2 Aug 2011 11:04:57 -0400 From: Arnaud Charlet To: gcc-patches@gcc.gnu.org Cc: Ed Schonberg Subject: [Ada] Inline expression functions whenever possible Message-ID: <20110802150457.GA17707@adacore.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.20 (2009-06-14) Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org This patch treats expression functions as functions with an implicit pragma Inline_Always. This ensures that they are chained to the list of inlined subprograms of the enclosing unit, and made available to the back end for inlining. The front-end does not examine whether inlining is actually possible because the back end can do this more accurately. Tested on x86_64-pc-linux-gnu, committed on trunk 2011-08-02 Ed Schonberg * sem_ch6 (Analyze_Expression_Function): treat the function as Inline_Always, and introduce a subprogram declaration for it when it is not a completion. * inline.adb (Add_Inlined_Body): recognize bodies that come from expression functions, so that the back-end can determine whether they can in fact be inlined. * sem_util.adb (Is_Expression_Function): predicate to determine whether a function body comes from an expression function. Index: inline.adb =================================================================== --- inline.adb (revision 177144) +++ inline.adb (working copy) @@ -6,7 +6,7 @@ -- -- -- B o d y -- -- -- --- Copyright (C) 1992-2010, Free Software Foundation, Inc. -- +-- Copyright (C) 1992-2011, Free Software Foundation, Inc. -- -- -- -- GNAT is free software; you can redistribute it and/or modify it under -- -- terms of the GNU General Public License as published by the Free Soft- -- @@ -342,7 +342,9 @@ null; elsif not Is_Inlined (Pack) - and then not Has_Completion (E) + and then + (not Has_Completion (E) + or else Is_Expression_Function (E)) then Set_Is_Inlined (Pack); Inlined_Bodies.Increment_Last; Index: sem_util.adb =================================================================== --- sem_util.adb (revision 177153) +++ sem_util.adb (working copy) @@ -6541,6 +6541,26 @@ end if; end Is_Descendent_Of; + ---------------------------- + -- Is_Expression_Function -- + ---------------------------- + + function Is_Expression_Function (Subp : Entity_Id) return Boolean is + Decl : constant Node_Id := Unit_Declaration_Node (Subp); + + begin + return Ekind (Subp) = E_Function + and then Nkind (Decl) = N_Subprogram_Declaration + and then + (Nkind (Original_Node (Decl)) = N_Expression_Function + or else + (Present (Corresponding_Body (Decl)) + and then + Nkind (Original_Node + (Unit_Declaration_Node (Corresponding_Body (Decl)))) + = N_Expression_Function)); + end Is_Expression_Function; + -------------- -- Is_False -- -------------- Index: sem_util.ads =================================================================== --- sem_util.ads (revision 177152) +++ sem_util.ads (working copy) @@ -6,7 +6,7 @@ -- -- -- S p e c -- -- -- --- Copyright (C) 1992-2010, Free Software Foundation, Inc. -- +-- Copyright (C) 1992-2011, Free Software Foundation, Inc. -- -- -- -- GNAT is free software; you can redistribute it and/or modify it under -- -- terms of the GNU General Public License as published by the Free Soft- -- @@ -741,6 +741,10 @@ -- First determine whether type T is an interface and then check whether -- it is of protected, synchronized or task kind. + function Is_Expression_Function (Subp : Entity_Id) return Boolean; + -- Predicate to determine whether a function entity comes from a rewritten + -- expression function, and should be inlined unconditionally. + function Is_False (U : Uint) return Boolean; pragma Inline (Is_False); -- The argument is a Uint value which is the Boolean'Pos value of a Boolean Index: sem_ch6.adb =================================================================== --- sem_ch6.adb (revision 177172) +++ sem_ch6.adb (working copy) @@ -271,6 +271,7 @@ LocX : constant Source_Ptr := Sloc (Expression (N)); Def_Id : constant Entity_Id := Defining_Entity (Specification (N)); New_Body : Node_Id; + New_Decl : Node_Id; Prev : constant Entity_Id := Current_Entity_In_Scope (Def_Id); -- If the expression is a completion, Prev is the entity whose @@ -278,9 +279,14 @@ begin -- This is one of the occasions on which we transform the tree during - -- semantic analysis. Transform the expression function into an - -- equivalent subprogram body, and then analyze that. + -- semantic analysis. If this is a completion, transform the expression + -- function into an equivalent subprogram body, and analyze it. + -- Expression functions are inlined unconditionally. The back-end will + -- determine whether this is possible. + + Inline_Processing_Required := True; + New_Body := Make_Subprogram_Body (Loc, Specification => Specification (N), @@ -304,10 +310,37 @@ Rewrite (N, Make_Null_Statement (Loc)); Analyze (N); Analyze (New_Body); + Set_Is_Inlined (Prev); - else + elsif Present (Prev) then Rewrite (N, New_Body); + Set_Is_Inlined (Prev); Analyze (N); + + -- If this is not a completion, create both a declaration and a body, + -- so that the expression can be inlined whenever possible. + + else + New_Decl := + Make_Subprogram_Declaration (Loc, + Specification => Specification (N)); + Rewrite (N, New_Decl); + Analyze (N); + Set_Is_Inlined (Defining_Entity (New_Decl)); + + -- Create new set of formals for specification in body. + + Set_Specification (New_Body, + Make_Function_Specification (Loc, + Defining_Unit_Name => + Make_Defining_Identifier (Loc, Chars (Defining_Entity (N))), + Parameter_Specifications => + Copy_Parameter_List (Defining_Entity (New_Decl)), + Result_Definition => + New_Copy_Tree (Result_Definition (Specification (New_Decl))))); + + Insert_After (N, New_Body); + Analyze (New_Body); end if; end Analyze_Expression_Function;