From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 79184 invoked by alias); 26 May 2015 10:35:54 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 79175 invoked by uid 89); 26 May 2015 10:35:54 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=0.8 required=5.0 tests=BAYES_50,NO_DNS_FOR_FROM autolearn=no version=3.3.2 X-HELO: rock.gnat.com Received: from Unknown (HELO rock.gnat.com) (205.232.38.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-SHA encrypted) ESMTPS; Tue, 26 May 2015 10:35:28 +0000 Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id A3F6428A4F; Tue, 26 May 2015 06:35:20 -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 wkczS88aet85; Tue, 26 May 2015 06:35:20 -0400 (EDT) Received: from kwai.gnat.com (kwai.gnat.com [IPv6:2620:20:4000:0:7a2b:cbff:fe60:cb11]) by rock.gnat.com (Postfix) with ESMTP id 93110D393B; Tue, 26 May 2015 06:35:20 -0400 (EDT) Received: by kwai.gnat.com (Postfix, from userid 4192) id 8D608439C4; Tue, 26 May 2015 06:35:20 -0400 (EDT) Date: Tue, 26 May 2015 11:03:00 -0000 From: Arnaud Charlet To: gcc-patches@gcc.gnu.org Cc: Robert Dewar Subject: [Ada] Ensure consistency of fpt exponentiation results Message-ID: <20150526103520.GA27917@adacore.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="BOKacYhQ+x31HxR3" Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-SW-Source: 2015-05/txt/msg02316.txt.bz2 --BOKacYhQ+x31HxR3 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-length: 538 This change ensures on all targets that A**B = A**C when B is a small static constant in the range 0 .. 4 and C is a variable with the same value. Previously for Float and Long_Float on some targets, this was not the case. The results given were both within the error bounds that are allowed by the Ada standard, but it is desirable not to have this discrepancy. Tested on x86_64-pc-linux-gnu, committed on trunk 2015-05-26 Robert Dewar * exp_ch4.adb (Wrap_MA): New function. (Expand_N_Op_Expon): Use Wrap_MA. --BOKacYhQ+x31HxR3 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=difs Content-length: 8026 Index: exp_ch4.adb =================================================================== --- exp_ch4.adb (revision 223672) +++ exp_ch4.adb (working copy) @@ -7580,6 +7580,33 @@ Etyp : Entity_Id; Xnode : Node_Id; + function Wrap_MA (Exp : Node_Id) return Node_Id; + -- Given an expression Exp, if the root type is Float or Long_Float, + -- then wrap the expression in a call of Bastyp'Machine, to stop any + -- extra precision. This is done to ensure that X**A = X**B when A is + -- a static constant and B is a variable with the same value. For any + -- other type, the node Exp is returned unchanged. + + ------------- + -- Wrap_MA -- + ------------- + + function Wrap_MA (Exp : Node_Id) return Node_Id is + Loc : constant Source_Ptr := Sloc (Exp); + begin + if Rtyp = Standard_Float or else Rtyp = Standard_Long_Float then + return + Make_Attribute_Reference (Loc, + Attribute_Name => Name_Machine, + Prefix => New_Occurrence_Of (Bastyp, Loc), + Expressions => New_List (Relocate_Node (Exp))); + else + return Exp; + end if; + end Wrap_MA; + + -- Start of processing for Expand_N_Op + begin Binary_Op_Validity_Checks (N); @@ -7637,7 +7664,7 @@ -- could fold small negative exponents for the real case, but we -- can't because we are required to raise Constraint_Error for -- the case of 0.0 ** (negative) even if Machine_Overflows = False. - -- See ACVC test C4A012B. + -- See ACVC test C4A012B, and it is not worth generating the test. if Expv >= 0 and then Expv <= 4 then @@ -7666,20 +7693,22 @@ elsif Expv = 2 then Xnode := - Make_Op_Multiply (Loc, - Left_Opnd => Duplicate_Subexpr (Base), - Right_Opnd => Duplicate_Subexpr_No_Checks (Base)); + Wrap_MA ( + Make_Op_Multiply (Loc, + Left_Opnd => Duplicate_Subexpr (Base), + Right_Opnd => Duplicate_Subexpr_No_Checks (Base))); -- X ** 3 = X * X * X elsif Expv = 3 then Xnode := - Make_Op_Multiply (Loc, - Left_Opnd => - Make_Op_Multiply (Loc, - Left_Opnd => Duplicate_Subexpr (Base), - Right_Opnd => Duplicate_Subexpr_No_Checks (Base)), - Right_Opnd => Duplicate_Subexpr_No_Checks (Base)); + Wrap_MA ( + Make_Op_Multiply (Loc, + Left_Opnd => + Make_Op_Multiply (Loc, + Left_Opnd => Duplicate_Subexpr (Base), + Right_Opnd => Duplicate_Subexpr_No_Checks (Base)), + Right_Opnd => Duplicate_Subexpr_No_Checks (Base))); -- X ** 4 -> @@ -7700,16 +7729,18 @@ Constant_Present => True, Object_Definition => New_Occurrence_Of (Typ, Loc), Expression => - Make_Op_Multiply (Loc, - Left_Opnd => - Duplicate_Subexpr (Base), - Right_Opnd => - Duplicate_Subexpr_No_Checks (Base)))), + Wrap_MA ( + Make_Op_Multiply (Loc, + Left_Opnd => + Duplicate_Subexpr (Base), + Right_Opnd => + Duplicate_Subexpr_No_Checks (Base))))), Expression => - Make_Op_Multiply (Loc, - Left_Opnd => New_Occurrence_Of (Temp, Loc), - Right_Opnd => New_Occurrence_Of (Temp, Loc))); + Wrap_MA ( + Make_Op_Multiply (Loc, + Left_Opnd => New_Occurrence_Of (Temp, Loc), + Right_Opnd => New_Occurrence_Of (Temp, Loc)))); end if; Rewrite (N, Xnode); @@ -7900,10 +7931,10 @@ if Is_Modular_Integer_Type (Rtyp) then - -- Nonbinary case, we call the special exponentiation routine for - -- the nonbinary case, converting the argument to Long_Long_Integer - -- and passing the modulus value. Then the result is converted back - -- to the base type. + -- Nonbinary modular case, we call the special exponentiation + -- routine for the nonbinary case, converting the argument to + -- Long_Long_Integer and passing the modulus value. Then the + -- result is converted back to the base type. if Non_Binary_Modulus (Rtyp) then Rewrite (N, @@ -7916,9 +7947,9 @@ Make_Integer_Literal (Loc, Modulus (Rtyp)), Exp)))); - -- Binary case, in this case, we call one of two routines, either the - -- unsigned integer case, or the unsigned long long integer case, - -- with a final "and" operation to do the required mod. + -- Binary modular case, in this case, we call one of two routines, + -- either the unsigned integer case, or the unsigned long long + -- integer case, with a final "and" operation to do the required mod. else if UI_To_Int (Esize (Rtyp)) <= Standard_Integer_Size then @@ -7986,16 +8017,32 @@ Rent := RE_Exn_Integer; end if; - -- Floating-point cases, always done using Long_Long_Float. We do not - -- need separate routines for the overflow case here, since in the case - -- of floating-point, we generate infinities anyway as a rule (either - -- that or we automatically trap overflow), and if there is an infinity - -- generated and a range check is required, the check will fail anyway. + -- Floating-point cases. We do not need separate routines for the + -- overflow case here, since in the case of floating-point, we generate + -- infinities anyway as a rule (either that or we automatically trap + -- overflow), and if there is an infinity generated and a range check + -- is required, the check will fail anyway. + -- Historical note: we used to convert everything to Long_Long_Float + -- and call a single common routine, but this had the undesirable effect + -- of giving different results for small static exponent values and the + -- same dynamic values. + else pragma Assert (Is_Floating_Point_Type (Rtyp)); - Etyp := Standard_Long_Long_Float; - Rent := RE_Exn_Long_Long_Float; + + if Rtyp = Standard_Float then + Etyp := Standard_Float; + Rent := RE_Exn_Float; + + elsif Rtyp = Standard_Long_Float then + Etyp := Standard_Long_Float; + Rent := RE_Exn_Long_Float; + + else + Etyp := Standard_Long_Long_Float; + Rent := RE_Exn_Long_Long_Float; + end if; end if; -- Common processing for integer cases and floating-point cases. @@ -8006,9 +8053,10 @@ and then Rtyp /= Universal_Real then Rewrite (N, - Make_Function_Call (Loc, - Name => New_Occurrence_Of (RTE (Rent), Loc), - Parameter_Associations => New_List (Base, Exp))); + Wrap_MA ( + Make_Function_Call (Loc, + Name => New_Occurrence_Of (RTE (Rent), Loc), + Parameter_Associations => New_List (Base, Exp)))); -- Otherwise we have to introduce conversions (conversions are also -- required in the universal cases, since the runtime routine is --BOKacYhQ+x31HxR3--