OSDN Git Service

PR c/12553
[pf3gnuchains/gcc-fork.git] / gcc / expmed.c
index 68163e9..d93be93 100644 (file)
@@ -461,7 +461,9 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
         VOIDmode, because that is what store_field uses to indicate that this
         is a bit field, but passing VOIDmode to operand_subword_force will
         result in an abort.  */
-      fieldmode = smallest_mode_for_size (nwords * BITS_PER_WORD, MODE_INT);
+      fieldmode = GET_MODE (value);
+      if (fieldmode == VOIDmode)
+       fieldmode = smallest_mode_for_size (nwords * BITS_PER_WORD, MODE_INT);
 
       for (i = 0; i < nwords; i++)
        {
@@ -477,10 +479,7 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
          store_bit_field (op0, MIN (BITS_PER_WORD,
                                     bitsize - i * BITS_PER_WORD),
                           bitnum + bit_offset, word_mode,
-                          operand_subword_force (value, wordnum,
-                                                 (GET_MODE (value) == VOIDmode
-                                                  ? fieldmode
-                                                  : GET_MODE (value))),
+                          operand_subword_force (value, wordnum, fieldmode),
                           total_size);
        }
       return value;
@@ -2300,7 +2299,8 @@ synth_mult (struct algorithm *alg_out, unsigned HOST_WIDE_INT t,
    you should swap the two operands if OP0 would be constant.  */
 
 rtx
-expand_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target, int unsignedp)
+expand_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target,
+            int unsignedp)
 {
   rtx const_op1 = op1;
 
@@ -2514,6 +2514,28 @@ expand_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target, int unsignedp
        }
     }
 
+  if (GET_CODE (op0) == CONST_DOUBLE)
+    {
+      rtx temp = op0;
+      op0 = op1;
+      op1 = temp;
+    }
+
+  /* Expand x*2.0 as x+x.  */
+  if (GET_CODE (op1) == CONST_DOUBLE
+      && GET_MODE_CLASS (mode) == MODE_FLOAT)
+    {
+      REAL_VALUE_TYPE d;
+      REAL_VALUE_FROM_CONST_DOUBLE (d, op1);
+
+      if (REAL_VALUES_EQUAL (d, dconst2))
+       {
+         op0 = force_reg (GET_MODE (op0), op0);
+         return expand_binop (mode, add_optab, op0, op0,
+                              target, unsignedp, OPTAB_LIB_WIDEN);
+       }
+    }
+
   /* This used to use umul_optab if unsigned, but for non-widening multiply
      there is no difference between signed and unsigned.  */
   op0 = expand_binop (mode,
@@ -2605,7 +2627,7 @@ choose_multiplier (unsigned HOST_WIDE_INT d, int n, int precision,
     abort ();
   if (mhigh_hi > 1 || mlow_hi > 1)
     abort ();
-  /* assert that mlow < mhigh.  */
+  /* Assert that mlow < mhigh.  */
   if (! (mlow_hi < mhigh_hi || (mlow_hi == mhigh_hi && mlow_lo < mhigh_lo)))
     abort ();
 
@@ -3801,7 +3823,7 @@ expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode,
                               build_int_2 (pre_shift, 0), NULL_RTX, unsignedp);
            quotient = expand_mult (compute_mode, t1,
                                    gen_int_mode (ml, compute_mode),
-                                   NULL_RTX, 0);
+                                   NULL_RTX, 1);
 
            insn = get_last_insn ();
            set_unique_reg_note (insn,
@@ -4092,12 +4114,10 @@ make_tree (tree type, rtx x)
       t = make_node (RTL_EXPR);
       TREE_TYPE (t) = type;
 
-#ifdef POINTERS_EXTEND_UNSIGNED
       /* If TYPE is a POINTER_TYPE, X might be Pmode with TYPE_MODE being
         ptr_mode.  So convert.  */
-      if (POINTER_TYPE_P (type) && GET_MODE (x) != TYPE_MODE (type))
+      if (POINTER_TYPE_P (type))
        x = convert_memory_address (TYPE_MODE (type), x);
-#endif
 
       RTL_EXPR_RTL (t) = x;
       /* There are no insns to be output