From patchwork Wed Apr 27 11:01:53 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnaud Charlet X-Patchwork-Id: 615557 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]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3qvy2135PTz9sC3 for ; Wed, 27 Apr 2016 21:11:05 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=NEfZXGaw; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:mime-version:content-type; q=dns; s=default; b=GS1TyId7GgVIeCI2UlDN8/qUZGeAAFDxYGabSP9e6phx//khKl sQaFmgxgd2zUAGveeLSqey+dGSjv4dIwg0o2DNDNHMoDU+tsHRSVOgeK6SrblkKt e+rVILMhkqUdll9CMcbR+N2JhluQ9qDzJR/lbbBNzmU4mGRDwByy0pqes= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:mime-version:content-type; s= default; bh=yZvTr2EEhUOEtanFt/nG/Lm9lJE=; b=NEfZXGawT+nEeqxrBCSe MMY7mytYJuX8f64tVJ2JvMkJnxPAulRWHF72Yy74jDaGrOeNXhiXjq67zjYuEWju aWfA+WRN9u9+O7z5Q1+Ka2bQwg14aTjYNsxphq8s3OndeYwQssMoVmFoYDUA7Vac wfPV2GeVaHkgAr/HKIwIc4U= Received: (qmail 693 invoked by alias); 27 Apr 2016 11:10:27 -0000 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 Received: (qmail 74897 invoked by uid 89); 27 Apr 2016 11:02:10 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=1.0 required=5.0 tests=AWL, BAYES_00, KAM_ASCII_DIVIDERS, KAM_LAZY_DOMAIN_SECURITY, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.2 spammy=ebotcazouadacorecom, ebotcazou@adacore.com, entity_id, ekind X-HELO: rock.gnat.com Received: from rock.gnat.com (HELO rock.gnat.com) (205.232.38.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-SHA encrypted) ESMTPS; Wed, 27 Apr 2016 11:01:55 +0000 Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id ECE42116CA8; Wed, 27 Apr 2016 07:01:53 -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 mW62G6XIYfNk; Wed, 27 Apr 2016 07:01:53 -0400 (EDT) Received: from tron.gnat.com (tron.gnat.com [205.232.38.10]) by rock.gnat.com (Postfix) with ESMTP id DC682116CA6; Wed, 27 Apr 2016 07:01:53 -0400 (EDT) Received: by tron.gnat.com (Postfix, from userid 4192) id DB5BA370; Wed, 27 Apr 2016 07:01:53 -0400 (EDT) Date: Wed, 27 Apr 2016 07:01:53 -0400 From: Arnaud Charlet To: gcc-patches@gcc.gnu.org Cc: Eric Botcazou Subject: [Ada] Expression functions need not trigger loading of package body Message-ID: <20160427110153.GA54961@adacore.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.23 (2014-03-12) The expression functions introduced in Ada 2012 implicitly come with the Inline aspect in GNAT. And, for inter-unit inlining, they were handled by the inlining machinery as any other inlined subprograms, which means that they were causing the package body (if any) to be loaded and analyzed. That's both unnecessary and inefficient, so this patch corrects it as well as streamlines the implementation of the main entry point for inlining. The change can be exhibited by the now quiet compilation of Client in: with P; procedure Client is X : Boolean := P.Foo; begin null; end Client; package P is function Foo return Boolean is (True); procedure Other; end P; package body P is procedure Other is begin Unrelated; end Other; end P; Tested on x86_64-pc-linux-gnu, committed on trunk 2016-04-27 Eric Botcazou * inline.adb (Add_Inlined_Body): Overhaul implementation, robustify handling of -gnatn1, add special treatment for expression functions. Index: inline.adb =================================================================== --- inline.adb (revision 235481) +++ inline.adb (working copy) @@ -6,7 +6,7 @@ -- -- -- B o d y -- -- -- --- Copyright (C) 1992-2015, Free Software Foundation, Inc. -- +-- Copyright (C) 1992-2016, 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- -- @@ -390,6 +390,40 @@ return; end if; + -- Find out whether the call must be inlined. Unless the result is + -- Dont_Inline, Must_Inline also creates an edge for the call in the + -- callgraph; however, it will not be activated until after Is_Called + -- is set on the subprogram. + + Level := Must_Inline; + + if Level = Dont_Inline then + return; + end if; + + -- If the call was generated by the compiler and is to a subprogram in + -- a run-time unit, we need to suppress debugging information for it, + -- so that the code that is eventually inlined will not affect the + -- debugging of the program. We do not do it if the call comes from + -- source because, even if the call is inlined, the user may expect it + -- to be present in the debugging information. + + if not Comes_From_Source (N) + and then In_Extended_Main_Source_Unit (N) + and then + Is_Predefined_File_Name (Unit_File_Name (Get_Source_Unit (E))) + then + Set_Needs_Debug_Info (E, False); + end if; + + -- If the subprogram is an expression function, then there is no need to + -- load any package body since the body of the function is in the spec. + + if Is_Expression_Function (E) then + Set_Is_Called (E); + return; + end if; + -- Find unit containing E, and add to list of inlined bodies if needed. -- If the body is already present, no need to load any other unit. This -- is the case for an initialization procedure, which appears in the @@ -403,77 +437,48 @@ -- no enclosing package to retrieve. In this case, it is the body of -- the function that will have to be loaded. - Level := Must_Inline; + declare + Pack : constant Entity_Id := Get_Code_Unit_Entity (E); - if Level /= Dont_Inline then - declare - Pack : constant Entity_Id := Get_Code_Unit_Entity (E); + begin + if Pack = E then + Set_Is_Called (E); + Inlined_Bodies.Increment_Last; + Inlined_Bodies.Table (Inlined_Bodies.Last) := E; - begin - -- Ensure that Analyze_Inlined_Bodies will be invoked after - -- completing the analysis of the current unit. + elsif Ekind (Pack) = E_Package then + Set_Is_Called (E); - Inline_Processing_Required := True; + if Is_Generic_Instance (Pack) then + null; - if Pack = E then + -- Do not inline the package if the subprogram is an init proc + -- or other internally generated subprogram, because in that + -- case the subprogram body appears in the same unit that + -- declares the type, and that body is visible to the back end. + -- Do not inline it either if it is in the main unit. + -- Extend the -gnatn2 processing to -gnatn1 for Inline_Always + -- calls if the back-end takes care of inlining the call. - -- Library-level inlined function. Add function itself to - -- list of needed units. - - Set_Is_Called (E); + elsif (Level = Inline_Package + or else (Level = Inline_Call + and then Has_Pragma_Inline_Always (E) + and then Back_End_Inlining)) + and then not Is_Inlined (Pack) + and then not Is_Internal (E) + and then not In_Main_Unit_Or_Subunit (Pack) + then + Set_Is_Inlined (Pack); Inlined_Bodies.Increment_Last; - Inlined_Bodies.Table (Inlined_Bodies.Last) := E; - - elsif Ekind (Pack) = E_Package then - Set_Is_Called (E); - - if Is_Generic_Instance (Pack) then - null; - - -- Do not inline the package if the subprogram is an init proc - -- or other internally generated subprogram, because in that - -- case the subprogram body appears in the same unit that - -- 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 Level = Inline_Package - and then not Is_Inlined (Pack) - and then not Is_Internal (E) - and then not In_Main_Unit_Or_Subunit (Pack) - then - Set_Is_Inlined (Pack); - Inlined_Bodies.Increment_Last; - Inlined_Bodies.Table (Inlined_Bodies.Last) := Pack; - - -- Extend the -gnatn2 processing to -gnatn1 for Inline_Always - -- calls if the back-end takes care of inlining the call. - - elsif Level = Inline_Call - and then Has_Pragma_Inline_Always (E) - and then Back_End_Inlining - then - Set_Is_Inlined (Pack); - Inlined_Bodies.Increment_Last; - Inlined_Bodies.Table (Inlined_Bodies.Last) := Pack; - end if; + Inlined_Bodies.Table (Inlined_Bodies.Last) := Pack; end if; + end if; - -- If the call was generated by the compiler and is to a function - -- in a run-time unit, we need to suppress debugging information - -- for it, so that the code that is eventually inlined will not - -- affect debugging of the program. We do not do it if the call - -- comes from source because, even if the call is inlined, the - -- user may expect it to be present in the debugging information. + -- Ensure that Analyze_Inlined_Bodies will be invoked after + -- completing the analysis of the current unit. - if not Comes_From_Source (N) - and then In_Extended_Main_Source_Unit (N) - and then - Is_Predefined_File_Name (Unit_File_Name (Get_Source_Unit (E))) - then - Set_Needs_Debug_Info (E, False); - end if; - end; - end if; + Inline_Processing_Required := True; + end; end Add_Inlined_Body; ----------------------------