In most cases, the common operations for fixed-point types are implemented
by means of corresponding integer operations, in particular multiplication
and division. Because scaling is required to go back and forth between
the two representations, the expander needs to control the magnitude of
operands in order to avoid a spurious overflow during the computation.
It turns out that this control is suboptimal for the multiplication, thus
leading to operations of an unnecessarily large magnitude in some cases.
Tested on x86_64-pc-linux-gnu, committed on trunk
gcc/ada/
* exp_fixd.adb (Build_Double_Divide): Use the RM size of types and
a more precise estimate for the size of the denominator.
(Build_Double_Divide_Code): Likewise.
(Build_Multiply): Use a more precise estimate for the size of the
result.
(Build_Scaled_Divide): Use the RM size of types and a more precise
estimate for the size of the numerator.
(Build_Scaled_Divide_Code): Likewise.
diff --git a/gcc/ada/exp_fixd.adb b/gcc/ada/exp_fixd.adb
--- a/gcc/ada/exp_fixd.adb
+++ b/gcc/ada/exp_fixd.adb
@@ -448,15 +448,15 @@ package body Exp_Fixd is
(N : Node_Id;
X, Y, Z : Node_Id) return Node_Id
is
- Y_Size : constant Nat := UI_To_Int (Esize (Etype (Y)));
- Z_Size : constant Nat := UI_To_Int (Esize (Etype (Z)));
+ Y_Size : constant Nat := UI_To_Int (RM_Size (Etype (Y)));
+ Z_Size : constant Nat := UI_To_Int (RM_Size (Etype (Z)));
Expr : Node_Id;
begin
-- If the denominator fits in Max_Integer_Size bits, we can build the
-- operations directly without causing any intermediate overflow.
- if 2 * Nat'Max (Y_Size, Z_Size) <= System_Max_Integer_Size then
+ if Y_Size + Z_Size <= System_Max_Integer_Size then
return Build_Divide (N, X, Build_Multiply (N, Y, Z));
-- Otherwise we use the runtime routine
@@ -516,9 +516,9 @@ package body Exp_Fixd is
is
Loc : constant Source_Ptr := Sloc (N);
- X_Size : constant Nat := UI_To_Int (Esize (Etype (X)));
- Y_Size : constant Nat := UI_To_Int (Esize (Etype (Y)));
- Z_Size : constant Nat := UI_To_Int (Esize (Etype (Z)));
+ X_Size : constant Nat := UI_To_Int (RM_Size (Etype (X)));
+ Y_Size : constant Nat := UI_To_Int (RM_Size (Etype (Y)));
+ Z_Size : constant Nat := UI_To_Int (RM_Size (Etype (Z)));
QR_Id : RE_Id;
QR_Siz : Nat;
@@ -533,7 +533,7 @@ package body Exp_Fixd is
begin
-- Find type that will allow computation of denominator
- QR_Siz := Nat'Max (X_Size, 2 * Nat'Max (Y_Size, Z_Size));
+ QR_Siz := Nat'Max (X_Size, Y_Size + Z_Size);
if QR_Siz <= 16 then
QR_Typ := Standard_Integer_16;
@@ -724,10 +724,10 @@ package body Exp_Fixd is
end;
end if;
- -- Now the result size must be at least twice the longer of
- -- the two sizes, to accommodate all possible results.
+ -- Now the result size must be at least the sum of the two sizes,
+ -- to accommodate all possible results.
- Rsize := 2 * Int'Max (Left_Size, Right_Size);
+ Rsize := Left_Size + Right_Size;
if Rsize <= 8 then
Result_Type := Standard_Integer_8;
@@ -828,15 +828,15 @@ package body Exp_Fixd is
(N : Node_Id;
X, Y, Z : Node_Id) return Node_Id
is
- X_Size : constant Nat := UI_To_Int (Esize (Etype (X)));
- Y_Size : constant Nat := UI_To_Int (Esize (Etype (Y)));
+ X_Size : constant Nat := UI_To_Int (RM_Size (Etype (X)));
+ Y_Size : constant Nat := UI_To_Int (RM_Size (Etype (Y)));
Expr : Node_Id;
begin
-- If the numerator fits in Max_Integer_Size bits, we can build the
-- operations directly without causing any intermediate overflow.
- if 2 * Nat'Max (X_Size, Y_Size) <= System_Max_Integer_Size then
+ if X_Size + Y_Size <= System_Max_Integer_Size then
return Build_Divide (N, Build_Multiply (N, X, Y), Z);
-- Otherwise we use the runtime routine
@@ -893,9 +893,9 @@ package body Exp_Fixd is
is
Loc : constant Source_Ptr := Sloc (N);
- X_Size : constant Nat := UI_To_Int (Esize (Etype (X)));
- Y_Size : constant Nat := UI_To_Int (Esize (Etype (Y)));
- Z_Size : constant Nat := UI_To_Int (Esize (Etype (Z)));
+ X_Size : constant Nat := UI_To_Int (RM_Size (Etype (X)));
+ Y_Size : constant Nat := UI_To_Int (RM_Size (Etype (Y)));
+ Z_Size : constant Nat := UI_To_Int (RM_Size (Etype (Z)));
QR_Id : RE_Id;
QR_Siz : Nat;
@@ -910,7 +910,7 @@ package body Exp_Fixd is
begin
-- Find type that will allow computation of numerator
- QR_Siz := Nat'Max (2 * Nat'Max (X_Size, Y_Size), Z_Size);
+ QR_Siz := Nat'Max (X_Size + Y_Size, Z_Size);
if QR_Siz <= 16 then
QR_Typ := Standard_Integer_16;