OSDN Git Service

* tree.h (DECIMAL_FLOAT_TYPE_P): New.
[pf3gnuchains/gcc-fork.git] / gcc / expr.c
index 324a427..e46e3e7 100644 (file)
@@ -1940,14 +1940,17 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
       if (start < finish)
        {
          inner = GET_MODE (tmps[start]);
-         bytepos = subreg_lowpart_offset (outer, inner);
+         bytepos = subreg_lowpart_offset (inner, outer);
          if (INTVAL (XEXP (XVECEXP (src, 0, start), 1)) == bytepos)
            {
              temp = simplify_gen_subreg (outer, tmps[start],
-                                         inner, bytepos);
-             emit_move_insn (dst, temp);
-             done = true;
-             start++;
+                                         inner, 0);
+             if (temp)
+               {
+                 emit_move_insn (dst, temp);
+                 done = true;
+                 start++;
+               }
            }
        }
 
@@ -1956,14 +1959,17 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
          && start < finish - 1)
        {
          inner = GET_MODE (tmps[finish - 1]);
-         bytepos = subreg_lowpart_offset (outer, inner);
+         bytepos = subreg_lowpart_offset (inner, outer);
          if (INTVAL (XEXP (XVECEXP (src, 0, finish - 1), 1)) == bytepos)
            {
              temp = simplify_gen_subreg (outer, tmps[finish - 1],
-                                         inner, bytepos);
-             emit_move_insn (dst, temp);
-             done = true;
-             finish--;
+                                         inner, 0);
+             if (temp)
+               {
+                 emit_move_insn (dst, temp);
+                 done = true;
+                 finish--;
+               }
            }
        }
 
@@ -3090,6 +3096,38 @@ emit_move_ccmode (enum machine_mode mode, rtx x, rtx y)
   return ret;
 }
 
+/* Return true if word I of OP lies entirely in the
+   undefined bits of a paradoxical subreg.  */
+
+static bool
+undefined_operand_subword_p (rtx op, int i)
+{
+  enum machine_mode innermode, innermostmode;
+  int offset;
+  if (GET_CODE (op) != SUBREG)
+    return false;
+  innermode = GET_MODE (op);
+  innermostmode = GET_MODE (SUBREG_REG (op));
+  offset = i * UNITS_PER_WORD + SUBREG_BYTE (op);
+  /* The SUBREG_BYTE represents offset, as if the value were stored in
+     memory, except for a paradoxical subreg where we define
+     SUBREG_BYTE to be 0; undo this exception as in
+     simplify_subreg.  */
+  if (SUBREG_BYTE (op) == 0
+      && GET_MODE_SIZE (innermostmode) < GET_MODE_SIZE (innermode))
+    {
+      int difference = (GET_MODE_SIZE (innermostmode) - GET_MODE_SIZE (innermode));
+      if (WORDS_BIG_ENDIAN)
+       offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
+      if (BYTES_BIG_ENDIAN)
+       offset += difference % UNITS_PER_WORD;
+    }
+  if (offset >= GET_MODE_SIZE (innermostmode)
+      || offset <= -GET_MODE_SIZE (word_mode))
+    return true;
+  return false;
+}
+
 /* A subroutine of emit_move_insn_1.  Generate a move from Y into X.
    MODE is any multi-word or full-word mode that lacks a move_insn
    pattern.  Note that you will get better code if you define such
@@ -3127,7 +3165,14 @@ emit_move_multi_word (enum machine_mode mode, rtx x, rtx y)
        i++)
     {
       rtx xpart = operand_subword (x, i, 1, mode);
-      rtx ypart = operand_subword (y, i, 1, mode);
+      rtx ypart;
+
+      /* Do not generate code for a move if it would come entirely
+        from the undefined bits of a paradoxical subreg.  */
+      if (undefined_operand_subword_p (y, i))
+       continue;
+
+      ypart = operand_subword (y, i, 1, mode);
 
       /* If we can't get a part of Y, put Y into memory if it is a
         constant.  Otherwise, force it into a register.  Then we must
@@ -3340,7 +3385,11 @@ compress_float_constant (rtx x, rtx y)
        }
       else
        continue;
+
+      /* For CSE's benefit, force the compressed constant pool entry
+        into a new pseudo.  This constant may be used in different modes,
+        and if not, combine will put things back together for us.  */
+      trunc_y = force_reg (srcmode, trunc_y);
       emit_unop_insn (ic, x, trunc_y, UNKNOWN);
       last_insn = get_last_insn ();
 
@@ -3978,13 +4027,16 @@ expand_assignment (tree to, tree from)
   rtx result;
 
   /* Don't crash if the lhs of the assignment was erroneous.  */
-
   if (TREE_CODE (to) == ERROR_MARK)
     {
       result = expand_normal (from);
       return;
     }
 
+  /* Optimize away no-op moves without side-effects.  */
+  if (operand_equal_p (to, from, 0))
+    return;
+
   /* Assignment of a structure component needs special treatment
      if the structure component's rtx is not simply a MEM.
      Assignment of an array element at a constant index, and assignment of
@@ -4282,14 +4334,14 @@ store_expr (tree exp, rtx target, int call_param_p)
        {
          if (TYPE_UNSIGNED (TREE_TYPE (exp))
              != SUBREG_PROMOTED_UNSIGNED_P (target))
-           exp = convert
+           exp = fold_convert
              (lang_hooks.types.signed_or_unsigned_type
               (SUBREG_PROMOTED_UNSIGNED_P (target), TREE_TYPE (exp)), exp);
 
-         exp = convert (lang_hooks.types.type_for_mode
-                        (GET_MODE (SUBREG_REG (target)),
-                         SUBREG_PROMOTED_UNSIGNED_P (target)),
-                        exp);
+         exp = fold_convert (lang_hooks.types.type_for_mode
+                               (GET_MODE (SUBREG_REG (target)),
+                                SUBREG_PROMOTED_UNSIGNED_P (target)),
+                             exp);
 
          inner_target = SUBREG_REG (target);
        }
@@ -4957,13 +5009,13 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
                  {
                    type = lang_hooks.types.type_for_size
                      (BITS_PER_WORD, TYPE_UNSIGNED (type));
-                   value = convert (type, value);
+                   value = fold_convert (type, value);
                  }
                
                if (BYTES_BIG_ENDIAN)
                  value
                   = fold_build2 (LSHIFT_EXPR, type, value,
-                                  build_int_cst (NULL_TREE,
+                                  build_int_cst (type,
                                                  BITS_PER_WORD - bitsize));
                bitsize = BITS_PER_WORD;
                mode = word_mode;
@@ -5161,13 +5213,17 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
                    emit_label (loop_start);
 
                    /* Assign value to element index.  */
-                   position
-                     = convert (ssizetype,
-                                fold_build2 (MINUS_EXPR, TREE_TYPE (index),
-                                             index, TYPE_MIN_VALUE (domain)));
-                   position = size_binop (MULT_EXPR, position,
-                                          convert (ssizetype,
-                                                   TYPE_SIZE_UNIT (elttype)));
+                   position =
+                     fold_convert (ssizetype,
+                                   fold_build2 (MINUS_EXPR,
+                                                TREE_TYPE (index),
+                                                index,
+                                                TYPE_MIN_VALUE (domain)));
+
+                   position =
+                       size_binop (MULT_EXPR, position,
+                                   fold_convert (ssizetype,
+                                                 TYPE_SIZE_UNIT (elttype)));
                    
                    pos_rtx = expand_normal (position);
                    xtarget = offset_address (target, pos_rtx,
@@ -5211,9 +5267,10 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
                                                     index,
                                                     TYPE_MIN_VALUE (domain)));
                
-               position = size_binop (MULT_EXPR, index,
-                                      convert (ssizetype,
-                                               TYPE_SIZE_UNIT (elttype)));
+               position =
+                 size_binop (MULT_EXPR, index,
+                             fold_convert (ssizetype,
+                                           TYPE_SIZE_UNIT (elttype)));
                xtarget = offset_address (target,
                                          expand_normal (position),
                                          highest_pow2_factor (position));
@@ -5314,7 +5371,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
          }
        
        /* Inform later passes that the old value is dead.  */
-       if (!cleared && REG_P (target))
+       if (!cleared && !vector && REG_P (target))
          emit_move_insn (target, CONST0_RTX (GET_MODE (target)));
 
         /* Store each element of the constructor into the corresponding
@@ -5666,7 +5723,7 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
 
            offset = size_binop (PLUS_EXPR, offset,
                                 size_binop (MULT_EXPR,
-                                            convert (sizetype, index),
+                                            fold_convert (sizetype, index),
                                             unit_size));
          }
          break;
@@ -5705,7 +5762,8 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
   /* If OFFSET is constant, see if we can return the whole thing as a
      constant bit position.  Otherwise, split it up.  */
   if (host_integerp (offset, 0)
-      && 0 != (tem = size_binop (MULT_EXPR, convert (bitsizetype, offset),
+      && 0 != (tem = size_binop (MULT_EXPR,
+                                fold_convert (bitsizetype, offset),
                                 bitsize_unit_node))
       && 0 != (tem = size_binop (PLUS_EXPR, tem, bit_offset))
       && host_integerp (tem, 0))
@@ -6056,6 +6114,19 @@ safe_from_p (rtx x, tree exp, int top_p)
                return safe_from_p (x, exp, 0);
            }
        }
+      else if (TREE_CODE (exp) == CONSTRUCTOR)
+       {
+         constructor_elt *ce;
+         unsigned HOST_WIDE_INT idx;
+
+         for (idx = 0;
+              VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (exp), idx, ce);
+              idx++)
+           if ((ce->index != NULL_TREE && !safe_from_p (x, ce->index, 0))
+               || !safe_from_p (x, ce->value, 0))
+             return 0;
+         return 1;
+       }
       else if (TREE_CODE (exp) == ERROR_MARK)
        return 1;       /* An already-visited SAVE_EXPR? */
       else
@@ -6868,14 +6939,23 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       return temp;
 
     case VECTOR_CST:
-      if (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (exp))) == MODE_VECTOR_INT
-         || GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (exp))) == MODE_VECTOR_FLOAT)
-       return const_vector_from_tree (exp);
-      else
-       return expand_expr (build_constructor_from_list
-                           (TREE_TYPE (exp),
-                            TREE_VECTOR_CST_ELTS (exp)),
-                           ignore ? const0_rtx : target, tmode, modifier);
+      {
+       tree tmp = NULL_TREE;
+       if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT
+           || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
+         return const_vector_from_tree (exp);
+       if (GET_MODE_CLASS (mode) == MODE_INT)
+         {
+           tree type_for_mode = lang_hooks.types.type_for_mode (mode, 1);
+           if (type_for_mode)
+             tmp = fold_unary (VIEW_CONVERT_EXPR, type_for_mode, exp);
+         }
+       if (!tmp)
+         tmp = build_constructor_from_list (type,
+                                            TREE_VECTOR_CST_ELTS (exp));
+       return expand_expr (tmp, ignore ? const0_rtx : target,
+                           tmode, modifier);
+      }
 
     case CONST_DECL:
       return expand_expr (DECL_INITIAL (exp), target, VOIDmode, modifier);
@@ -7705,7 +7785,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       else if (!MEM_P (op0))
        {
          /* If the operand is not a MEM, force it into memory.  Since we
-            are going to be be changing the mode of the MEM, don't call
+            are going to be changing the mode of the MEM, don't call
             force_const_mem for constants because we don't allow pool
             constants to change mode.  */
          tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
@@ -8494,14 +8574,11 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
            && integer_onep (DECL_SIZE (TREE_OPERAND (TREE_OPERAND (rhs, 1), 1))))
          {
            rtx label = gen_label_rtx ();
-
+           int value = TREE_CODE (rhs) == BIT_IOR_EXPR;
            do_jump (TREE_OPERAND (rhs, 1),
-                    TREE_CODE (rhs) == BIT_IOR_EXPR ? label : 0,
-                    TREE_CODE (rhs) == BIT_AND_EXPR ? label : 0);
-           expand_assignment (lhs, convert (TREE_TYPE (rhs),
-                                            (TREE_CODE (rhs) == BIT_IOR_EXPR
-                                             ? integer_one_node
-                                             : integer_zero_node)));
+                    value ? label : 0,
+                    value ? 0 : label);
+           expand_assignment (lhs, build_int_cst (TREE_TYPE (rhs), value));
            do_pending_stack_adjust ();
            emit_label (label);
            return const0_rtx;
@@ -8821,7 +8898,7 @@ string_constant (tree arg, tree *ptr_offset)
 
   if (TREE_CODE (array) == STRING_CST)
     {
-      *ptr_offset = convert (sizetype, offset);
+      *ptr_offset = fold_convert (sizetype, offset);
       return array;
     }
   else if (TREE_CODE (array) == VAR_DECL)
@@ -8848,7 +8925,7 @@ string_constant (tree arg, tree *ptr_offset)
 
       /* If variable is bigger than the string literal, OFFSET must be constant
         and inside of the bounds of the string literal.  */
-      offset = convert (sizetype, offset);
+      offset = fold_convert (sizetype, offset);
       if (compare_tree_int (DECL_SIZE_UNIT (array), length) > 0
          && (! host_integerp (offset, 1)
              || compare_tree_int (offset, length) >= 0))
@@ -9160,9 +9237,8 @@ try_casesi (tree index_type, tree index_expr, tree minval, tree range,
     {
       if (TYPE_MODE (index_type) != index_mode)
        {
-         index_expr = convert (lang_hooks.types.type_for_size
-                               (index_bits, 0), index_expr);
-         index_type = TREE_TYPE (index_expr);
+         index_type = lang_hooks.types.type_for_size (index_bits, 0);
+         index_expr = fold_convert (index_type, index_expr);
        }
 
       index = expand_normal (index_expr);
@@ -9288,8 +9364,8 @@ try_tablejump (tree index_type, tree index_expr, tree minval, tree range,
     return 0;
 
   index_expr = fold_build2 (MINUS_EXPR, index_type,
-                           convert (index_type, index_expr),
-                           convert (index_type, minval));
+                           fold_convert (index_type, index_expr),
+                           fold_convert (index_type, minval));
   index = expand_normal (index_expr);
   do_pending_stack_adjust ();