OSDN Git Service

2010-04-22 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / expr.c
index 923db8f..2547511 100644 (file)
@@ -1,6 +1,6 @@
 /* Convert tree expression to rtl instructions, for GNU compiler.
    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -774,18 +774,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.  */
-         val &= ((HOST_WIDE_INT) 1 << width) - 1;
-       }
+      /* We need to zero extend VAL.  */
+      if (oldmode != VOIDmode)
+       val = double_int_zext (val, GET_MODE_BITSIZE (oldmode));
 
-      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
@@ -1194,6 +1189,7 @@ emit_block_move_hints (rtx x, rtx y, rtx size, enum block_op_methods method,
     }
 
   align = MIN (MEM_ALIGN (x), MEM_ALIGN (y));
+  gcc_assert (align >= BITS_PER_UNIT);
 
   gcc_assert (MEM_P (x));
   gcc_assert (MEM_P (y));
@@ -1261,6 +1257,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;
@@ -2311,7 +2310,7 @@ can_store_by_pieces (unsigned HOST_WIDE_INT len,
   if (len == 0)
     return 1;
 
-  if (! (memsetp 
+  if (! (memsetp
         ? SET_BY_PIECES_P (len, align)
         : STORE_BY_PIECES_P (len, align)))
     return 0;
@@ -4431,9 +4430,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)
     {
@@ -4511,7 +4512,7 @@ emit_storent_insn (rtx to, rtx from)
 
    If CALL_PARAM_P is nonzero, this is a store into a call param on the
    stack, and block moves may need to be treated specially.
+
    If NONTEMPORAL is true, try using a nontemporal store instruction.  */
 
 rtx
@@ -4550,7 +4551,7 @@ store_expr (tree exp, rtx target, int call_param_p, bool nontemporal)
 
       do_pending_stack_adjust ();
       NO_DEFER_POP;
-      jumpifnot (TREE_OPERAND (exp, 0), lab1);
+      jumpifnot (TREE_OPERAND (exp, 0), lab1, -1);
       store_expr (TREE_OPERAND (exp, 1), target, call_param_p,
                  nontemporal);
       emit_jump_insn (gen_jump (lab2));
@@ -4855,9 +4856,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);
@@ -4919,12 +4919,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;
        }
     }
@@ -5546,7 +5551,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
                    /* Generate a conditional jump to exit the loop.  */
                    exit_cond = build2 (LT_EXPR, integer_type_node,
                                        index, hi_index);
-                   jumpif (exit_cond, loop_end);
+                   jumpif (exit_cond, loop_end, -1);
 
                    /* Update the loop counter, and jump to the head of
                       the loop.  */
@@ -5753,7 +5758,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
    ALIAS_SET is the alias set for the destination.  This value will
    (in general) be different from that for TARGET, since TARGET is a
    reference to the containing structure.
-   
+
    If NONTEMPORAL is true, try generating a nontemporal store.  */
 
 static rtx
@@ -5967,6 +5972,7 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
 
   /* First get the mode, signedness, and size.  We do this from just the
      outermost expression.  */
+  *pbitsize = -1;
   if (TREE_CODE (exp) == COMPONENT_REF)
     {
       tree field = TREE_OPERAND (exp, 1);
@@ -6143,7 +6149,7 @@ contains_packed_reference (const_tree exp)
        case COMPONENT_REF:
          {
            tree field = TREE_OPERAND (exp, 1);
-           packed_p = DECL_PACKED (field) 
+           packed_p = DECL_PACKED (field)
                       || TYPE_PACKED (TREE_TYPE (field))
                       || TYPE_PACKED (TREE_TYPE (exp));
            if (packed_p)
@@ -6750,7 +6756,7 @@ highest_pow2_factor_for_target (const_tree target, const_tree exp)
 {
   unsigned HOST_WIDE_INT talign = target_align (target) / BITS_PER_UNIT;
   unsigned HOST_WIDE_INT factor = highest_pow2_factor (exp);
-  
+
   return MAX (factor, talign);
 }
 \f
@@ -6840,9 +6846,8 @@ expand_expr_addr_expr_1 (tree exp, rtx target, enum machine_mode tmode,
       return expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
 
     case CONST_DECL:
-      /* Recurse and make the output_constant_def clause above handle this.  */
-      return expand_expr_addr_expr_1 (DECL_INITIAL (exp), target,
-                                     tmode, modifier, as);
+      /* Expand the initializer like constants above.  */
+      return XEXP (expand_expr_constant (DECL_INITIAL (exp), 0, modifier), 0);
 
     case REALPART_EXPR:
       /* The real part of the complex number is always first, therefore
@@ -6940,7 +6945,7 @@ expand_expr_addr_expr_1 (tree exp, rtx target, enum machine_mode tmode,
 
       if (modifier != EXPAND_NORMAL)
        result = force_operand (result, NULL);
-      tmp = expand_expr (offset, NULL_RTX, tmode, 
+      tmp = expand_expr (offset, NULL_RTX, tmode,
                         modifier == EXPAND_INITIALIZER
                          ? EXPAND_INITIALIZER : EXPAND_NORMAL);
 
@@ -7173,6 +7178,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);
 
@@ -7182,6 +7189,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
     {
@@ -7390,9 +7399,9 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
        return CONST0_RTX (mode);
       }
 
-    case POINTER_PLUS_EXPR: 
+    case POINTER_PLUS_EXPR:
       /* Even though the sizetype mode and the pointer's mode can be different
-         expand is able to handle this correctly and get the correct result out 
+         expand is able to handle this correctly and get the correct result out
          of the PLUS_EXPR code.  */
       /* Make sure to sign-extend the sizetype offset in a POINTER_PLUS_EXPR
          if sizetype precision is smaller than pointer precision.  */
@@ -8012,7 +8021,8 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
 
        temp = gen_label_rtx ();
        do_compare_rtx_and_jump (target, cmpop1, comparison_code,
-                                unsignedp, mode, NULL_RTX, NULL_RTX, temp);
+                                unsignedp, mode, NULL_RTX, NULL_RTX, temp,
+                                -1);
       }
       emit_move_insn (target, op1);
       emit_label (temp);
@@ -8120,7 +8130,7 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
       emit_move_insn (target, const0_rtx);
 
       op1 = gen_label_rtx ();
-      jumpifnot_1 (code, treeop0, treeop1, op1);
+      jumpifnot_1 (code, treeop0, treeop1, op1, -1);
 
       emit_move_insn (target, const1_rtx);
 
@@ -8405,8 +8415,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);
@@ -8722,6 +8732,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);
@@ -8729,6 +8740,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;
 
@@ -9330,7 +9351,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       /* 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))
-       op0 = convert_modes (mode, GET_MODE (op0), op0, 
+       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
         different mode.  */
@@ -9417,7 +9438,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        emit_move_insn (target, const0_rtx);
 
       op1 = gen_label_rtx ();
-      jumpifnot_1 (code, treeop0, treeop1, op1);
+      jumpifnot_1 (code, treeop0, treeop1, op1, -1);
 
       if (target)
        emit_move_insn (target, const1_rtx);
@@ -9474,7 +9495,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        NO_DEFER_POP;
        op0 = gen_label_rtx ();
        op1 = gen_label_rtx ();
-       jumpifnot (treeop0, op0);
+       jumpifnot (treeop0, op0, -1);
        store_expr (treeop1, temp,
                  modifier == EXPAND_STACK_PARM,
                  false);
@@ -9520,7 +9541,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
            int value = TREE_CODE (rhs) == BIT_IOR_EXPR;
            do_jump (TREE_OPERAND (rhs, 1),
                     value ? label : 0,
-                    value ? 0 : label);
+                    value ? 0 : label, -1);
            expand_assignment (lhs, build_int_cst (TREE_TYPE (rhs), value),
                               MOVE_NONTEMPORAL (exp));
            do_pending_stack_adjust ();
@@ -9660,15 +9681,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
@@ -10254,9 +10268,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.  */