OSDN Git Service

PR c++/47132
[pf3gnuchains/gcc-fork.git] / gcc / expr.c
index 4db1c77..971432c 100644 (file)
@@ -616,7 +616,7 @@ convert_move (rtx to, rtx from, int unsignedp)
        {
          enum machine_mode intermediate;
          rtx tmp;
-         tree shift_amount;
+         int shift_amount;
 
          /* Search for a mode to convert via.  */
          for (intermediate = from_mode; intermediate != VOIDmode;
@@ -636,9 +636,8 @@ convert_move (rtx to, rtx from, int unsignedp)
 
          /* No suitable intermediate mode.
             Generate what we need with shifts.  */
-         shift_amount = build_int_cst (NULL_TREE,
-                                       GET_MODE_BITSIZE (to_mode)
-                                       - GET_MODE_BITSIZE (from_mode));
+         shift_amount = (GET_MODE_BITSIZE (to_mode)
+                         - GET_MODE_BITSIZE (from_mode));
          from = gen_lowpart (to_mode, force_reg (from_mode, from));
          tmp = expand_shift (LSHIFT_EXPR, to_mode, from, shift_amount,
                              to, unsignedp);
@@ -1293,17 +1292,18 @@ emit_block_move_via_movmem (rtx x, rtx y, rtx size, unsigned int align,
             nice if there were some way to inform the backend, so
             that it doesn't fail the expansion because it thinks
             emitting the libcall would be more efficient.  */
-         nops = insn_data[(int) code].n_operands;
+         nops = insn_data[(int) code].n_generator_args;
+         gcc_assert (nops == 4 || nops == 6);
+
          create_fixed_operand (&ops[0], x);
          create_fixed_operand (&ops[1], y);
          /* The check above guarantees that this size conversion is valid.  */
          create_convert_operand_to (&ops[2], size, mode, true);
          create_integer_operand (&ops[3], align / BITS_PER_UNIT);
-         if (nops != 4)
+         if (nops == 6)
            {
              create_integer_operand (&ops[4], expected_align / BITS_PER_UNIT);
              create_integer_operand (&ops[5], expected_size);
-             nops = 6;
            }
          if (maybe_expand_insn (code, nops, ops))
            {
@@ -1484,7 +1484,7 @@ move_block_to_reg (int regno, rtx x, int nregs, enum machine_mode mode)
   if (nregs == 0)
     return;
 
-  if (CONSTANT_P (x) && ! LEGITIMATE_CONSTANT_P (x))
+  if (CONSTANT_P (x) && !targetm.legitimate_constant_p (mode, x))
     x = validize_mem (force_const_mem (mode, x));
 
   /* See if the machine can do this with a load multiple insn.  */
@@ -1752,7 +1752,7 @@ emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, int ssize)
 
       if (shift)
        tmps[i] = expand_shift (LSHIFT_EXPR, mode, tmps[i],
-                               build_int_cst (NULL_TREE, shift), tmps[i], 0);
+                               shift, tmps[i], 0);
     }
 }
 
@@ -2049,8 +2049,7 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
            {
              int shift = (bytelen - (ssize - bytepos)) * BITS_PER_UNIT;
              tmps[i] = expand_shift (RSHIFT_EXPR, mode, tmps[i],
-                                     build_int_cst (NULL_TREE, shift),
-                                     tmps[i], 0);
+                                     shift, tmps[i], 0);
            }
          bytelen = adj_bytelen;
        }
@@ -2295,7 +2294,7 @@ can_store_by_pieces (unsigned HOST_WIDE_INT len,
                    offset -= size;
 
                  cst = (*constfun) (constfundata, offset, mode);
-                 if (!LEGITIMATE_CONSTANT_P (cst))
+                 if (!targetm.legitimate_constant_p (mode, cst))
                    return 0;
 
                  if (!reverse)
@@ -2715,17 +2714,18 @@ set_storage_via_setmem (rtx object, rtx size, rtx val, unsigned int align,
          struct expand_operand ops[6];
          unsigned int nops;
 
-         nops = insn_data[(int) code].n_operands;
+         nops = insn_data[(int) code].n_generator_args;
+         gcc_assert (nops == 4 || nops == 6);
+
          create_fixed_operand (&ops[0], object);
          /* The check above guarantees that this size conversion is valid.  */
          create_convert_operand_to (&ops[1], size, mode, true);
          create_convert_operand_from (&ops[2], val, byte_mode, true);
          create_integer_operand (&ops[3], align / BITS_PER_UNIT);
-         if (nops != 4)
+         if (nops == 6)
            {
              create_integer_operand (&ops[4], expected_align / BITS_PER_UNIT);
              create_integer_operand (&ops[5], expected_size);
-             nops = 6;
            }
          if (maybe_expand_insn (code, nops, ops))
            return true;
@@ -3327,7 +3327,7 @@ emit_move_insn (rtx x, rtx y)
 
       y_cst = y;
 
-      if (!LEGITIMATE_CONSTANT_P (y))
+      if (!targetm.legitimate_constant_p (mode, y))
        {
          y = force_const_mem (mode, y);
 
@@ -3383,7 +3383,7 @@ compress_float_constant (rtx x, rtx y)
 
   REAL_VALUE_FROM_CONST_DOUBLE (r, y);
 
-  if (LEGITIMATE_CONSTANT_P (y))
+  if (targetm.legitimate_constant_p (dstmode, y))
     oldcost = rtx_cost (y, SET, speed);
   else
     oldcost = rtx_cost (force_const_mem (dstmode, y), SET, speed);
@@ -3406,7 +3406,7 @@ compress_float_constant (rtx x, rtx y)
 
       trunc_y = CONST_DOUBLE_FROM_REAL_VALUE (r, srcmode);
 
-      if (LEGITIMATE_CONSTANT_P (trunc_y))
+      if (targetm.legitimate_constant_p (srcmode, trunc_y))
        {
          /* Skip if the target needs extra instructions to perform
             the extension.  */
@@ -3818,7 +3818,7 @@ emit_push_insn (rtx x, enum machine_mode mode, tree type, rtx size,
         by setting SKIP to 0.  */
       skip = (reg_parm_stack_space == 0) ? 0 : not_stack;
 
-      if (CONSTANT_P (x) && ! LEGITIMATE_CONSTANT_P (x))
+      if (CONSTANT_P (x) && !targetm.legitimate_constant_p (mode, x))
        x = validize_mem (force_const_mem (mode, x));
 
       /* If X is a hard register in a non-integer mode, copy it into a pseudo;
@@ -4050,8 +4050,7 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,
          binop = xor_optab;
        }
       value = expand_shift (LSHIFT_EXPR, str_mode, value,
-                           build_int_cst (NULL_TREE, bitpos),
-                           NULL_RTX, 1);
+                           bitpos, NULL_RTX, 1);
       result = expand_binop (str_mode, binop, str_rtx,
                             value, str_rtx, 1, OPTAB_WIDEN);
       if (result != str_rtx)
@@ -4085,8 +4084,7 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize,
                              NULL_RTX);
        }
       value = expand_shift (LSHIFT_EXPR, GET_MODE (str_rtx), value,
-                           build_int_cst (NULL_TREE, bitpos),
-                           NULL_RTX, 1);
+                           bitpos, NULL_RTX, 1);
       result = expand_binop (GET_MODE (str_rtx), binop, str_rtx,
                             value, str_rtx, 1, OPTAB_WIDEN);
       if (result != str_rtx)
@@ -4116,7 +4114,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
   /* Don't crash if the lhs of the assignment was erroneous.  */
   if (TREE_CODE (to) == ERROR_MARK)
     {
-      result = expand_normal (from);
+      expand_normal (from);
       return;
     }
 
@@ -4278,16 +4276,47 @@ expand_assignment (tree to, tree from, bool nontemporal)
       /* Handle expand_expr of a complex value returning a CONCAT.  */
       else if (GET_CODE (to_rtx) == CONCAT)
        {
-         if (COMPLEX_MODE_P (TYPE_MODE (TREE_TYPE (from))))
+         unsigned short mode_bitsize = GET_MODE_BITSIZE (GET_MODE (to_rtx));
+         if (COMPLEX_MODE_P (TYPE_MODE (TREE_TYPE (from)))
+             && bitpos == 0
+             && bitsize == mode_bitsize)
+           result = store_expr (from, to_rtx, false, nontemporal);
+         else if (bitsize == mode_bitsize / 2
+                  && (bitpos == 0 || bitpos == mode_bitsize / 2))
+           result = store_expr (from, XEXP (to_rtx, bitpos != 0), false,
+                                nontemporal);
+         else if (bitpos + bitsize <= mode_bitsize / 2)
+           result = store_field (XEXP (to_rtx, 0), bitsize, bitpos,
+                                 mode1, from, TREE_TYPE (tem),
+                                 get_alias_set (to), nontemporal);
+         else if (bitpos >= mode_bitsize / 2)
+           result = store_field (XEXP (to_rtx, 1), bitsize,
+                                 bitpos - mode_bitsize / 2, mode1, from,
+                                 TREE_TYPE (tem), get_alias_set (to),
+                                 nontemporal);
+         else if (bitpos == 0 && bitsize == mode_bitsize)
            {
-             gcc_assert (bitpos == 0);
-             result = store_expr (from, to_rtx, false, nontemporal);
+             rtx from_rtx;
+             result = expand_normal (from);
+             from_rtx = simplify_gen_subreg (GET_MODE (to_rtx), result,
+                                             TYPE_MODE (TREE_TYPE (from)), 0);
+             emit_move_insn (XEXP (to_rtx, 0),
+                             read_complex_part (from_rtx, false));
+             emit_move_insn (XEXP (to_rtx, 1),
+                             read_complex_part (from_rtx, true));
            }
          else
            {
-             gcc_assert (bitpos == 0 || bitpos == GET_MODE_BITSIZE (mode1));
-             result = store_expr (from, XEXP (to_rtx, bitpos != 0), false,
-                                  nontemporal);
+             rtx temp = assign_stack_temp (GET_MODE (to_rtx),
+                                           GET_MODE_SIZE (GET_MODE (to_rtx)),
+                                           0);
+             write_complex_part (temp, XEXP (to_rtx, 0), false);
+             write_complex_part (temp, XEXP (to_rtx, 1), true);
+             result = store_field (temp, bitsize, bitpos, mode1, from,
+                                   TREE_TYPE (tem), get_alias_set (to),
+                                   nontemporal);
+             emit_move_insn (XEXP (to_rtx, 0), read_complex_part (temp, false));
+             emit_move_insn (XEXP (to_rtx, 1), read_complex_part (temp, true));
            }
        }
       else
@@ -5636,7 +5665,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
                int n_elts_here = tree_low_cst
                  (int_const_binop (TRUNC_DIV_EXPR,
                                    TYPE_SIZE (TREE_TYPE (value)),
-                                   TYPE_SIZE (elttype), 0), 1);
+                                   TYPE_SIZE (elttype)), 1);
 
                count += n_elts_here;
                if (mostly_zeros_p (value))
@@ -5849,8 +5878,7 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
          && bitsize < (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (temp))
          && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
        temp = expand_shift (RSHIFT_EXPR, GET_MODE (temp), temp,
-                            size_int (GET_MODE_BITSIZE (GET_MODE (temp))
-                                      - bitsize),
+                            GET_MODE_BITSIZE (GET_MODE (temp)) - bitsize,
                             NULL_RTX, 1);
 
       /* Unless MODE is VOIDmode or BLKmode, convert TEMP to
@@ -7327,7 +7355,10 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
       else if (CONSTANT_P (op0))
        {
          tree inner_type = TREE_TYPE (treeop0);
-         enum machine_mode inner_mode = TYPE_MODE (inner_type);
+         enum machine_mode inner_mode = GET_MODE (op0);
+
+         if (inner_mode == VOIDmode)
+           inner_mode = TYPE_MODE (inner_type);
 
          if (modifier == EXPAND_INITIALIZER)
            op0 = simplify_gen_subreg (mode, op0, inner_mode,
@@ -8028,8 +8059,8 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
        target = 0;
       op0 = expand_expr (treeop0, subtarget,
                         VOIDmode, EXPAND_NORMAL);
-      temp = expand_shift (code, mode, op0, treeop1, target,
-                          unsignedp);
+      temp = expand_variable_shift (code, mode, op0, treeop1, target,
+                                   unsignedp);
       if (code == LSHIFT_EXPR)
        temp = REDUCE_BIT_FIELD (temp);
       return temp;
@@ -8074,7 +8105,10 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
       op1 = gen_label_rtx ();
       jumpifnot_1 (code, treeop0, treeop1, op1, -1);
 
-      emit_move_insn (target, const1_rtx);
+      if (TYPE_PRECISION (type) == 1 && !TYPE_UNSIGNED (type))
+       emit_move_insn (target, constm1_rtx);
+      else
+       emit_move_insn (target, const1_rtx);
 
       emit_label (op1);
       return target;
@@ -8162,7 +8196,6 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
     case VEC_UNPACK_LO_EXPR:
       {
        op0 = expand_normal (treeop0);
-       this_optab = optab_for_tree_code (code, type, optab_default);
        temp = expand_widen_pattern_expr (ops, op0, NULL_RTX, NULL_RTX,
                                          target, unsignedp);
        gcc_assert (temp);
@@ -8174,9 +8207,6 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
       {
        op0 = expand_normal (treeop0);
        /* The signedness is determined from input operand.  */
-       this_optab = optab_for_tree_code (code,
-                                         TREE_TYPE (treeop0),
-                                         optab_default);
        temp = expand_widen_pattern_expr
          (ops, op0, NULL_RTX, NULL_RTX,
           target, TYPE_UNSIGNED (TREE_TYPE (treeop0)));
@@ -8326,7 +8356,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        {
          temp = expand_expr (exp, NULL_RTX, VOIDmode, modifier);
          if (MEM_P (temp))
-           temp = copy_to_reg (temp);
+           copy_to_reg (temp);
          return const0_rtx;
        }
 
@@ -8422,18 +8452,11 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       gcc_assert (decl_rtl);
       decl_rtl = copy_rtx (decl_rtl);
       /* Record writes to register variables.  */
-      if (modifier == EXPAND_WRITE && REG_P (decl_rtl)
-         && REGNO (decl_rtl) < FIRST_PSEUDO_REGISTER)
-       {
-           int i = REGNO (decl_rtl);
-           int nregs = hard_regno_nregs[i][GET_MODE (decl_rtl)];
-           while (nregs)
-             {
-               SET_HARD_REG_BIT (crtl->asm_clobbers, i);
-               i++;
-               nregs--;
-             }
-       }
+      if (modifier == EXPAND_WRITE
+         && REG_P (decl_rtl)
+         && HARD_REGISTER_P (decl_rtl))
+        add_to_hard_reg_set (&crtl->asm_clobbers,
+                            GET_MODE (decl_rtl), REGNO (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
@@ -8503,10 +8526,12 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
          if (code == SSA_NAME
              && (g = SSA_NAME_DEF_STMT (ssa_name))
              && gimple_code (g) == GIMPLE_CALL)
-           pmode = promote_function_mode (type, mode, &unsignedp,
-                                          TREE_TYPE
-                                          (TREE_TYPE (gimple_call_fn (g))),
-                                          2);
+           {
+             gcc_assert (!gimple_call_internal_p (g));
+             pmode = promote_function_mode (type, mode, &unsignedp,
+                                            gimple_call_fntype (g),
+                                            2);
+           }
          else
            pmode = promote_decl_mode (exp, &unsignedp);
          gcc_assert (GET_MODE (decl_rtl) == pmode);
@@ -8953,9 +8978,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                      }
                    else
                      {
-                       tree count
-                         = build_int_cst (NULL_TREE,
-                                          GET_MODE_BITSIZE (imode) - bitsize);
+                       int count = GET_MODE_BITSIZE (imode) - bitsize;
 
                        op0 = expand_shift (LSHIFT_EXPR, imode, op0, count,
                                            target, 0);
@@ -9066,7 +9089,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
           constant and we don't need a memory reference.  */
        if (CONSTANT_P (op0)
            && mode2 != BLKmode
-           && LEGITIMATE_CONSTANT_P (op0)
+           && targetm.legitimate_constant_p (mode2, op0)
            && !must_force_mem)
          op0 = force_reg (mode2, op0);
 
@@ -9224,9 +9247,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
                && bitsize < (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (op0)))
              op0 = expand_shift (LSHIFT_EXPR, GET_MODE (op0), op0,
-                                 size_int (GET_MODE_BITSIZE (GET_MODE (op0))
-                                           - bitsize),
-                                 op0, 1);
+                                 GET_MODE_BITSIZE (GET_MODE (op0))
+                                 - bitsize, op0, 1);
 
            /* If the result type is BLKmode, store the data into a temporary
               of the appropriate type, but with the mode corresponding to the
@@ -9723,10 +9745,11 @@ reduce_to_bit_field_precision (rtx exp, rtx target, tree type)
     }
   else
     {
-      tree count = build_int_cst (NULL_TREE,
-                                 GET_MODE_BITSIZE (GET_MODE (exp)) - prec);
-      exp = expand_shift (LSHIFT_EXPR, GET_MODE (exp), exp, count, target, 0);
-      return expand_shift (RSHIFT_EXPR, GET_MODE (exp), exp, count, target, 0);
+      int count = GET_MODE_BITSIZE (GET_MODE (exp)) - prec;
+      exp = expand_shift (LSHIFT_EXPR, GET_MODE (exp),
+                         exp, count, target, 0);
+      return expand_shift (RSHIFT_EXPR, GET_MODE (exp),
+                          exp, count, target, 0);
     }
 }
 \f
@@ -10030,7 +10053,8 @@ do_store_flag (sepops ops, rtx target, enum machine_mode mode)
 
   if ((code == NE || code == EQ)
       && TREE_CODE (arg0) == BIT_AND_EXPR && integer_zerop (arg1)
-      && integer_pow2p (TREE_OPERAND (arg0, 1)))
+      && integer_pow2p (TREE_OPERAND (arg0, 1))
+      && (TYPE_PRECISION (ops->type) != 1 || TYPE_UNSIGNED (ops->type)))
     {
       tree type = lang_hooks.types.type_for_mode (mode, unsignedp);
       return expand_expr (fold_single_bit_test (loc,
@@ -10050,7 +10074,9 @@ do_store_flag (sepops ops, rtx target, enum machine_mode mode)
 
   /* Try a cstore if possible.  */
   return emit_store_flag_force (target, code, op0, op1,
-                               operand_mode, unsignedp, 1);
+                               operand_mode, unsignedp,
+                               (TYPE_PRECISION (ops->type) == 1
+                                && !TYPE_UNSIGNED (ops->type)) ? -1 : 1);
 }
 \f