OSDN Git Service

PR middle-end/44337
[pf3gnuchains/gcc-fork.git] / gcc / expr.c
index cd013b0..6b2feb6 100644 (file)
@@ -24,7 +24,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "machmode.h"
-#include "real.h"
 #include "rtl.h"
 #include "tree.h"
 #include "flags.h"
@@ -43,7 +42,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "output.h"
 #include "typeclass.h"
 #include "toplev.h"
-#include "ggc.h"
 #include "langhooks.h"
 #include "intl.h"
 #include "tm_p.h"
@@ -774,18 +772,13 @@ convert_modes (enum machine_mode mode, enum machine_mode oldmode, rtx x, int uns
       && GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_WIDE_INT
       && CONST_INT_P (x) && INTVAL (x) < 0)
     {
-      HOST_WIDE_INT val = INTVAL (x);
+      double_int val = uhwi_to_double_int (INTVAL (x));
 
-      if (oldmode != VOIDmode
-         && HOST_BITS_PER_WIDE_INT > GET_MODE_BITSIZE (oldmode))
-       {
-         int width = GET_MODE_BITSIZE (oldmode);
+      /* We need to zero extend VAL.  */
+      if (oldmode != VOIDmode)
+       val = double_int_zext (val, GET_MODE_BITSIZE (oldmode));
 
-         /* We need to zero extend VAL.  */
-         val &= ((HOST_WIDE_INT) 1 << width) - 1;
-       }
-
-      return immed_double_const (val, (HOST_WIDE_INT) 0, mode);
+      return immed_double_int_const (val, mode);
     }
 
   /* We can do this with a gen_lowpart if both desired and current modes
@@ -1262,6 +1255,9 @@ block_move_libcall_safe_for_call_parm (void)
      an outgoing argument.  */
 #if defined (REG_PARM_STACK_SPACE)
   fn = emit_block_move_libcall_fn (false);
+  /* Avoid set but not used warning if *REG_PARM_STACK_SPACE doesn't
+     depend on its argument.  */
+  (void) fn;
   if (OUTGOING_REG_PARM_STACK_SPACE ((!fn ? NULL_TREE : TREE_TYPE (fn)))
       && REG_PARM_STACK_SPACE (fn) != 0)
     return false;
@@ -4272,8 +4268,19 @@ expand_assignment (tree to, tree from, bool nontemporal)
                                                                   offset));
        }
 
+      /* No action is needed if the target is not a memory and the field
+        lies completely outside that target.  This can occur if the source
+        code contains an out-of-bounds access to a small array.  */
+      if (!MEM_P (to_rtx)
+         && GET_MODE (to_rtx) != BLKmode
+         && (unsigned HOST_WIDE_INT) bitpos
+            >= GET_MODE_BITSIZE (GET_MODE (to_rtx)))
+       {
+         expand_normal (from);
+         result = NULL;
+       }
       /* Handle expand_expr of a complex value returning a CONCAT.  */
-      if (GET_CODE (to_rtx) == CONCAT)
+      else if (GET_CODE (to_rtx) == CONCAT)
        {
          if (COMPLEX_MODE_P (TYPE_MODE (TREE_TYPE (from))))
            {
@@ -4432,9 +4439,11 @@ expand_assignment (tree to, tree from, bool nontemporal)
   /* In case we are returning the contents of an object which overlaps
      the place the value is being stored, use a safe function when copying
      a value through a pointer into a structure value return block.  */
-  if (TREE_CODE (to) == RESULT_DECL && TREE_CODE (from) == INDIRECT_REF
+  if (TREE_CODE (to) == RESULT_DECL
+      && TREE_CODE (from) == INDIRECT_REF
       && ADDR_SPACE_GENERIC_P
-         (TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (from, 0)))))
+          (TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (from, 0)))))
+      && refs_may_alias_p (to, from)
       && cfun->returns_struct
       && !cfun->returns_pcc_struct)
     {
@@ -4856,9 +4865,8 @@ categorize_ctor_elements_1 (const_tree ctor, HOST_WIDE_INT *p_nz_elts,
 
   FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), idx, purpose, value)
     {
-      HOST_WIDE_INT mult;
+      HOST_WIDE_INT mult = 1;
 
-      mult = 1;
       if (TREE_CODE (purpose) == RANGE_EXPR)
        {
          tree lo_index = TREE_OPERAND (purpose, 0);
@@ -4920,12 +4928,17 @@ categorize_ctor_elements_1 (const_tree ctor, HOST_WIDE_INT *p_nz_elts,
          break;
 
        default:
-         nz_elts += mult;
-         elt_count += mult;
+         {
+           HOST_WIDE_INT tc = count_type_elements (TREE_TYPE (value), true);
+           if (tc < 1)
+             tc = 1;
+           nz_elts += mult * tc;
+           elt_count += mult * tc;
 
-         if (const_from_elts_p && const_p)
-           const_p = initializer_constant_valid_p (value, TREE_TYPE (value))
-                     != NULL_TREE;
+           if (const_from_elts_p && const_p)
+             const_p = initializer_constant_valid_p (value, TREE_TYPE (value))
+                       != NULL_TREE;
+         }
          break;
        }
     }
@@ -7174,6 +7187,8 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode,
   if (cfun && EXPR_HAS_LOCATION (exp))
     {
       location_t saved_location = input_location;
+      location_t saved_curr_loc = get_curr_insn_source_location ();
+      tree saved_block = get_curr_insn_block ();
       input_location = EXPR_LOCATION (exp);
       set_curr_insn_source_location (input_location);
 
@@ -7183,6 +7198,8 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode,
       ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl);
 
       input_location = saved_location;
+      set_curr_insn_block (saved_block);
+      set_curr_insn_source_location (saved_curr_loc);
     }
   else
     {
@@ -7204,7 +7221,6 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
   optab this_optab;
   rtx subtarget, original_target;
   int ignore;
-  tree subexp0, subexp1;
   bool reduce_bit_field;
   gimple subexp0_def, subexp1_def;
   tree top0, top1;
@@ -7659,13 +7675,7 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
 
       goto binop2;
 
-    case MULT_EXPR:
-      /* If this is a fixed-point operation, then we cannot use the code
-        below because "expand_mult" doesn't support sat/no-sat fixed-point
-         multiplications.   */
-      if (ALL_FIXED_POINT_MODE_P (mode))
-       goto binop;
-
+    case WIDEN_MULT_EXPR:
       /* If first operand is constant, swap them.
         Thus the following special case checks need only
         check the second operand.  */
@@ -7676,96 +7686,35 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
          treeop1 = t1;
        }
 
-      /* Attempt to return something suitable for generating an
-        indexed address, for machines that support that.  */
-
-      if (modifier == EXPAND_SUM && mode == ptr_mode
-         && host_integerp (treeop1, 0))
-       {
-         tree exp1 = treeop1;
-
-         op0 = expand_expr (treeop0, subtarget, VOIDmode,
-                            EXPAND_SUM);
-
-         if (!REG_P (op0))
-           op0 = force_operand (op0, NULL_RTX);
-         if (!REG_P (op0))
-           op0 = copy_to_mode_reg (mode, op0);
-
-         return REDUCE_BIT_FIELD (gen_rtx_MULT (mode, op0,
-                              gen_int_mode (tree_low_cst (exp1, 0),
-                                            TYPE_MODE (TREE_TYPE (exp1)))));
-       }
-
-      if (modifier == EXPAND_STACK_PARM)
-       target = 0;
-
-      /* Check for multiplying things that have been extended
-        from a narrower type.  If this machine supports multiplying
-        in that narrower type with a result in the desired type,
-        do it that way, and avoid the explicit type-conversion.  */
-
-      subexp0 = treeop0;
-      subexp1 = treeop1;
-      subexp0_def = get_def_for_expr (subexp0, NOP_EXPR);
-      subexp1_def = get_def_for_expr (subexp1, NOP_EXPR);
-      top0 = top1 = NULL_TREE;
-
       /* First, check if we have a multiplication of one signed and one
         unsigned operand.  */
-      if (subexp0_def
-         && (top0 = gimple_assign_rhs1 (subexp0_def))
-         && subexp1_def
-         && (top1 = gimple_assign_rhs1 (subexp1_def))
-         && TREE_CODE (type) == INTEGER_TYPE
-         && (TYPE_PRECISION (TREE_TYPE (top0))
-             < TYPE_PRECISION (TREE_TYPE (subexp0)))
-         && (TYPE_PRECISION (TREE_TYPE (top0))
-             == TYPE_PRECISION (TREE_TYPE (top1)))
-         && (TYPE_UNSIGNED (TREE_TYPE (top0))
-             != TYPE_UNSIGNED (TREE_TYPE (top1))))
-       {
-         enum machine_mode innermode
-           = TYPE_MODE (TREE_TYPE (top0));
+      if (TREE_CODE (treeop1) != INTEGER_CST
+         && (TYPE_UNSIGNED (TREE_TYPE (treeop0))
+             != TYPE_UNSIGNED (TREE_TYPE (treeop1))))
+       {
+         enum machine_mode innermode = TYPE_MODE (TREE_TYPE (treeop0));
          this_optab = usmul_widen_optab;
-         if (mode == GET_MODE_WIDER_MODE (innermode))
+         if (mode == GET_MODE_2XWIDER_MODE (innermode))
            {
              if (optab_handler (this_optab, mode)->insn_code != CODE_FOR_nothing)
                {
-                 if (TYPE_UNSIGNED (TREE_TYPE (top0)))
-                   expand_operands (top0, top1, NULL_RTX, &op0, &op1,
+                 if (TYPE_UNSIGNED (TREE_TYPE (treeop0)))
+                   expand_operands (treeop0, treeop1, subtarget, &op0, &op1,
                                     EXPAND_NORMAL);
                  else
-                   expand_operands (top0, top1, NULL_RTX, &op1, &op0,
+                   expand_operands (treeop0, treeop1, subtarget, &op1, &op0,
                                     EXPAND_NORMAL);
-
                  goto binop3;
                }
            }
        }
-      /* Check for a multiplication with matching signedness.  If
-        valid, TOP0 and TOP1 were set in the previous if
-        condition.  */
-      else if (top0
-         && TREE_CODE (type) == INTEGER_TYPE
-         && (TYPE_PRECISION (TREE_TYPE (top0))
-             < TYPE_PRECISION (TREE_TYPE (subexp0)))
-         && ((TREE_CODE (subexp1) == INTEGER_CST
-              && int_fits_type_p (subexp1, TREE_TYPE (top0))
-              /* Don't use a widening multiply if a shift will do.  */
-              && ((GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (subexp1)))
-                   > HOST_BITS_PER_WIDE_INT)
-                  || exact_log2 (TREE_INT_CST_LOW (subexp1)) < 0))
-             ||
-             (top1
-              && (TYPE_PRECISION (TREE_TYPE (top1))
-                  == TYPE_PRECISION (TREE_TYPE (top0))
-              /* If both operands are extended, they must either both
-                 be zero-extended or both be sign-extended.  */
-              && (TYPE_UNSIGNED (TREE_TYPE (top1))
-                  == TYPE_UNSIGNED (TREE_TYPE (top0)))))))
-       {
-         tree op0type = TREE_TYPE (top0);
+      /* Check for a multiplication with matching signedness.  */
+      else if ((TREE_CODE (treeop1) == INTEGER_CST
+               && int_fits_type_p (treeop1, TREE_TYPE (treeop0)))
+              || (TYPE_UNSIGNED (TREE_TYPE (treeop1))
+                  == TYPE_UNSIGNED (TREE_TYPE (treeop0))))
+       {
+         tree op0type = TREE_TYPE (treeop0);
          enum machine_mode innermode = TYPE_MODE (op0type);
          bool zextend_p = TYPE_UNSIGNED (op0type);
          optab other_optab = zextend_p ? smul_widen_optab : umul_widen_optab;
@@ -7775,24 +7724,22 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
            {
              if (optab_handler (this_optab, mode)->insn_code != CODE_FOR_nothing)
                {
-                 if (TREE_CODE (subexp1) == INTEGER_CST)
-                   expand_operands (top0, subexp1, NULL_RTX, &op0, &op1,
-                                    EXPAND_NORMAL);
-                 else
-                   expand_operands (top0, top1, NULL_RTX, &op0, &op1,
-                                    EXPAND_NORMAL);
-                 goto binop3;
+                 expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1,
+                                  EXPAND_NORMAL);
+                 temp = expand_widening_mult (mode, op0, op1, target,
+                                              unsignedp, this_optab);
+                 return REDUCE_BIT_FIELD (temp);
                }
-             else if (optab_handler (other_optab, mode)->insn_code != CODE_FOR_nothing
-                      && innermode == word_mode)
+             if (optab_handler (other_optab, mode)->insn_code != CODE_FOR_nothing
+                 && innermode == word_mode)
                {
                  rtx htem, hipart;
-                 op0 = expand_normal (top0);
-                 if (TREE_CODE (subexp1) == INTEGER_CST)
+                 op0 = expand_normal (treeop0);
+                 if (TREE_CODE (treeop1) == INTEGER_CST)
                    op1 = convert_modes (innermode, mode,
-                                        expand_normal (subexp1), unsignedp);
+                                        expand_normal (treeop1), unsignedp);
                  else
-                   op1 = expand_normal (top1);
+                   op1 = expand_normal (treeop1);
                  temp = expand_binop (mode, other_optab, op0, op1, target,
                                       unsignedp, OPTAB_LIB_WIDEN);
                  hipart = gen_highpart (innermode, temp);
@@ -7805,7 +7752,53 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
                }
            }
        }
-      expand_operands (subexp0, subexp1, subtarget, &op0, &op1, EXPAND_NORMAL);
+      treeop0 = fold_build1 (CONVERT_EXPR, type, treeop0);
+      treeop1 = fold_build1 (CONVERT_EXPR, type, treeop1);
+      expand_operands (treeop0, treeop1, subtarget, &op0, &op1, EXPAND_NORMAL);
+      return REDUCE_BIT_FIELD (expand_mult (mode, op0, op1, target, unsignedp));
+
+    case MULT_EXPR:
+      /* If this is a fixed-point operation, then we cannot use the code
+        below because "expand_mult" doesn't support sat/no-sat fixed-point
+         multiplications.   */
+      if (ALL_FIXED_POINT_MODE_P (mode))
+       goto binop;
+
+      /* If first operand is constant, swap them.
+        Thus the following special case checks need only
+        check the second operand.  */
+      if (TREE_CODE (treeop0) == INTEGER_CST)
+       {
+         tree t1 = treeop0;
+         treeop0 = treeop1;
+         treeop1 = t1;
+       }
+
+      /* Attempt to return something suitable for generating an
+        indexed address, for machines that support that.  */
+
+      if (modifier == EXPAND_SUM && mode == ptr_mode
+         && host_integerp (treeop1, 0))
+       {
+         tree exp1 = treeop1;
+
+         op0 = expand_expr (treeop0, subtarget, VOIDmode,
+                            EXPAND_SUM);
+
+         if (!REG_P (op0))
+           op0 = force_operand (op0, NULL_RTX);
+         if (!REG_P (op0))
+           op0 = copy_to_mode_reg (mode, op0);
+
+         return REDUCE_BIT_FIELD (gen_rtx_MULT (mode, op0,
+                              gen_int_mode (tree_low_cst (exp1, 0),
+                                            TYPE_MODE (TREE_TYPE (exp1)))));
+       }
+
+      if (modifier == EXPAND_STACK_PARM)
+       target = 0;
+
+      expand_operands (treeop0, treeop1, subtarget, &op0, &op1, EXPAND_NORMAL);
       return REDUCE_BIT_FIELD (expand_mult (mode, op0, op1, target, unsignedp));
 
     case TRUNC_DIV_EXPR:
@@ -8407,8 +8400,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       {
        gimple g = get_gimple_for_ssa_name (exp);
        if (g)
-         return expand_expr_real_1 (gimple_assign_rhs_to_tree (g), target,
-                                    tmode, modifier, NULL);
+         return expand_expr_real (gimple_assign_rhs_to_tree (g), target,
+                                  tmode, modifier, NULL);
       }
       decl_rtl = get_rtx_for_ssa_name (exp);
       exp = SSA_NAME_VAR (exp);
@@ -8441,6 +8434,19 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
     expand_decl_rtl:
       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--;
+             }
+       }
 
       /* 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
@@ -8724,6 +8730,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       {
        addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (exp));
        struct mem_address addr;
+       tree base;
 
        get_address_description (exp, &addr);
        op0 = addr_for_mem_ref (&addr, as, true);
@@ -8731,6 +8738,16 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        temp = gen_rtx_MEM (mode, op0);
        set_mem_attributes (temp, TMR_ORIGINAL (exp), 0);
        set_mem_addr_space (temp, as);
+       base = get_base_address (TMR_ORIGINAL (exp));
+       if (INDIRECT_REF_P (base)
+           && TMR_BASE (exp)
+           && TREE_CODE (TMR_BASE (exp)) == SSA_NAME
+           && POINTER_TYPE_P (TREE_TYPE (TMR_BASE (exp))))
+         {
+           set_mem_expr (temp, build1 (INDIRECT_REF,
+                                       TREE_TYPE (exp), TMR_BASE (exp)));
+           set_mem_offset (temp, NULL_RTX);
+         }
       }
       return temp;
 
@@ -9329,9 +9346,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
            op0 = force_reg (GET_MODE (op0), op0);
          op0 = gen_lowpart (mode, op0);
        }
-      /* If both modes are integral, then we can convert from one to the
-        other.  */
-      else if (SCALAR_INT_MODE_P (GET_MODE (op0)) && SCALAR_INT_MODE_P (mode))
+      /* If both types are integral, convert from one mode to the other.  */
+      else if (INTEGRAL_TYPE_P (type) && INTEGRAL_TYPE_P (TREE_TYPE (treeop0)))
        op0 = convert_modes (mode, GET_MODE (op0), op0,
                             TYPE_UNSIGNED (TREE_TYPE (treeop0)));
       /* As a last resort, spill op0 to memory, and reload it in a
@@ -9662,15 +9678,8 @@ reduce_to_bit_field_precision (rtx exp, rtx target, tree type)
     }
   else if (TYPE_UNSIGNED (type))
     {
-      rtx mask;
-      if (prec < HOST_BITS_PER_WIDE_INT)
-       mask = immed_double_const (((unsigned HOST_WIDE_INT) 1 << prec) - 1, 0,
-                                  GET_MODE (exp));
-      else
-       mask = immed_double_const ((unsigned HOST_WIDE_INT) -1,
-                                  ((unsigned HOST_WIDE_INT) 1
-                                   << (prec - HOST_BITS_PER_WIDE_INT)) - 1,
-                                  GET_MODE (exp));
+      rtx mask = immed_double_int_const (double_int_mask (prec),
+                                        GET_MODE (exp));
       return expand_and (GET_MODE (exp), exp, mask, target);
     }
   else
@@ -10256,9 +10265,8 @@ const_vector_from_tree (tree exp)
        RTVEC_ELT (v, i) = CONST_FIXED_FROM_FIXED_VALUE (TREE_FIXED_CST (elt),
                                                         inner);
       else
-       RTVEC_ELT (v, i) = immed_double_const (TREE_INT_CST_LOW (elt),
-                                              TREE_INT_CST_HIGH (elt),
-                                              inner);
+       RTVEC_ELT (v, i) = immed_double_int_const (tree_to_double_int (elt),
+                                                  inner);
     }
 
   /* Initialize remaining elements to 0.  */