参照元

説明

引数

返り値

参考

実装

/* Major LRA entry function.  F is a file should be used to dump LRA
   debug info.  */
void
lra (FILE *f)
{
  int i;
  bool live_p, inserted_p;

  lra_dump_file = f;

  timevar_push (TV_LRA);
  /* Make sure that the last insn is a note.  Some subsequent passes
     need it.  */
  emit_note (NOTE_INSN_DELETED);

  COPY_HARD_REG_SET (lra_no_alloc_regs, ira_no_alloc_regs);

  init_reg_info ();
  expand_reg_info ();

  init_insn_recog_data ();
  /* Some quick check on RTL generated by previous passes.  */
  if (flag_checking)
    check_rtl (false);

  lra_in_progress = 1;

  lra_live_range_iter = lra_coalesce_iter = lra_constraint_iter = 0;
  lra_assignment_iter = lra_assignment_iter_after_spill = 0;
  lra_inheritance_iter = lra_undo_inheritance_iter = 0;
  lra_rematerialization_iter = 0;

  setup_reg_spill_flag ();
  /* Function remove_scratches can creates new pseudos for clobbers --
     so set up lra_constraint_new_regno_start before its call to
     permit changing reg classes for pseudos created by this
     simplification.  */
  lra_constraint_new_regno_start = lra_new_regno_start = max_reg_num ();
  lra_bad_spill_regno_start = INT_MAX;
  remove_scratches ();
  /* A function that has a non-local label that can reach the exit
     block via non-exceptional paths must save all call-saved
     registers.	 */
  if (cfun->has_nonlocal_label && has_nonexceptional_receiver ())
    crtl->saves_all_registers = 1;

  if (crtl->saves_all_registers)
    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
      if (! call_used_regs[i] && ! fixed_regs[i] && ! LOCAL_REGNO (i))
	df_set_regs_ever_live (i, true);
  /* We don't DF from now and avoid its using because it is to
     expensive when a lot of RTL changes are made.  */
  df_set_flags (DF_NO_INSN_RESCAN);
  lra_constraint_insn_stack.create (get_max_uid ());
  lra_constraint_insn_stack_bitmap = sbitmap_alloc (get_max_uid ());
  bitmap_clear (lra_constraint_insn_stack_bitmap);
  lra_live_ranges_init ();
  lra_constraints_init ();
  lra_curr_reload_num = 0;
  push_insns (get_last_insn (), NULL);
  /* It is needed for the 1st coalescing.  */
  bitmap_initialize (&lra_inheritance_pseudos, &reg_obstack);
  bitmap_initialize (&lra_split_regs, &reg_obstack);
  bitmap_initialize (&lra_optional_reload_pseudos, &reg_obstack);
  bitmap_initialize (&lra_subreg_reload_pseudos, &reg_obstack);
  live_p = false;
  if (maybe_ne (get_frame_size (), 0) && crtl->stack_alignment_needed)
    /* If we have a stack frame, we must align it now.  The stack size
       may be a part of the offset computation for register
       elimination.  */
    assign_stack_local (BLKmode, 0, crtl->stack_alignment_needed);
  lra_init_equiv ();
  for (;;)
    {
      for (;;)
	{
	  bool reloads_p = lra_constraints (lra_constraint_iter == 0);
	  /* Constraint transformations may result in that eliminable
	     hard regs become uneliminable and pseudos which use them
	     should be spilled.	 It is better to do it before pseudo
	     assignments.

	     For example, rs6000 can make
	     RS6000_PIC_OFFSET_TABLE_REGNUM uneliminable if we started
	     to use a constant pool.  */
	  lra_eliminate (false, false);
	  /* We should try to assign hard registers to scratches even
	     if there were no RTL transformations in lra_constraints.
	     Also we should check IRA assignments on the first
	     iteration as they can be wrong because of early clobbers
	     operands which are ignored in IRA.  */
	  if (! reloads_p && lra_constraint_iter > 1)
	    {
	      /* Stack is not empty here only when there are changes
		 during the elimination sub-pass.  */
	      if (bitmap_empty_p (lra_constraint_insn_stack_bitmap))
		break;
	      else
		/* If there are no reloads but changing due
		   elimination, restart the constraint sub-pass
		   first.  */
		continue;
	    }
	  /* Do inheritance only for regular algorithms.  */
	  if (! lra_simple_p)
	    {
	      if (flag_ipa_ra)
		{
		  if (live_p)
		    lra_clear_live_ranges ();
		  /* As a side-effect of lra_create_live_ranges, we calculate
		     actual_call_used_reg_set,  which is needed during
		     lra_inheritance.  */
		  lra_create_live_ranges (true, true);
		  live_p = true;
		}
	      lra_inheritance ();
	    }
	  if (live_p)
	    lra_clear_live_ranges ();
	  bool fails_p;
	  do
	    {
	      /* We need live ranges for lra_assign -- so build them.
		 But don't remove dead insns or change global live
		 info as we can undo inheritance transformations after
		 inheritance pseudo assigning.  */
	      lra_create_live_ranges (true, false);
	      live_p = true;
	      /* If we don't spill non-reload and non-inheritance
		 pseudos, there is no sense to run memory-memory move
		 coalescing.  If inheritance pseudos were spilled, the
		 memory-memory moves involving them will be removed by
		 pass undoing inheritance.  */
	      if (lra_simple_p)
		lra_assign (fails_p);
	      else
		{
		  bool spill_p = !lra_assign (fails_p);
		  
		  if (lra_undo_inheritance ())
		    live_p = false;
		  if (spill_p && ! fails_p)
		    {
		      if (! live_p)
			{
			  lra_create_live_ranges (true, true);
			  live_p = true;
			}
		      if (lra_coalesce ())
			live_p = false;
		    }
		  if (! live_p)
		    lra_clear_live_ranges ();
		}
	      if (fails_p)
		{
		  /* It is a very rare case.  It is the last hope to
		     split a hard regno live range for a reload
		     pseudo.  */
		  if (live_p)
		    lra_clear_live_ranges ();
		  live_p = false;
		  if (! lra_split_hard_reg_for ())
		    break;
		}
	    }
	  while (fails_p);
	}
      /* Don't clear optional reloads bitmap until all constraints are
	 satisfied as we need to differ them from regular reloads.  */
      bitmap_clear (&lra_optional_reload_pseudos);
      bitmap_clear (&lra_subreg_reload_pseudos);
      bitmap_clear (&lra_inheritance_pseudos);
      bitmap_clear (&lra_split_regs);
      if (! live_p)
	{
	  /* We need full live info for spilling pseudos into
	     registers instead of memory.  */
	  lra_create_live_ranges (lra_reg_spill_p, true);
	  live_p = true;
	}
      /* We should check necessity for spilling here as the above live
	 range pass can remove spilled pseudos.  */
      if (! lra_need_for_spills_p ())
	break;
      /* Now we know what pseudos should be spilled.  Try to
	 rematerialize them first.  */
      if (lra_remat ())
	{
	  /* We need full live info -- see the comment above.  */
	  lra_create_live_ranges (lra_reg_spill_p, true);
	  live_p = true;
	  if (! lra_need_for_spills_p ())
	    break;
	}
      lra_spill ();
      /* Assignment of stack slots changes elimination offsets for
	 some eliminations.  So update the offsets here.  */
      lra_eliminate (false, false);
      lra_constraint_new_regno_start = max_reg_num ();
      if (lra_bad_spill_regno_start == INT_MAX
	  && lra_inheritance_iter > LRA_MAX_INHERITANCE_PASSES
	  && lra_rematerialization_iter > LRA_MAX_REMATERIALIZATION_PASSES)
	/* After switching off inheritance and rematerialization
	   passes, avoid spilling reload pseudos will be created to
	   prevent LRA cycling in some complicated cases.  */
	lra_bad_spill_regno_start = lra_constraint_new_regno_start;
      lra_assignment_iter_after_spill = 0;
    }
  restore_scratches ();
  lra_eliminate (true, false);
  lra_final_code_change ();
  lra_in_progress = 0;
  if (live_p)
    lra_clear_live_ranges ();
  lra_live_ranges_finish ();
  lra_constraints_finish ();
  finish_reg_info ();
  sbitmap_free (lra_constraint_insn_stack_bitmap);
  lra_constraint_insn_stack.release ();
  finish_insn_recog_data ();
  regstat_free_n_sets_and_refs ();
  regstat_free_ri ();
  reload_completed = 1;
  update_inc_notes ();

  inserted_p = fixup_abnormal_edges ();
  /* We've possibly turned single trapping insn into multiple ones.  */
  if (cfun->can_throw_non_call_exceptions)
    {
      auto_sbitmap blocks (last_basic_block_for_fn (cfun));
      bitmap_ones (blocks);
      find_many_sub_basic_blocks (blocks);
    }

  if (inserted_p)
    commit_edge_insertions ();
  /* Replacing pseudos with their memory equivalents might have
     created shared rtx.  Subsequent passes would get confused
     by this, so unshare everything here.  */
  unshare_all_rtl_again (get_insns ());

  if (flag_checking)
    check_rtl (true);

  timevar_pop (TV_LRA);
}

コメント


トップ   編集 凍結 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2019-06-07 (金) 14:33:07