This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC] Removal of loop notes


Hello,

here is a proposal for the patch to remove loop notes (I still need to
benchmark it, and probably split into smaller parts).  However, I do not
understand some of the code from that it removes loop note usage, so I
would appreciate comments on them:

cse.c:cse_end_of_basic_block -- something related to jump following.
  Steven, you had some patches towards removing this, right?

jump.c:follow_jumps -- claims something about creating loops with
  multiple entries.  However, it seemts to be only used in cse (that won't
  affect cfg), and then in dbr_schedule (way after the point where we
  care about loop structures).

*sched* -- no idea what happens there; it seems to make REG_SAVE_NOTE
  notes from loop notes, and then makes some magic, but I do not
  understand what and why.

config/sh/sh.c: sh_adjust_unroll_max seems unused,
  sh_optimize_target_register_callee_saved contains some heuristics
  based on loops, I have no idea how important that heuristics is
  (and I do not have hardware to benchmark it).

Zdenek

Index: doc/tm.texi
===================================================================
*** doc/tm.texi	(revision 111675)
--- doc/tm.texi	(working copy)
*************** The maximum number of bytes to skip when
*** 7942,7949 ****
  @end defmac
  
  @defmac LOOP_ALIGN (@var{label})
! The alignment (log base 2) to put in front of @var{label}, which follows
! a @code{NOTE_INSN_LOOP_BEG} note.
  
  This macro need not be defined if you don't want any special alignment
  to be done at such a time.  Most machine descriptions do not currently
--- 7942,7949 ----
  @end defmac
  
  @defmac LOOP_ALIGN (@var{label})
! The alignment (log base 2) to put in front of @var{label} at the beginning
! of the loop.
  
  This macro need not be defined if you don't want any special alignment
  to be done at such a time.  Most machine descriptions do not currently
Index: doc/rtl.texi
===================================================================
*** doc/rtl.texi	(revision 111675)
--- doc/rtl.texi	(working copy)
*************** level of scoping for exception handling.
*** 3139,3168 ****
  identifies which @code{CODE_LABEL} or @code{note} of type
  @code{NOTE_INSN_DELETED_LABEL} is associated with the given region.
  
- @findex NOTE_INSN_LOOP_BEG
- @findex NOTE_INSN_LOOP_END
- @item NOTE_INSN_LOOP_BEG
- @itemx NOTE_INSN_LOOP_END
- These types of notes indicate the position of the beginning and end
- of a @code{while} or @code{for} loop.  They enable the loop optimizer
- to find loops quickly.
- 
- @findex NOTE_INSN_LOOP_CONT
- @item NOTE_INSN_LOOP_CONT
- Appears at the place in a loop that @code{continue} statements jump to.
- 
- @findex NOTE_INSN_LOOP_VTOP
- @item NOTE_INSN_LOOP_VTOP
- This note indicates the place in a loop where the exit test begins for
- those loops in which the exit test has been duplicated.  This position
- becomes another virtual start of the loop when considering loop
- invariants.
- 
- @findex NOTE_INSN_FUNCTION_BEG
- @item NOTE_INSN_FUNCTION_BEG
- Appears at the start of the function body, after the function
- prologue.
- 
  @findex NOTE_INSN_FUNCTION_END
  @item NOTE_INSN_FUNCTION_END
  Appears near the end of the function body, just before the label that
--- 3139,3144 ----
Index: cfgloopmanip.c
===================================================================
*** cfgloopmanip.c	(revision 111675)
--- cfgloopmanip.c	(working copy)
*************** loop_split_edge_with (edge e, rtx insns)
*** 1275,1374 ****
    return new_bb;
  }
  
- /* Uses the natural loop discovery to recreate loop notes.  */
- void
- create_loop_notes (void)
- {
-   rtx insn, head, end;
-   struct loops loops;
-   struct loop *loop;
-   basic_block *first, *last, bb, pbb;
-   struct loop **stack, **top;
- 
- #ifdef ENABLE_CHECKING
-   /* Verify that there really are no loop notes.  */
-   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
-     gcc_assert (!NOTE_P (insn) ||
- 		NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_BEG);
- #endif
- 
-   flow_loops_find (&loops);
-   free_dominance_info (CDI_DOMINATORS);
-   if (loops.num > 1)
-     {
-       last = XCNEWVEC (basic_block, loops.num);
- 
-       FOR_EACH_BB (bb)
- 	{
- 	  for (loop = bb->loop_father; loop->outer; loop = loop->outer)
- 	    last[loop->num] = bb;
- 	}
- 
-       first = XCNEWVEC (basic_block, loops.num);
-       stack = XCNEWVEC (struct loop *, loops.num);
-       top = stack;
- 
-       FOR_EACH_BB (bb)
- 	{
- 	  for (loop = bb->loop_father; loop->outer; loop = loop->outer)
- 	    {
- 	      if (!first[loop->num])
- 		{
- 		  *top++ = loop;
- 		  first[loop->num] = bb;
- 		}
- 
- 	      if (bb == last[loop->num])
- 		{
- 		  /* Prevent loops from overlapping.  */
- 		  while (*--top != loop)
- 		    last[(*top)->num] = EXIT_BLOCK_PTR;
- 
- 		  /* If loop starts with jump into it, place the note in
- 		     front of the jump.  */
- 		  insn = PREV_INSN (BB_HEAD (first[loop->num]));
- 		  if (insn
- 		      && BARRIER_P (insn))
- 		    insn = PREV_INSN (insn);
- 		  
- 		  if (insn
- 		      && JUMP_P (insn)
- 		      && any_uncondjump_p (insn)
- 		      && onlyjump_p (insn))
- 		    {
- 		      pbb = BLOCK_FOR_INSN (insn);
- 		      gcc_assert (pbb && single_succ_p (pbb));
- 
- 		      if (!flow_bb_inside_loop_p (loop, single_succ (pbb)))
- 			insn = BB_HEAD (first[loop->num]);
- 		    }
- 		  else
- 		    insn = BB_HEAD (first[loop->num]);
- 		    
- 		  head = BB_HEAD (first[loop->num]);
- 		  emit_note_before (NOTE_INSN_LOOP_BEG, insn);
- 		  BB_HEAD (first[loop->num]) = head;
- 
- 		  /* Position the note correctly wrto barrier.  */
- 		  insn = BB_END (last[loop->num]);
- 		  if (NEXT_INSN (insn)
- 		      && BARRIER_P (NEXT_INSN (insn)))
- 		    insn = NEXT_INSN (insn);
- 		  
- 		  end = BB_END (last[loop->num]);
- 		  emit_note_after (NOTE_INSN_LOOP_END, insn);
- 		  BB_END (last[loop->num]) = end;
- 		}
- 	    }
- 	}
- 
-       free (first);
-       free (last);
-       free (stack);
-     }
-   flow_loops_free (&loops);
- }
- 
  /* This function is called from loop_version.  It splits the entry edge
     of the loop we want to version, adds the versioning condition, and
     adjust the edges to the two versions of the loop appropriately.
--- 1275,1280 ----
Index: final.c
===================================================================
*** final.c	(revision 111675)
--- final.c	(working copy)
*************** shorten_branches (rtx first ATTRIBUTE_UN
*** 856,869 ****
  
        INSN_SHUID (insn) = i++;
        if (INSN_P (insn))
! 	{
! 	  /* reorg might make the first insn of a loop being run once only,
!              and delete the label in front of it.  Then we want to apply
!              the loop alignment to the new label created by reorg, which
!              is separated by the former loop start insn from the
! 	     NOTE_INSN_LOOP_BEG.  */
! 	}
!       else if (LABEL_P (insn))
  	{
  	  rtx next;
  
--- 856,864 ----
  
        INSN_SHUID (insn) = i++;
        if (INSN_P (insn))
! 	continue;
!       
!       if (LABEL_P (insn))
  	{
  	  rtx next;
  
*************** final_scan_insn (rtx insn, FILE *file, i
*** 1703,1710 ****
        switch (NOTE_LINE_NUMBER (insn))
  	{
  	case NOTE_INSN_DELETED:
- 	case NOTE_INSN_LOOP_BEG:
- 	case NOTE_INSN_LOOP_END:
  	case NOTE_INSN_FUNCTION_END:
  	case NOTE_INSN_REPEATED_LINE_NUMBER:
  	case NOTE_INSN_EXPECTED_VALUE:
--- 1698,1703 ----
Index: insn-notes.def
===================================================================
*** insn-notes.def	(revision 111675)
--- insn-notes.def	(working copy)
*************** INSN_NOTE (DELETED_LABEL)
*** 43,52 ****
  INSN_NOTE (BLOCK_BEG)
  INSN_NOTE (BLOCK_END)
  
- /* These mark the extremes of a loop.  */
- INSN_NOTE (LOOP_BEG)
- INSN_NOTE (LOOP_END)
- 
  /* This note indicates the start of the real body of the function,
     i.e. the point just after all of the parms have been moved into
     their homes, etc.  */
--- 43,48 ----
Index: haifa-sched.c
===================================================================
*** haifa-sched.c	(revision 111675)
--- haifa-sched.c	(working copy)
*************** unlink_other_notes (rtx insn, rtx tail)
*** 989,997 ****
  	PREV_INSN (next) = prev;
  
        /* See sched_analyze to see how these are handled.  */
!       if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_BEG
! 	  && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_END
! 	  && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK
  	  && NOTE_LINE_NUMBER (insn) != NOTE_INSN_EH_REGION_BEG
  	  && NOTE_LINE_NUMBER (insn) != NOTE_INSN_EH_REGION_END)
  	{
--- 989,995 ----
  	PREV_INSN (next) = prev;
  
        /* See sched_analyze to see how these are handled.  */
!       if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK
  	  && NOTE_LINE_NUMBER (insn) != NOTE_INSN_EH_REGION_BEG
  	  && NOTE_LINE_NUMBER (insn) != NOTE_INSN_EH_REGION_END)
  	{
*************** move_insn1 (rtx insn, rtx last)
*** 1615,1621 ****
  }
  
  /* Search INSN for REG_SAVE_NOTE note pairs for
!    NOTE_INSN_{LOOP,EHREGION}_{BEG,END}; and convert them back into
     NOTEs.  The REG_SAVE_NOTE note following first one is contains the
     saved value for NOTE_BLOCK_NUMBER which is useful for
     NOTE_INSN_EH_REGION_{BEG,END} NOTEs.  LAST is the last instruction
--- 1613,1619 ----
  }
  
  /* Search INSN for REG_SAVE_NOTE note pairs for
!    NOTE_INSN_EHREGION_{BEG,END}; and convert them back into
     NOTEs.  The REG_SAVE_NOTE note following first one is contains the
     saved value for NOTE_BLOCK_NUMBER which is useful for
     NOTE_INSN_EH_REGION_{BEG,END} NOTEs.  LAST is the last instruction
Index: cse.c
===================================================================
*** cse.c	(revision 111675)
--- cse.c	(working copy)
*************** cse_end_of_basic_block (rtx insn, struct
*** 6696,6702 ****
  	{
  	  for (q = PREV_INSN (JUMP_LABEL (p)); q; q = PREV_INSN (q))
  	    if ((!NOTE_P (q)
- 		 || NOTE_LINE_NUMBER (q) == NOTE_INSN_LOOP_END
  		 || (PREV_INSN (q) && CALL_P (PREV_INSN (q))
  		     && find_reg_note (PREV_INSN (q), REG_SETJMP, NULL)))
  		&& (!LABEL_P (q) || LABEL_NUSES (q) != 0))
--- 6696,6701 ----
Index: jump.c
===================================================================
*** jump.c	(revision 111675)
--- jump.c	(working copy)
*************** mark_all_labels (rtx f)
*** 260,270 ****
        }
  }
  
! /* Move all block-beg, block-end, loop-beg, loop-cont, loop-vtop, loop-end,
!    notes between START and END out before START.  START and END may be such
!    notes.  Returns the values of the new starting and ending insns, which
!    may be different if the original ones were such notes.
!    Return true if there were only such notes and no real instructions.  */
  
  bool
  squeeze_notes (rtx* startp, rtx* endp)
--- 260,270 ----
        }
  }
  
! /* Move all block-beg, block-end and loop-beg notes between START and END out
!    before START.  START and END may be such notes.  Returns the values of the
!    new starting and ending insns, which may be different if the original ones
!    were such notes.  Return true if there were only such notes and no real
!    instructions.  */
  
  bool
  squeeze_notes (rtx* startp, rtx* endp)
*************** squeeze_notes (rtx* startp, rtx* endp)
*** 282,290 ****
        next = NEXT_INSN (insn);
        if (NOTE_P (insn)
  	  && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END
! 	      || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG
! 	      || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
! 	      || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END))
  	{
  	  /* BLOCK_BEG or BLOCK_END notes only exist in the `final' pass.  */
  	  gcc_assert (NOTE_LINE_NUMBER (insn) != NOTE_INSN_BLOCK_BEG
--- 282,288 ----
        next = NEXT_INSN (insn);
        if (NOTE_P (insn)
  	  && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END
! 	      || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG))
  	{
  	  /* BLOCK_BEG or BLOCK_END notes only exist in the `final' pass.  */
  	  gcc_assert (NOTE_LINE_NUMBER (insn) != NOTE_INSN_BLOCK_BEG
*************** sets_cc0_p (rtx x)
*** 1041,1048 ****
     If the chain loops or we can't find end, return LABEL,
     since that tells caller to avoid changing the insn.
  
!    If RELOAD_COMPLETED is 0, we do not chain across a NOTE_INSN_LOOP_BEG or
!    a USE or CLOBBER.  */
  
  rtx
  follow_jumps (rtx label)
--- 1039,1045 ----
     If the chain loops or we can't find end, return LABEL,
     since that tells caller to avoid changing the insn.
  
!    If RELOAD_COMPLETED is 0, we do not chain across a USE or CLOBBER.  */
  
  rtx
  follow_jumps (rtx label)
*************** follow_jumps (rtx label)
*** 1063,1081 ****
  	&& BARRIER_P (next));
         depth++)
      {
-       /* Don't chain through the insn that jumps into a loop
- 	 from outside the loop,
- 	 since that would create multiple loop entry jumps
- 	 and prevent loop optimization.  */
        rtx tem;
!       if (!reload_completed)
! 	for (tem = value; tem != insn; tem = NEXT_INSN (tem))
! 	  if (NOTE_P (tem)
! 	      && (NOTE_LINE_NUMBER (tem) == NOTE_INSN_LOOP_BEG
! 		  /* ??? Optional.  Disables some optimizations, but makes
! 		     gcov output more accurate with -O.  */
! 		  || (flag_test_coverage && NOTE_LINE_NUMBER (tem) > 0)))
! 	    return value;
  
        /* If we have found a cycle, make the insn jump to itself.  */
        if (JUMP_LABEL (insn) == label)
--- 1060,1074 ----
  	&& BARRIER_P (next));
         depth++)
      {
        rtx tem;
!       if (!reload_completed && flag_test_coverage)
! 	{
! 	  /* ??? Optional.  Disables some optimizations, but makes
! 	     gcov output more accurate with -O.  */
! 	  for (tem = value; tem != insn; tem = NEXT_INSN (tem))
! 	    if (NOTE_P (tem) && NOTE_LINE_NUMBER (tem) > 0)
! 	      return value;
! 	}
  
        /* If we have found a cycle, make the insn jump to itself.  */
        if (JUMP_LABEL (insn) == label)
Index: cfgcleanup.c
===================================================================
*** cfgcleanup.c	(revision 111675)
--- cfgcleanup.c	(working copy)
*************** rest_of_handle_jump2 (void)
*** 2312,2319 ****
    cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0)
                 | (flag_thread_jumps ? CLEANUP_THREADING : 0));
  
-   create_loop_notes ();
- 
    purge_line_number_notes ();
  
    if (optimize)
--- 2312,2317 ----
Index: cfglayout.c
===================================================================
*** cfglayout.c	(revision 111675)
--- cfglayout.c	(working copy)
*************** skip_insns_after_block (basic_block bb)
*** 99,105 ****
  	case NOTE:
  	  switch (NOTE_LINE_NUMBER (insn))
  	    {
- 	    case NOTE_INSN_LOOP_END:
  	    case NOTE_INSN_BLOCK_END:
  	      last_insn = insn;
  	      continue;
--- 99,104 ----
*************** skip_insns_after_block (basic_block bb)
*** 135,146 ****
    /* It is possible to hit contradictory sequence.  For instance:
  
       jump_insn
!      NOTE_INSN_LOOP_BEG
       barrier
  
       Where barrier belongs to jump_insn, but the note does not.  This can be
       created by removing the basic block originally following
!      NOTE_INSN_LOOP_BEG.  In such case reorder the notes.  */
  
    for (insn = last_insn; insn != BB_END (bb); insn = prev)
      {
--- 134,145 ----
    /* It is possible to hit contradictory sequence.  For instance:
  
       jump_insn
!      NOTE_INSN_BLOCK_BEG
       barrier
  
       Where barrier belongs to jump_insn, but the note does not.  This can be
       created by removing the basic block originally following
!      NOTE_INSN_BLOCK_BEG.  In such case reorder the notes.  */
  
    for (insn = last_insn; insn != BB_END (bb); insn = prev)
      {
*************** skip_insns_after_block (basic_block bb)
*** 148,154 ****
        if (NOTE_P (insn))
  	switch (NOTE_LINE_NUMBER (insn))
  	  {
- 	  case NOTE_INSN_LOOP_END:
  	  case NOTE_INSN_BLOCK_END:
  	  case NOTE_INSN_DELETED:
  	  case NOTE_INSN_DELETED_LABEL:
--- 147,152 ----
*************** duplicate_insn_chain (rtx from, rtx to)
*** 986,995 ****
  	         in first BB, we may want to copy the block.  */
  	    case NOTE_INSN_PROLOGUE_END:
  
- 	    case NOTE_INSN_LOOP_BEG:
- 	    case NOTE_INSN_LOOP_END:
- 	      /* Strip down the loop notes - we don't really want to keep
- 	         them consistent in loop copies.  */
  	    case NOTE_INSN_DELETED:
  	    case NOTE_INSN_DELETED_LABEL:
  	      /* No problem to strip these.  */
--- 984,989 ----
Index: sched-deps.c
===================================================================
*** sched-deps.c	(revision 111675)
--- sched-deps.c	(working copy)
*************** static void fixup_sched_groups (rtx);
*** 96,102 ****
  static void flush_pending_lists (struct deps *, rtx, int, int);
  static void sched_analyze_1 (struct deps *, rtx, rtx);
  static void sched_analyze_2 (struct deps *, rtx, rtx);
! static void sched_analyze_insn (struct deps *, rtx, rtx, rtx);
  
  static rtx sched_get_condition (rtx);
  static int conditions_mutex_p (rtx, rtx);
--- 96,102 ----
  static void flush_pending_lists (struct deps *, rtx, int, int);
  static void sched_analyze_1 (struct deps *, rtx, rtx);
  static void sched_analyze_2 (struct deps *, rtx, rtx);
! static void sched_analyze_insn (struct deps *, rtx, rtx);
  
  static rtx sched_get_condition (rtx);
  static int conditions_mutex_p (rtx, rtx);
*************** sched_analyze_2 (struct deps *deps, rtx 
*** 881,887 ****
  /* Analyze an INSN with pattern X to find all dependencies.  */
  
  static void
! sched_analyze_insn (struct deps *deps, rtx x, rtx insn, rtx loop_notes)
  {
    RTX_CODE code = GET_CODE (x);
    rtx link;
--- 881,887 ----
  /* Analyze an INSN with pattern X to find all dependencies.  */
  
  static void
! sched_analyze_insn (struct deps *deps, rtx x, rtx insn)
  {
    RTX_CODE code = GET_CODE (x);
    rtx link;
*************** sched_analyze_insn (struct deps *deps, r
*** 1002,1029 ****
  	}
      }
  
-   /* If there is a {LOOP,EHREGION}_{BEG,END} note in the middle of a basic
-      block, then we must be sure that no instructions are scheduled across it.
-      Otherwise, the reg_n_refs info (which depends on loop_depth) would
-      become incorrect.  */
-   if (loop_notes)
-     {
-       rtx link;
- 
-       /* Update loop_notes with any notes from this insn.  */
-       link = loop_notes;
-       while (XEXP (link, 1))
- 	{
- 	  gcc_assert (INTVAL (XEXP (link, 0)) == NOTE_INSN_LOOP_BEG
- 		      || INTVAL (XEXP (link, 0)) == NOTE_INSN_LOOP_END);
- 
- 	  reg_pending_barrier = MOVE_BARRIER;
- 	  link = XEXP (link, 1);
- 	}
-       XEXP (link, 1) = REG_NOTES (insn);
-       REG_NOTES (insn) = loop_notes;
-     }
- 
    /* If this instruction can throw an exception, then moving it changes
       where block boundaries fall.  This is mighty confusing elsewhere.
       Therefore, prevent such an instruction from being moved.  */
--- 1002,1007 ----
*************** void
*** 1245,1251 ****
  sched_analyze (struct deps *deps, rtx head, rtx tail)
  {
    rtx insn;
-   rtx loop_notes = 0;
  
    if (current_sched_info->use_cselib)
      cselib_init (true);
--- 1223,1228 ----
*************** sched_analyze (struct deps *deps, rtx he
*** 1279,1286 ****
  		deps->last_pending_memory_flush
  		  = alloc_INSN_LIST (insn, deps->last_pending_memory_flush);
  	    }
! 	  sched_analyze_insn (deps, PATTERN (insn), insn, loop_notes);
! 	  loop_notes = 0;
  	}
        else if (CALL_P (insn))
  	{
--- 1256,1262 ----
  		deps->last_pending_memory_flush
  		  = alloc_INSN_LIST (insn, deps->last_pending_memory_flush);
  	    }
! 	  sched_analyze_insn (deps, PATTERN (insn), insn);
  	}
        else if (CALL_P (insn))
  	{
*************** sched_analyze (struct deps *deps, rtx he
*** 1334,1341 ****
  	  add_dependence_list_and_free (insn, &deps->sched_before_next_call, 1,
  					REG_DEP_ANTI);
  
! 	  sched_analyze_insn (deps, PATTERN (insn), insn, loop_notes);
! 	  loop_notes = 0;
  
  	  /* In the absence of interprocedural alias analysis, we must flush
  	     all pending reads and writes, and start new dependencies starting
--- 1310,1316 ----
  	  add_dependence_list_and_free (insn, &deps->sched_before_next_call, 1,
  					REG_DEP_ANTI);
  
! 	  sched_analyze_insn (deps, PATTERN (insn), insn);
  
  	  /* In the absence of interprocedural alias analysis, we must flush
  	     all pending reads and writes, and start new dependencies starting
*************** sched_analyze (struct deps *deps, rtx he
*** 1358,1376 ****
        if (NOTE_P (insn))
  	gcc_assert (NOTE_LINE_NUMBER (insn) != NOTE_INSN_EH_REGION_BEG
  		    && NOTE_LINE_NUMBER (insn) != NOTE_INSN_EH_REGION_END);
- 
-       /* See comments on reemit_notes as to why we do this.
- 	 ??? Actually, the reemit_notes just say what is done, not why.  */
- 
-       if (NOTE_P (insn)
- 	  && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
- 	      || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END))
- 	{
- 	  loop_notes = alloc_EXPR_LIST (REG_SAVE_NOTE,
- 					GEN_INT (NOTE_LINE_NUMBER (insn)),
- 					loop_notes);
- 	  CONST_OR_PURE_CALL_P (loop_notes) = CONST_OR_PURE_CALL_P (insn);
- 	}
  
        if (current_sched_info->use_cselib)
  	cselib_process_insn (insn);
--- 1333,1338 ----
Index: cfgloop.c
===================================================================
*** cfgloop.c	(revision 111675)
--- cfgloop.c	(working copy)
*************** flow_loop_dump (const struct loop *loop,
*** 127,134 ****
    if (! loop || ! loop->header)
      return;
  
!   fprintf (file, ";;\n;; Loop %d:%s\n", loop->num,
! 	     loop->invalid ? " invalid" : "");
  
    fprintf (file, ";;  header %d, latch %d\n",
  	   loop->header->index, loop->latch->index);
--- 127,133 ----
    if (! loop || ! loop->header)
      return;
  
!   fprintf (file, ";;\n;; Loop %d\n", loop->num);
  
    fprintf (file, ";;  header %d, latch %d\n",
  	   loop->header->index, loop->latch->index);
Index: cfgloop.h
===================================================================
*** cfgloop.h	(revision 111675)
--- cfgloop.h	(working copy)
*************** struct loop
*** 78,91 ****
    /* Average number of executed insns per iteration.  */
    unsigned av_ninsns;
  
-   /* The first block in the loop.  This is not necessarily the same as
-      the loop header.  */
-   basic_block first;
- 
-   /* The last block in the loop.  This is not necessarily the same as
-      the loop latch.  */
-   basic_block last;
- 
    /* Number of blocks contained within the loop.  */
    unsigned num_nodes;
  
--- 78,83 ----
*************** struct loop
*** 111,156 ****
    /* Loop that is copy of this loop.  */
    struct loop *copy;
  
-   /* Nonzero if the loop is invalid (e.g., contains setjmp.).  */
-   int invalid;
- 
    /* Auxiliary info specific to a pass.  */
    void *aux;
  
-   /* The following are currently used by loop.c but they are likely to
-      disappear when loop.c is replaced and removed.  */
- 
-   /* The NOTE_INSN_LOOP_BEG.  */
-   rtx start;
- 
-   /* The NOTE_INSN_LOOP_END.  */
-   rtx end;
- 
-   /* For a rotated loop that is entered near the bottom,
-      this is the label at the top.  Otherwise it is zero.  */
-   rtx top;
- 
-   /* Place in the loop where control enters.  */
-   rtx scan_start;
- 
-   /* The position where to sink insns out of the loop.  */
-   rtx sink;
- 
-   /* List of all LABEL_REFs which refer to code labels outside the
-      loop.  Used by routines that need to know all loop exits, such as
-      final_biv_value and final_giv_value.
- 
-      This does not include loop exits due to return instructions.
-      This is because all bivs and givs are pseudos, and hence must be
-      dead after a return, so the presence of a return does not affect
-      any of the optimizations that use this info.  It is simpler to
-      just not include return instructions on this list.  */
-   rtx exit_labels;
- 
-   /* The number of LABEL_REFs on exit_labels for this loop and all
-      loops nested inside it.  */
-   int exit_count;
- 
    /* The probable number of times the loop is executed at runtime.
       This is an INTEGER_CST or an expression containing symbolic
       names.  Don't access this field directly:
--- 103,111 ----
*************** int flow_loop_nodes_find (basic_block, s
*** 243,249 ****
  void fix_loop_structure (struct loops *, bitmap changed_bbs);
  void mark_irreducible_loops (struct loops *);
  void mark_single_exit_loops (struct loops *);
- extern void create_loop_notes (void);
  
  /* Loop data structure manipulation/querying.  */
  extern void flow_loop_tree_node_add (struct loop *, struct loop *);
--- 198,203 ----
Index: config/sh/sh.c
===================================================================
*** config/sh/sh.c	(revision 111675)
--- config/sh/sh.c	(working copy)
*************** static bool unspec_caller_rtx_p (rtx);
*** 241,249 ****
  static bool sh_cannot_copy_insn_p (rtx);
  static bool sh_rtx_costs (rtx, int, int, int *);
  static int sh_address_cost (rtx);
- #ifdef TARGET_ADJUST_UNROLL_MAX
- static int sh_adjust_unroll_max (struct loop *, int, int, int, int);
- #endif
  static int sh_pr_n_sets (void);
  static rtx sh_allocate_initial_value (rtx);
  static int shmedia_target_regs_stack_space (HARD_REG_SET *);
--- 241,246 ----
*************** static int hard_regs_intersect_p (HARD_R
*** 468,478 ****
  
  #endif /* SYMBIAN */
  
- #ifdef TARGET_ADJUST_UNROLL_MAX
- #undef TARGET_ADJUST_UNROLL_MAX
- #define TARGET_ADJUST_UNROLL_MAX sh_adjust_unroll_max
- #endif
- 
  #undef TARGET_SECONDARY_RELOAD
  #define TARGET_SECONDARY_RELOAD sh_secondary_reload
  
--- 465,470 ----
*************** static bool
*** 8906,8912 ****
  sh_optimize_target_register_callee_saved (bool after_prologue_epilogue_gen)
  {
    HARD_REG_SET dummy;
-   rtx insn;
  
    if (! shmedia_space_reserved_for_target_registers)
      return 0;
--- 8898,8903 ----
*************** sh_optimize_target_register_callee_saved
*** 8914,8941 ****
      return 0;
    if (calc_live_regs (&dummy) >= 6 * 8)
      return 1;
-   /* This is a borderline case.  See if we got a nested loop, or a loop
-      with a call, or with more than 4 labels inside.  */
-   for (insn = get_insns(); insn; insn = NEXT_INSN (insn))
-     {
-       if (GET_CODE (insn) == NOTE
- 	  && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
- 	{
- 	  int labels = 0;
- 
- 	  do
- 	    {
- 	      insn = NEXT_INSN (insn);
- 	      if ((GET_CODE (insn) == NOTE
- 		   && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
- 		  || GET_CODE (insn) == CALL_INSN
- 		  || (GET_CODE (insn) == CODE_LABEL && ++labels > 4))
- 		return 1;
- 	    }
- 	  while (GET_CODE (insn) != NOTE
- 		 || NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_END);
- 	}
-     }
    return 0;
  }
  
--- 8905,8910 ----
*************** hard_regs_intersect_p (HARD_REG_SET *a, 
*** 10173,10447 ****
  lose:
    return 0;
  }
- 
- #ifdef TARGET_ADJUST_UNROLL_MAX
- static int
- sh_adjust_unroll_max (struct loop * loop, int insn_count,
- 		      int max_unrolled_insns, int strength_reduce_p,
- 		      int unroll_type)
- {
- /* This doesn't work in 4.0 because the old unroller & loop.h  is gone.  */
-   if (TARGET_ADJUST_UNROLL && TARGET_SHMEDIA)
-     {
-       /* Throttle back loop unrolling so that the costs of using more
- 	 targets than the eight target register we have don't outweigh
- 	 the benefits of unrolling.  */
-       rtx insn;
-       int n_labels = 0, n_calls = 0, n_exit_dest = 0, n_inner_loops = -1;
-       int n_barriers = 0;
-       rtx dest;
-       int i;
-       rtx exit_dest[8];
-       int threshold;
-       int unroll_benefit = 0, mem_latency = 0;
-       int base_cost, best_cost, cost;
-       int factor, best_factor;
-       int n_dest;
-       unsigned max_iterations = 32767;
-       int n_iterations;
-       int need_precond = 0, precond = 0;
-       basic_block * bbs = get_loop_body (loop);
-       struct niter_desc *desc;
- 
-       /* Assume that all labels inside the loop are used from inside the
- 	 loop.  If the loop has multiple entry points, it is unlikely to
- 	 be unrolled anyways.
- 	 Also assume that all calls are to different functions.  That is
- 	 somewhat pessimistic, but if you have lots of calls, unrolling the
- 	 loop is not likely to gain you much in the first place.  */
-       i = loop->num_nodes - 1;
-       for (insn = BB_HEAD (bbs[i]); ; )
- 	{
- 	  if (GET_CODE (insn) == CODE_LABEL)
- 	    n_labels++;
- 	  else if (GET_CODE (insn) == CALL_INSN)
- 	    n_calls++;
- 	  else if (GET_CODE (insn) == NOTE
- 		   && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
- 	    n_inner_loops++;
- 	  else if (GET_CODE (insn) == BARRIER)
- 	    n_barriers++;
- 	  if (insn != BB_END (bbs[i]))
- 	    insn = NEXT_INSN (insn);
- 	  else if (--i >= 0)
- 	    insn = BB_HEAD (bbs[i]);
- 	   else
- 	    break;
- 	}
-       free (bbs);
-       /* One label for the loop top is normal, and it won't be duplicated by
- 	 unrolling.  */
-       if (n_labels <= 1)
- 	return max_unrolled_insns;
-       if (n_inner_loops > 0)
- 	return 0;
-       for (dest = loop->exit_labels; dest && n_exit_dest < 8;
- 	   dest = LABEL_NEXTREF (dest))
- 	{
- 	  for (i = n_exit_dest - 1;
- 	       i >= 0 && XEXP (dest, 0) != XEXP (exit_dest[i], 0); i--);
- 	  if (i < 0)
- 	    exit_dest[n_exit_dest++] = dest;
- 	}
-       /* If the loop top and call and exit destinations are enough to fill up
- 	 the target registers, we're unlikely to do any more damage by
- 	 unrolling.  */
-       if (n_calls + n_exit_dest >= 7)
- 	return max_unrolled_insns;
- 
-       /* ??? In the new loop unroller, there is no longer any strength
-          reduction information available.  Thus, when it comes to unrolling,
-          we know the cost of everything, but we know the value of nothing.  */
- #if 0
-       if (strength_reduce_p
- 	  && (unroll_type == LPT_UNROLL_RUNTIME
- 	      || unroll_type == LPT_UNROLL_CONSTANT
- 	      || unroll_type == LPT_PEEL_COMPLETELY))
- 	{
- 	  struct loop_ivs *ivs = LOOP_IVS (loop);
- 	  struct iv_class *bl;
- 
- 	  /* We'll save one compare-and-branch in each loop body copy
- 	     but the last one.  */
- 	  unroll_benefit = 1;
- 	  /* Assess the benefit of removing biv & giv updates.  */
- 	  for (bl = ivs->list; bl; bl = bl->next)
- 	    {
- 	      rtx increment = biv_total_increment (bl);
- 	      struct induction *v;
- 
- 	      if (increment && GET_CODE (increment) == CONST_INT)
- 		{
- 		  unroll_benefit++;
- 		  for (v = bl->giv; v; v = v->next_iv)
- 		    {
- 		      if (! v->ignore && v->same == 0
- 			  && GET_CODE (v->mult_val) == CONST_INT)
- 			unroll_benefit++;
- 		      /* If this giv uses an array, try to determine
- 			 a maximum iteration count from the size of the
- 			 array.  This need not be correct all the time,
- 			 but should not be too far off the mark too often.  */
- 		      while (v->giv_type == DEST_ADDR)
- 			{
- 			  rtx mem = PATTERN (v->insn);
- 			  tree mem_expr, type, size_tree;
- 
- 			  if (GET_CODE (SET_SRC (mem)) == MEM)
- 			    mem = SET_SRC (mem);
- 			  else if (GET_CODE (SET_DEST (mem)) == MEM)
- 			    mem = SET_DEST (mem);
- 			  else
- 			    break;
- 			  mem_expr = MEM_EXPR (mem);
- 			  if (! mem_expr)
- 			    break;
- 			  type = TREE_TYPE (mem_expr);
- 			  if (TREE_CODE (type) != ARRAY_TYPE
- 			      || ! TYPE_SIZE (type) || ! TYPE_SIZE_UNIT (type))
- 			    break;
- 			  size_tree = fold_build2 (TRUNC_DIV_EXPR,
- 						   bitsizetype,
- 						   TYPE_SIZE (type),
- 						   TYPE_SIZE_UNIT (type));
- 			  if (TREE_CODE (size_tree) == INTEGER_CST
- 			      && ! TREE_INT_CST_HIGH (size_tree)
- 			      && TREE_INT_CST_LOW  (size_tree) < max_iterations)
- 			    max_iterations = TREE_INT_CST_LOW  (size_tree);
- 			  break;
- 			}
- 		    }
- 		}
- 	    }
- 	}
- #else /* 0 */
-       /* Assume there is at least some benefit.  */
-       unroll_benefit = 1;
- #endif /* 0 */
- 
-       desc = get_simple_loop_desc (loop);
-       n_iterations = desc->const_iter ? desc->niter : 0;
-       max_iterations
- 	= max_iterations < desc->niter_max ? max_iterations : desc->niter_max;
- 
-       if (! strength_reduce_p || ! n_iterations)
- 	need_precond = 1;
-       if (! n_iterations)
- 	{
- 	  n_iterations
- 	    = max_iterations < 3 ? max_iterations : max_iterations * 3 / 4;
- 	  if (! n_iterations)
- 	    return 0;
- 	}
- #if 0 /* ??? See above - missing induction variable information.  */
-       while (unroll_benefit > 1) /* no loop */
- 	{
- 	  /* We include the benefit of biv/ giv updates.  Check if some or
- 	     all of these updates are likely to fit into a scheduling
- 	     bubble of a load.
- 	     We check for the following case:
- 	     - All the insns leading to the first JUMP_INSN are in a strict
- 	       dependency chain.
- 	     - there is at least one memory reference in them.
- 
- 	     When we find such a pattern, we assume that we can hide as many
- 	     updates as the total of the load latency is, if we have an
- 	     unroll factor of at least two.  We might or might not also do
- 	     this without unrolling, so rather than considering this as an
- 	     extra unroll benefit, discount it in the unroll benefits of unroll
- 	     factors higher than two.  */
- 		
- 	  rtx set, last_set;
- 
- 	  insn = next_active_insn (loop->start);
- 	  last_set = single_set (insn);
- 	  if (! last_set)
- 	    break;
- 	  if (GET_CODE (SET_SRC (last_set)) == MEM)
- 	    mem_latency += 2;
- 	  for (insn = NEXT_INSN (insn); insn != end; insn = NEXT_INSN (insn))
- 	    {
- 	      if (! INSN_P (insn))
- 		continue;
- 	      if (GET_CODE (insn) == JUMP_INSN)
- 		break;
- 	      if (! reg_referenced_p (SET_DEST (last_set), PATTERN (insn)))
- 		{
- 		  /* Check if this is a to-be-reduced giv insn.  */
- 		  struct loop_ivs *ivs = LOOP_IVS (loop);
- 		  struct iv_class *bl;
- 		  struct induction *v;
- 		  for (bl = ivs->list; bl; bl = bl->next)
- 		    {
- 		      if (bl->biv->insn == insn)
- 			goto is_biv;
- 		      for (v = bl->giv; v; v = v->next_iv)
- 			if (v->insn == insn)
- 			  goto is_giv;
- 		    }
- 		  mem_latency--;
- 		is_biv:
- 		is_giv:
- 		  continue;
- 		}
- 	      set = single_set (insn);
- 	      if (! set)
- 		continue;
- 	      if (GET_CODE (SET_SRC (set)) == MEM)
- 		mem_latency += 2;
- 	      last_set = set;
- 	    }
- 	  if (mem_latency < 0)
- 	    mem_latency = 0;
- 	  else if (mem_latency > unroll_benefit - 1)
- 	    mem_latency = unroll_benefit - 1;
- 	  break;
- 	}
- #endif /* 0 */
-       if (n_labels + (unroll_benefit + n_labels * 8) / n_iterations
- 	  <= unroll_benefit)
- 	return max_unrolled_insns;
- 
-       n_dest = n_labels + n_calls + n_exit_dest;
-       base_cost = n_dest <= 8 ? 0 : n_dest - 7;
-       best_cost = 0;
-       best_factor = 1;
-       if (n_barriers * 2 > n_labels - 1)
- 	n_barriers = (n_labels - 1) / 2;
-       for (factor = 2; factor <= 8; factor++)
- 	{
- 	  /* Bump up preconditioning cost for each power of two.  */
- 	  if (! (factor & (factor-1)))
- 	    precond += 4;
- 	  /* When preconditioning, only powers of two will be considered.  */
- 	  else if (need_precond)
- 	    continue;
- 	  n_dest = ((unroll_type != LPT_PEEL_COMPLETELY)
- 		    + (n_labels - 1) * factor + n_calls + n_exit_dest
- 		    - (n_barriers * factor >> 1)
- 		    + need_precond);
- 	  cost
- 	    = ((n_dest <= 8 ? 0 : n_dest - 7)
- 	       - base_cost * factor
- 	       - ((factor > 2 ? unroll_benefit - mem_latency : unroll_benefit)
- 		  * (factor - (unroll_type != LPT_PEEL_COMPLETELY)))
- 	       + ((unroll_benefit + 1 + (n_labels - 1) * factor)
- 		  / n_iterations));
- 	  if (need_precond)
- 	    cost += (precond + unroll_benefit * factor / 2) / n_iterations;
- 	  if (cost < best_cost)
- 	    {
- 	      best_cost = cost;
- 	      best_factor = factor;
- 	    }
- 	}
-       threshold = best_factor * insn_count;
-       if (max_unrolled_insns > threshold)
- 	max_unrolled_insns = threshold;
-     }
-   return max_unrolled_insns;
- }
- #endif /* TARGET_ADJUST_UNROLL_MAX */
  
  /* Replace any occurrence of FROM(n) in X with TO(n).  The function does
     not enter into CONST_DOUBLE for the replace.
--- 10142,10147 ----
Index: cfgrtl.c
===================================================================
*** cfgrtl.c	(revision 111675)
--- cfgrtl.c	(working copy)
*************** Software Foundation, 51 Franklin Street,
*** 64,71 ****
  static int can_delete_note_p (rtx);
  static int can_delete_label_p (rtx);
  static void commit_one_edge_insertion (edge, int);
- static rtx last_loop_beg_note (rtx);
- static bool back_edge_of_syntactic_loop_p (basic_block, basic_block);
  static basic_block rtl_split_edge (edge);
  static bool rtl_move_block_after (basic_block, basic_block);
  static int rtl_verify_flow_info (void);
--- 64,69 ----
*************** try_redirect_by_replacing_jump (edge e, 
*** 861,888 ****
    return e;
  }
  
- /* Return last loop_beg note appearing after INSN, before start of next
-    basic block.  Return INSN if there are no such notes.
- 
-    When emitting jump to redirect a fallthru edge, it should always appear
-    after the LOOP_BEG notes, as loop optimizer expect loop to either start by
-    fallthru edge or jump following the LOOP_BEG note jumping to the loop exit
-    test.  */
- 
- static rtx
- last_loop_beg_note (rtx insn)
- {
-   rtx last = insn;
- 
-   for (insn = NEXT_INSN (insn); insn && NOTE_P (insn)
-        && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK;
-        insn = NEXT_INSN (insn))
-     if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
-       last = insn;
- 
-   return last;
- }
- 
  /* Redirect edge representing branch of (un)conditional jump or tablejump,
     NULL on failure  */
  static edge
--- 859,864 ----
*************** force_nonfallthru_and_redirect (edge e, 
*** 1100,1108 ****
  	 forward from the last instruction of the old block.  */
        if (!tablejump_p (BB_END (e->src), NULL, &note))
  	note = BB_END (e->src);
- 
-       /* Position the new block correctly relative to loop notes.  */
-       note = last_loop_beg_note (note);
        note = NEXT_INSN (note);
  
        jump_block = create_basic_block (note, NULL, e->src);
--- 1076,1081 ----
*************** rtl_tidy_fallthru_edge (edge e)
*** 1254,1293 ****
    e->flags |= EDGE_FALLTHRU;
  }
  
- /* Helper function for split_edge.  Return true in case edge BB2 to BB1
-    is back edge of syntactic loop.  */
- 
- static bool
- back_edge_of_syntactic_loop_p (basic_block bb1, basic_block bb2)
- {
-   rtx insn;
-   int count = 0;
-   basic_block bb;
- 
-   if (bb1 == bb2)
-     return true;
- 
-   /* ??? Could we guarantee that bb indices are monotone, so that we could
-      just compare them?  */
-   for (bb = bb1; bb && bb != bb2; bb = bb->next_bb)
-     continue;
- 
-   if (!bb)
-     return false;
- 
-   for (insn = BB_END (bb1); insn != BB_HEAD (bb2) && count >= 0;
-        insn = NEXT_INSN (insn))
-     if (NOTE_P (insn))
-       {
- 	if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
- 	  count++;
- 	else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
- 	  count--;
-       }
- 
-   return count >= 0;
- }
- 
  /* Should move basic block BB after basic block AFTER.  NIY.  */
  
  static bool
--- 1227,1232 ----
*************** rtl_split_edge (edge edge_in)
*** 1328,1359 ****
  	force_nonfallthru (e);
      }
  
!   /* Create the basic block note.
! 
!      Where we place the note can have a noticeable impact on the generated
!      code.  Consider this cfg:
! 
! 		        E
! 			|
! 			0
! 		       / \
! 		   +->1-->2--->E
!                    |  |
! 		   +--+
! 
!       If we need to insert an insn on the edge from block 0 to block 1,
!       we want to ensure the instructions we insert are outside of any
!       loop notes that physically sit between block 0 and block 1.  Otherwise
!       we confuse the loop optimizer into thinking the loop is a phony.  */
! 
!   if (edge_in->dest != EXIT_BLOCK_PTR
!       && PREV_INSN (BB_HEAD (edge_in->dest))
!       && NOTE_P (PREV_INSN (BB_HEAD (edge_in->dest)))
!       && (NOTE_LINE_NUMBER (PREV_INSN (BB_HEAD (edge_in->dest)))
! 	  == NOTE_INSN_LOOP_BEG)
!       && !back_edge_of_syntactic_loop_p (edge_in->dest, edge_in->src))
!     before = PREV_INSN (BB_HEAD (edge_in->dest));
!   else if (edge_in->dest != EXIT_BLOCK_PTR)
      before = BB_HEAD (edge_in->dest);
    else
      before = NULL_RTX;
--- 1267,1274 ----
  	force_nonfallthru (e);
      }
  
!   /* Create the basic block note.  */
!   if (edge_in->dest != EXIT_BLOCK_PTR)
      before = BB_HEAD (edge_in->dest);
    else
      before = NULL_RTX;
*************** rtl_split_edge (edge edge_in)
*** 1363,1372 ****
    if (edge_in->flags & EDGE_FALLTHRU && edge_in->dest == EXIT_BLOCK_PTR)
      {
        before = NEXT_INSN (BB_END (edge_in->src));
-       if (before
- 	  && NOTE_P (before)
- 	  && NOTE_LINE_NUMBER (before) == NOTE_INSN_LOOP_END)
- 	before = NEXT_INSN (before);
        bb = create_basic_block (before, NULL, edge_in->src);
        BB_COPY_PARTITION (bb, edge_in->src);
      }
--- 1278,1283 ----
*************** commit_one_edge_insertion (edge e, int w
*** 1596,1606 ****
  	     We know this block has a single successor, so we can just emit
  	     the queued insns before the jump.  */
  	  if (JUMP_P (BB_END (bb)))
! 	    for (before = BB_END (bb);
! 		 NOTE_P (PREV_INSN (before))
! 		 && NOTE_LINE_NUMBER (PREV_INSN (before)) ==
! 		 NOTE_INSN_LOOP_BEG; before = PREV_INSN (before))
! 	      ;
  	  else
  	    {
  	      /* We'd better be fallthru, or we've lost track of
--- 1507,1513 ----
  	     We know this block has a single successor, so we can just emit
  	     the queued insns before the jump.  */
  	  if (JUMP_P (BB_END (bb)))
! 	    before = BB_END (bb);
  	  else
  	    {
  	      /* We'd better be fallthru, or we've lost track of


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]