From patchwork Tue Oct 2 08:05:19 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arnaud Charlet X-Patchwork-Id: 188419 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 CD7172C00A5 for ; Tue, 2 Oct 2012 18:05:45 +1000 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1349769946; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Received:Received:Date:From:To:Cc:Subject:Message-ID: MIME-Version:Content-Type:Content-Disposition:User-Agent: Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:Sender:Delivered-To; bh=qyzjOQpG9SWey7ROmuaA FNQFnGk=; b=KU4idwLvGViTy461QQgluAr6N2TXlT+BKG56AAHMcLWSpupJo9hE kQawW8ViMzvQxS4cW6UNi68lObd5ObLS4dJW8A9kdCBGgUobn8+2rvrtMtkMLW1X 2Uwb1ARM6xPjUPvo74ZSAZ4yCcFtDihjGrtSdIOq3IljeNHgaqHLJLE= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:Received:Received:Received:Date:From:To:Cc:Subject:Message-ID:MIME-Version:Content-Type:Content-Disposition:User-Agent:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=iyPw1nT+w6dhDN5uSxvk1hhnymt9nsoak0kS2tYx1yluViB6VBkmsk5JAfQA9o XKe/YnRESSBZgpJu8lk/5M9sONACkSPU4pWC1M4xI6t39tdoyfIdF0RRulEroi6U 8tVfss2/JA4PlHNYcSf6afO8ugtjD6+arhCtC4vl1lS7k=; Received: (qmail 22039 invoked by alias); 2 Oct 2012 08:05:29 -0000 Received: (qmail 22002 invoked by uid 22791); 2 Oct 2012 08:05:26 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL, BAYES_00, KHOP_SPAMHAUS_DROP, RCVD_IN_HOSTKARMA_NO 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 Oct 2012 08:05:20 +0000 Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id 9A7DF1C61E2; Tue, 2 Oct 2012 04:05:19 -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 Z+3C4fsL5JkT; Tue, 2 Oct 2012 04:05:19 -0400 (EDT) Received: from kwai.gnat.com (kwai.gnat.com [205.232.38.4]) by rock.gnat.com (Postfix) with ESMTP id 7EFE11C6112; Tue, 2 Oct 2012 04:05:19 -0400 (EDT) Received: by kwai.gnat.com (Postfix, from userid 4192) id 7B4BB919E3; Tue, 2 Oct 2012 04:05:19 -0400 (EDT) Date: Tue, 2 Oct 2012 04:05:19 -0400 From: Arnaud Charlet To: gcc-patches@gcc.gnu.org Cc: Robert Dewar Subject: [Ada] Avoid unnecessary use of Bignums for ELIMINATED mode Message-ID: <20121002080519.GA27067@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 Previously there were cases where the result of an operator was converted to Bignum, only to be immediately converted back to Long_Long_Integer with an overflow check. This patch removes this unnecessary inefficiency. The following program: 1. procedure toplevov 2. (a : in out long_long_integer; 3. b : long_long_integer) 4. is 5. begin 6. a := b * b; 7. end; Now generates the following output when compiled with -gnatG -gnato3. procedure toplevov (a : in out long_long_integer; b : long_long_integer) is begin a := long_long_integer(b) {*} long_long_integer(b); return; end toplevov; Previously it generated Bignum operations Tested on x86_64-pc-linux-gnu, committed on trunk 2012-10-02 Robert Dewar * checks.ads, exp_ch4.adb, checks.adb (Minimize_Eliminate_Overflow_Checks): Add Top_Level parameter to avoid unnecessary conversions to Bignum. Minor reformatting. Index: checks.adb =================================================================== --- checks.adb (revision 191921) +++ checks.adb (working copy) @@ -1113,8 +1113,11 @@ -- Otherwise, we have a top level arithmetic operator node, and this -- is where we commence the special processing for minimize/eliminate. + -- This is the case where we tell the machinery not to move into Bignum + -- mode at this top level (of course the top level operation will still + -- be in Bignum mode if either of its operands are of type Bignum). - Minimize_Eliminate_Overflow_Checks (Op, Lo, Hi); + Minimize_Eliminate_Overflow_Checks (Op, Lo, Hi, Top_Level => True); -- That call may but does not necessarily change the result type of Op. -- It is the job of this routine to undo such changes, so that at the @@ -2333,23 +2336,24 @@ Error_Msg_N ("\this will result in infinite recursion?", Parent (N)); Insert_Action (N, - Make_Raise_Storage_Error - (Sloc (N), Reason => SE_Infinite_Recursion)); + Make_Raise_Storage_Error (Sloc (N), + Reason => SE_Infinite_Recursion)); + -- Here for normal case of predicate active. + else - -- If the predicate is a static predicate and the operand is -- static, the predicate must be evaluated statically. If the -- evaluation fails this is a static constraint error. if Is_OK_Static_Expression (N) then - if Present (Static_Predicate (Typ)) then + if Present (Static_Predicate (Typ)) then if Eval_Static_Predicate_Check (N, Typ) then return; else Error_Msg_NE ("static expression fails static predicate check on&", - N, Typ); + N, Typ); end if; end if; end if; @@ -6549,9 +6553,10 @@ ---------------------------------------- procedure Minimize_Eliminate_Overflow_Checks - (N : Node_Id; - Lo : out Uint; - Hi : out Uint) + (N : Node_Id; + Lo : out Uint; + Hi : out Uint; + Top_Level : Boolean) is pragma Assert (Is_Signed_Integer_Type (Etype (N))); @@ -6578,6 +6583,11 @@ OK : Boolean; -- Used in call to Determine_Range + Bignum_Operands : Boolean; + -- Set True if one or more operands is already of type Bignum, meaning + -- that for sure (regardless of Top_Level setting) we are committed to + -- doing the operation in Bignum mode. + procedure Max (A : in out Uint; B : Uint); -- If A is No_Uint, sets A to B, else to UI_Max (A, B); @@ -6609,7 +6619,7 @@ -- Start of processing for Minimize_Eliminate_Overflow_Checks begin - -- Case where we do not have an arithmetic operator. + -- Case where we do not have an arithmetic operator if not Is_Signed_Integer_Arithmetic_Op (N) then @@ -6638,10 +6648,12 @@ -- that lies below us!) else - Minimize_Eliminate_Overflow_Checks (Right_Opnd (N), Rlo, Rhi); + Minimize_Eliminate_Overflow_Checks + (Right_Opnd (N), Rlo, Rhi, Top_Level => False); if Binary then - Minimize_Eliminate_Overflow_Checks (Left_Opnd (N), Llo, Lhi); + Minimize_Eliminate_Overflow_Checks + (Left_Opnd (N), Llo, Lhi, Top_Level => False); end if; end if; @@ -6650,10 +6662,13 @@ if Rlo = No_Uint or else (Binary and then Llo = No_Uint) then Lo := No_Uint; Hi := No_Uint; + Bignum_Operands := True; -- Otherwise compute result range else + Bignum_Operands := False; + case Nkind (N) is -- Absolute value @@ -7007,15 +7022,34 @@ if Lo = No_Uint or else Lo < LLLo or else Hi > LLHi then - -- In MINIMIZED mode, note that an overflow check is required - -- Note that we know we don't have a Bignum, since Bignums only - -- appear in Eliminated mode. + -- OK, we are definitely outside the range of Long_Long_Integer. The + -- question is whether to move into Bignum mode, or remain the domain + -- of Long_Long_Integer, signalling that an overflow check is needed. - if Check_Mode = Minimized then + -- Obviously in MINIMIZED mode we stay with LLI, since we are not in + -- the Bignum business. In ELIMINATED mode, we will normally move + -- into Bignum mode, but there is an exception if neither of our + -- operands is Bignum now, and we are at the top level (Top_Level + -- set True). In this case, there is no point in moving into Bignum + -- mode to prevent overflow if the caller will immediately convert + -- the Bignum value back to LLI with an overflow check. It's more + -- efficient to stay in LLI mode with an overflow check. + + if Check_Mode = Minimized + or else (Top_Level and not Bignum_Operands) + then Enable_Overflow_Check (N); - -- Otherwise we are in ELIMINATED mode, switch to bignum + -- Since we are doing an overflow check, the result has to be in + -- Long_Long_Integer mode, so adjust the possible range to reflect + -- this. Note these calls also change No_Uint values from the top + -- level case to LLI bounds. + Max (Lo, LLLo); + Min (Hi, LLHi); + + -- Otherwise we are in ELIMINATED mode and we switch to Bignum mode + else pragma Assert (Check_Mode = Eliminated); @@ -7079,6 +7113,11 @@ Name => New_Occurrence_Of (Fent, Loc), Parameter_Associations => Args)); Analyze_And_Resolve (N, RTE (RE_Bignum)); + + -- Indicate result is Bignum mode + + Lo := No_Uint; + Hi := No_Uint; return; end; end if; Index: checks.ads =================================================================== --- checks.ads (revision 191920) +++ checks.ads (working copy) @@ -260,9 +260,10 @@ -- parameter is used to supply Sloc values for the constructed tree. procedure Minimize_Eliminate_Overflow_Checks - (N : Node_Id; - Lo : out Uint; - Hi : out Uint); + (N : Node_Id; + Lo : out Uint; + Hi : out Uint; + Top_Level : Boolean); -- This is the main routine for handling MINIMIZED and ELIMINATED overflow -- checks. On entry N is a node whose result is a signed integer subtype. -- If the node is an artihmetic operation, then a range analysis is carried @@ -321,6 +322,16 @@ -- -- Note that if Bignum values appear, the caller must take care of doing -- the appropriate mark/release operation on the secondary stack. + -- + -- Top_Level is used to avoid inefficient unnecessary transitions into the + -- Bignum domain. If Top_Level is True, it means that the caller will have + -- to convert any Bignum value back to Long_Long_Integer, checking that the + -- value is in range. This is the normal case for a top level operator in + -- a subexpression. There is no point in going into Bignum mode to avoid an + -- overflow just so we can check for overflow the next moment. For calls + -- from comparisons and membership tests, and for all recursive calls, we + -- do want to transition into the Bignum domain if necessary. Note that + -- this setting is only relevant in ELIMINATED mode. ------------------------------------------------------- -- Control and Optimization of Range/Overflow Checks -- Index: exp_ch4.adb =================================================================== --- exp_ch4.adb (revision 191920) +++ exp_ch4.adb (working copy) @@ -2345,8 +2345,10 @@ -- our operands using the Minimize_Eliminate circuitry which applies -- this processing to the two operand subtrees. - Minimize_Eliminate_Overflow_Checks (Left_Opnd (N), Llo, Lhi); - Minimize_Eliminate_Overflow_Checks (Right_Opnd (N), Rlo, Rhi); + Minimize_Eliminate_Overflow_Checks + (Left_Opnd (N), Llo, Lhi, Top_Level => False); + Minimize_Eliminate_Overflow_Checks + (Right_Opnd (N), Rlo, Rhi, Top_Level => False); -- See if the range information decides the result of the comparison @@ -3735,7 +3737,7 @@ -- Entity for Long_Long_Integer'Base (Standard should export this???) begin - Minimize_Eliminate_Overflow_Checks (Lop, Lo, Hi); + Minimize_Eliminate_Overflow_Checks (Lop, Lo, Hi, Top_Level => False); -- If right operand is a subtype name, and the subtype name has no -- predicate, then we can just replace the right operand with an @@ -3760,8 +3762,10 @@ -- have not been processed for minimized or eliminated checks. if Nkind (Rop) = N_Range then - Minimize_Eliminate_Overflow_Checks (Low_Bound (Rop), Lo, Hi); - Minimize_Eliminate_Overflow_Checks (High_Bound (Rop), Lo, Hi); + Minimize_Eliminate_Overflow_Checks + (Low_Bound (Rop), Lo, Hi, Top_Level => False); + Minimize_Eliminate_Overflow_Checks + (High_Bound (Rop), Lo, Hi, Top_Level => False); -- We have A in B .. C, treated as A >= B and then A <= C