OSDN Git Service

(c_sizeof, build_c_cast): Set TREE_OVERFLOW in addition
[pf3gnuchains/gcc-fork.git] / gcc / unroll.c
index 530babc..fc8a3f6 100644 (file)
@@ -1,5 +1,5 @@
 /* Try to unroll loops, and split induction variables.
-   Copyright (C) 1992 Free Software Foundation, Inc.
+   Copyright (C) 1992, 1993 Free Software Foundation, Inc.
    Contributed by James E. Wilson, Cygnus Support/UC Berkeley.
 
 This file is part of GNU CC.
@@ -1318,7 +1318,10 @@ calculate_giv_inc (pattern, src_insn, regno)
      int regno;
 {
   rtx increment;
+  rtx increment_total = 0;
+  int tries = 0;
 
+ retry:
   /* Verify that we have an increment insn here.  First check for a plus
      as the set source.  */
   if (GET_CODE (SET_SRC (pattern)) != PLUS)
@@ -1341,7 +1344,8 @@ calculate_giv_inc (pattern, src_insn, regno)
     {
       /* SR sometimes puts the constant in a register, especially if it is
         too big to be an add immed operand.  */
-      increment = SET_SRC (PATTERN (PREV_INSN (src_insn)));
+      src_insn = PREV_INSN (src_insn);
+      increment = SET_SRC (PATTERN (src_insn));
 
       /* SR may have used LO_SUM to compute the constant if it is too large
         for a load immed operand.  In this case, the constant is in operand
@@ -1357,14 +1361,81 @@ calculate_giv_inc (pattern, src_insn, regno)
       delete_insn (get_last_insn ());
     }
 
-  /* Check that the source register is the same as the dest register.  */
+  if (increment_total)
+    increment_total = GEN_INT (INTVAL (increment_total) + INTVAL (increment));
+  else
+    increment_total = increment;
+
+  /* Check that the source register is the same as the register we expected
+     to see as the source.  If not, something is seriously wrong.  */
   if (GET_CODE (XEXP (SET_SRC (pattern), 0)) != REG
       || REGNO (XEXP (SET_SRC (pattern), 0)) != regno)
+    {
+      /* Some machines (e.g. the romp), may emit two add instructions for
+        certain constants, so lets try looking for another add immediately
+        before this one if we have only seen one add insn so far.  */
+
+      if (tries == 0)
+       {
+         tries++;
+
+         src_insn = PREV_INSN (src_insn);
+         pattern = PATTERN (src_insn);
+
+         delete_insn (get_last_insn ());
+
+         goto retry;
+       }
+
+      abort ();
+    }
+
+  return increment_total;
+}
+
+/* Copy REG_NOTES, except for insn references, because not all insn_map
+   entries are valid yet.  We do need to copy registers now though, because
+   the reg_map entries can change during copying.  */
+
+static rtx
+initial_reg_note_copy (notes, map)
+     rtx notes;
+     struct inline_remap *map;
+{
+  rtx copy;
+
+  if (notes == 0)
+    return 0;
+
+  copy = rtx_alloc (GET_CODE (notes));
+  PUT_MODE (copy, GET_MODE (notes));
+
+  if (GET_CODE (notes) == EXPR_LIST)
+    XEXP (copy, 0) = copy_rtx_and_substitute (XEXP (notes, 0), map);
+  else if (GET_CODE (notes) == INSN_LIST)
+    /* Don't substitute for these yet.  */
+    XEXP (copy, 0) = XEXP (notes, 0);
+  else
     abort ();
 
-  return increment;
+  XEXP (copy, 1) = initial_reg_note_copy (XEXP (notes, 1), map);
+
+  return copy;
 }
 
+/* Fixup insn references in copied REG_NOTES.  */
+
+static void
+final_reg_note_copy (notes, map)
+     rtx notes;
+     struct inline_remap *map;
+{
+  rtx note;
+
+  for (note = notes; note; note = XEXP (note, 1))
+    if (GET_CODE (note) == INSN_LIST)
+      XEXP (note, 0) = map->insn_map[INSN_UID (XEXP (note, 0))];
+}
 
 /* Copy each instruction in the loop, substituting from map as appropriate.
    This is very similar to a loop in expand_inline_function.  */
@@ -1611,7 +1682,7 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
              pattern = copy_rtx_and_substitute (pattern, map);
              copy = emit_insn (pattern);
            }
-         /* REG_NOTES will be copied later.  */
+         REG_NOTES (copy) = initial_reg_note_copy (REG_NOTES (insn), map);
          
 #ifdef HAVE_cc0
          /* If this insn is setting CC0, it may need to look at
@@ -1655,6 +1726,7 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
        case JUMP_INSN:
          pattern = copy_rtx_and_substitute (PATTERN (insn), map);
          copy = emit_jump_insn (pattern);
+         REG_NOTES (copy) = initial_reg_note_copy (REG_NOTES (insn), map);
 
          if (JUMP_LABEL (insn) == start_label && insn == copy_end
              && ! last_iteration)
@@ -1756,6 +1828,7 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
        case CALL_INSN:
          pattern = copy_rtx_and_substitute (PATTERN (insn), map);
          copy = emit_call_insn (pattern);
+         REG_NOTES (copy) = initial_reg_note_copy (REG_NOTES (insn), map);
 
 #ifdef HAVE_cc0
          if (cc0_insn)
@@ -1806,7 +1879,7 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
     }
   while (insn != copy_end);
   
-  /* Now copy the REG_NOTES.  */
+  /* Now finish coping the REG_NOTES.  */
   insn = copy_start;
   do
     {
@@ -1814,8 +1887,7 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
       if ((GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
           || GET_CODE (insn) == CALL_INSN)
          && map->insn_map[INSN_UID (insn)])
-       REG_NOTES (map->insn_map[INSN_UID (insn)])
-         = copy_rtx_and_substitute (REG_NOTES (insn), map);
+       final_reg_note_copy (REG_NOTES (map->insn_map[INSN_UID (insn)]), map);
     }
   while (insn != copy_end);