OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [gcc/] [tree-optimize.c] - Diff between revs 154 and 816

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 154 Rev 816
/* Top-level control of tree optimizations.
/* Top-level control of tree optimizations.
   Copyright 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
   Copyright 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
   Contributed by Diego Novillo <dnovillo@redhat.com>
   Contributed by Diego Novillo <dnovillo@redhat.com>
 
 
This file is part of GCC.
This file is part of GCC.
 
 
GCC is free software; you can redistribute it and/or modify
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
the Free Software Foundation; either version 3, or (at your option)
any later version.
any later version.
 
 
GCC is distributed in the hope that it will be useful,
GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
GNU General Public License for more details.
 
 
You should have received a copy of the GNU General Public License
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */
<http://www.gnu.org/licenses/>.  */
 
 
#include "config.h"
#include "config.h"
#include "system.h"
#include "system.h"
#include "coretypes.h"
#include "coretypes.h"
#include "tm.h"
#include "tm.h"
#include "tree.h"
#include "tree.h"
#include "rtl.h"
#include "rtl.h"
#include "tm_p.h"
#include "tm_p.h"
#include "hard-reg-set.h"
#include "hard-reg-set.h"
#include "basic-block.h"
#include "basic-block.h"
#include "output.h"
#include "output.h"
#include "expr.h"
#include "expr.h"
#include "diagnostic.h"
#include "diagnostic.h"
#include "basic-block.h"
#include "basic-block.h"
#include "flags.h"
#include "flags.h"
#include "tree-flow.h"
#include "tree-flow.h"
#include "tree-dump.h"
#include "tree-dump.h"
#include "timevar.h"
#include "timevar.h"
#include "function.h"
#include "function.h"
#include "langhooks.h"
#include "langhooks.h"
#include "toplev.h"
#include "toplev.h"
#include "flags.h"
#include "flags.h"
#include "cgraph.h"
#include "cgraph.h"
#include "tree-inline.h"
#include "tree-inline.h"
#include "tree-mudflap.h"
#include "tree-mudflap.h"
#include "tree-pass.h"
#include "tree-pass.h"
#include "ggc.h"
#include "ggc.h"
#include "cgraph.h"
#include "cgraph.h"
#include "graph.h"
#include "graph.h"
#include "cfgloop.h"
#include "cfgloop.h"
#include "except.h"
#include "except.h"
 
 
 
 
/* Gate: execute, or not, all of the non-trivial optimizations.  */
/* Gate: execute, or not, all of the non-trivial optimizations.  */
 
 
static bool
static bool
gate_all_optimizations (void)
gate_all_optimizations (void)
{
{
  return (optimize >= 1
  return (optimize >= 1
          /* Don't bother doing anything if the program has errors.  */
          /* Don't bother doing anything if the program has errors.  */
          && !(errorcount || sorrycount));
          && !(errorcount || sorrycount));
}
}
 
 
struct tree_opt_pass pass_all_optimizations =
struct tree_opt_pass pass_all_optimizations =
{
{
  NULL,                                 /* name */
  NULL,                                 /* name */
  gate_all_optimizations,               /* gate */
  gate_all_optimizations,               /* gate */
  NULL,                                 /* execute */
  NULL,                                 /* execute */
  NULL,                                 /* sub */
  NULL,                                 /* sub */
  NULL,                                 /* next */
  NULL,                                 /* next */
  0,                                     /* static_pass_number */
  0,                                     /* static_pass_number */
  0,                                     /* tv_id */
  0,                                     /* tv_id */
  0,                                     /* properties_required */
  0,                                     /* properties_required */
  0,                                     /* properties_provided */
  0,                                     /* properties_provided */
  0,                                     /* properties_destroyed */
  0,                                     /* properties_destroyed */
  0,                                     /* todo_flags_start */
  0,                                     /* todo_flags_start */
  0,                                     /* todo_flags_finish */
  0,                                     /* todo_flags_finish */
  0                                      /* letter */
  0                                      /* letter */
};
};
 
 
struct tree_opt_pass pass_early_local_passes =
struct tree_opt_pass pass_early_local_passes =
{
{
  NULL,                                 /* name */
  NULL,                                 /* name */
  gate_all_optimizations,               /* gate */
  gate_all_optimizations,               /* gate */
  NULL,                                 /* execute */
  NULL,                                 /* execute */
  NULL,                                 /* sub */
  NULL,                                 /* sub */
  NULL,                                 /* next */
  NULL,                                 /* next */
  0,                                     /* static_pass_number */
  0,                                     /* static_pass_number */
  0,                                     /* tv_id */
  0,                                     /* tv_id */
  0,                                     /* properties_required */
  0,                                     /* properties_required */
  0,                                     /* properties_provided */
  0,                                     /* properties_provided */
  0,                                     /* properties_destroyed */
  0,                                     /* properties_destroyed */
  0,                                     /* todo_flags_start */
  0,                                     /* todo_flags_start */
  0,                                     /* todo_flags_finish */
  0,                                     /* todo_flags_finish */
  0                                      /* letter */
  0                                      /* letter */
};
};
 
 
/* Pass: cleanup the CFG just before expanding trees to RTL.
/* Pass: cleanup the CFG just before expanding trees to RTL.
   This is just a round of label cleanups and case node grouping
   This is just a round of label cleanups and case node grouping
   because after the tree optimizers have run such cleanups may
   because after the tree optimizers have run such cleanups may
   be necessary.  */
   be necessary.  */
 
 
static unsigned int
static unsigned int
execute_cleanup_cfg_pre_ipa (void)
execute_cleanup_cfg_pre_ipa (void)
{
{
  cleanup_tree_cfg ();
  cleanup_tree_cfg ();
  return 0;
  return 0;
}
}
 
 
struct tree_opt_pass pass_cleanup_cfg =
struct tree_opt_pass pass_cleanup_cfg =
{
{
  "cleanup_cfg",                        /* name */
  "cleanup_cfg",                        /* name */
  NULL,                                 /* gate */
  NULL,                                 /* gate */
  execute_cleanup_cfg_pre_ipa,          /* execute */
  execute_cleanup_cfg_pre_ipa,          /* execute */
  NULL,                                 /* sub */
  NULL,                                 /* sub */
  NULL,                                 /* next */
  NULL,                                 /* next */
  0,                                     /* static_pass_number */
  0,                                     /* static_pass_number */
  0,                                     /* tv_id */
  0,                                     /* tv_id */
  PROP_cfg,                             /* properties_required */
  PROP_cfg,                             /* properties_required */
  0,                                     /* properties_provided */
  0,                                     /* properties_provided */
  0,                                     /* properties_destroyed */
  0,                                     /* properties_destroyed */
  0,                                     /* todo_flags_start */
  0,                                     /* todo_flags_start */
  TODO_dump_func,                                       /* todo_flags_finish */
  TODO_dump_func,                                       /* todo_flags_finish */
  0                                      /* letter */
  0                                      /* letter */
};
};
 
 
 
 
/* Pass: cleanup the CFG just before expanding trees to RTL.
/* Pass: cleanup the CFG just before expanding trees to RTL.
   This is just a round of label cleanups and case node grouping
   This is just a round of label cleanups and case node grouping
   because after the tree optimizers have run such cleanups may
   because after the tree optimizers have run such cleanups may
   be necessary.  */
   be necessary.  */
 
 
static unsigned int
static unsigned int
execute_cleanup_cfg_post_optimizing (void)
execute_cleanup_cfg_post_optimizing (void)
{
{
  fold_cond_expr_cond ();
  fold_cond_expr_cond ();
  cleanup_tree_cfg ();
  cleanup_tree_cfg ();
  cleanup_dead_labels ();
  cleanup_dead_labels ();
  group_case_labels ();
  group_case_labels ();
  return 0;
  return 0;
}
}
 
 
struct tree_opt_pass pass_cleanup_cfg_post_optimizing =
struct tree_opt_pass pass_cleanup_cfg_post_optimizing =
{
{
  "final_cleanup",                      /* name */
  "final_cleanup",                      /* name */
  NULL,                                 /* gate */
  NULL,                                 /* gate */
  execute_cleanup_cfg_post_optimizing,  /* execute */
  execute_cleanup_cfg_post_optimizing,  /* execute */
  NULL,                                 /* sub */
  NULL,                                 /* sub */
  NULL,                                 /* next */
  NULL,                                 /* next */
  0,                                     /* static_pass_number */
  0,                                     /* static_pass_number */
  0,                                     /* tv_id */
  0,                                     /* tv_id */
  PROP_cfg,                             /* properties_required */
  PROP_cfg,                             /* properties_required */
  0,                                     /* properties_provided */
  0,                                     /* properties_provided */
  0,                                     /* properties_destroyed */
  0,                                     /* properties_destroyed */
  0,                                     /* todo_flags_start */
  0,                                     /* todo_flags_start */
  TODO_dump_func,                                       /* todo_flags_finish */
  TODO_dump_func,                                       /* todo_flags_finish */
  0                                      /* letter */
  0                                      /* letter */
};
};
 
 
/* Pass: do the actions required to finish with tree-ssa optimization
/* Pass: do the actions required to finish with tree-ssa optimization
   passes.  */
   passes.  */
 
 
static unsigned int
static unsigned int
execute_free_datastructures (void)
execute_free_datastructures (void)
{
{
  /* ??? This isn't the right place for this.  Worse, it got computed
  /* ??? This isn't the right place for this.  Worse, it got computed
     more or less at random in various passes.  */
     more or less at random in various passes.  */
  free_dominance_info (CDI_DOMINATORS);
  free_dominance_info (CDI_DOMINATORS);
  free_dominance_info (CDI_POST_DOMINATORS);
  free_dominance_info (CDI_POST_DOMINATORS);
 
 
  /* Remove the ssa structures.  Do it here since this includes statement
  /* Remove the ssa structures.  Do it here since this includes statement
     annotations that need to be intact during disband_implicit_edges.  */
     annotations that need to be intact during disband_implicit_edges.  */
  delete_tree_ssa ();
  delete_tree_ssa ();
  return 0;
  return 0;
}
}
 
 
struct tree_opt_pass pass_free_datastructures =
struct tree_opt_pass pass_free_datastructures =
{
{
  NULL,                                 /* name */
  NULL,                                 /* name */
  NULL,                                 /* gate */
  NULL,                                 /* gate */
  execute_free_datastructures,                  /* execute */
  execute_free_datastructures,                  /* execute */
  NULL,                                 /* sub */
  NULL,                                 /* sub */
  NULL,                                 /* next */
  NULL,                                 /* next */
  0,                                     /* static_pass_number */
  0,                                     /* static_pass_number */
  0,                                     /* tv_id */
  0,                                     /* tv_id */
  PROP_cfg,                             /* properties_required */
  PROP_cfg,                             /* properties_required */
  0,                                     /* properties_provided */
  0,                                     /* properties_provided */
  0,                                     /* properties_destroyed */
  0,                                     /* properties_destroyed */
  0,                                     /* todo_flags_start */
  0,                                     /* todo_flags_start */
  0,                                     /* todo_flags_finish */
  0,                                     /* todo_flags_finish */
  0                                      /* letter */
  0                                      /* letter */
};
};
/* Pass: free cfg annotations.  */
/* Pass: free cfg annotations.  */
 
 
static unsigned int
static unsigned int
execute_free_cfg_annotations (void)
execute_free_cfg_annotations (void)
{
{
  basic_block bb;
  basic_block bb;
  block_stmt_iterator bsi;
  block_stmt_iterator bsi;
 
 
  /* Emit gotos for implicit jumps.  */
  /* Emit gotos for implicit jumps.  */
  disband_implicit_edges ();
  disband_implicit_edges ();
 
 
  /* Remove annotations from every tree in the function.  */
  /* Remove annotations from every tree in the function.  */
  FOR_EACH_BB (bb)
  FOR_EACH_BB (bb)
    for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
    for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
      {
      {
        tree stmt = bsi_stmt (bsi);
        tree stmt = bsi_stmt (bsi);
        ggc_free (stmt->common.ann);
        ggc_free (stmt->common.ann);
        stmt->common.ann = NULL;
        stmt->common.ann = NULL;
      }
      }
 
 
  /* And get rid of annotations we no longer need.  */
  /* And get rid of annotations we no longer need.  */
  delete_tree_cfg_annotations ();
  delete_tree_cfg_annotations ();
 
 
#ifdef ENABLE_CHECKING
#ifdef ENABLE_CHECKING
  /* Once the statement annotations have been removed, we can verify
  /* Once the statement annotations have been removed, we can verify
     the integrity of statements in the EH throw table.  */
     the integrity of statements in the EH throw table.  */
  verify_eh_throw_table_statements ();
  verify_eh_throw_table_statements ();
#endif
#endif
  return 0;
  return 0;
}
}
 
 
struct tree_opt_pass pass_free_cfg_annotations =
struct tree_opt_pass pass_free_cfg_annotations =
{
{
  NULL,                                 /* name */
  NULL,                                 /* name */
  NULL,                                 /* gate */
  NULL,                                 /* gate */
  execute_free_cfg_annotations,         /* execute */
  execute_free_cfg_annotations,         /* execute */
  NULL,                                 /* sub */
  NULL,                                 /* sub */
  NULL,                                 /* next */
  NULL,                                 /* next */
  0,                                     /* static_pass_number */
  0,                                     /* static_pass_number */
  0,                                     /* tv_id */
  0,                                     /* tv_id */
  PROP_cfg,                             /* properties_required */
  PROP_cfg,                             /* properties_required */
  0,                                     /* properties_provided */
  0,                                     /* properties_provided */
  0,                                     /* properties_destroyed */
  0,                                     /* properties_destroyed */
  0,                                     /* todo_flags_start */
  0,                                     /* todo_flags_start */
  0,                                     /* todo_flags_finish */
  0,                                     /* todo_flags_finish */
  0                                      /* letter */
  0                                      /* letter */
};
};
 
 
/* Return true if BB has at least one abnormal outgoing edge.  */
/* Return true if BB has at least one abnormal outgoing edge.  */
 
 
static inline bool
static inline bool
has_abnormal_outgoing_edge_p (basic_block bb)
has_abnormal_outgoing_edge_p (basic_block bb)
{
{
  edge e;
  edge e;
  edge_iterator ei;
  edge_iterator ei;
 
 
  FOR_EACH_EDGE (e, ei, bb->succs)
  FOR_EACH_EDGE (e, ei, bb->succs)
    if (e->flags & EDGE_ABNORMAL)
    if (e->flags & EDGE_ABNORMAL)
      return true;
      return true;
 
 
  return false;
  return false;
}
}
 
 
/* Pass: fixup_cfg.  IPA passes, compilation of earlier functions or inlining
/* Pass: fixup_cfg.  IPA passes, compilation of earlier functions or inlining
   might have changed some properties, such as marked functions nothrow or
   might have changed some properties, such as marked functions nothrow or
   added calls that can potentially go to non-local labels.  Remove redundant
   added calls that can potentially go to non-local labels.  Remove redundant
   edges and basic blocks, and create new ones if necessary.  */
   edges and basic blocks, and create new ones if necessary.  */
 
 
static unsigned int
static unsigned int
execute_fixup_cfg (void)
execute_fixup_cfg (void)
{
{
  basic_block bb;
  basic_block bb;
  block_stmt_iterator bsi;
  block_stmt_iterator bsi;
 
 
  if (cfun->eh)
  if (cfun->eh)
    FOR_EACH_BB (bb)
    FOR_EACH_BB (bb)
      {
      {
        for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
        for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
          {
          {
            tree stmt = bsi_stmt (bsi);
            tree stmt = bsi_stmt (bsi);
            tree call = get_call_expr_in (stmt);
            tree call = get_call_expr_in (stmt);
 
 
            if (call && call_expr_flags (call) & (ECF_CONST | ECF_PURE))
            if (call && call_expr_flags (call) & (ECF_CONST | ECF_PURE))
              TREE_SIDE_EFFECTS (call) = 0;
              TREE_SIDE_EFFECTS (call) = 0;
            if (!tree_could_throw_p (stmt) && lookup_stmt_eh_region (stmt))
            if (!tree_could_throw_p (stmt) && lookup_stmt_eh_region (stmt))
              remove_stmt_from_eh_region (stmt);
              remove_stmt_from_eh_region (stmt);
          }
          }
        tree_purge_dead_eh_edges (bb);
        tree_purge_dead_eh_edges (bb);
      }
      }
 
 
  if (current_function_has_nonlocal_label)
  if (current_function_has_nonlocal_label)
    FOR_EACH_BB (bb)
    FOR_EACH_BB (bb)
      {
      {
        for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
        for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
          {
          {
            tree stmt = bsi_stmt (bsi);
            tree stmt = bsi_stmt (bsi);
            if (tree_can_make_abnormal_goto (stmt))
            if (tree_can_make_abnormal_goto (stmt))
              {
              {
                if (stmt == bsi_stmt (bsi_last (bb)))
                if (stmt == bsi_stmt (bsi_last (bb)))
                  {
                  {
                    if (!has_abnormal_outgoing_edge_p (bb))
                    if (!has_abnormal_outgoing_edge_p (bb))
                      make_abnormal_goto_edges (bb, true);
                      make_abnormal_goto_edges (bb, true);
                  }
                  }
                else
                else
                  {
                  {
                    edge e = split_block (bb, stmt);
                    edge e = split_block (bb, stmt);
                    bb = e->src;
                    bb = e->src;
                    make_abnormal_goto_edges (bb, true);
                    make_abnormal_goto_edges (bb, true);
                  }
                  }
                break;
                break;
              }
              }
          }
          }
      }
      }
 
 
  cleanup_tree_cfg ();
  cleanup_tree_cfg ();
 
 
  /* Dump a textual representation of the flowgraph.  */
  /* Dump a textual representation of the flowgraph.  */
  if (dump_file)
  if (dump_file)
    dump_tree_cfg (dump_file, dump_flags);
    dump_tree_cfg (dump_file, dump_flags);
 
 
  return 0;
  return 0;
}
}
 
 
struct tree_opt_pass pass_fixup_cfg =
struct tree_opt_pass pass_fixup_cfg =
{
{
  "fixupcfg",                           /* name */
  "fixupcfg",                           /* name */
  NULL,                                 /* gate */
  NULL,                                 /* gate */
  execute_fixup_cfg,                    /* execute */
  execute_fixup_cfg,                    /* execute */
  NULL,                                 /* sub */
  NULL,                                 /* sub */
  NULL,                                 /* next */
  NULL,                                 /* next */
  0,                                     /* static_pass_number */
  0,                                     /* static_pass_number */
  0,                                     /* tv_id */
  0,                                     /* tv_id */
  PROP_cfg,                             /* properties_required */
  PROP_cfg,                             /* properties_required */
  0,                                     /* properties_provided */
  0,                                     /* properties_provided */
  0,                                     /* properties_destroyed */
  0,                                     /* properties_destroyed */
  0,                                     /* todo_flags_start */
  0,                                     /* todo_flags_start */
  0,                                     /* todo_flags_finish */
  0,                                     /* todo_flags_finish */
  0                                      /* letter */
  0                                      /* letter */
};
};
 
 
/* Do the actions required to initialize internal data structures used
/* Do the actions required to initialize internal data structures used
   in tree-ssa optimization passes.  */
   in tree-ssa optimization passes.  */
 
 
static unsigned int
static unsigned int
execute_init_datastructures (void)
execute_init_datastructures (void)
{
{
  /* Allocate hash tables, arrays and other structures.  */
  /* Allocate hash tables, arrays and other structures.  */
  init_tree_ssa ();
  init_tree_ssa ();
  return 0;
  return 0;
}
}
 
 
struct tree_opt_pass pass_init_datastructures =
struct tree_opt_pass pass_init_datastructures =
{
{
  NULL,                                 /* name */
  NULL,                                 /* name */
  NULL,                                 /* gate */
  NULL,                                 /* gate */
  execute_init_datastructures,          /* execute */
  execute_init_datastructures,          /* execute */
  NULL,                                 /* sub */
  NULL,                                 /* sub */
  NULL,                                 /* next */
  NULL,                                 /* next */
  0,                                     /* static_pass_number */
  0,                                     /* static_pass_number */
  0,                                     /* tv_id */
  0,                                     /* tv_id */
  PROP_cfg,                             /* properties_required */
  PROP_cfg,                             /* properties_required */
  0,                                     /* properties_provided */
  0,                                     /* properties_provided */
  0,                                     /* properties_destroyed */
  0,                                     /* properties_destroyed */
  0,                                     /* todo_flags_start */
  0,                                     /* todo_flags_start */
  0,                                     /* todo_flags_finish */
  0,                                     /* todo_flags_finish */
  0                                      /* letter */
  0                                      /* letter */
};
};
 
 
void
void
tree_lowering_passes (tree fn)
tree_lowering_passes (tree fn)
{
{
  tree saved_current_function_decl = current_function_decl;
  tree saved_current_function_decl = current_function_decl;
 
 
  current_function_decl = fn;
  current_function_decl = fn;
  push_cfun (DECL_STRUCT_FUNCTION (fn));
  push_cfun (DECL_STRUCT_FUNCTION (fn));
  tree_register_cfg_hooks ();
  tree_register_cfg_hooks ();
  bitmap_obstack_initialize (NULL);
  bitmap_obstack_initialize (NULL);
  execute_pass_list (all_lowering_passes);
  execute_pass_list (all_lowering_passes);
  free_dominance_info (CDI_POST_DOMINATORS);
  free_dominance_info (CDI_POST_DOMINATORS);
  compact_blocks ();
  compact_blocks ();
  current_function_decl = saved_current_function_decl;
  current_function_decl = saved_current_function_decl;
  bitmap_obstack_release (NULL);
  bitmap_obstack_release (NULL);
  pop_cfun ();
  pop_cfun ();
}
}
 
 
/* Update recursively all inlined_to pointers of functions
/* Update recursively all inlined_to pointers of functions
   inlined into NODE to INLINED_TO.  */
   inlined into NODE to INLINED_TO.  */
static void
static void
update_inlined_to_pointers (struct cgraph_node *node,
update_inlined_to_pointers (struct cgraph_node *node,
                            struct cgraph_node *inlined_to)
                            struct cgraph_node *inlined_to)
{
{
  struct cgraph_edge *e;
  struct cgraph_edge *e;
  for (e = node->callees; e; e = e->next_callee)
  for (e = node->callees; e; e = e->next_callee)
    {
    {
      if (e->callee->global.inlined_to)
      if (e->callee->global.inlined_to)
        {
        {
          e->callee->global.inlined_to = inlined_to;
          e->callee->global.inlined_to = inlined_to;
          update_inlined_to_pointers (e->callee, inlined_to);
          update_inlined_to_pointers (e->callee, inlined_to);
        }
        }
    }
    }
}
}
 
 


/* For functions-as-trees languages, this performs all optimization and
/* For functions-as-trees languages, this performs all optimization and
   compilation for FNDECL.  */
   compilation for FNDECL.  */
 
 
void
void
tree_rest_of_compilation (tree fndecl)
tree_rest_of_compilation (tree fndecl)
{
{
  location_t saved_loc;
  location_t saved_loc;
  struct cgraph_node *node;
  struct cgraph_node *node;
 
 
  timevar_push (TV_EXPAND);
  timevar_push (TV_EXPAND);
 
 
  gcc_assert (!flag_unit_at_a_time || cgraph_global_info_ready);
  gcc_assert (!flag_unit_at_a_time || cgraph_global_info_ready);
 
 
  node = cgraph_node (fndecl);
  node = cgraph_node (fndecl);
 
 
  /* We might need the body of this function so that we can expand
  /* We might need the body of this function so that we can expand
     it inline somewhere else.  */
     it inline somewhere else.  */
  if (cgraph_preserve_function_body_p (fndecl))
  if (cgraph_preserve_function_body_p (fndecl))
    save_inline_function_body (node);
    save_inline_function_body (node);
 
 
  /* Initialize the RTL code for the function.  */
  /* Initialize the RTL code for the function.  */
  current_function_decl = fndecl;
  current_function_decl = fndecl;
  saved_loc = input_location;
  saved_loc = input_location;
  input_location = DECL_SOURCE_LOCATION (fndecl);
  input_location = DECL_SOURCE_LOCATION (fndecl);
  init_function_start (fndecl);
  init_function_start (fndecl);
 
 
  /* Even though we're inside a function body, we still don't want to
  /* Even though we're inside a function body, we still don't want to
     call expand_expr to calculate the size of a variable-sized array.
     call expand_expr to calculate the size of a variable-sized array.
     We haven't necessarily assigned RTL to all variables yet, so it's
     We haven't necessarily assigned RTL to all variables yet, so it's
     not safe to try to expand expressions involving them.  */
     not safe to try to expand expressions involving them.  */
  cfun->x_dont_save_pending_sizes_p = 1;
  cfun->x_dont_save_pending_sizes_p = 1;
  cfun->after_inlining = true;
  cfun->after_inlining = true;
 
 
  if (flag_inline_trees)
  if (flag_inline_trees)
    {
    {
      struct cgraph_edge *e;
      struct cgraph_edge *e;
      for (e = node->callees; e; e = e->next_callee)
      for (e = node->callees; e; e = e->next_callee)
        if (!e->inline_failed || warn_inline)
        if (!e->inline_failed || warn_inline)
          break;
          break;
      if (e)
      if (e)
        {
        {
          timevar_push (TV_INTEGRATION);
          timevar_push (TV_INTEGRATION);
          optimize_inline_calls (fndecl);
          optimize_inline_calls (fndecl);
          timevar_pop (TV_INTEGRATION);
          timevar_pop (TV_INTEGRATION);
        }
        }
    }
    }
  /* In non-unit-at-a-time we must mark all referenced functions as needed.
  /* In non-unit-at-a-time we must mark all referenced functions as needed.
     */
     */
  if (!flag_unit_at_a_time)
  if (!flag_unit_at_a_time)
    {
    {
      struct cgraph_edge *e;
      struct cgraph_edge *e;
      for (e = node->callees; e; e = e->next_callee)
      for (e = node->callees; e; e = e->next_callee)
        if (e->callee->analyzed)
        if (e->callee->analyzed)
          cgraph_mark_needed_node (e->callee);
          cgraph_mark_needed_node (e->callee);
    }
    }
 
 
  /* We are not going to maintain the cgraph edges up to date.
  /* We are not going to maintain the cgraph edges up to date.
     Kill it so it won't confuse us.  */
     Kill it so it won't confuse us.  */
  cgraph_node_remove_callees (node);
  cgraph_node_remove_callees (node);
 
 
 
 
  /* Initialize the default bitmap obstack.  */
  /* Initialize the default bitmap obstack.  */
  bitmap_obstack_initialize (NULL);
  bitmap_obstack_initialize (NULL);
  bitmap_obstack_initialize (&reg_obstack); /* FIXME, only at RTL generation*/
  bitmap_obstack_initialize (&reg_obstack); /* FIXME, only at RTL generation*/
 
 
  tree_register_cfg_hooks ();
  tree_register_cfg_hooks ();
  /* Perform all tree transforms and optimizations.  */
  /* Perform all tree transforms and optimizations.  */
  execute_pass_list (all_passes);
  execute_pass_list (all_passes);
 
 
  bitmap_obstack_release (&reg_obstack);
  bitmap_obstack_release (&reg_obstack);
 
 
  /* Release the default bitmap obstack.  */
  /* Release the default bitmap obstack.  */
  bitmap_obstack_release (NULL);
  bitmap_obstack_release (NULL);
 
 
  DECL_SAVED_TREE (fndecl) = NULL;
  DECL_SAVED_TREE (fndecl) = NULL;
  cfun = 0;
  cfun = 0;
 
 
  /* If requested, warn about function definitions where the function will
  /* If requested, warn about function definitions where the function will
     return a value (usually of some struct or union type) which itself will
     return a value (usually of some struct or union type) which itself will
     take up a lot of stack space.  */
     take up a lot of stack space.  */
  if (warn_larger_than && !DECL_EXTERNAL (fndecl) && TREE_TYPE (fndecl))
  if (warn_larger_than && !DECL_EXTERNAL (fndecl) && TREE_TYPE (fndecl))
    {
    {
      tree ret_type = TREE_TYPE (TREE_TYPE (fndecl));
      tree ret_type = TREE_TYPE (TREE_TYPE (fndecl));
 
 
      if (ret_type && TYPE_SIZE_UNIT (ret_type)
      if (ret_type && TYPE_SIZE_UNIT (ret_type)
          && TREE_CODE (TYPE_SIZE_UNIT (ret_type)) == INTEGER_CST
          && TREE_CODE (TYPE_SIZE_UNIT (ret_type)) == INTEGER_CST
          && 0 < compare_tree_int (TYPE_SIZE_UNIT (ret_type),
          && 0 < compare_tree_int (TYPE_SIZE_UNIT (ret_type),
                                   larger_than_size))
                                   larger_than_size))
        {
        {
          unsigned int size_as_int
          unsigned int size_as_int
            = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ret_type));
            = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ret_type));
 
 
          if (compare_tree_int (TYPE_SIZE_UNIT (ret_type), size_as_int) == 0)
          if (compare_tree_int (TYPE_SIZE_UNIT (ret_type), size_as_int) == 0)
            warning (0, "size of return value of %q+D is %u bytes",
            warning (0, "size of return value of %q+D is %u bytes",
                     fndecl, size_as_int);
                     fndecl, size_as_int);
          else
          else
            warning (0, "size of return value of %q+D is larger than %wd bytes",
            warning (0, "size of return value of %q+D is larger than %wd bytes",
                     fndecl, larger_than_size);
                     fndecl, larger_than_size);
        }
        }
    }
    }
 
 
  if (!flag_inline_trees)
  if (!flag_inline_trees)
    {
    {
      DECL_SAVED_TREE (fndecl) = NULL;
      DECL_SAVED_TREE (fndecl) = NULL;
      if (DECL_STRUCT_FUNCTION (fndecl) == 0
      if (DECL_STRUCT_FUNCTION (fndecl) == 0
          && !cgraph_node (fndecl)->origin)
          && !cgraph_node (fndecl)->origin)
        {
        {
          /* Stop pointing to the local nodes about to be freed.
          /* Stop pointing to the local nodes about to be freed.
             But DECL_INITIAL must remain nonzero so we know this
             But DECL_INITIAL must remain nonzero so we know this
             was an actual function definition.
             was an actual function definition.
             For a nested function, this is done in c_pop_function_context.
             For a nested function, this is done in c_pop_function_context.
             If rest_of_compilation set this to 0, leave it 0.  */
             If rest_of_compilation set this to 0, leave it 0.  */
          if (DECL_INITIAL (fndecl) != 0)
          if (DECL_INITIAL (fndecl) != 0)
            DECL_INITIAL (fndecl) = error_mark_node;
            DECL_INITIAL (fndecl) = error_mark_node;
        }
        }
    }
    }
 
 
  input_location = saved_loc;
  input_location = saved_loc;
 
 
  ggc_collect ();
  ggc_collect ();
  timevar_pop (TV_EXPAND);
  timevar_pop (TV_EXPAND);
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.