OSDN Git Service

(LINK_COST_ZERO, LINK_COST_FREE): New macros.
[pf3gnuchains/gcc-fork.git] / gcc / unroll.c
index 0502eb8..2bb5900 100644 (file)
@@ -783,15 +783,14 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
             improperly shared rtl.  */
 
          diff = expand_binop (mode, sub_optab, copy_rtx (final_value),
-                              copy_rtx (initial_value), 0, 0,
+                              copy_rtx (initial_value), NULL_RTX, 0,
                               OPTAB_LIB_WIDEN);
 
          /* Now calculate (diff % (unroll * abs (increment))) by using an
             and instruction.  */
          diff = expand_binop (GET_MODE (diff), and_optab, diff,
-                              gen_rtx (CONST_INT, VOIDmode,
-                                       unroll_number * abs_inc - 1),
-                              0, 0, OPTAB_LIB_WIDEN);
+                              GEN_INT (unroll_number * abs_inc - 1),
+                              NULL_RTX, 0, OPTAB_LIB_WIDEN);
 
          /* Now emit a sequence of branches to jump to the proper precond
             loop entry point.  */
@@ -826,9 +825,8 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
              else
                cmp_const = i;
 
-             emit_cmp_insn (diff, gen_rtx (CONST_INT, VOIDmode,
-                                           abs_inc * cmp_const),
-                            EQ, 0, mode, 0, 0);
+             emit_cmp_insn (diff, GEN_INT (abs_inc * cmp_const),
+                            EQ, NULL_RTX, mode, 0, 0);
 
              if (i == 0)
                emit_jump_insn (gen_beq (labels[i]));
@@ -858,8 +856,8 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
              else
                cmp_const = abs_inc * (unroll_number - 1) + 1;
 
-             emit_cmp_insn (diff, gen_rtx (CONST_INT, VOIDmode, cmp_const),
-                            EQ, 0, mode, 0, 0);
+             emit_cmp_insn (diff, GEN_INT (cmp_const), EQ, NULL_RTX,
+                            mode, 0, 0);
 
              if (neg_inc)
                emit_jump_insn (gen_ble (labels[0]));
@@ -1137,19 +1135,6 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
      not taken.  */
   if (exit_label)
     emit_label_after (exit_label, loop_end);
-
-  /* If debugging, we must replicate the tree nodes corresponding to the blocks
-     inside the loop, so that the original one to one mapping will remain.  */
-
-  if (write_symbols != NO_DEBUG)
-    {
-      int copies = unroll_number;
-
-      if (loop_preconditioned)
-       copies += unroll_number - 1;
-
-      unroll_block_trees (uid_loop_num[INSN_UID (loop_start)], copies);
-    }
 }
 \f
 /* Return true if the loop can be safely, and profitably, preconditioned
@@ -1178,7 +1163,7 @@ precondition_loop_p (initial_value, final_value, increment, loop_start,
     {
       *initial_value = const0_rtx;
       *increment = const1_rtx;
-      *final_value = gen_rtx (CONST_INT, VOIDmode, loop_n_iterations);
+      *final_value = GEN_INT (loop_n_iterations);
 
       if (loop_dump_stream)
        fprintf (loop_dump_stream,
@@ -1388,6 +1373,7 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
                copy_notes_from)
      rtx copy_start, copy_end;
      struct inline_remap *map;
+     rtx exit_label;
      int last_iteration;
      enum unroll_types unroll_type;
      rtx start_label, loop_end, insert_before, copy_notes_from;
@@ -1583,8 +1569,7 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
 #endif
                  
                  splittable_regs[regno]
-                   = gen_rtx (CONST_INT, VOIDmode,
-                              INTVAL (giv_inc)
+                   = GEN_INT (INTVAL (giv_inc)
                               + INTVAL (splittable_regs[regno]));
                  giv_inc = splittable_regs[regno];
                  
@@ -1678,23 +1663,18 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
              int fall_through;
 
              /* Never map the label in this case.  */
-             pattern = copy_rtx (PATTERN (insn));
+             rtx tmp_pattern = copy_rtx (PATTERN (insn));
              
-             /* Assume a conditional branch, since the code above
-                does not let unconditional branches be copied.  */
-             if (! condjump_p (insn))
+             /* Set the fall through case to the exit label.  If we 
+                can't do this in place, abort for now.  Maybe
+                we can do something more sophisticated eventually.  */
+
+             if (! invert_exp (tmp_pattern, insn)
+                 || ! redirect_exp (&tmp_pattern, JUMP_LABEL (insn),
+                                    exit_label, insn))
                abort ();
-             fall_through
-               = (XEXP (SET_SRC (PATTERN (insn)), 2) == pc_rtx) + 1;
 
-             /* Set the fall through case to the exit label.  Must
-                create a new label_ref since they can't be shared.  */
-             XEXP (SET_SRC (pattern), fall_through)
-               = gen_rtx (LABEL_REF, VOIDmode, exit_label);
-                     
-             /* Set the original branch case to fall through.  */
-             XEXP (SET_SRC (pattern), 3 - fall_through)
-               = pc_rtx;
+             pattern = tmp_pattern;
            }
          else
            pattern = copy_rtx_and_substitute (PATTERN (insn), map);
@@ -1810,7 +1790,12 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
          break;
          
        case NOTE:
-         if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED)
+         /* VTOP notes are valid only before the loop exit test.  If placed
+            anywhere else, loop may generate bad code.  */
+            
+         if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED
+             && (NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_VTOP
+                 || (last_iteration && unroll_type != UNROLL_COMPLETELY)))
            copy = emit_note (NOTE_SOURCE_FILE (insn),
                              NOTE_LINE_NUMBER (insn));
          else
@@ -2391,7 +2376,7 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment,
               /* Check for the case where the pseudo is set by a shift/add
                  sequence, in which case the first insn setting the pseudo
                  is the first insn of the shift/add sequence.  */
-              && (! (tem = find_reg_note (v->insn, REG_RETVAL, 0))
+              && (! (tem = find_reg_note (v->insn, REG_RETVAL, NULL_RTX))
                   || (regno_first_uid[REGNO (v->dest_reg)]
                       != INSN_UID (XEXP (tem, 0)))))
              /* Line above always fails if INSN was moved by loop opt.  */
@@ -2454,7 +2439,28 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment,
          /* If the giv is an address destination, it could be something other
             than a simple register, these have to be treated differently.  */
          else if (v->giv_type == DEST_REG)
-           splittable_regs[REGNO (v->new_reg)] = value;
+           {
+             /* If value is not a constant, register, or register plus
+                constant, then compute its value into a register before
+                loop start.  This prevents illegal rtx sharing, and should
+                generate better code.  We can use bl->initial_value here
+                instead of splittable_regs[bl->regno] because this code
+                is going before the loop start.  */
+             if (unroll_type == UNROLL_COMPLETELY
+                 && GET_CODE (value) != CONST_INT
+                 && GET_CODE (value) != REG
+                 && (GET_CODE (value) != PLUS
+                     || GET_CODE (XEXP (value, 0)) != REG
+                     || GET_CODE (XEXP (value, 1)) != CONST_INT))
+               {
+                 rtx tem = gen_reg_rtx (v->mode);
+                 emit_iv_add_mult (bl->initial_value, v->mult_val,
+                                   v->add_val, tem, loop_start);
+                 value = tem;
+               }
+               
+             splittable_regs[REGNO (v->new_reg)] = value;
+           }
          else
            {
              /* Splitting address givs is useful since it will often allow us
@@ -2764,8 +2770,7 @@ final_biv_value (bl, loop_start, loop_end)
             case it is needed later.  */
 
          tem = gen_reg_rtx (bl->biv->mode);
-         emit_iv_add_mult (increment,
-                           gen_rtx (CONST_INT, VOIDmode, loop_n_iterations),
+         emit_iv_add_mult (increment, GEN_INT (loop_n_iterations),
                            bl->initial_value, tem, NEXT_INSN (loop_end));
 
          if (loop_dump_stream)
@@ -2856,8 +2861,7 @@ final_giv_value (v, loop_start, loop_end)
 
          /* Put the final biv value in tem.  */
          tem = gen_reg_rtx (bl->biv->mode);
-         emit_iv_add_mult (increment,
-                           gen_rtx (CONST_INT, VOIDmode, loop_n_iterations),
+         emit_iv_add_mult (increment, GEN_INT (loop_n_iterations),
                            bl->initial_value, tem, insert_before);
 
          /* Subtract off extra increments as we find them.  */
@@ -2883,7 +2887,7 @@ final_giv_value (v, loop_start, loop_end)
                  
                  start_sequence ();
                  tem = expand_binop (GET_MODE (tem), sub_optab, tem,
-                                     XEXP (SET_SRC (pattern), 1), 0, 0,
+                                     XEXP (SET_SRC (pattern), 1), NULL_RTX, 0,
                                      OPTAB_LIB_WIDEN);
                  seq = gen_sequence ();
                  end_sequence ();
@@ -2926,14 +2930,15 @@ final_giv_value (v, loop_start, loop_end)
 /* Calculate the number of loop iterations.  Returns the exact number of loop
    iterations if it can be calculated, otherwise returns zero.  */
 
-unsigned long
+unsigned HOST_WIDE_INT
 loop_iterations (loop_start, loop_end)
      rtx loop_start, loop_end;
 {
   rtx comparison, comparison_value;
   rtx iteration_var, initial_value, increment, final_value;
   enum rtx_code comparison_code;
-  int i, increment_dir;
+  HOST_WIDE_INT i;
+  int increment_dir;
   int unsigned_compare, compare_dir, final_larger;
   unsigned long tempu;
   rtx last_loop_insn;
@@ -3023,7 +3028,7 @@ loop_iterations (loop_start, loop_end)
                   && (set = single_set (insn))
                   && (SET_DEST (set) == comparison_value))
            {
-             rtx note = find_reg_note (insn, REG_EQUAL, 0);
+             rtx note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
 
              if (note && GET_CODE (XEXP (note, 0)) != EXPR_LIST)
                comparison_value = XEXP (note, 0);
@@ -3073,11 +3078,13 @@ loop_iterations (loop_start, loop_end)
   /* Final_larger is 1 if final larger, 0 if they are equal, otherwise -1.  */
   if (unsigned_compare)
     final_larger
-      = ((unsigned) INTVAL (final_value) > (unsigned) INTVAL (initial_value)) -
-       ((unsigned) INTVAL (final_value) < (unsigned) INTVAL (initial_value));
+      = ((unsigned HOST_WIDE_INT) INTVAL (final_value)
+        > (unsigned HOST_WIDE_INT) INTVAL (initial_value))
+       - ((unsigned HOST_WIDE_INT) INTVAL (final_value)
+          < (unsigned HOST_WIDE_INT) INTVAL (initial_value));
   else
-    final_larger = (INTVAL (final_value) > INTVAL (initial_value)) -
-      (INTVAL (final_value) < INTVAL (initial_value));
+    final_larger = (INTVAL (final_value) > INTVAL (initial_value))
+      (INTVAL (final_value) < INTVAL (initial_value));
 
   if (INTVAL (increment) > 0)
     increment_dir = 1;