unroll.c (simplify_cmp_and_jump_insns): New.
authorRichard Henderson <rth@redhat.com>
Fri, 27 Sep 2002 22:41:07 +0000 (15:41 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Fri, 27 Sep 2002 22:41:07 +0000 (15:41 -0700)
* unroll.c (simplify_cmp_and_jump_insns): New.
(unroll_loop): Use it.  Use simplify_gen_foo+force_operand
instead of expand_simple_foo.

From-SVN: r57596

gcc/ChangeLog
gcc/unroll.c

index ebf0d324635afa8d60ed18b01782cb09ac62b091..c354cf995f4ef9172258ab83646067d66dd7c92e 100644 (file)
@@ -1,3 +1,9 @@
+2002-09-27  Richard Henderson  <rth@redhat.com>
+
+       * unroll.c (simplify_cmp_and_jump_insns): New.
+       (unroll_loop): Use it.  Use simplify_gen_foo+force_operand
+       instead of expand_simple_foo.
+
 2002-09-27  Richard Henderson  <rth@redhat.com>
 
        PR optimization/7520
index c1c0059e573fc85c3a0d7edd66c639748a1da0c9..126b586808d2ca8ab0dacfa9aca628e348bf64c4 100644 (file)
@@ -193,6 +193,9 @@ static int *splittable_regs_updates;
 
 /* Forward declarations.  */
 
+static rtx simplify_cmp_and_jump_insns PARAMS ((enum rtx_code,
+                                               enum machine_mode,
+                                               rtx, rtx, rtx));
 static void init_reg_map PARAMS ((struct inline_remap *, int));
 static rtx calculate_giv_inc PARAMS ((rtx, rtx, unsigned int));
 static rtx initial_reg_note_copy PARAMS ((rtx, struct inline_remap *));
@@ -843,7 +846,7 @@ unroll_loop (loop, insn_count, strength_reduce_p)
                               &initial_value, &final_value, &increment,
                               &mode))
        {
-         rtx diff;
+         rtx diff, insn;
          rtx *labels;
          int abs_inc, neg_inc;
          enum rtx_code cc = loop_info->comparison_code;
@@ -875,26 +878,20 @@ unroll_loop (loop, insn_count, strength_reduce_p)
 
          start_sequence ();
 
+         /* We must copy the final and initial values here to avoid
+            improperly shared rtl.  */
+         final_value = copy_rtx (final_value);
+         initial_value = copy_rtx (initial_value);
+
          /* Final value may have form of (PLUS val1 const1_rtx).  We need
             to convert it into general operand, so compute the real value.  */
 
-         if (GET_CODE (final_value) == PLUS)
-           {
-             final_value = expand_simple_binop (mode, PLUS,
-                                                copy_rtx (XEXP (final_value, 0)),
-                                                copy_rtx (XEXP (final_value, 1)),
-                                                NULL_RTX, 0, OPTAB_LIB_WIDEN);
-           }
+         final_value = force_operand (final_value, NULL_RTX);
          if (!nonmemory_operand (final_value, VOIDmode))
-           final_value = force_reg (mode, copy_rtx (final_value));
+           final_value = force_reg (mode, final_value);
 
          /* Calculate the difference between the final and initial values.
             Final value may be a (plus (reg x) (const_int 1)) rtx.
-            Let the following cse pass simplify this if initial value is
-            a constant.
-
-            We must copy the final and initial values here to avoid
-            improperly shared rtl.
 
             We have to deal with for (i = 0; --i < 6;) type loops.
             For such loops the real final value is the first time the
@@ -907,18 +904,18 @@ unroll_loop (loop, insn_count, strength_reduce_p)
             so we can pretend that the overflow value is 0/~0.  */
 
          if (cc == NE || less_p != neg_inc)
-           diff = expand_simple_binop (mode, MINUS, final_value,
-                                       copy_rtx (initial_value), NULL_RTX, 0,
-                                       OPTAB_LIB_WIDEN);
+           diff = simplify_gen_binary (MINUS, mode, final_value,
+                                       initial_value);
          else
-           diff = expand_simple_unop (mode, neg_inc ? NOT : NEG,
-                                      copy_rtx (initial_value), NULL_RTX, 0);
+           diff = simplify_gen_unary (neg_inc ? NOT : NEG, mode,
+                                      initial_value, mode);
+         diff = force_operand (diff, NULL_RTX);
 
          /* Now calculate (diff % (unroll * abs (increment))) by using an
             and instruction.  */
-         diff = expand_simple_binop (GET_MODE (diff), AND, diff,
-                                     GEN_INT (unroll_number * abs_inc - 1),
-                                     NULL_RTX, 0, OPTAB_LIB_WIDEN);
+         diff = simplify_gen_binary (AND, mode, diff,
+                                     GEN_INT (unroll_number*abs_inc - 1));
+         diff = force_operand (diff, NULL_RTX);
 
          /* Now emit a sequence of branches to jump to the proper precond
             loop entry point.  */
@@ -936,18 +933,22 @@ unroll_loop (loop, insn_count, strength_reduce_p)
          if (cc != NE)
            {
              rtx incremented_initval;
-             incremented_initval = expand_simple_binop (mode, PLUS,
-                                                        initial_value,
-                                                        increment,
-                                                        NULL_RTX, 0,
-                                                        OPTAB_LIB_WIDEN);
-             emit_cmp_and_jump_insns (incremented_initval, final_value,
-                                      less_p ? GE : LE, NULL_RTX,
-                                      mode, unsigned_p, labels[1]);
-             predict_insn_def (get_last_insn (), PRED_LOOP_CONDITION,
-                               TAKEN);
-             JUMP_LABEL (get_last_insn ()) = labels[1];
-             LABEL_NUSES (labels[1])++;
+             enum rtx_code cmp_code;
+
+             incremented_initval
+               = simplify_gen_binary (PLUS, mode, initial_value, increment);
+             incremented_initval
+               = force_operand (incremented_initval, NULL_RTX);
+
+             cmp_code = (less_p
+                         ? (unsigned_p ? GEU : GE)
+                         : (unsigned_p ? LEU : LE));
+
+             insn = simplify_cmp_and_jump_insns (cmp_code, mode,
+                                                 incremented_initval,
+                                                 final_value, labels[1]);
+             if (insn)
+               predict_insn_def (insn, PRED_LOOP_CONDITION, TAKEN);
            }
 
          /* Assuming the unroll_number is 4, and the increment is 2, then
@@ -986,12 +987,12 @@ unroll_loop (loop, insn_count, strength_reduce_p)
                  cmp_code = LE;
                }
 
-             emit_cmp_and_jump_insns (diff, GEN_INT (abs_inc * cmp_const),
-                                      cmp_code, NULL_RTX, mode, 0, labels[i]);
-             JUMP_LABEL (get_last_insn ()) = labels[i];
-             LABEL_NUSES (labels[i])++;
-             predict_insn (get_last_insn (), PRED_LOOP_PRECONDITIONING,
-                           REG_BR_PROB_BASE / (unroll_number - i));
+             insn = simplify_cmp_and_jump_insns (cmp_code, mode, diff,
+                                                 GEN_INT (abs_inc*cmp_const),
+                                                 labels[i]);
+             if (insn)
+               predict_insn (insn, PRED_LOOP_PRECONDITIONING,
+                             REG_BR_PROB_BASE / (unroll_number - i));
            }
 
          /* If the increment is greater than one, then we need another branch,
@@ -1019,10 +1020,8 @@ unroll_loop (loop, insn_count, strength_reduce_p)
                  cmp_code = GE;
                }
 
-             emit_cmp_and_jump_insns (diff, GEN_INT (cmp_const), cmp_code,
-                                      NULL_RTX, mode, 0, labels[0]);
-             JUMP_LABEL (get_last_insn ()) = labels[0];
-             LABEL_NUSES (labels[0])++;
+             simplify_cmp_and_jump_insns (cmp_code, mode, diff,
+                                          GEN_INT (cmp_const), labels[0]);
            }
 
          sequence = get_insns ();
@@ -1324,6 +1323,43 @@ unroll_loop (loop, insn_count, strength_reduce_p)
     free (map->reg_map);
   free (map);
 }
+
+/* A helper function for unroll_loop.  Emit a compare and branch to 
+   satisfy (CMP OP1 OP2), but pass this through the simplifier first.
+   If the branch turned out to be conditional, return it, otherwise
+   return NULL.  */
+
+static rtx
+simplify_cmp_and_jump_insns (code, mode, op0, op1, label)
+     enum rtx_code code;
+     enum machine_mode mode;
+     rtx op0, op1, label;
+{
+  rtx t, insn;
+
+  t = simplify_relational_operation (code, mode, op0, op1);
+  if (!t)
+    {
+      enum rtx_code scode = signed_condition (code);
+      emit_cmp_and_jump_insns (op0, op1, scode, NULL_RTX, mode,
+                              code != scode, label);
+      insn = get_last_insn ();
+
+      JUMP_LABEL (insn) = label;
+      LABEL_NUSES (label) += 1;
+
+      return insn;
+    }
+  else if (t == const_true_rtx)
+    {
+      insn = emit_jump_insn (gen_jump (label));
+      emit_barrier ();
+      JUMP_LABEL (insn) = label;
+      LABEL_NUSES (label) += 1;
+    }
+
+  return NULL_RTX;
+}
 \f
 /* Return true if the loop can be safely, and profitably, preconditioned
    so that the unrolled copies of the loop body don't need exit tests.