OSDN Git Service

Use cbranch patterns when available
authorcrux <crux@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 23 Sep 1999 11:34:49 +0000 (11:34 +0000)
committercrux <crux@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 23 Sep 1999 11:34:49 +0000 (11:34 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@29613 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/expmed.c
gcc/expr.c
gcc/expr.h
gcc/genopinit.c
gcc/optabs.c

index a381ea8..912eee5 100644 (file)
@@ -1,3 +1,27 @@
+Thu Sep 23 11:15:36 1999  Bernd Schmidt  <bernds@cygnus.co.uk>
+
+       * expmed.c (do_cmp_and_jump): Pass ccp_jump to can_compare_p.
+       * expr.c (expand_expr): Likewise.
+       (do_jump): Likewise.
+       (do_store_flag): Pass ccp_store_flag to can_compare_p.
+       * expr.h (enum optab_index): Add cbranch, cmov, cstore optabs and
+       accessor macros.
+       (enum can_compare_purpose): New.
+       (can_compare_p): Adjust prototype.
+       (prepare_cmp_insn, prepare_operand): Declare.
+       * genopinit.c (optabs): Add cbranch_optab, cmov_optab, cstore_optab.
+       * optabs.c (cmp_available_p): Deleted.
+       (expand_abs): Pass ccp_jump to can_compare_p.
+       (can_compare_p): New arg PURPOSE.  Check for combined optabs.
+       (prepare_cmp_insn): No longer static.  Add arg PURPOSE.
+       Call can_compare_p rather than cmp_available_p.
+       (prepare_operand): No longer static.
+       (emit_cmp_and_jump_insn): Check for and use cbranch patterns.
+       (emit_cmp_and_jump_insns): Pass ccp_jump to prepare_cmp_insn.
+       (expand_float): Fix a slightly broken emit_cmp_insn/emit_jump_insn
+       sequence to use emit_cmp_and_jump_insns.
+       (init_optabs): Initialize cbranch_optab, cmov_optab, cstore_optab.
+
 Wed Sep 22 17:58:01 1999  Stan Cox  <scox@cygnus.com>
 
        * mips.h (GO_IF_LEGITIMATE_ADDRESS): Don't accept large
index c0fa722..291d766 100644 (file)
@@ -4548,7 +4548,7 @@ do_cmp_and_jump (arg1, arg2, op, mode, label)
   /* If this mode is an integer too wide to compare properly,
      compare word by word.  Rely on cse to optimize constant cases.  */
 
-  if (GET_MODE_CLASS (mode) == MODE_INT && ! can_compare_p (mode))
+  if (GET_MODE_CLASS (mode) == MODE_INT && ! can_compare_p (mode, ccp_jump))
     {
       rtx label2 = gen_label_rtx ();
 
index fc08068..568460b 100644 (file)
@@ -7388,7 +7388,7 @@ expand_expr (exp, target, tmode, modifier)
 
       /* If this mode is an integer too wide to compare properly,
         compare word by word.  Rely on cse to optimize constant cases.  */
-      if (GET_MODE_CLASS (mode) == MODE_INT && ! can_compare_p (mode))
+      if (GET_MODE_CLASS (mode) == MODE_INT && ! can_compare_p (mode, ccp_jump))
        {
          if (code == MAX_EXPR)
            do_jump_by_parts_greater_rtx (mode, TREE_UNSIGNED (type),
@@ -8938,7 +8938,7 @@ do_jump (exp, if_false_label, if_true_label)
          do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
 
        else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_INT
-                && !can_compare_p (TYPE_MODE (inner_type)))
+                && !can_compare_p (TYPE_MODE (inner_type), ccp_jump))
          do_jump_by_parts_equality (exp, if_false_label, if_true_label);
        else
          do_compare_and_jump (exp, EQ, EQ, if_false_label, if_true_label);
@@ -8978,7 +8978,7 @@ do_jump (exp, if_false_label, if_true_label)
          do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
 
        else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_INT
-                && !can_compare_p (TYPE_MODE (inner_type)))
+                && !can_compare_p (TYPE_MODE (inner_type), ccp_jump))
          do_jump_by_parts_equality (exp, if_true_label, if_false_label);
        else
          do_compare_and_jump (exp, NE, NE, if_false_label, if_true_label);
@@ -8986,36 +8986,36 @@ do_jump (exp, if_false_label, if_true_label)
       }
 
     case LT_EXPR:
-      if ((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
-          == MODE_INT)
-         && !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
+      mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
+      if (GET_MODE_CLASS (mode) == MODE_INT
+         && ! can_compare_p (mode, ccp_jump))
        do_jump_by_parts_greater (exp, 1, if_false_label, if_true_label);
       else
        do_compare_and_jump (exp, LT, LTU, if_false_label, if_true_label);
       break;
 
     case LE_EXPR:
-      if ((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
-          == MODE_INT)
-         && !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
+      mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
+      if (GET_MODE_CLASS (mode) == MODE_INT
+         && ! can_compare_p (mode, ccp_jump))
        do_jump_by_parts_greater (exp, 0, if_true_label, if_false_label);
       else
        do_compare_and_jump (exp, LE, LEU, if_false_label, if_true_label);
       break;
 
     case GT_EXPR:
-      if ((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
-          == MODE_INT)
-         && !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
+      mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
+      if (GET_MODE_CLASS (mode) == MODE_INT
+         && ! can_compare_p (mode, ccp_jump))
        do_jump_by_parts_greater (exp, 0, if_false_label, if_true_label);
       else
        do_compare_and_jump (exp, GT, GTU, if_false_label, if_true_label);
       break;
 
     case GE_EXPR:
-      if ((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
-          == MODE_INT)
-         && !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
+      mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
+      if (GET_MODE_CLASS (mode) == MODE_INT
+         && ! can_compare_p (mode, ccp_jump))
        do_jump_by_parts_greater (exp, 1, if_true_label, if_false_label);
       else
        do_compare_and_jump (exp, GE, GEU, if_false_label, if_true_label);
@@ -9044,7 +9044,7 @@ do_jump (exp, if_false_label, if_true_label)
            emit_jump (target);
        }
       else if (GET_MODE_CLASS (GET_MODE (temp)) == MODE_INT
-              && ! can_compare_p (GET_MODE (temp)))
+              && ! can_compare_p (GET_MODE (temp), ccp_jump))
        /* Note swapping the labels gives us not-equal.  */
        do_jump_by_parts_equality_rtx (temp, if_true_label, if_false_label);
       else if (GET_MODE (temp) != VOIDmode)
@@ -9658,7 +9658,7 @@ do_store_flag (exp, target, mode, only_cheap)
     }
 
   /* Now see if we are likely to be able to do this.  Return if not.  */
-  if (! can_compare_p (operand_mode))
+  if (! can_compare_p (operand_mode, ccp_store_flag))
     return 0;
   icode = setcc_gen_code[(int) code];
   if (icode == CODE_FOR_nothing
index 53cb9a9..52f743b 100644 (file)
@@ -377,6 +377,11 @@ enum optab_index
   /* String length */
   OTI_strlen,
 
+  /* Combined compare & jump/store flags/move operations.  */
+  OTI_cbranch,
+  OTI_cmov,
+  OTI_cstore,
+    
   OTI_MAX
 };
 
@@ -427,6 +432,10 @@ extern optab optab_table[OTI_MAX];
 
 #define strlen_optab (optab_table[OTI_strlen])
 
+#define cbranch_optab (optab_table[OTI_cbranch])
+#define cmov_optab (optab_table[OTI_cmov])
+#define cstore_optab (optab_table[OTI_cstore])
+
 /* Tables of patterns for extending one integer mode to another.  */
 extern enum insn_code extendtab[MAX_MACHINE_MODE][MAX_MACHINE_MODE][2];
 
@@ -778,9 +787,24 @@ extern void emit_cmp_insn PROTO((rtx, rtx, enum rtx_code, rtx,
 extern void emit_cmp_and_jump_insns PROTO((rtx, rtx, enum rtx_code, rtx,
                                           enum machine_mode, int, int, rtx));
 
+/* The various uses that a comparison can have; used by can_compare_p:
+   jumps, conditional moves, store flag operations.  */
+enum can_compare_purpose
+{
+  ccp_jump,
+  ccp_cmov,
+  ccp_store_flag
+};
 /* Nonzero if a compare of mode MODE can be done straightforwardly
    (without splitting it into pieces).  */
-extern int can_compare_p PROTO((enum machine_mode));
+extern int can_compare_p PROTO((enum machine_mode, enum can_compare_purpose));
+
+extern void prepare_cmp_insn PROTO((rtx *, rtx *, enum rtx_code *, rtx,
+                                   enum machine_mode *, int *, int,
+                                   enum can_compare_purpose));
+
+extern rtx prepare_operand PROTO((int, rtx, int, enum machine_mode,
+                                 enum machine_mode, int));
 
 /* Generate code to indirectly jump to a location given in the rtx LOC.  */
 extern void emit_indirect_jump PROTO((rtx));
index 5884691..81366f0 100644 (file)
@@ -113,6 +113,9 @@ const char * const optabs[] =
   "bcc_gen_fctn[(int) %C] = gen_%(b%c%)",
   "setcc_gen_code[(int) %C] = CODE_FOR_%(s%c%)",
   "movcc_gen_code[(int) %A] = CODE_FOR_%(mov%acc%)",
+  "cbranch_optab->handlers[(int) %A].insn_code = CODE_FOR_%(cbranch%a4%)",
+  "cmov_optab->handlers[(int) %A].insn_code = CODE_FOR_%(cmov%a6%)",
+  "cstore_optab->handlers[(int) %A].insn_code = CODE_FOR_%(cstore%a4%)",
   "reload_in_optab[(int) %A] = CODE_FOR_%(reload_in%a%)",
   "reload_out_optab[(int) %A] = CODE_FOR_%(reload_out%a%)",
   "movstr_optab[(int) %A] = CODE_FOR_%(movstr%a%)",
index a683fef..b424f1b 100644 (file)
@@ -105,13 +105,8 @@ static void init_floating_libfuncs PROTO((optab, const char *, int));
 #ifdef HAVE_conditional_trap
 static void init_traps PROTO((void));
 #endif
-static int cmp_available_p PROTO((enum machine_mode, int));
 static void emit_cmp_and_jump_insn_1 PROTO((rtx, rtx, enum machine_mode,
                                            enum rtx_code, int, rtx));
-static void prepare_cmp_insn PROTO((rtx *, rtx *, enum rtx_code *, rtx,
-                                   enum machine_mode *, int *, int));
-static rtx prepare_operand PROTO((int, rtx, int, enum machine_mode,
-                                 enum machine_mode, int));
 static void prepare_float_lib_cmp PROTO((rtx *, rtx *, enum rtx_code *,
                                         enum machine_mode *, int *));
 \f
@@ -2309,7 +2304,7 @@ expand_abs (mode, op0, target, safe)
 
   /* If this mode is an integer too wide to compare properly,
      compare word by word.  Rely on CSE to optimize constant cases.  */
-  if (GET_MODE_CLASS (mode) == MODE_INT && ! can_compare_p (mode))
+  if (GET_MODE_CLASS (mode) == MODE_INT && ! can_compare_p (mode, ccp_jump))
     do_jump_by_parts_greater_rtx (mode, 0, target, const0_rtx, 
                                  NULL_RTX, op1);
   else
@@ -2823,22 +2818,32 @@ emit_0_to_1_insn (x)
   emit_move_insn (x, const1_rtx);
 }
 
-/* Nonzero if we can perform a comparison of mode MODE for a conditional jump
-   straightforwardly.  */
-
-static int
-cmp_available_p (mode, can_use_tst_p)
+/* Nonzero if we can perform a comparison of mode MODE straightforwardly.
+   If FOR_JUMP is nonzero, we will be generating a jump based on this
+   comparison, otherwise a store-flags operation.  */
+  
+int
+can_compare_p (mode, purpose)
      enum machine_mode mode;
-     int can_use_tst_p;
+     enum can_compare_purpose purpose;
 {
   do
     {
-      if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing
-         || (can_use_tst_p
-             && tst_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing))
+      if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
        return 1;
+      if (purpose == ccp_jump
+         && cbranch_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
+       return 1;
+      if (purpose == ccp_cmov
+         && cmov_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
+       return 1;
+      if (purpose == ccp_store_flag
+         && cstore_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
+       return 1;
+
       mode = GET_MODE_WIDER_MODE (mode);
-    } while (mode != VOIDmode);
+    }
+  while (mode != VOIDmode);
 
   return 0;
 }
@@ -2860,14 +2865,16 @@ cmp_available_p (mode, can_use_tst_p)
    The values which are passed in through pointers can be modified; the caller
    should perform the comparison on the modified values.  */
 
-static void
-prepare_cmp_insn (px, py, pcomparison, size, pmode, punsignedp, align)
+void
+prepare_cmp_insn (px, py, pcomparison, size, pmode, punsignedp, align,
+                 purpose)
      rtx *px, *py;
      enum rtx_code *pcomparison;
      rtx size;
      enum machine_mode *pmode;
      int *punsignedp;
      int align;
+     enum can_compare_purpose purpose;
 {
   enum machine_mode mode = *pmode;
   rtx x = *px, y = *py;
@@ -2988,7 +2995,7 @@ prepare_cmp_insn (px, py, pcomparison, size, pmode, punsignedp, align)
 
   *px = x;
   *py = y;
-  if (cmp_available_p (mode, y == CONST0_RTX (mode)))
+  if (can_compare_p (mode, purpose))
     return;
 
   /* Handle a lib call just for the mode we are using.  */
@@ -3032,7 +3039,7 @@ prepare_cmp_insn (px, py, pcomparison, size, pmode, punsignedp, align)
    to be used for operand OPNUM of the insn, is converted from mode MODE to
    WIDER_MODE (UNSIGNEDP determines whether it is a unsigned conversion), and
    that it is accepted by the operand predicate.  Return the new value.  */
-static rtx
+rtx
 prepare_operand (icode, x, opnum, mode, wider_mode, unsignedp)
      int icode;
      rtx x;
@@ -3074,6 +3081,20 @@ emit_cmp_and_jump_insn_1 (x, y, mode, comparison, unsignedp, label)
       enum insn_code icode;
       PUT_MODE (test, wider_mode);
 
+      if (label)
+       {         
+         icode = cbranch_optab->handlers[(int)wider_mode].insn_code;
+         
+         if (icode != CODE_FOR_nothing
+             && (*insn_data[icode].operand[0].predicate) (test, wider_mode))
+           {
+             x = prepare_operand (icode, x, 1, mode, wider_mode, unsignedp);
+             y = prepare_operand (icode, y, 2, mode, wider_mode, unsignedp);
+             emit_jump_insn (GEN_FCN (icode) (test, x, y, label));
+             return;
+           }
+       }
+
       /* Handle some compares against zero.  */
       icode = (int) tst_optab->handlers[(int) wider_mode].insn_code;
       if (y == CONST0_RTX (mode) && icode != CODE_FOR_nothing)
@@ -3164,7 +3185,8 @@ emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, align, label)
   emit_queue ();
   if (unsignedp)
     comparison = unsigned_condition (comparison);
-  prepare_cmp_insn (&op0, &op1, &comparison, size, &mode, &unsignedp, align);
+  prepare_cmp_insn (&op0, &op1, &comparison, size, &mode, &unsignedp, align,
+                   ccp_jump);
   emit_cmp_and_jump_insn_1 (op0, op1, mode, comparison, unsignedp, label);
 }
 
@@ -3180,24 +3202,6 @@ emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
 {
   emit_cmp_and_jump_insns (x, y, comparison, size, mode, unsignedp, align, 0);
 }
-
-
-/* Nonzero if a compare of mode MODE can be done straightforwardly
-   (without splitting it into pieces).  */
-
-int
-can_compare_p (mode)
-     enum machine_mode mode;
-{
-  do
-    {
-      if (cmp_optab->handlers[(int)mode].insn_code != CODE_FOR_nothing)
-       return 1;
-      mode = GET_MODE_WIDER_MODE (mode);
-    } while (mode != VOIDmode);
-
-  return 0;
-}
 \f
 /* Emit a library call comparison between floating point X and Y.
    COMPARISON is the rtl operator to compare with (EQ, NE, GT, etc.).  */
@@ -3876,8 +3880,8 @@ expand_float (to, from, unsignedp)
              do_pending_stack_adjust ();
 
              /* Test whether the sign bit is set.  */
-             emit_cmp_insn (from, const0_rtx, GE, NULL_RTX, imode, 0, 0);
-             emit_jump_insn (gen_blt (neglabel));
+             emit_cmp_and_jump_insns (from, const0_rtx, LT, NULL_RTX, imode,
+                                      0, 0, neglabel);
 
              /* The sign bit is not set.  Convert as signed.  */
              expand_float (target, from, 0);
@@ -4467,6 +4471,9 @@ init_optabs ()
   sin_optab = init_optab (UNKNOWN);
   cos_optab = init_optab (UNKNOWN);
   strlen_optab = init_optab (UNKNOWN);
+  cbranch_optab = init_optab (UNKNOWN);
+  cmov_optab = init_optab (UNKNOWN);
+  cstore_optab = init_optab (UNKNOWN);
 
   for (i = 0; i < NUM_MACHINE_MODES; i++)
     {