[Ada] Initialize_Scalars optimization causes spurious runtime check failure
authorHristian Kirtchev <kirtchev@adacore.com>
Wed, 23 May 2018 10:21:42 +0000 (10:21 +0000)
committerPierre-Marie de Rodat <pmderodat@gcc.gnu.org>
Wed, 23 May 2018 10:21:42 +0000 (10:21 +0000)
This patch suppresses the optimization of scalar arrays when pragma
Initialize_Scalars is in effect if the component type is subject to
predicates. Since the scalar array is initialized with invalid values,
these values may violate the predicate or a validity check within the
predicate.

------------
-- Source --
------------

--  gnat.adc

pragma Initialize_Scalars;

--  types.ads

with System; use System;

package Types is
   type Byte is mod System.Storage_Unit;

   subtype Inter_Byte is Byte;

   function Always_OK (B : Inter_Byte) return Boolean is (True);
   function Is_OK     (B : Inter_Byte) return Boolean is (Always_OK (B));

   subtype Final_Byte is Byte with Predicate => Is_OK (Final_Byte);

   type Bytes is array (1 .. 5) of Final_Byte;

   Obj : Bytes;
end Types;

--  main.adb

with Types; use Types;

procedure Main is begin null; end Main;

-----------------
-- Compilation --
-----------------

$ gnatmake -q -gnata -gnatVa main.adb
$ ./main

2018-05-23  Hristian Kirtchev  <kirtchev@adacore.com>

gcc/ada/

* exp_ch3.adb (Default_Initialize_Object): Do not optimize scalar array
initialization when the component type has predicates.
* exp_ch4.adb (Expand_N_Allocator): Do not optimize scalar array
allocation when the component type has predicates.

From-SVN: r260572

gcc/ada/ChangeLog
gcc/ada/exp_ch3.adb
gcc/ada/exp_ch4.adb

index bb1e21f70823075c01f4a29bc1d9222bc0a7d6bb..5feb05b664b5472222915d8261f07fc50dfa11f7 100644 (file)
@@ -1,3 +1,10 @@
+2018-05-23  Hristian Kirtchev  <kirtchev@adacore.com>
+
+       * exp_ch3.adb (Default_Initialize_Object): Do not optimize scalar array
+       initialization when the component type has predicates.
+       * exp_ch4.adb (Expand_N_Allocator): Do not optimize scalar array
+       allocation when the component type has predicates.
+
 2018-05-23  Hristian Kirtchev  <kirtchev@adacore.com>
 
        * einfo.adb, exp_disp.adb, sem_ch3.adb, sem_ch6.adb, sem_prag.adb:
index fe755e3b1238d69096d701f25e96b9758de8c63c..f4d2117b67d0475b370c9014b8c81d15c9b8269a 100644 (file)
@@ -6069,29 +6069,43 @@ package body Exp_Ch3 is
                   null;
 
                --  Optimize the default initialization of an array object when
-               --  the following conditions are met:
-               --
-               --    * Pragma Initialize_Scalars or Normalize_Scalars is in
-               --      effect.
-               --
-               --    * The bounds of the array type are static and lack empty
-               --      ranges.
-               --
-               --    * The array type does not contain atomic components or is
-               --      treated as packed.
-               --
-               --    * The component is of a scalar type which requires simple
-               --      initialization.
-               --
+               --  pragma Initialize_Scalars or Normalize_Scalars is in effect.
                --  Construct an in-place initialization aggregate which may be
                --  convert into a fast memset by the backend.
 
                elsif Init_Or_Norm_Scalars
                  and then Is_Array_Type (Typ)
+
+                 --  The array must lack atomic components because they are
+                 --  treated as non-static, and as a result the backend will
+                 --  not initialize the memory in one go.
+
                  and then not Has_Atomic_Components (Typ)
+
+                 --  The array must not be packed because the invalid values
+                 --  in System.Scalar_Values are multiples of Storage_Unit.
+
                  and then not Is_Packed (Typ)
+
+                 --  The array must have static non-empty ranges, otherwise
+                 --  the backend cannot initialize the memory in one go.
+
                  and then Has_Static_Non_Empty_Array_Bounds (Typ)
+
+                 --  The optimization is only relevant for arrays of scalar
+                 --  types.
+
                  and then Is_Scalar_Type (Component_Type (Typ))
+
+                 --  Similar to regular array initialization using a type
+                 --  init proc, predicate checks are not performed because the
+                 --  initialization values are intentionally invalid, and may
+                 --  violate the predicate.
+
+                 and then not Has_Predicates (Component_Type (Typ))
+
+                 --  The component type must have a single initialization value
+
                  and then Simple_Initialization_OK (Component_Type (Typ))
                then
                   Set_No_Initialization (N, False);
index 87a00826a77263f9c81b6d974814fb2a4007a323..3378580740edb662538285504038cc7b0b567da6 100644 (file)
@@ -4618,28 +4618,42 @@ package body Exp_Ch4 is
                   Is_Allocate => True);
             end if;
 
-         --  Optimize the default allocation of an array object when the
-         --  following conditions are met:
-         --
-         --    * Pragma Initialize_Scalars or Normalize_Scalars is in effect
-         --
-         --    * The bounds of the array type are static and lack empty ranges
-         --
-         --    * The array type does not contain atomic components or is
-         --      treated as packed.
-         --
-         --    * The component is of a scalar type which requires simple
-         --      initialization.
-         --
-         --  Construct an in-place initialization aggregate which may be
-         --  convert into a fast memset by the backend.
+         --  Optimize the default allocation of an array object when pragma
+         --  Initialize_Scalars or Normalize_Scalars is in effect. Construct an
+         --  in-place initialization aggregate which may be convert into a fast
+         --  memset by the backend.
 
          elsif Init_Or_Norm_Scalars
            and then Is_Array_Type (T)
+
+           --  The array must lack atomic components because they are treated
+           --  as non-static, and as a result the backend will not initialize
+           --  the memory in one go.
+
            and then not Has_Atomic_Components (T)
+
+           --  The array must not be packed because the invalid values in
+           --  System.Scalar_Values are multiples of Storage_Unit.
+
            and then not Is_Packed (T)
+
+           --  The array must have static non-empty ranges, otherwise the
+           --  backend cannot initialize the memory in one go.
+
            and then Has_Static_Non_Empty_Array_Bounds (T)
+
+           --  The optimization is only relevant for arrays of scalar types
+
            and then Is_Scalar_Type (Component_Type (T))
+
+           --  Similar to regular array initialization using a type init proc,
+           --  predicate checks are not performed because the initialization
+           --  values are intentionally invalid, and may violate the predicate.
+
+           and then not Has_Predicates (Component_Type (T))
+
+           --  The component type must have a single initialization value
+
            and then Needs_Simple_Initialization
                       (Typ         => Component_Type (T),
                        Consider_IS => True)