public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-4302] [Ada] Fix internal error on fixed-point divide, multiply and scaling
@ 2021-10-11 13:39 Pierre-Marie de Rodat
  0 siblings, 0 replies; only message in thread
From: Pierre-Marie de Rodat @ 2021-10-11 13:39 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:cea83351a2a023a07ba5577cd91b5edcd690299b

commit r12-4302-gcea83351a2a023a07ba5577cd91b5edcd690299b
Author: Eric Botcazou <ebotcazou@adacore.com>
Date:   Thu Sep 30 12:50:38 2021 +0200

    [Ada] Fix internal error on fixed-point divide, multiply and scaling
    
    gcc/ada/
    
            * exp_fixd.adb (Get_Size_For_Value): New function returning a size
            suitable for a non-negative integer value.
            (Get_Type_For_Size): New function returning a standard type suitable
            for a size.
            (Build_Divide): Call both functions to compute the result type, but
            make sure to pass a non-negative value to the first.
            (Build_Multiply): Likewise.
            (Do_Multiply_Fixed_Universal): Minor consistency tweak.
            (Integer_Literal): Call both functions to compute the type.

Diff:
---
 gcc/ada/exp_fixd.adb | 171 +++++++++++++++++++++++++++------------------------
 1 file changed, 92 insertions(+), 79 deletions(-)

diff --git a/gcc/ada/exp_fixd.adb b/gcc/ada/exp_fixd.adb
index 8d7624f8532..94a61df4511 100644
--- a/gcc/ada/exp_fixd.adb
+++ b/gcc/ada/exp_fixd.adb
@@ -190,6 +190,15 @@ package body Exp_Fixd is
    --  The expression returned is neither analyzed nor resolved. The Etype
    --  of the result is properly set (to Universal_Real).
 
+   function Get_Size_For_Value (V : Uint) return Pos;
+   --  Given a non-negative universal integer value, return the size of a small
+   --  signed integer type covering -V .. V, or Pos'Max if no such type exists.
+
+   function Get_Type_For_Size (Siz : Pos; Force : Boolean) return Entity_Id;
+   --  Return the smallest signed integer type containing at least Siz bits.
+   --  If no such type exists, return Empty if Force is False or the largest
+   --  signed integer type if Force is True.
+
    function Integer_Literal
      (N        : Node_Id;
       V        : Uint;
@@ -324,7 +333,6 @@ package body Exp_Fixd is
       Right_Type  : constant Entity_Id  := Base_Type (Etype (R));
       Left_Size   : Int;
       Right_Size  : Int;
-      Rsize       : Int;
       Result_Type : Entity_Id;
       Rnode       : Node_Id;
 
@@ -354,20 +362,17 @@ package body Exp_Fixd is
          --  the effective size of an operand is the RM_Size of the operand.
          --  But a special case arises with operands whose size is known at
          --  compile time. In this case, we can use the actual value of the
-         --  operand to get its size if it would fit in signed 8/16/32 bits.
+         --  operand to get a size if it would fit in a small signed integer.
 
          Left_Size := UI_To_Int (RM_Size (Left_Type));
 
          if Compile_Time_Known_Value (L) then
             declare
-               Val : constant Uint := Expr_Value (L);
+               Siz : constant Int :=
+                       Get_Size_For_Value (UI_Abs (Expr_Value (L)));
             begin
-               if Val < Uint_2 ** 7 then
-                  Left_Size := 8;
-               elsif Val < Uint_2 ** 15 then
-                  Left_Size := 16;
-               elsif Val < Uint_2 ** 31 then
-                  Left_Size := 32;
+               if Siz < Left_Size then
+                  Left_Size := Siz;
                end if;
             end;
          end if;
@@ -376,35 +381,19 @@ package body Exp_Fixd is
 
          if Compile_Time_Known_Value (R) then
             declare
-               Val : constant Uint := Expr_Value (R);
+               Siz : constant Int :=
+                       Get_Size_For_Value (UI_Abs (Expr_Value (R)));
             begin
-               if Val <= Int'(2 ** 7) then
-                  Right_Size := 8;
-               elsif Val <= Int'(2 ** 15) then
-                  Right_Size := 16;
+               if Siz < Right_Size then
+                  Right_Size := Siz;
                end if;
             end;
          end if;
 
          --  Do the operation using the longer of the two sizes
 
-         Rsize := Int'Max (Left_Size, Right_Size);
-
-         if Rsize <= 8 then
-            Result_Type := Standard_Integer_8;
-
-         elsif Rsize <= 16 then
-            Result_Type := Standard_Integer_16;
-
-         elsif Rsize <= 32 then
-            Result_Type := Standard_Integer_32;
-
-         elsif Rsize <= 64 or else System_Max_Integer_Size < 128 then
-            Result_Type := Standard_Integer_64;
-
-         else
-            Result_Type := Standard_Integer_128;
-         end if;
+         Result_Type :=
+           Get_Type_For_Size (Int'Max (Left_Size, Right_Size), Force => True);
 
          Rnode :=
             Make_Op_Divide (Loc,
@@ -664,7 +653,6 @@ package body Exp_Fixd is
       Right_Type  : constant Entity_Id  := Etype (R);
       Left_Size   : Int;
       Right_Size  : Int;
-      Rsize       : Int;
       Result_Type : Entity_Id;
       Rnode       : Node_Id;
 
@@ -697,20 +685,17 @@ package body Exp_Fixd is
          --  the effective size of an operand is the RM_Size of the operand.
          --  But a special case arises with operands whose size is known at
          --  compile time. In this case, we can use the actual value of the
-         --  operand to get its size if it would fit in signed 8/16/32 bits.
+         --  operand to get a size if it would fit in a small signed integer.
 
          Left_Size := UI_To_Int (RM_Size (Left_Type));
 
          if Compile_Time_Known_Value (L) then
             declare
-               Val : constant Uint := Expr_Value (L);
+               Siz : constant Int :=
+                       Get_Size_For_Value (UI_Abs (Expr_Value (L)));
             begin
-               if Val < Uint_2 ** 7 then
-                  Left_Size := 8;
-               elsif Val < Uint_2 ** 15 then
-                  Left_Size := 16;
-               elsif Val < Uint_2 ** 31 then
-                  Left_Size := 32;
+               if Siz < Left_Size then
+                  Left_Size := Siz;
                end if;
             end;
          end if;
@@ -719,12 +704,11 @@ package body Exp_Fixd is
 
          if Compile_Time_Known_Value (R) then
             declare
-               Val : constant Uint := Expr_Value (R);
+               Siz : constant Int :=
+                       Get_Size_For_Value (UI_Abs (Expr_Value (R)));
             begin
-               if Val <= Int'(2 ** 7) then
-                  Right_Size := 8;
-               elsif Val <= Int'(2 ** 15) then
-                  Right_Size := 16;
+               if Siz < Right_Size then
+                  Right_Size := Siz;
                end if;
             end;
          end if;
@@ -732,23 +716,8 @@ package body Exp_Fixd is
          --  Now the result size must be at least the sum of the two sizes,
          --  to accommodate all possible results.
 
-         Rsize := Left_Size + Right_Size;
-
-         if Rsize <= 8 then
-            Result_Type := Standard_Integer_8;
-
-         elsif Rsize <= 16 then
-            Result_Type := Standard_Integer_16;
-
-         elsif Rsize <= 32 then
-            Result_Type := Standard_Integer_32;
-
-         elsif Rsize <= 64 or else System_Max_Integer_Size < 128 then
-            Result_Type := Standard_Integer_64;
-
-         else
-            Result_Type := Standard_Integer_128;
-         end if;
+         Result_Type :=
+           Get_Type_For_Size (Left_Size + Right_Size, Force => True);
 
          Rnode :=
             Make_Op_Multiply (Loc,
@@ -1542,7 +1511,7 @@ package body Exp_Fixd is
 
       else
          Lit_Int := Integer_Literal (N, Frac_Den, UR_Is_Negative (Frac));
-         Lit_K   := Integer_Literal (N, Frac_Num);
+         Lit_K   := Integer_Literal (N, Frac_Num, False);
 
          if Present (Lit_Int) and then Present (Lit_K) then
             Set_Result (N, Build_Scaled_Divide (N, Left, Lit_K, Lit_Int));
@@ -2422,6 +2391,64 @@ package body Exp_Fixd is
       return Build_Conversion (N, Universal_Real, N);
    end Fpt_Value;
 
+   ------------------------
+   -- Get_Size_For_Value --
+   ------------------------
+
+   function Get_Size_For_Value (V : Uint) return Pos is
+   begin
+      pragma Assert (V >= Uint_0);
+
+      if V < Uint_2 ** 7 then
+         return 8;
+
+      elsif V < Uint_2 ** 15 then
+         return 16;
+
+      elsif V < Uint_2 ** 31 then
+         return 32;
+
+      elsif V < Uint_2 ** 63 then
+         return 64;
+
+      elsif V < Uint_2 ** 127 then
+         return 128;
+
+      else
+         return Pos'Last;
+      end if;
+   end Get_Size_For_Value;
+
+   -----------------------
+   -- Get_Type_For_Size --
+   -----------------------
+
+   function Get_Type_For_Size (Siz : Pos; Force : Boolean) return Entity_Id is
+   begin
+      if Siz <= 8 then
+         return Standard_Integer_8;
+
+      elsif Siz <= 16 then
+         return Standard_Integer_16;
+
+      elsif Siz <= 32 then
+         return Standard_Integer_32;
+
+      elsif Siz <= 64
+        or else (Force and then System_Max_Integer_Size < 128)
+      then
+         return Standard_Integer_64;
+
+      elsif (Siz <= 128 and then System_Max_Integer_Size = 128)
+        or else Force
+      then
+         return Standard_Integer_128;
+
+      else
+         return Empty;
+      end if;
+   end Get_Type_For_Size;
+
    ---------------------
    -- Integer_Literal --
    ---------------------
@@ -2435,22 +2462,8 @@ package body Exp_Fixd is
       L : Node_Id;
 
    begin
-      if V < Uint_2 ** 7 then
-         T := Standard_Integer_8;
-
-      elsif V < Uint_2 ** 15 then
-         T := Standard_Integer_16;
-
-      elsif V < Uint_2 ** 31 then
-         T := Standard_Integer_32;
-
-      elsif V < Uint_2 ** 63 then
-         T := Standard_Integer_64;
-
-      elsif V < Uint_2 ** 127 and then System_Max_Integer_Size = 128 then
-         T := Standard_Integer_128;
-
-      else
+      T := Get_Type_For_Size (Get_Size_For_Value (V), Force => False);
+      if No (T) then
          return Empty;
       end if;


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-10-11 13:39 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-11 13:39 [gcc r12-4302] [Ada] Fix internal error on fixed-point divide, multiply and scaling Pierre-Marie de Rodat

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