aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/exp_fixd.adb
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2020-11-10 12:14:56 +0100
committerPierre-Marie de Rodat <derodat@adacore.com>2020-11-30 09:16:19 -0500
commit2bf891fa752e18b872d6c06d541aed1ae0b94580 (patch)
tree6a8fff173b3bcbfd5f3745318cd7d21dcf321d06 /gcc/ada/exp_fixd.adb
parenta18d46a4b6cd2b3c6f6506d09a3bd547b20293bf (diff)
downloadgcc-2bf891fa752e18b872d6c06d541aed1ae0b94580.zip
gcc-2bf891fa752e18b872d6c06d541aed1ae0b94580.tar.gz
gcc-2bf891fa752e18b872d6c06d541aed1ae0b94580.tar.bz2
[Ada] Expand integer-only implementation of ordinary fixed-point types
gcc/ada/ * doc/gnat_rm/implementation_defined_attributes.rst (Pool_Address): Fix pasto. (Small_Denominator): New entry. (Small_Numerator): Likewise. * doc/gnat_rm/implementation_defined_characteristics.rst (3.5.9): Relax conditions on 128-bit smalls and integer-only implementation. * gnat_rm.texi: Regenerate. * exp_attr.adb (Expand_N_Attribute_Reference) <Attribute_Fore>: Relax conditions on integer implementation for ordinary fixed-point types and pass a third parameter to the routine. <Attribute_Small_Denominator>: Raise Program_Error. <Attribute_Small_Numerator>: Likewise. * exp_fixd.adb (Expand_Convert_Fixed_To_Fixed): Use a scaled divide if the numerator and denominator of the small ratio are sufficiently small integers. (Expand_Convert_Fixed_To_Integer): Use a scaled divide if numerator and denominator of the small value are sufficiently small integers. (Expand_Convert_Integer_To_Fixed): Likewise. * exp_imgv.adb (Expand_Image_Attribute): Relax the conditions on the integer implementation for ordinary fixed-point types. (Expand_Value_Attribute): Likewise. * freeze.adb (Freeze_Fixed_Point_Type): Relax conditions on 128-bit smalls. * sem_attr.adb (Analyze_Attribute) <Attribute_Small_Denominator>: Check no arguments, fixed-point and set type to Universal_Integer. <Attribute_Small_Numerator>: Likewise. (Eval_Attribute) <Attribute_Small_Denominator>: Fold statically. <Attribute_Small_Numerator>: Likewise. * snames.ads-tmpl (Name_Small_Denominator): New attribute name. (Name_Small_Numerator): Likewise. (Attribute_Id): Add Attribute_Small_{Denominator,Numerator}. * libgnat/a-tifiio.adb (Exact): Delete. (Need_64): Likewise. (OK_Get_32): New boolean constant. (OK_Put_32): Likewise. (OK_Get_64): Likewise. (OK_Put_64): Likewise. (E): Adjust. (Get procedures): Likewise. (Put procedures): Likewise. * libgnat/a-tifiio__128.adb (Exact): Delete. (Need_64): Likewise. (Need_128): Likewise. (OK_Get_32): New boolean constant. (OK_Put_32): Likewise. (OK_Get_64): Likewise. (OK_Put_64): Likewise. (OK_Get_128): Likewise. (OK_Put_128): Likewise. (E): Adjust. (Get procedures): Likewise. (Put procedures): Likewise. * libgnat/a-wtfiio.adb (Exact): Delete. (Need_64): Likewise. (OK_Get_32): New boolean constant. (OK_Put_32): Likewise. (OK_Get_64): Likewise. (OK_Put_64): Likewise. (E): Adjust. (Get procedures): Likewise. (Put procedures): Likewise. * libgnat/a-wtfiio__128.adb (Exact): Delete. (Need_64): Likewise. (Need_128): Likewise. (OK_Get_32): New boolean constant. (OK_Put_32): Likewise. (OK_Get_64): Likewise. (OK_Put_64): Likewise. (OK_Get_128): Likewise. (OK_Put_128): Likewise. (E): Adjust. (Get procedures): Likewise. (Put procedures): Likewise. * libgnat/a-ztfiio.adb (Exact): Delete. (Need_64): Likewise. (OK_Get_32): New boolean constant. (OK_Put_32): Likewise. (OK_Get_64): Likewise. (OK_Put_64): Likewise. (E): Adjust. (Get procedures): Likewise. (Put procedures): Likewise. * libgnat/a-ztfiio__128.adb (Exact): Delete. (Need_64): Likewise. (Need_128): Likewise. (OK_Get_32): New boolean constant. (OK_Put_32): Likewise. (OK_Get_64): Likewise. (OK_Put_64): Likewise. (OK_Get_128): Likewise. (OK_Put_128): Likewise. (E): Adjust. (Get procedures): Likewise. (Put procedures): Likewise. * libgnat/s-fore_f.ads (Fore_Fixed): Adjust signature. * libgnat/s-fore_f.adb (Fore_Fixed): Reimplement. * libgnat/s-fofi32.ads (Fore_Fixed32): Adjust signature. * libgnat/s-fofi64.ads (Fore_Fixed64): Likewise. * libgnat/s-fofi128.ads (Fore_Fixed128): Likewise. * libgnat/s-imagef.ads: Adjust description. * libgnat/s-imagef.adb (Maxdigs): Move around. (Set_Image_Integer): Remove assertion. * libgnat/s-valuef.ads: Adjust description. * libgnat/s-valuef.adb (Integer_To_Fixed): Minor tweak.
Diffstat (limited to 'gcc/ada/exp_fixd.adb')
-rw-r--r--gcc/ada/exp_fixd.adb105
1 files changed, 75 insertions, 30 deletions
diff --git a/gcc/ada/exp_fixd.adb b/gcc/ada/exp_fixd.adb
index a85b6e7..3bb7207 100644
--- a/gcc/ada/exp_fixd.adb
+++ b/gcc/ada/exp_fixd.adb
@@ -1594,6 +1594,10 @@ package body Exp_Fixd is
-- If the small ratio is the reciprocal of a sufficiently small integer,
-- then the perfect result set is obtained by a single integer division.
+ -- If the numerator and denominator of the small ratio are sufficiently
+ -- small integers, then the perfect result set is obtained by a scaled
+ -- divide operation.
+
-- In other cases, we obtain the close result set by calculating the
-- result in floating-point.
@@ -1605,7 +1609,8 @@ package body Exp_Fixd is
Small_Ratio : Ureal;
Ratio_Num : Uint;
Ratio_Den : Uint;
- Lit : Node_Id;
+ Lit_Num : Node_Id;
+ Lit_Den : Node_Id;
begin
if Is_OK_Static_Expression (Expr) then
@@ -1623,26 +1628,36 @@ package body Exp_Fixd is
return;
else
- Lit := Integer_Literal (N, Ratio_Num);
+ Lit_Num := Integer_Literal (N, Ratio_Num);
- if Present (Lit) then
- Set_Result (N, Build_Multiply (N, Expr, Lit));
+ if Present (Lit_Num) then
+ Set_Result (N, Build_Multiply (N, Expr, Lit_Num));
return;
end if;
end if;
elsif Ratio_Num = 1 then
- Lit := Integer_Literal (N, Ratio_Den);
+ Lit_Den := Integer_Literal (N, Ratio_Den);
- if Present (Lit) then
- Set_Result (N, Build_Divide (N, Expr, Lit), Rng_Check);
+ if Present (Lit_Den) then
+ Set_Result (N, Build_Divide (N, Expr, Lit_Den), Rng_Check);
+ return;
+ end if;
+
+ else
+ Lit_Num := Integer_Literal (N, Ratio_Num);
+ Lit_Den := Integer_Literal (N, Ratio_Den);
+
+ if Present (Lit_Num) and then Present (Lit_Den) then
+ Set_Result
+ (N, Build_Scaled_Divide (N, Expr, Lit_Num, Lit_Den), Rng_Check);
return;
end if;
end if;
- -- Fall through to use floating-point for the close result set case
- -- either as a result of the small ratio not being an integer or the
- -- reciprocal of an integer, or if the integer is out of range.
+ -- Fall through to use floating-point for the close result set case,
+ -- as a result of the numerator or denominator of the small ratio not
+ -- being a sufficiently small integer.
Set_Result (N,
Build_Multiply (N,
@@ -1698,6 +1713,10 @@ package body Exp_Fixd is
-- If the small value is the reciprocal of a sufficiently small integer,
-- then the perfect result set is obtained by a single integer division.
+ -- If the numerator and denominator of the small value are sufficiently
+ -- small integers, then the perfect result set is obtained by a scaled
+ -- divide operation.
+
-- In other cases, we obtain the close result set by calculating the
-- result in floating-point.
@@ -1708,7 +1727,8 @@ package body Exp_Fixd is
Small : constant Ureal := Small_Value (Source_Type);
Small_Num : constant Uint := Norm_Num (Small);
Small_Den : constant Uint := Norm_Den (Small);
- Lit : Node_Id;
+ Lit_Num : Node_Id;
+ Lit_Den : Node_Id;
begin
if Is_OK_Static_Expression (Expr) then
@@ -1717,25 +1737,35 @@ package body Exp_Fixd is
end if;
if Small_Den = 1 then
- Lit := Integer_Literal (N, Small_Num);
+ Lit_Num := Integer_Literal (N, Small_Num);
- if Present (Lit) then
- Set_Result (N, Build_Multiply (N, Expr, Lit), Rng_Check);
+ if Present (Lit_Num) then
+ Set_Result (N, Build_Multiply (N, Expr, Lit_Num), Rng_Check);
return;
end if;
elsif Small_Num = 1 then
- Lit := Integer_Literal (N, Small_Den);
+ Lit_Den := Integer_Literal (N, Small_Den);
+
+ if Present (Lit_Den) then
+ Set_Result (N, Build_Divide (N, Expr, Lit_Den), Rng_Check);
+ return;
+ end if;
+
+ else
+ Lit_Num := Integer_Literal (N, Small_Num);
+ Lit_Den := Integer_Literal (N, Small_Den);
- if Present (Lit) then
- Set_Result (N, Build_Divide (N, Expr, Lit), Rng_Check);
+ if Present (Lit_Num) and then Present (Lit_Den) then
+ Set_Result
+ (N, Build_Scaled_Divide (N, Expr, Lit_Num, Lit_Den), Rng_Check);
return;
end if;
end if;
- -- Fall through to use floating-point for the close result set case
- -- either as a result of the small value not being an integer or the
- -- reciprocal of an integer, or if the integer is out of range.
+ -- Fall through to use floating-point for the close result set case,
+ -- as a result of the numerator or denominator of the small value not
+ -- being a sufficiently small integer.
Set_Result (N,
Build_Multiply (N,
@@ -1817,6 +1847,10 @@ package body Exp_Fixd is
-- If the small value is the reciprocal of a sufficiently small integer,
-- the perfect result set is obtained by a single integer multiplication.
+ -- If the numerator and denominator of the small value are sufficiently
+ -- small integers, then the perfect result set is obtained by a scaled
+ -- divide operation.
+
-- In other cases, we obtain the close result set by calculating the
-- result in floating-point using a multiplication by the reciprocal
-- of the Result_Small.
@@ -1828,29 +1862,40 @@ package body Exp_Fixd is
Small : constant Ureal := Small_Value (Result_Type);
Small_Num : constant Uint := Norm_Num (Small);
Small_Den : constant Uint := Norm_Den (Small);
- Lit : Node_Id;
+ Lit_Num : Node_Id;
+ Lit_Den : Node_Id;
begin
if Small_Den = 1 then
- Lit := Integer_Literal (N, Small_Num);
+ Lit_Num := Integer_Literal (N, Small_Num);
- if Present (Lit) then
- Set_Result (N, Build_Divide (N, Expr, Lit), Rng_Check);
+ if Present (Lit_Num) then
+ Set_Result (N, Build_Divide (N, Expr, Lit_Num), Rng_Check);
return;
end if;
elsif Small_Num = 1 then
- Lit := Integer_Literal (N, Small_Den);
+ Lit_Den := Integer_Literal (N, Small_Den);
+
+ if Present (Lit_Den) then
+ Set_Result (N, Build_Multiply (N, Expr, Lit_Den), Rng_Check);
+ return;
+ end if;
+
+ else
+ Lit_Num := Integer_Literal (N, Small_Num);
+ Lit_Den := Integer_Literal (N, Small_Den);
- if Present (Lit) then
- Set_Result (N, Build_Multiply (N, Expr, Lit), Rng_Check);
+ if Present (Lit_Num) and then Present (Lit_Den) then
+ Set_Result
+ (N, Build_Scaled_Divide (N, Expr, Lit_Den, Lit_Num), Rng_Check);
return;
end if;
end if;
- -- Fall through to use floating-point for the close result set case
- -- either as a result of the small value not being an integer or the
- -- reciprocal of an integer, or if the integer is out of range.
+ -- Fall through to use floating-point for the close result set case,
+ -- as a result of the numerator or denominator of the small value not
+ -- being a sufficiently small integer.
Set_Result (N,
Build_Multiply (N,