OSDN Git Service

* unroll.c (copy_loop_body): Always ensure at least two insns
[pf3gnuchains/gcc-fork.git] / gcc / unroll.c
index 28c3e7b..9c0109d 100644 (file)
@@ -1671,6 +1671,12 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
 
   start_sequence ();
 
+  /* Emit a NOTE_INSN_DELETED to force at least two insns onto the sequence.
+     Else gen_sequence could return a raw pattern for a jump which we pass
+     off to emit_insn_before (instead of emit_jump_insn_before) which causes
+     a variety of losing behaviors later.  */
+  emit_note (0, NOTE_INSN_DELETED);
+
   insn = copy_start;
   do
     {
@@ -2127,15 +2133,16 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
          break;
 
        case NOTE:
-         /* VTOP notes are valid only before the loop exit test.  If placed
-            anywhere else, loop may generate bad code.  */
+         /* VTOP and CONT notes are valid only before the loop exit test.
+            If placed anywhere else, loop may generate bad code.  */
          /* BASIC_BLOCK notes exist to stabilize basic block structures with
             the associated rtl.  We do not want to share the structure in 
             this new block.  */
 
          if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED
              && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK
-             && (NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_VTOP
+             && ((NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_VTOP
+                  && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_CONT)
                  || (last_iteration && unroll_type != UNROLL_COMPLETELY)))
            copy = emit_note (NOTE_SOURCE_FILE (insn),
                              NOTE_LINE_NUMBER (insn));
@@ -3819,6 +3826,12 @@ loop_iterations (loop_start, loop_end, loop_info)
   loop_info->initial_equiv_value = initial_value;
   loop_info->final_equiv_value = final_value;
 
+  /* For EQ comparison loops, we don't have a valid final value.
+     Check this now so that we won't leave an invalid value if we
+     return early for any other reason.  */
+  if (comparison_code == EQ)
+      loop_info->final_equiv_value = loop_info->final_value = 0;
+
   if (increment == 0)
     {
       if (loop_dump_stream)
@@ -3829,7 +3842,11 @@ loop_iterations (loop_start, loop_end, loop_info)
 
   if (GET_CODE (increment) != CONST_INT)
     {
-      increment = loop_find_equiv_value (loop_start, increment);
+      /* If we have a REG, check to see if REG holds a constant value.  */
+      /* ??? Other RTL, such as (neg (reg)) is possible here, but it isn't
+        clear if it is worthwhile to try to handle such RTL.  */
+      if (GET_CODE (increment) == REG || GET_CODE (increment) == SUBREG)
+       increment = loop_find_equiv_value (loop_start, increment);
 
       if (GET_CODE (increment) != CONST_INT)
        {