public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [Ada] Ensure consistency of fpt exponentiation results
@ 2015-05-26 11:03 Arnaud Charlet
  2015-05-26 21:31 ` Eric Botcazou
  0 siblings, 1 reply; 2+ messages in thread
From: Arnaud Charlet @ 2015-05-26 11:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: Robert Dewar

[-- Attachment #1: Type: text/plain, Size: 538 bytes --]

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  <dewar@adacore.com>

	* exp_ch4.adb (Wrap_MA): New function.
	(Expand_N_Op_Expon): Use Wrap_MA.


[-- Attachment #2: difs --]
[-- Type: text/plain, Size: 8026 bytes --]

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

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [Ada] Ensure consistency of fpt exponentiation results
  2015-05-26 11:03 [Ada] Ensure consistency of fpt exponentiation results Arnaud Charlet
@ 2015-05-26 21:31 ` Eric Botcazou
  0 siblings, 0 replies; 2+ messages in thread
From: Eric Botcazou @ 2015-05-26 21:31 UTC (permalink / raw)
  To: gcc-patches; +Cc: Arnaud Charlet, Robert Dewar

[-- Attachment #1: Type: text/plain, Size: 754 bytes --]

> 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.

This uncovered a bug in gigi, responsible for 

                === acats tests ===
FAIL:  c44003d


Fixed thusly, tested on x86_64-suse-linux, applied on the mainline.


2015-05-26  Eric Botcazou  <ebotcazou@adacore.com>

	* gcc-interface/trans.c (Attribute_to_gnu) <Attr_Machine>: Do not apply
	extra-precision trick to literals.  Build SAVE_EXPR manually.


-- 
Eric Botcazou

[-- Attachment #2: p.diff --]
[-- Type: text/x-patch, Size: 896 bytes --]

Index: gcc-interface/trans.c
===================================================================
--- gcc-interface/trans.c	(revision 223709)
+++ gcc-interface/trans.c	(working copy)
@@ -2428,7 +2428,8 @@ Attribute_to_gnu (Node_Id gnat_node, tre
       gnu_result_type = get_unpadded_type (Etype (gnat_node));
       gnu_result = convert (gnu_result_type, gnu_expr);
 
-      if (fp_arith_may_widen
+      if (TREE_CODE (gnu_result) != REAL_CST
+	  && fp_arith_may_widen
 	  && TYPE_PRECISION (gnu_result_type)
 	     < TYPE_PRECISION (longest_float_type_node))
 	{
@@ -2441,7 +2442,7 @@ Attribute_to_gnu (Node_Id gnat_node, tre
 	  finish_record_type (rec_type, field, 0, false);
 
 	  rec_val = build_constructor_single (rec_type, field, gnu_result);
-	  rec_val = save_expr (rec_val);
+	  rec_val = build1 (SAVE_EXPR, rec_type, rec_val);
 
 	  asm_expr
 	    = build5 (ASM_EXPR, void_type_node,

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2015-05-26 20:20 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-26 11:03 [Ada] Ensure consistency of fpt exponentiation results Arnaud Charlet
2015-05-26 21:31 ` Eric Botcazou

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).