[Ada] Almost always inline init. procedure of small and simple records
authorEric Botcazou <ebotcazou@adacore.com>
Tue, 11 Dec 2018 11:08:45 +0000 (11:08 +0000)
committerPierre-Marie de Rodat <pmderodat@gcc.gnu.org>
Tue, 11 Dec 2018 11:08:45 +0000 (11:08 +0000)
2018-12-11  Eric Botcazou  <ebotcazou@adacore.com>

gcc/ada/

* fe.h (Debug_Generated_Code): Declare.
* gcc-interface/gigi.h (enum inline_status_t): Rename
is_disabled to is_default, is_enabled to is_requested and add
is_prescribed.
* gcc-interface/decl.c (inline_status_for_subprog): New function.
(gnat_to_gnu_entity) <E_Subprogram_Type>: Use it to get the
inlining status of the subprogram.
* gcc-interface/trans.c (gigi): Adjust to above renaming.
(build_raise_check): Likewise.
(Compilation_Unit_to_gnu): Likewise.
(gnat_to_gnu): Likewise.
* gcc-interface/utils.c (create_subprog_decl): Likewise.  Deal
with is_prescribed status by setting
DECL_DISREGARD_INLINE_LIMITS.  Do not set the
DECL_NO_INLINE_WARNING_P flag if Debug_Generated_Code is true.

From-SVN: r266976

gcc/ada/ChangeLog
gcc/ada/fe.h
gcc/ada/gcc-interface/decl.c
gcc/ada/gcc-interface/gigi.h
gcc/ada/gcc-interface/trans.c
gcc/ada/gcc-interface/utils.c

index b48c757..b2e6e14 100644 (file)
@@ -1,3 +1,21 @@
+2018-12-11  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * fe.h (Debug_Generated_Code): Declare.
+       * gcc-interface/gigi.h (enum inline_status_t): Rename
+       is_disabled to is_default, is_enabled to is_requested and add
+       is_prescribed.
+       * gcc-interface/decl.c (inline_status_for_subprog): New function.
+       (gnat_to_gnu_entity) <E_Subprogram_Type>: Use it to get the
+       inlining status of the subprogram.
+       * gcc-interface/trans.c (gigi): Adjust to above renaming.
+       (build_raise_check): Likewise.
+       (Compilation_Unit_to_gnu): Likewise.
+       (gnat_to_gnu): Likewise.
+       * gcc-interface/utils.c (create_subprog_decl): Likewise.  Deal
+       with is_prescribed status by setting
+       DECL_DISREGARD_INLINE_LIMITS.  Do not set the
+       DECL_NO_INLINE_WARNING_P flag if Debug_Generated_Code is true.
+
 2018-12-03  Gary Dismukes  <dismukes@adacore.com>
 
        * sem_aux.adb (Object_Type_Has_Constrained_Partial_View): Return
index d4c4265..c85d69c 100644 (file)
@@ -185,6 +185,7 @@ extern Boolean In_Same_Source_Unit              (Node_Id, Node_Id);
 /* opt: */
 
 #define Back_End_Inlining              opt__back_end_inlining
+#define Debug_Generated_Code           opt__debug_generated_code
 #define Exception_Extra_Info           opt__exception_extra_info
 #define Exception_Locations_Suppressed opt__exception_locations_suppressed
 #define Exception_Mechanism            opt__exception_mechanism
@@ -200,6 +201,7 @@ typedef enum {
 } Exception_Mechanism_Type;
 
 extern Boolean Back_End_Inlining;
+extern Boolean Debug_Generated_Code;
 extern Boolean Exception_Extra_Info;
 extern Boolean Exception_Locations_Suppressed;
 extern Exception_Mechanism_Type Exception_Mechanism;
index d8fb8ee..758f2c3 100644 (file)
@@ -205,6 +205,7 @@ static tree gnat_to_gnu_component_type (Entity_Id, bool, bool);
 static tree gnat_to_gnu_subprog_type (Entity_Id, bool, bool, tree *);
 static int adjust_packed (tree, tree, int);
 static tree gnat_to_gnu_field (Entity_Id, tree, int, bool, bool);
+static enum inline_status_t inline_status_for_subprog (Entity_Id);
 static tree gnu_ext_name_for_subprog (Entity_Id, tree);
 static void set_nonaliased_component_on_array_type (tree);
 static void set_reverse_storage_order_on_array_type (tree);
@@ -3883,12 +3884,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
       {
        tree gnu_ext_name
          = gnu_ext_name_for_subprog (gnat_entity, gnu_entity_name);
-       enum inline_status_t inline_status
-         = Has_Pragma_No_Inline (gnat_entity)
-           ? is_suppressed
-           : Has_Pragma_Inline_Always (gnat_entity)
-             ? is_required
-             : (Is_Inlined (gnat_entity) ? is_enabled : is_disabled);
+       const enum inline_status_t inline_status
+         = inline_status_for_subprog (gnat_entity);
        bool public_flag = Is_Public (gnat_entity) || imported_p;
        /* Subprograms marked both Intrinsic and Always_Inline need not
           have a body of their own.  */
@@ -4934,6 +4931,44 @@ is_cplusplus_method (Entity_Id gnat_entity)
   return false;
 }
 
+/* Return the inlining status of the GNAT subprogram SUBPROG.  */
+
+static enum inline_status_t
+inline_status_for_subprog (Entity_Id subprog)
+{
+  if (Has_Pragma_No_Inline (subprog))
+    return is_suppressed;
+
+  if (Has_Pragma_Inline_Always (subprog))
+    return is_required;
+
+  if (Is_Inlined (subprog))
+    {
+      tree gnu_type;
+
+      /* This is a kludge to work around a pass ordering issue: for small
+        record types with many components, i.e. typically bit-fields, the
+        initialization routine can contain many assignments that will be
+        merged by the GIMPLE store merging pass.  But this pass runs very
+        late in the pipeline, in particular after the inlining decisions
+        are made, so the inlining heuristics cannot take its outcome into
+        account.  Therefore, we optimistically override the heuristics for
+        the initialization routine in this case.  */
+      if (Is_Init_Proc (subprog)
+         && flag_store_merging
+         && Is_Record_Type (Etype (First_Formal (subprog)))
+         && (gnu_type = gnat_to_gnu_type (Etype (First_Formal (subprog))))
+         && !TYPE_IS_BY_REFERENCE_P (gnu_type)
+         && tree_fits_uhwi_p (TYPE_SIZE (gnu_type))
+         && compare_tree_int (TYPE_SIZE (gnu_type), MAX_FIXED_MODE_SIZE) <= 0)
+       return is_prescribed;
+
+      return is_requested;
+    }
+
+  return is_default;
+}
+
 /* Finalize the processing of From_Limited_With incomplete types.  */
 
 void
index 3029732..f25c328 100644 (file)
@@ -439,9 +439,11 @@ enum inline_status_t
   /* Inlining is suppressed for the subprogram.  */
   is_suppressed,
   /* No inlining is requested for the subprogram.  */
-  is_disabled,
+  is_default,
   /* Inlining is requested for the subprogram.  */
-  is_enabled,
+  is_requested,
+  /* Inlining is strongly requested for the subprogram.  */
+  is_prescribed,
   /* Inlining is required for the subprogram.  */
   is_required
 };
index 4c066c0..db9223e 100644 (file)
@@ -412,7 +412,7 @@ gigi (Node_Id gnat_root,
     = create_subprog_decl (get_identifier ("__gnat_malloc"), NULL_TREE,
                           build_function_type_list (ptr_type_node, sizetype,
                                                     NULL_TREE),
-                          NULL_TREE, is_disabled, true, true, true, false,
+                          NULL_TREE, is_default, true, true, true, false,
                           false, NULL, Empty);
   DECL_IS_MALLOC (malloc_decl) = 1;
 
@@ -420,7 +420,7 @@ gigi (Node_Id gnat_root,
     = create_subprog_decl (get_identifier ("__gnat_free"), NULL_TREE,
                           build_function_type_list (void_type_node,
                                                     ptr_type_node, NULL_TREE),
-                          NULL_TREE, is_disabled, true, true, true, false,
+                          NULL_TREE, is_default, true, true, true, false,
                           false, NULL, Empty);
 
   realloc_decl
@@ -428,7 +428,7 @@ gigi (Node_Id gnat_root,
                           build_function_type_list (ptr_type_node,
                                                     ptr_type_node, sizetype,
                                                     NULL_TREE),
-                          NULL_TREE, is_disabled, true, true, true, false,
+                          NULL_TREE, is_default, true, true, true, false,
                           false, NULL, Empty);
 
   /* This is used for 64-bit multiplication with overflow checking.  */
@@ -437,7 +437,7 @@ gigi (Node_Id gnat_root,
     = create_subprog_decl (get_identifier ("__gnat_mulv64"), NULL_TREE,
                           build_function_type_list (int64_type, int64_type,
                                                     int64_type, NULL_TREE),
-                          NULL_TREE, is_disabled, true, true, true, false,
+                          NULL_TREE, is_default, true, true, true, false,
                           false, NULL, Empty);
 
   /* Name of the _Parent field in tagged record types.  */
@@ -461,21 +461,21 @@ gigi (Node_Id gnat_root,
     = create_subprog_decl
       (get_identifier ("system__soft_links__get_jmpbuf_address_soft"),
        NULL_TREE, build_function_type_list (jmpbuf_ptr_type, NULL_TREE),
-       NULL_TREE, is_disabled, true, true, true, false, false, NULL, Empty);
+       NULL_TREE, is_default, true, true, true, false, false, NULL, Empty);
 
   set_jmpbuf_decl
     = create_subprog_decl
       (get_identifier ("system__soft_links__set_jmpbuf_address_soft"),
        NULL_TREE, build_function_type_list (void_type_node, jmpbuf_ptr_type,
                                            NULL_TREE),
-       NULL_TREE, is_disabled, true, true, true, false, false, NULL, Empty);
+       NULL_TREE, is_default, true, true, true, false, false, NULL, Empty);
 
   get_excptr_decl
     = create_subprog_decl
       (get_identifier ("system__soft_links__get_gnat_exception"), NULL_TREE,
        build_function_type_list (build_pointer_type (except_type_node),
                                 NULL_TREE),
-       NULL_TREE, is_disabled, true, true, true, false, false, NULL, Empty);
+       NULL_TREE, is_default, true, true, true, false, false, NULL, Empty);
 
   not_handled_by_others_decl = get_identifier ("not_handled_by_others");
   for (t = TYPE_FIELDS (except_type_node); t; t = DECL_CHAIN (t))
@@ -493,7 +493,7 @@ gigi (Node_Id gnat_root,
       (get_identifier ("__builtin_setjmp"), NULL_TREE,
        build_function_type_list (integer_type_node, jmpbuf_ptr_type,
                                 NULL_TREE),
-       NULL_TREE, is_disabled, true, true, true, false, false, NULL, Empty);
+       NULL_TREE, is_default, true, true, true, false, false, NULL, Empty);
   DECL_BUILT_IN_CLASS (setjmp_decl) = BUILT_IN_NORMAL;
   DECL_FUNCTION_CODE (setjmp_decl) = BUILT_IN_SETJMP;
 
@@ -503,7 +503,7 @@ gigi (Node_Id gnat_root,
     = create_subprog_decl
       (get_identifier ("__builtin_update_setjmp_buf"), NULL_TREE,
        build_function_type_list (void_type_node, jmpbuf_ptr_type, NULL_TREE),
-       NULL_TREE, is_disabled, true, true, true, false, false, NULL, Empty);
+       NULL_TREE, is_default, true, true, true, false, false, NULL, Empty);
   DECL_BUILT_IN_CLASS (update_setjmp_buf_decl) = BUILT_IN_NORMAL;
   DECL_FUNCTION_CODE (update_setjmp_buf_decl) = BUILT_IN_UPDATE_SETJMP_BUF;
 
@@ -515,14 +515,14 @@ gigi (Node_Id gnat_root,
   raise_nodefer_decl
     = create_subprog_decl
       (get_identifier ("__gnat_raise_nodefer_with_msg"), NULL_TREE, ftype,
-       NULL_TREE, is_disabled, true, true, true, false, false, NULL, Empty);
+       NULL_TREE, is_default, true, true, true, false, false, NULL, Empty);
 
   set_exception_parameter_decl
     = create_subprog_decl
       (get_identifier ("__gnat_set_exception_parameter"), NULL_TREE,
        build_function_type_list (void_type_node, ptr_type_node, ptr_type_node,
                                 NULL_TREE),
-       NULL_TREE, is_disabled, true, true, true, false, false, NULL, Empty);
+       NULL_TREE, is_default, true, true, true, false, false, NULL, Empty);
 
   /* Hooks to call when entering/leaving an exception handler.  */
   ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
@@ -530,7 +530,7 @@ gigi (Node_Id gnat_root,
   begin_handler_decl
     = create_subprog_decl (get_identifier ("__gnat_begin_handler"), NULL_TREE,
                           ftype, NULL_TREE,
-                          is_disabled, true, true, true, false, false, NULL,
+                          is_default, true, true, true, false, false, NULL,
                           Empty);
   /* __gnat_begin_handler is a dummy procedure.  */
   TREE_NOTHROW (begin_handler_decl) = 1;
@@ -538,13 +538,13 @@ gigi (Node_Id gnat_root,
   end_handler_decl
     = create_subprog_decl (get_identifier ("__gnat_end_handler"), NULL_TREE,
                           ftype, NULL_TREE,
-                          is_disabled, true, true, true, false, false, NULL,
+                          is_default, true, true, true, false, false, NULL,
                           Empty);
 
   unhandled_except_decl
     = create_subprog_decl (get_identifier ("__gnat_unhandled_except_handler"),
                           NULL_TREE, ftype, NULL_TREE,
-                          is_disabled, true, true, true, false, false, NULL,
+                          is_default, true, true, true, false, false, NULL,
                           Empty);
 
   /* Indicate that it never returns.  */
@@ -552,7 +552,7 @@ gigi (Node_Id gnat_root,
   reraise_zcx_decl
     = create_subprog_decl (get_identifier ("__gnat_reraise_zcx"), NULL_TREE,
                           ftype, NULL_TREE,
-                          is_disabled, true, true, true, false, false, NULL,
+                          is_default, true, true, true, false, false, NULL,
                           Empty);
 
   /* Dummy objects to materialize "others" and "all others" in the exception
@@ -592,7 +592,7 @@ gigi (Node_Id gnat_root,
       tree decl
        = create_subprog_decl
          (get_identifier ("__gnat_last_chance_handler"), NULL_TREE, ftype,
-          NULL_TREE, is_disabled, true, true, true, false, false, NULL,
+          NULL_TREE, is_default, true, true, true, false, false, NULL,
           Empty);
       for (i = 0; i < (int) ARRAY_SIZE (gnat_raise_decls); i++)
        gnat_raise_decls[i] = decl;
@@ -756,7 +756,7 @@ build_raise_check (int check, enum exception_info_kind kind)
   ftype = build_qualified_type (ftype, TYPE_QUAL_VOLATILE);
   result
     = create_subprog_decl (get_identifier (Name_Buffer), NULL_TREE, ftype,
-                          NULL_TREE, is_disabled, true, true, true, false,
+                          NULL_TREE, is_default, true, true, true, false,
                           false, NULL, Empty);
 
   return result;
@@ -6134,7 +6134,7 @@ Compilation_Unit_to_gnu (Node_Id gnat_node)
     = create_subprog_decl
       (create_concat_name (gnat_unit_entity, body_p ? "elabb" : "elabs"),
        NULL_TREE, void_ftype, NULL_TREE,
-       is_disabled, true, false, true, true, false, NULL, gnat_unit);
+       is_default, true, false, true, true, false, NULL, gnat_unit);
   struct elab_info *info;
 
   vec_safe_push (gnu_elab_proc_stack, gnu_elab_proc_decl);
@@ -7144,7 +7144,7 @@ gnat_to_gnu (Node_Id gnat_node)
            create_subprog_decl (create_concat_name
                                 (Entity (Prefix (gnat_node)),
                                  attr == Attr_Elab_Body ? "elabb" : "elabs"),
-                                NULL_TREE, void_ftype, NULL_TREE, is_disabled,
+                                NULL_TREE, void_ftype, NULL_TREE, is_default,
                                 true, true, true, true, false, NULL,
                                 gnat_node);
 
index 05959d6..5646051 100644 (file)
@@ -3235,20 +3235,17 @@ create_subprog_decl (tree name, tree asm_name, tree type, tree param_decl_list,
 
   DECL_ARTIFICIAL (subprog_decl) = artificial_p;
   DECL_EXTERNAL (subprog_decl) = extern_flag;
+  DECL_FUNCTION_IS_DEF (subprog_decl) = definition;
+  DECL_IGNORED_P (subprog_decl) = !debug_info_p;
   TREE_PUBLIC (subprog_decl) = public_flag;
 
-  if (!debug_info_p)
-    DECL_IGNORED_P (subprog_decl) = 1;
-  if (definition)
-    DECL_FUNCTION_IS_DEF (subprog_decl) = 1;
-
   switch (inline_status)
     {
     case is_suppressed:
       DECL_UNINLINABLE (subprog_decl) = 1;
       break;
 
-    case is_disabled:
+    case is_default:
       break;
 
     case is_required:
@@ -3269,9 +3266,15 @@ create_subprog_decl (tree name, tree asm_name, tree type, tree param_decl_list,
 
       /* ... fall through ... */
 
-    case is_enabled:
+    case is_prescribed:
+      DECL_DISREGARD_INLINE_LIMITS (subprog_decl) = 1;
+
+      /* ... fall through ... */
+
+    case is_requested:
       DECL_DECLARED_INLINE_P (subprog_decl) = 1;
-      DECL_NO_INLINE_WARNING_P (subprog_decl) = artificial_p;
+      if (!Debug_Generated_Code)
+       DECL_NO_INLINE_WARNING_P (subprog_decl) = artificial_p;
       break;
 
     default: