------- Comment #7 from hubicka at ucw dot cz  2008-09-02 20:29 -------
Subject: Re:  [4.4 Regression]: gcc.c-torture/execute/931018-1.c  int-compare.c
ieee/inf-2.c mzero6.c

> 
> 
> ------- Comment #6 from hp at gcc dot gnu dot org  2008-09-02 10:41 -------
> (In reply to comment #5)
> 
> > Well, the code is not mine, but it was wirtten at a time struct_function
> > did hold a lot of extra stuff.
> 
> SVN blamed you for that code in tree-inline.c and the revision range is yours.

I've moved that code around from verioning function and enabled it by
default.

I am attaching patch I am testing now. It makes versioning to copy only
fields needed and I also noticed that we leak memory in gimple_body
pointer.  This pointer is pointing to sequence holding first basicblock
after build_cfg and when this block is removed it is pointing to bogus
sequence then. Setting this pointer to 0 confuse some places that use
gimple_body to check presence of functionbody.
I added predicate for this and replaced checks by cgraph's analyzed
flag that will be needed for WHOPR anyway.

Index: cgraph.c
===================================================================
*** cgraph.c    (revision 139886)
--- cgraph.c    (working copy)
*************** cgraph_create_edge (struct cgraph_node *
*** 631,637 ****

    gcc_assert (is_gimple_call (call_stmt));

!   if (!gimple_body (callee->decl))
      edge->inline_failed = N_("function body not available");
    else if (callee->local.redefined_extern_inline)
      edge->inline_failed = N_("redefined extern inline functions are not "
--- 631,637 ----

    gcc_assert (is_gimple_call (call_stmt));

!   if (!callee->analyzed)
      edge->inline_failed = N_("function body not available");
    else if (callee->local.redefined_extern_inline)
      edge->inline_failed = N_("redefined extern inline functions are not "
*************** dump_cgraph_node (FILE *f, struct cgraph
*** 1059,1065 ****
      fprintf (f, " needed");
    else if (node->reachable)
      fprintf (f, " reachable");
!   if (gimple_body (node->decl))
      fprintf (f, " body");
    if (node->output)
      fprintf (f, " output");
--- 1059,1065 ----
      fprintf (f, " needed");
    else if (node->reachable)
      fprintf (f, " reachable");
!   if (gimple_has_body_p (node->decl))
      fprintf (f, " body");
    if (node->output)
      fprintf (f, " output");
Index: cgraphunit.c
===================================================================
*** cgraphunit.c        (revision 139886)
--- cgraphunit.c        (working copy)
*************** verify_cgraph_node (struct cgraph_node *
*** 639,645 ****
      }

    if (node->analyzed
-       && gimple_body (node->decl)
        && !TREE_ASM_WRITTEN (node->decl)
        && (!DECL_EXTERNAL (node->decl) || node->global.inlined_to))
      {
--- 639,644 ----
*************** cgraph_analyze_functions (void)
*** 860,866 ****
      {
        fprintf (cgraph_dump_file, "Initial entry points:");
        for (node = cgraph_nodes; node != first_analyzed; node = node->next)
!       if (node->needed && gimple_body (node->decl))
          fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
        fprintf (cgraph_dump_file, "\n");
      }
--- 859,865 ----
      {
        fprintf (cgraph_dump_file, "Initial entry points:");
        for (node = cgraph_nodes; node != first_analyzed; node = node->next)
!       if (node->needed)
          fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
        fprintf (cgraph_dump_file, "\n");
      }
*************** cgraph_analyze_functions (void)
*** 912,918 ****
      {
        fprintf (cgraph_dump_file, "Unit entry points:");
        for (node = cgraph_nodes; node != first_analyzed; node = node->next)
!       if (node->needed && gimple_body (node->decl))
          fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
        fprintf (cgraph_dump_file, "\n\nInitial ");
        dump_cgraph (cgraph_dump_file);
--- 911,917 ----
      {
        fprintf (cgraph_dump_file, "Unit entry points:");
        for (node = cgraph_nodes; node != first_analyzed; node = node->next)
!       if (node->needed)
          fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
        fprintf (cgraph_dump_file, "\n\nInitial ");
        dump_cgraph (cgraph_dump_file);
*************** cgraph_analyze_functions (void)
*** 926,935 ****
        tree decl = node->decl;
        next = node->next;

!       if (node->local.finalized && !gimple_body (decl))
        cgraph_reset_node (node);

!       if (!node->reachable && gimple_body (decl))
        {
          if (cgraph_dump_file)
            fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
--- 925,934 ----
        tree decl = node->decl;
        next = node->next;

!       if (node->local.finalized && !gimple_has_body_p (decl))
        cgraph_reset_node (node);

!       if (!node->reachable && gimple_has_body_p (decl))
        {
          if (cgraph_dump_file)
            fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
*************** cgraph_analyze_functions (void)
*** 938,944 ****
        }
        else
        node->next_needed = NULL;
!       gcc_assert (!node->local.finalized || gimple_body (decl));
        gcc_assert (node->analyzed == node->local.finalized);
      }
    if (cgraph_dump_file)
--- 937,943 ----
        }
        else
        node->next_needed = NULL;
!       gcc_assert (!node->local.finalized || gimple_has_body_p (decl));
        gcc_assert (node->analyzed == node->local.finalized);
      }
    if (cgraph_dump_file)
*************** cgraph_mark_functions_to_output (void)
*** 991,997 ****
        /* We need to output all local functions that are used and not
         always inlined, as well as those that are reachable from
         outside the current compilation unit.  */
!       if (gimple_body (decl)
          && !node->global.inlined_to
          && (node->needed
              || (e && node->reachable))
--- 990,996 ----
        /* We need to output all local functions that are used and not
         always inlined, as well as those that are reachable from
         outside the current compilation unit.  */
!       if (node->analyzed
          && !node->global.inlined_to
          && (node->needed
              || (e && node->reachable))
*************** cgraph_mark_functions_to_output (void)
*** 1003,1009 ****
          /* We should've reclaimed all functions that are not needed.  */
  #ifdef ENABLE_CHECKING
          if (!node->global.inlined_to
!             && gimple_body (decl)
              && !DECL_EXTERNAL (decl))
            {
              dump_cgraph_node (stderr, node);
--- 1002,1008 ----
          /* We should've reclaimed all functions that are not needed.  */
  #ifdef ENABLE_CHECKING
          if (!node->global.inlined_to
!             && gimple_has_body_p (decl)
              && !DECL_EXTERNAL (decl))
            {
              dump_cgraph_node (stderr, node);
*************** cgraph_mark_functions_to_output (void)
*** 1011,1017 ****
            }
  #endif
          gcc_assert (node->global.inlined_to
!                     || !gimple_body (decl)
                      || DECL_EXTERNAL (decl));

        }
--- 1010,1016 ----
            }
  #endif
          gcc_assert (node->global.inlined_to
!                     || !gimple_has_body_p (decl)
                      || DECL_EXTERNAL (decl));

        }
*************** cgraph_expand_function (struct cgraph_no
*** 1042,1054 ****
    /* ??? Can happen with nested function of extern inline.  */
    gcc_assert (TREE_ASM_WRITTEN (decl));
    current_function_decl = NULL;
!   if (!cgraph_preserve_function_body_p (decl))
!     {
!       cgraph_release_function_body (node);
!       /* Eliminate all call edges.  This is important so the call_expr no
longer
!        points to the dead function body.  */
!       cgraph_node_remove_callees (node);
!     }

    cgraph_function_flags_ready = true;
  }
--- 1041,1051 ----
    /* ??? Can happen with nested function of extern inline.  */
    gcc_assert (TREE_ASM_WRITTEN (decl));
    current_function_decl = NULL;
!   gcc_assert (!cgraph_preserve_function_body_p (decl));
!   cgraph_release_function_body (node);
!   /* Eliminate all call edges.  This is important so the call_expr no longer
!      points to the dead function body.  */
!   cgraph_node_remove_callees (node);

    cgraph_function_flags_ready = true;
  }
*************** cgraph_optimize (void)
*** 1329,1335 ****
        for (node = cgraph_nodes; node; node = node->next)
        if (node->analyzed
            && (node->global.inlined_to
!               || gimple_body (node->decl)))
          {
            error_found = true;
            dump_cgraph_node (stderr, node);
--- 1326,1332 ----
        for (node = cgraph_nodes; node; node = node->next)
        if (node->analyzed
            && (node->global.inlined_to
!               || gimple_has_body_p (node->decl)))
          {
            error_found = true;
            dump_cgraph_node (stderr, node);
Index: ipa-inline.c
===================================================================
*** ipa-inline.c        (revision 139886)
--- ipa-inline.c        (working copy)
*************** cgraph_clone_inlined_nodes (struct cgrap
*** 212,218 ****
          && !cgraph_new_nodes)
        {
          gcc_assert (!e->callee->global.inlined_to);
!         if (gimple_body (e->callee->decl))
            overall_insns -= e->callee->global.insns, nfunctions_inlined++;
          duplicate = false;
        }
--- 212,218 ----
          && !cgraph_new_nodes)
        {
          gcc_assert (!e->callee->global.inlined_to);
!         if (e->callee->analyzed)
            overall_insns -= e->callee->global.insns, nfunctions_inlined++;
          duplicate = false;
        }
*************** cgraph_decide_inlining_incrementally (st
*** 1388,1394 ****
            }
          continue;
        }
!       if (!gimple_body (e->callee->decl) && !e->callee->inline_decl)
        {
          if (dump_file)
            {
--- 1388,1394 ----
            }
          continue;
        }
!       if (!e->callee->analyzed && !e->callee->inline_decl)
        {
          if (dump_file)
            {
*************** cgraph_decide_inlining_incrementally (st
*** 1463,1469 ****
              }
            continue;
          }
!       if (!gimple_body (e->callee->decl) && !e->callee->inline_decl)
          {
            if (dump_file)
              {
--- 1463,1469 ----
              }
            continue;
          }
!       if (!e->callee->analyzed && !e->callee->inline_decl)
          {
            if (dump_file)
              {
*************** inline_transform (struct cgraph_node *no
*** 1706,1712 ****

    /* We might need the body of this function so that we can expand
       it inline somewhere else.  */
!   if (cgraph_preserve_function_body_p (current_function_decl))
      save_inline_function_body (node);

    for (e = node->callees; e; e = e->next_callee)
--- 1706,1712 ----

    /* We might need the body of this function so that we can expand
       it inline somewhere else.  */
!   if (cgraph_preserve_function_body_p (node->decl))
      save_inline_function_body (node);

    for (e = node->callees; e; e = e->next_callee)
Index: predict.c
===================================================================
*** predict.c   (revision 139886)
--- predict.c   (working copy)
*************** struct gimple_opt_pass pass_strip_predic
*** 2179,2185 ****
  {
   {
    GIMPLE_PASS,
!   "",                                 /* name */
    NULL,                                       /* gate */
    strip_predict_hints,                        /* execute */
    NULL,                                       /* sub */
--- 2179,2185 ----
  {
   {
    GIMPLE_PASS,
!   NULL,                                       /* name */
    NULL,                                       /* gate */
    strip_predict_hints,                        /* execute */
    NULL,                                       /* sub */
Index: expmed.c
===================================================================
*** expmed.c    (revision 139886)
--- expmed.c    (working copy)
*************** expand_divmod (int rem_flag, enum tree_c
*** 4086,4093 ****
                      goto fail1;
                  }
                else if (EXACT_POWER_OF_2_OR_ZERO_P (d)
!                        && (rem_flag ? smod_pow2_cheap[compute_mode]
!                                     : sdiv_pow2_cheap[compute_mode])
                         /* We assume that cheap metric is true if the
                            optab has an expander for this mode.  */
                         && ((optab_handler ((rem_flag ? smod_optab
--- 4086,4093 ----
                      goto fail1;
                  }
                else if (EXACT_POWER_OF_2_OR_ZERO_P (d)
!                        && (rem_flag ? smod_pow2_cheap[speed][compute_mode]
!                                     : sdiv_pow2_cheap[speed][compute_mode])
                         /* We assume that cheap metric is true if the
                            optab has an expander for this mode.  */
                         && ((optab_handler ((rem_flag ? smod_optab
*************** expand_divmod (int rem_flag, enum tree_c
*** 4107,4113 ****
                          return gen_lowpart (mode, remainder);
                      }

!                   if (sdiv_pow2_cheap[compute_mode]
                        && ((optab_handler (sdiv_optab,
compute_mode)->insn_code
                             != CODE_FOR_nothing)
                            || (optab_handler (sdivmod_optab,
compute_mode)->insn_code
--- 4107,4113 ----
                          return gen_lowpart (mode, remainder);
                      }

!                   if (sdiv_pow2_cheap[speed][compute_mode]
                        && ((optab_handler (sdiv_optab,
compute_mode)->insn_code
                             != CODE_FOR_nothing)
                            || (optab_handler (sdivmod_optab,
compute_mode)->insn_code
Index: tree-inline.c
===================================================================
*** tree-inline.c       (revision 139886)
--- tree-inline.c       (working copy)
*************** static void
*** 1686,1693 ****
  initialize_cfun (tree new_fndecl, tree callee_fndecl, gcov_type count,
                 int frequency)
  {
-   struct function *new_cfun
-      = (struct function *) ggc_alloc_cleared (sizeof (struct function));
    struct function *src_cfun = DECL_STRUCT_FUNCTION (callee_fndecl);
    gcov_type count_scale, frequency_scale;

--- 1686,1691 ----
*************** initialize_cfun (tree new_fndecl, tree c
*** 1706,1719 ****

    /* Register specific tree functions.  */
    gimple_register_cfg_hooks ();
!   *new_cfun = *DECL_STRUCT_FUNCTION (callee_fndecl);
!   new_cfun->funcdef_no = get_next_funcdef_no ();
!   VALUE_HISTOGRAMS (new_cfun) = NULL;
!   new_cfun->local_decls = NULL;
!   new_cfun->cfg = NULL;
!   new_cfun->decl = new_fndecl /*= copy_node (callee_fndecl)*/;
!   DECL_STRUCT_FUNCTION (new_fndecl) = new_cfun;
!   push_cfun (new_cfun);
    init_empty_tree_cfg ();

    ENTRY_BLOCK_PTR->count =
--- 1704,1743 ----

    /* Register specific tree functions.  */
    gimple_register_cfg_hooks ();
! 
!   /* Get clean struct function.  */
!   push_struct_function (new_fndecl);
! 
!   /* We will rebuild these, so just sanity check that they are empty.  */
!   gcc_assert (VALUE_HISTOGRAMS (cfun) == NULL);
!   gcc_assert (cfun->local_decls == NULL);
!   gcc_assert (cfun->cfg == NULL);
!   gcc_assert (cfun->decl == new_fndecl);
! 
!   /* No need to copy; this is initialized later in compilation.  */
!   gcc_assert (!src_cfun->calls_setjmp);
!   gcc_assert (!src_cfun->calls_alloca);
! 
!   /* Copy items we preserve during clonning.  */
!   cfun->static_chain_decl = src_cfun->static_chain_decl;
!   cfun->nonlocal_goto_save_area = src_cfun->nonlocal_goto_save_area;
!   cfun->function_end_locus = src_cfun->function_end_locus;
!   cfun->curr_properties = src_cfun->curr_properties;
!   cfun->last_verified = src_cfun->last_verified;
!   if (src_cfun->ipa_transforms_to_apply)
!     cfun->ipa_transforms_to_apply = VEC_copy (ipa_opt_pass, heap,
!                                            
src_cfun->ipa_transforms_to_apply);
!   cfun->va_list_gpr_size = src_cfun->va_list_gpr_size;
!   cfun->va_list_fpr_size = src_cfun->va_list_fpr_size;
!   cfun->function_frequency = src_cfun->function_frequency;
!   cfun->has_nonlocal_label = src_cfun->has_nonlocal_label;
!   cfun->stdarg = src_cfun->stdarg;
!   cfun->dont_save_pending_sizes_p = src_cfun->dont_save_pending_sizes_p;
!   cfun->after_inlining = src_cfun->after_inlining;
!   cfun->returns_struct = src_cfun->returns_struct;
!   cfun->returns_pcc_struct = src_cfun->returns_pcc_struct;
!   cfun->after_tree_profile = src_cfun->after_tree_profile;
! 
    init_empty_tree_cfg ();

    ENTRY_BLOCK_PTR->count =
*************** inlinable_function_p (tree fn)
*** 2575,2586 ****
        inlinable = false;
      }

-   /* If we don't have the function body available, we can't inline it.
-      However, this should not be recorded since we also get here for
-      forward declared inline functions.  Therefore, return at once.  */
-   if (!gimple_body (fn))
-     return false;
- 
    else if (inline_forbidden_p (fn))
      {
        /* See if we should warn about uninlinable functions.  Previously,
--- 2599,2604 ----
*************** expand_call_inline (basic_block bb, gimp
*** 3083,3089 ****
       gimple_body.  */
    if (!DECL_INITIAL (fn)
        && DECL_ABSTRACT_ORIGIN (fn)
!       && gimple_body (DECL_ABSTRACT_ORIGIN (fn)))
      fn = DECL_ABSTRACT_ORIGIN (fn);

    /* Objective C and fortran still calls tree_rest_of_compilation directly.
--- 3101,3107 ----
       gimple_body.  */
    if (!DECL_INITIAL (fn)
        && DECL_ABSTRACT_ORIGIN (fn)
!       && gimple_has_body_p (DECL_ABSTRACT_ORIGIN (fn)))
      fn = DECL_ABSTRACT_ORIGIN (fn);

    /* Objective C and fortran still calls tree_rest_of_compilation directly.
Index: gimple.c
===================================================================
*** gimple.c    (revision 139886)
--- gimple.c    (working copy)
*************** gimple_body (tree fndecl)
*** 1816,1821 ****
--- 1816,1829 ----
    return fn ? fn->gimple_body : NULL;
  }

+ /* Return true when FNDECL has Gimple body either in unlowered
+    or CFG form.  */
+ bool
+ gimple_has_body_p (tree fndecl)
+ {
+   struct function *fn = DECL_STRUCT_FUNCTION (fndecl);
+   return (gimple_body (fndecl) || (fn && fn->cfg));
+ }

  /* Detect flags from a GIMPLE_CALL.  This is just like
     call_expr_flags, but for gimple tuples.  */
Index: gimple.h
===================================================================
*** gimple.h    (revision 139886)
--- gimple.h    (working copy)
*************** enum gimple_statement_structure_enum gss
*** 816,821 ****
--- 816,822 ----
  void sort_case_labels (VEC(tree,heap) *);
  void gimple_set_body (tree, gimple_seq);
  gimple_seq gimple_body (tree);
+ bool gimple_has_body_p (tree);
  gimple_seq gimple_seq_alloc (void);
  void gimple_seq_free (gimple_seq);
  void gimple_seq_add_seq (gimple_seq *, gimple_seq);
Index: tree-cfg.c
===================================================================
*** tree-cfg.c  (revision 139886)
--- tree-cfg.c  (working copy)
*************** build_gimple_cfg (gimple_seq seq)
*** 217,223 ****
  static unsigned int
  execute_build_cfg (void)
  {
!   build_gimple_cfg (gimple_body (current_function_decl));
    return 0;
  }

--- 217,226 ----
  static unsigned int
  execute_build_cfg (void)
  {
!   gimple_seq body = gimple_body (current_function_decl);
! 
!   build_gimple_cfg (body);
!   gimple_set_body (current_function_decl, NULL);
    return 0;
  }

*************** dump_function_to_file (tree fn, FILE *fi
*** 5898,5904 ****
    if (dsf && (flags & TDF_DETAILS))
      dump_eh_tree (file, dsf);

!   if (flags & TDF_RAW && !gimple_body (fn))
      {
        dump_node (fn, TDF_SLIM | flags, file);
        return;
--- 5901,5907 ----
    if (dsf && (flags & TDF_DETAILS))
      dump_eh_tree (file, dsf);

!   if (flags & TDF_RAW && !gimple_has_body_p (fn))
      {
        dump_node (fn, TDF_SLIM | flags, file);
        return;


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37315

Reply via email to