OSDN Git Service

Fixup whitespaces
[pf3gnuchains/gcc-fork.git] / gcc / expr.c
index 537ce1e..904d4fc 100644 (file)
@@ -1409,6 +1409,8 @@ init_block_move_fn (const char *asmspec)
       TREE_PUBLIC (fn) = 1;
       DECL_ARTIFICIAL (fn) = 1;
       TREE_NOTHROW (fn) = 1;
+      DECL_VISIBILITY (fn) = VISIBILITY_DEFAULT;
+      DECL_VISIBILITY_SPECIFIED (fn) = 1;
 
       block_move_fn = fn;
     }
@@ -1855,7 +1857,7 @@ void
 emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
 {
   rtx *tmps, dst;
-  int start, i;
+  int start, finish, i;
   enum machine_mode m = GET_MODE (orig_dst);
 
   gcc_assert (GET_CODE (src) == PARALLEL);
@@ -1881,15 +1883,21 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
     start = 0;
   else
     start = 1;
+  finish = XVECLEN (src, 0);
 
-  tmps = alloca (sizeof (rtx) * XVECLEN (src, 0));
+  tmps = alloca (sizeof (rtx) * finish);
 
   /* Copy the (probable) hard regs into pseudos.  */
-  for (i = start; i < XVECLEN (src, 0); i++)
+  for (i = start; i < finish; i++)
     {
       rtx reg = XEXP (XVECEXP (src, 0, i), 0);
-      tmps[i] = gen_reg_rtx (GET_MODE (reg));
-      emit_move_insn (tmps[i], reg);
+      if (!REG_P (reg) || REGNO (reg) < FIRST_PSEUDO_REGISTER)
+       {
+         tmps[i] = gen_reg_rtx (GET_MODE (reg));
+         emit_move_insn (tmps[i], reg);
+       }
+      else
+       tmps[i] = reg;
     }
 
   /* If we won't be storing directly into memory, protect the real destination
@@ -1916,13 +1924,62 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
     }
   else if (!MEM_P (dst) && GET_CODE (dst) != CONCAT)
     {
-      dst = gen_reg_rtx (GET_MODE (orig_dst));
+      enum machine_mode outer = GET_MODE (dst);
+      enum machine_mode inner;
+      HOST_WIDE_INT bytepos;
+      bool done = false;
+      rtx temp;
+
+      if (!REG_P (dst) || REGNO (dst) < FIRST_PSEUDO_REGISTER)
+       dst = gen_reg_rtx (outer);
+
       /* Make life a bit easier for combine.  */
-      emit_move_insn (dst, CONST0_RTX (GET_MODE (orig_dst)));
+      /* If the first element of the vector is the low part
+        of the destination mode, use a paradoxical subreg to
+        initialize the destination.  */
+      if (start < finish)
+       {
+         inner = GET_MODE (tmps[start]);
+         bytepos = subreg_lowpart_offset (outer, inner);
+         if (INTVAL (XEXP (XVECEXP (src, 0, start), 1)) == bytepos)
+           {
+             temp = simplify_gen_subreg (outer, tmps[start],
+                                         inner, bytepos);
+             if (temp)
+               {
+                 emit_move_insn (dst, temp);
+                 done = true;
+                 start++;
+               }
+           }
+       }
+
+      /* If the first element wasn't the low part, try the last.  */
+      if (!done
+         && start < finish - 1)
+       {
+         inner = GET_MODE (tmps[finish - 1]);
+         bytepos = subreg_lowpart_offset (outer, inner);
+         if (INTVAL (XEXP (XVECEXP (src, 0, finish - 1), 1)) == bytepos)
+           {
+             temp = simplify_gen_subreg (outer, tmps[finish - 1],
+                                         inner, bytepos);
+             if (temp)
+               {
+                 emit_move_insn (dst, temp);
+                 done = true;
+                 finish--;
+               }
+           }
+       }
+
+      /* Otherwise, simply initialize the result to zero.  */
+      if (!done)
+        emit_move_insn (dst, CONST0_RTX (outer));
     }
 
   /* Process the pieces.  */
-  for (i = start; i < XVECLEN (src, 0); i++)
+  for (i = start; i < finish; i++)
     {
       HOST_WIDE_INT bytepos = INTVAL (XEXP (XVECEXP (src, 0, i), 1));
       enum machine_mode mode = GET_MODE (tmps[i]);
@@ -2556,6 +2613,8 @@ init_block_clear_fn (const char *asmspec)
       TREE_PUBLIC (fn) = 1;
       DECL_ARTIFICIAL (fn) = 1;
       TREE_NOTHROW (fn) = 1;
+      DECL_VISIBILITY (fn) = VISIBILITY_DEFAULT;
+      DECL_VISIBILITY_SPECIFIED (fn) = 1;
 
       block_clear_fn = fn;
     }
@@ -3081,7 +3140,7 @@ emit_move_multi_word (enum machine_mode mode, rtx x, rtx y)
         be able to get a part of Y.  */
       if (ypart == 0 && CONSTANT_P (y))
        {
-         y = force_const_mem (mode, y);
+         y = use_anchored_address (force_const_mem (mode, y));
          ypart = operand_subword (y, i, 1, mode);
        }
       else if (ypart == 0)
@@ -3194,6 +3253,8 @@ emit_move_insn (rtx x, rtx y)
             of the non-legitimate constant.  */
          if (!y)
            y = y_cst;
+         else
+           y = use_anchored_address (y);
        }
     }
 
@@ -4227,14 +4288,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);
        }
@@ -4902,13 +4963,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;
@@ -5106,13 +5167,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,
@@ -5156,9 +5221,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));
@@ -5611,7 +5677,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;
@@ -5650,7 +5716,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))
@@ -6280,6 +6347,20 @@ expand_operands (tree exp0, tree exp1, rtx target, rtx *op0, rtx *op1,
 }
 
 \f
+/* Return a MEM that contains constant EXP.  DEFER is as for
+   output_constant_def and MODIFIER is as for expand_expr.  */
+
+static rtx
+expand_expr_constant (tree exp, int defer, enum expand_modifier modifier)
+{
+  rtx mem;
+
+  mem = output_constant_def (exp, defer);
+  if (modifier != EXPAND_INITIALIZER)
+    mem = use_anchored_address (mem);
+  return mem;
+}
+
 /* A subroutine of expand_expr_addr_expr.  Evaluate the address of EXP.
    The TARGET, TMODE and MODIFIER arguments are as for expand_expr.  */
 
@@ -6301,14 +6382,14 @@ expand_expr_addr_expr_1 (tree exp, rtx target, enum machine_mode tmode,
      exception here is STRING_CST.  */
   if (TREE_CODE (exp) == CONSTRUCTOR
       || CONSTANT_CLASS_P (exp))
-    return XEXP (output_constant_def (exp, 0), 0);
+    return XEXP (expand_expr_constant (exp, 0, modifier), 0);
 
   /* Everything must be something allowed by is_gimple_addressable.  */
   switch (TREE_CODE (exp))
     {
     case INDIRECT_REF:
       /* This case will happen via recursion for &a->b.  */
-      return expand_expr (TREE_OPERAND (exp, 0), target, tmode, EXPAND_NORMAL);
+      return expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
 
     case CONST_DECL:
       /* Recurse and make the output_constant_def clause above handle this.  */
@@ -6579,7 +6660,7 @@ static rtx
 expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                    enum expand_modifier modifier, rtx *alt_rtl)
 {
-  rtx op0, op1, temp;
+  rtx op0, op1, temp, decl_rtl;
   tree type = TREE_TYPE (exp);
   int unsignedp;
   enum machine_mode mode;
@@ -6701,7 +6782,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
 
     case FUNCTION_DECL:
     case RESULT_DECL:
-      gcc_assert (DECL_RTL (exp));
+      decl_rtl = DECL_RTL (exp);
+      gcc_assert (decl_rtl);
 
       /* Ensure variable marked as used even if it doesn't go through
         a parser.  If it hasn't be used yet, write out an external
@@ -6728,27 +6810,24 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
         from its initializer, while the initializer is still being parsed.
         See expand_decl.  */
 
-      if (MEM_P (DECL_RTL (exp))
-              && REG_P (XEXP (DECL_RTL (exp), 0)))
-       temp = validize_mem (DECL_RTL (exp));
+      if (MEM_P (decl_rtl) && REG_P (XEXP (decl_rtl, 0)))
+       temp = validize_mem (decl_rtl);
 
       /* If DECL_RTL is memory, we are in the normal case and either
         the address is not valid or it is not a register and -fforce-addr
         is specified, get the address into a register.  */
 
-      else if (MEM_P (DECL_RTL (exp))
-              && modifier != EXPAND_CONST_ADDRESS
-              && modifier != EXPAND_SUM
-              && modifier != EXPAND_INITIALIZER
-              && (! memory_address_p (DECL_MODE (exp),
-                                      XEXP (DECL_RTL (exp), 0))
-                  || (flag_force_addr
-                      && !REG_P (XEXP (DECL_RTL (exp), 0)))))
+      else if (MEM_P (decl_rtl) && modifier != EXPAND_INITIALIZER)
        {
          if (alt_rtl)
-           *alt_rtl = DECL_RTL (exp);
-         temp = replace_equiv_address (DECL_RTL (exp),
-                                       copy_rtx (XEXP (DECL_RTL (exp), 0)));
+           *alt_rtl = decl_rtl;
+         decl_rtl = use_anchored_address (decl_rtl);
+         if (modifier != EXPAND_CONST_ADDRESS
+             && modifier != EXPAND_SUM
+             && (!memory_address_p (DECL_MODE (exp), XEXP (decl_rtl, 0))
+                 || (flag_force_addr && !REG_P (XEXP (decl_rtl, 0)))))
+           temp = replace_equiv_address (decl_rtl,
+                                         copy_rtx (XEXP (decl_rtl, 0)));
        }
 
       /* If we got something, return it.  But first, set the alignment
@@ -6765,8 +6844,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
         must be a promoted value.  We return a SUBREG of the wanted mode,
         but mark it so that we know that it was already extended.  */
 
-      if (REG_P (DECL_RTL (exp))
-         && GET_MODE (DECL_RTL (exp)) != DECL_MODE (exp))
+      if (REG_P (decl_rtl)
+         && GET_MODE (decl_rtl) != DECL_MODE (exp))
        {
          enum machine_mode pmode;
          
@@ -6775,15 +6854,15 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
          pmode = promote_mode (type, DECL_MODE (exp), &unsignedp,
                                (TREE_CODE (exp) == RESULT_DECL
                                 || TREE_CODE (exp) == PARM_DECL) ? 1 : 0);
-         gcc_assert (GET_MODE (DECL_RTL (exp)) == pmode);
+         gcc_assert (GET_MODE (decl_rtl) == pmode);
 
-         temp = gen_lowpart_SUBREG (mode, DECL_RTL (exp));
+         temp = gen_lowpart_SUBREG (mode, decl_rtl);
          SUBREG_PROMOTED_VAR_P (temp) = 1;
          SUBREG_PROMOTED_UNSIGNED_SET (temp, unsignedp);
          return temp;
        }
 
-      return DECL_RTL (exp);
+      return decl_rtl;
 
     case INTEGER_CST:
       temp = immed_double_const (TREE_INT_CST_LOW (exp),
@@ -6852,7 +6931,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       /* ... fall through ...  */
 
     case STRING_CST:
-      temp = output_constant_def (exp, 1);
+      temp = expand_expr_constant (exp, 1, modifier);
 
       /* temp contains a constant address.
         On RISC machines where a constant address isn't valid,
@@ -6953,7 +7032,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                    || modifier == EXPAND_CONST_ADDRESS)
                   && TREE_CONSTANT (exp)))
        {
-         rtx constructor = output_constant_def (exp, 1);
+         rtx constructor = expand_expr_constant (exp, 1, modifier);
 
          if (modifier != EXPAND_CONST_ADDRESS
              && modifier != EXPAND_INITIALIZER
@@ -8184,24 +8263,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
          emit_move_insn (target, op0);
 
        temp = gen_label_rtx ();
-
-       /* 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 (GE, mode, ccp_jump))
-         {
-           if (code == MAX_EXPR)
-             do_jump_by_parts_greater_rtx (mode, unsignedp, target, op1,
-                                           NULL_RTX, temp);
-           else
-             do_jump_by_parts_greater_rtx (mode, unsignedp, op1, target,
-                                           NULL_RTX, temp);
-         }
-       else
-         {
-           do_compare_rtx_and_jump (target, cmpop1, comparison_code,
-                                    unsignedp, mode, NULL_RTX, NULL_RTX, temp);
-         }
+       do_compare_rtx_and_jump (target, cmpop1, comparison_code,
+                                unsignedp, mode, NULL_RTX, NULL_RTX, temp);
       }
       emit_move_insn (target, op1);
       emit_label (temp);
@@ -8443,14 +8506,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;
@@ -8770,7 +8830,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)
@@ -8797,7 +8857,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))
@@ -9109,9 +9169,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);
@@ -9237,8 +9296,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 ();