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

Reply via email to