OSDN Git Service

* c-common.c (shorten_compare): Use force_fit_type directly.
[pf3gnuchains/gcc-fork.git] / gcc / expmed.c
index 9ceee9f..7ee5964 100644 (file)
@@ -59,8 +59,8 @@ static rtx expand_sdiv_pow2 (enum machine_mode, rtx, HOST_WIDE_INT);
    Usually, this will mean that the MD file will emit non-branch
    sequences.  */
 
-static int sdiv_pow2_cheap[NUM_MACHINE_MODES];
-static int smod_pow2_cheap[NUM_MACHINE_MODES];
+static bool sdiv_pow2_cheap[NUM_MACHINE_MODES];
+static bool smod_pow2_cheap[NUM_MACHINE_MODES];
 
 #ifndef SLOW_UNALIGNED_ACCESS
 #define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) STRICT_ALIGNMENT
@@ -109,7 +109,7 @@ init_expmed (void)
 {
   struct
   {
-    struct rtx_def reg;
+    struct rtx_def reg;                rtunion reg_fld[2];
     struct rtx_def plus;       rtunion plus_fld1;
     struct rtx_def neg;
     struct rtx_def udiv;       rtunion udiv_fld1;
@@ -2075,11 +2075,11 @@ expand_shift (enum tree_code code, enum machine_mode mode, rtx shifted,
              tree type = TREE_TYPE (amount);
              tree new_amount = make_tree (type, op1);
              tree other_amount
-               = fold (build (MINUS_EXPR, type,
-                              convert (type,
-                                       build_int_2 (GET_MODE_BITSIZE (mode),
-                                                    0)),
-                              amount));
+               = fold (build2 (MINUS_EXPR, type,
+                               convert (type,
+                                        build_int_2 (GET_MODE_BITSIZE (mode),
+                                                     0)),
+                               amount));
 
              shifted = force_reg (mode, shifted);
 
@@ -3194,6 +3194,31 @@ expand_sdiv_pow2 (enum machine_mode mode, rtx op0, HOST_WIDE_INT d)
       return expand_shift (RSHIFT_EXPR, mode, temp, shift, NULL_RTX, 0);
     }
 
+#ifdef HAVE_conditional_move
+  if (BRANCH_COST >= 2)
+    {
+      rtx temp2;
+
+      start_sequence ();
+      temp2 = copy_to_mode_reg (mode, op0);
+      temp = expand_binop (mode, add_optab, temp2, GEN_INT (d-1),
+                          NULL_RTX, 0, OPTAB_LIB_WIDEN);
+      temp = force_reg (mode, temp);
+
+      /* Construct "temp2 = (temp2 < 0) ? temp : temp2".  */
+      temp2 = emit_conditional_move (temp2, LT, temp2, const0_rtx,
+                                    mode, temp, temp2, mode, 0);
+      if (temp2)
+       {
+         rtx seq = get_insns ();
+         end_sequence ();
+         emit_insn (seq);
+         return expand_shift (RSHIFT_EXPR, mode, temp2, shift, NULL_RTX, 0);
+       }
+      end_sequence ();
+    }
+#endif
+
   if (BRANCH_COST >= 2)
     {
       int ushift = GET_MODE_BITSIZE (mode) - logd;
@@ -4312,10 +4337,24 @@ expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode,
        target = 0;
 
       if (quotient == 0)
-       /* No divide instruction either.  Use library for remainder.  */
-       remainder = sign_expand_binop (compute_mode, umod_optab, smod_optab,
-                                      op0, op1, target,
-                                      unsignedp, OPTAB_LIB_WIDEN);
+       {
+         /* No divide instruction either.  Use library for remainder.  */
+         remainder = sign_expand_binop (compute_mode, umod_optab, smod_optab,
+                                        op0, op1, target,
+                                        unsignedp, OPTAB_LIB_WIDEN);
+         /* No remainder function.  Try a quotient-and-remainder
+            function, keeping the remainder.  */
+         if (!remainder)
+           {
+             remainder = gen_reg_rtx (compute_mode);
+             if (!expand_twoval_binop_libfunc 
+                 (unsignedp ? udivmod_optab : sdivmod_optab,
+                  op0, op1,
+                  NULL_RTX, remainder,
+                  unsignedp ? UMOD : MOD))
+               remainder = NULL_RTX;
+           }
+       }
       else
        {
          /* We divided.  Now finish doing X - Y * (X / Y).  */
@@ -4386,37 +4425,37 @@ make_tree (tree type, rtx x)
       }
 
     case PLUS:
-      return fold (build (PLUS_EXPR, type, make_tree (type, XEXP (x, 0)),
-                         make_tree (type, XEXP (x, 1))));
+      return fold (build2 (PLUS_EXPR, type, make_tree (type, XEXP (x, 0)),
+                          make_tree (type, XEXP (x, 1))));
 
     case MINUS:
-      return fold (build (MINUS_EXPR, type, make_tree (type, XEXP (x, 0)),
-                         make_tree (type, XEXP (x, 1))));
+      return fold (build2 (MINUS_EXPR, type, make_tree (type, XEXP (x, 0)),
+                          make_tree (type, XEXP (x, 1))));
 
     case NEG:
       return fold (build1 (NEGATE_EXPR, type, make_tree (type, XEXP (x, 0))));
 
     case MULT:
-      return fold (build (MULT_EXPR, type, make_tree (type, XEXP (x, 0)),
-                         make_tree (type, XEXP (x, 1))));
+      return fold (build2 (MULT_EXPR, type, make_tree (type, XEXP (x, 0)),
+                          make_tree (type, XEXP (x, 1))));
 
     case ASHIFT:
-      return fold (build (LSHIFT_EXPR, type, make_tree (type, XEXP (x, 0)),
-                         make_tree (type, XEXP (x, 1))));
+      return fold (build2 (LSHIFT_EXPR, type, make_tree (type, XEXP (x, 0)),
+                          make_tree (type, XEXP (x, 1))));
 
     case LSHIFTRT:
       t = lang_hooks.types.unsigned_type (type);
       return fold (convert (type,
-                           build (RSHIFT_EXPR, t,
-                                  make_tree (t, XEXP (x, 0)),
-                                  make_tree (type, XEXP (x, 1)))));
+                           build2 (RSHIFT_EXPR, t,
+                                   make_tree (t, XEXP (x, 0)),
+                                   make_tree (type, XEXP (x, 1)))));
 
     case ASHIFTRT:
       t = lang_hooks.types.signed_type (type);
       return fold (convert (type,
-                           build (RSHIFT_EXPR, t,
-                                  make_tree (t, XEXP (x, 0)),
-                                  make_tree (type, XEXP (x, 1)))));
+                           build2 (RSHIFT_EXPR, t,
+                                   make_tree (t, XEXP (x, 0)),
+                                   make_tree (type, XEXP (x, 1)))));
 
     case DIV:
       if (TREE_CODE (type) != REAL_TYPE)
@@ -4425,15 +4464,15 @@ make_tree (tree type, rtx x)
        t = type;
 
       return fold (convert (type,
-                           build (TRUNC_DIV_EXPR, t,
-                                  make_tree (t, XEXP (x, 0)),
-                                  make_tree (t, XEXP (x, 1)))));
+                           build2 (TRUNC_DIV_EXPR, t,
+                                   make_tree (t, XEXP (x, 0)),
+                                   make_tree (t, XEXP (x, 1)))));
     case UDIV:
       t = lang_hooks.types.unsigned_type (type);
       return fold (convert (type,
-                           build (TRUNC_DIV_EXPR, t,
-                                  make_tree (t, XEXP (x, 0)),
-                                  make_tree (t, XEXP (x, 1)))));
+                           build2 (TRUNC_DIV_EXPR, t,
+                                   make_tree (t, XEXP (x, 0)),
+                                   make_tree (t, XEXP (x, 1)))));
 
     case SIGN_EXTEND:
     case ZERO_EXTEND:
@@ -4483,11 +4522,11 @@ const_mult_add_overflow_p (rtx x, rtx mult, rtx add, enum machine_mode mode, int
   add_type = (GET_MODE (add) == VOIDmode ? mult_type
              : lang_hooks.types.type_for_mode (GET_MODE (add), unsignedp));
 
-  result = fold (build (PLUS_EXPR, mult_type,
-                       fold (build (MULT_EXPR, mult_type,
-                                    make_tree (mult_type, x),
-                                    make_tree (mult_type, mult))),
-                       make_tree (add_type, add)));
+  result = fold (build2 (PLUS_EXPR, mult_type,
+                        fold (build2 (MULT_EXPR, mult_type,
+                                      make_tree (mult_type, x),
+                                      make_tree (mult_type, mult))),
+                        make_tree (add_type, add)));
 
   return TREE_CONSTANT_OVERFLOW (result);
 }
@@ -4508,11 +4547,11 @@ expand_mult_add (rtx x, rtx target, rtx mult, rtx add, enum machine_mode mode,
   tree add_type = (GET_MODE (add) == VOIDmode
                   ? type: lang_hooks.types.type_for_mode (GET_MODE (add),
                                                           unsignedp));
-  tree result =  fold (build (PLUS_EXPR, type,
-                             fold (build (MULT_EXPR, type,
-                                          make_tree (type, x),
-                                          make_tree (type, mult))),
-                             make_tree (add_type, add)));
+  tree result =  fold (build2 (PLUS_EXPR, type,
+                              fold (build2 (MULT_EXPR, type,
+                                            make_tree (type, x),
+                                            make_tree (type, mult))),
+                              make_tree (add_type, add)));
 
   return expand_expr (result, target, VOIDmode, 0);
 }