参照元

説明

引数

返り値

参考

実装

/* This is the main entry of IRA.  */
static void
ira (FILE *f)
{
  bool loops_p;
  int ira_max_point_before_emit;
  bool saved_flag_caller_saves = flag_caller_saves;
  enum ira_region saved_flag_ira_region = flag_ira_region;

  clear_bb_flags ();
  /* Determine if the current function is a leaf before running IRA
     since this can impact optimizations done by the prologue and
     epilogue thus changing register elimination offsets.
     Other target callbacks may use crtl->is_leaf too, including
     SHRINK_WRAPPING_ENABLED, so initialize as early as possible.  */
  crtl->is_leaf = leaf_function_p ();
  /* Perform target specific PIC register initialization.  */
  targetm.init_pic_reg ();

  ira_conflicts_p = optimize > 0;

  /* If there are too many pseudos and/or basic blocks (e.g. 10K
     pseudos and 10K blocks or 100K pseudos and 1K blocks), we will
     use simplified and faster algorithms in LRA.  */
  lra_simple_p
    = (ira_use_lra_p
       && max_reg_num () >= (1 << 26) / last_basic_block_for_fn (cfun));
  if (lra_simple_p)
    {
      /* It permits to skip live range splitting in LRA.  */
      flag_caller_saves = false;
      /* There is no sense to do regional allocation when we use
	 simplified LRA.  */
      flag_ira_region = IRA_REGION_ONE;
      ira_conflicts_p = false;
    }
#ifndef IRA_NO_OBSTACK
  gcc_obstack_init (&ira_obstack);
#endif
  bitmap_obstack_initialize (&ira_bitmap_obstack);
  /* LRA uses its own infrastructure to handle caller save registers.  */
  if (flag_caller_saves && !ira_use_lra_p)
    init_caller_save ();
  if (flag_ira_verbose < 10)
    {
      internal_flag_ira_verbose = flag_ira_verbose;
      ira_dump_file = f;
    }
  else
    {
      internal_flag_ira_verbose = flag_ira_verbose - 10;
      ira_dump_file = stderr;
    }

  setup_prohibited_mode_move_regs ();
  decrease_live_ranges_number ();
  df_note_add_problem ();
  /* DF_LIVE can't be used in the register allocator, too many other
     parts of the compiler depend on using the "classic" liveness
     interpretation of the DF_LR problem.  See PR38711.
     Remove the problem, so that we don't spend time updating it in
     any of the df_analyze() calls during IRA/LRA.  */
  if (optimize > 1)
    df_remove_problem (df_live);
  gcc_checking_assert (df_live == NULL);
  if (flag_checking)
    df->changeable_flags |= DF_VERIFY_SCHEDULED;

  df_analyze ();
  init_reg_equiv ();
  if (ira_conflicts_p)
    {
      calculate_dominance_info (CDI_DOMINATORS);

      if (split_live_ranges_for_shrink_wrap ())
	df_analyze ();

      free_dominance_info (CDI_DOMINATORS);
    }
  df_clear_flags (DF_NO_INSN_RESCAN);

  indirect_jump_optimize ();
  if (delete_trivially_dead_insns (get_insns (), max_reg_num ()))
    df_analyze ();

  regstat_init_n_sets_and_refs ();
  regstat_compute_ri ();
  /* If we are not optimizing, then this is the only place before
     register allocation where dataflow is done.  And that is needed
     to generate these warnings.  */
  if (warn_clobbered)
    generate_setjmp_warnings ();

  if (resize_reg_info () && flag_ira_loop_pressure)
    ira_set_pseudo_classes (true, ira_dump_file);
  init_alias_analysis ();
  loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
  reg_equiv = XCNEWVEC (struct equivalence, max_reg_num ());
  update_equiv_regs ();
  /* Don't move insns if live range shrinkage or register
     pressure-sensitive scheduling were done because it will not
     improve allocation but likely worsen insn scheduling.  */
  if (optimize
      && !flag_live_range_shrinkage
      && !(flag_sched_pressure && flag_schedule_insns))
    combine_and_move_insns ();
  /* Gather additional equivalences with memory.  */
  if (optimize)
    add_store_equivs ();
  loop_optimizer_finalize ();
  free_dominance_info (CDI_DOMINATORS);
  end_alias_analysis ();
  free (reg_equiv);

  setup_reg_equiv ();
  grow_reg_equivs ();
  setup_reg_equiv_init ();

  allocated_reg_info_size = max_reg_num ();
  /* It is not worth to do such improvement when we use a simple
     allocation because of -O0 usage or because the function is too
     big.  */
  if (ira_conflicts_p)
    find_moveable_pseudos ();
  max_regno_before_ira = max_reg_num ();
  ira_setup_eliminable_regset ();
  ira_overall_cost = ira_reg_cost = ira_mem_cost = 0;
  ira_load_cost = ira_store_cost = ira_shuffle_cost = 0;
  ira_move_loops_num = ira_additional_jumps_num = 0;

  ira_assert (current_loops == NULL);
  if (flag_ira_region == IRA_REGION_ALL || flag_ira_region == IRA_REGION_MIXED)
    loop_optimizer_init (AVOID_CFG_MODIFICATIONS | LOOPS_HAVE_RECORDED_EXITS);
  if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
    fprintf (ira_dump_file, "Building IRA IR\n");
  loops_p = ira_build ();

  ira_assert (ira_conflicts_p || !loops_p);
  saved_flag_ira_share_spill_slots = flag_ira_share_spill_slots;
  if (too_high_register_pressure_p () || cfun->calls_setjmp)
    /* It is just wasting compiler's time to pack spilled pseudos into
       stack slots in this case -- prohibit it.  We also do this if
       there is setjmp call because a variable not modified between
       setjmp and longjmp the compiler is required to preserve its
       value and sharing slots does not guarantee it.  */
    flag_ira_share_spill_slots = FALSE;

  ira_color ();

  ira_max_point_before_emit = ira_max_point;

  ira_initiate_emit_data ();

  ira_emit (loops_p);
  max_regno = max_reg_num ();
  if (ira_conflicts_p)
    {
      if (! loops_p)
	{
	  if (! ira_use_lra_p)
	    ira_initiate_assign ();
	}
      else
	{
	  expand_reg_info ();

	  if (ira_use_lra_p)
	    {
	      ira_allocno_t a;
	      ira_allocno_iterator ai;

	      FOR_EACH_ALLOCNO (a, ai)
                {
                  int old_regno = ALLOCNO_REGNO (a);
                  int new_regno = REGNO (ALLOCNO_EMIT_DATA (a)->reg);

                  ALLOCNO_REGNO (a) = new_regno;

                  if (old_regno != new_regno)
                    setup_reg_classes (new_regno, reg_preferred_class (old_regno),
                                       reg_alternate_class (old_regno),
                                       reg_allocno_class (old_regno));
                }
	    }
	  else
	    {
	      if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
		fprintf (ira_dump_file, "Flattening IR\n");
	      ira_flattening (max_regno_before_ira, ira_max_point_before_emit);
	    }
	  /* New insns were generated: add notes and recalculate live
	     info.  */
	  df_analyze ();

	  /* ??? Rebuild the loop tree, but why?  Does the loop tree
	     change if new insns were generated?  Can that be handled
	     by updating the loop tree incrementally?  */
	  loop_optimizer_finalize ();
	  free_dominance_info (CDI_DOMINATORS);
	  loop_optimizer_init (AVOID_CFG_MODIFICATIONS
			       | LOOPS_HAVE_RECORDED_EXITS);
	  if (! ira_use_lra_p)
	    {
	      setup_allocno_assignment_flags ();
	      ira_initiate_assign ();
	      ira_reassign_conflict_allocnos (max_regno);
	    }
	}
    }
  ira_finish_emit_data ();

  setup_reg_renumber ();

  calculate_allocation_cost ();
#ifdef ENABLE_IRA_CHECKING
  if (ira_conflicts_p && ! ira_use_lra_p)
    /* Opposite to reload pass, LRA does not use any conflict info
       from IRA.  We don't rebuild conflict info for LRA (through
       ira_flattening call) and can not use the check here.  We could
       rebuild this info for LRA in the check mode but there is a risk
       that code generated with the check and without it will be a bit
       different.  Calling ira_flattening in any mode would be a
       wasting CPU time.  So do not check the allocation for LRA.  */
    check_allocation ();
#endif
  if (max_regno != max_regno_before_ira)
    {
      regstat_free_n_sets_and_refs ();
      regstat_free_ri ();
      regstat_init_n_sets_and_refs ();
      regstat_compute_ri ();
    }
  overall_cost_before = ira_overall_cost;
  if (! ira_conflicts_p)
    grow_reg_equivs ();
  else
    {
      fix_reg_equiv_init ();

#ifdef ENABLE_IRA_CHECKING
      print_redundant_copies ();
#endif
      if (! ira_use_lra_p)
	{
	  ira_spilled_reg_stack_slots_num = 0;
	  ira_spilled_reg_stack_slots
	    = ((struct ira_spilled_reg_stack_slot *)
	       ira_allocate (max_regno
			     * sizeof (struct ira_spilled_reg_stack_slot)));
	  memset (ira_spilled_reg_stack_slots, 0,
		  max_regno * sizeof (struct ira_spilled_reg_stack_slot));
	}
    }
  allocate_initial_values ();
  /* See comment for find_moveable_pseudos call.  */
  if (ira_conflicts_p)
    move_unallocated_pseudos ();
  /* Restore original values.  */
  if (lra_simple_p)
    {
      flag_caller_saves = saved_flag_caller_saves;
      flag_ira_region = saved_flag_ira_region;
    }
}

コメント


トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS