OSDN Git Service

gcc/
[pf3gnuchains/gcc-fork.git] / gcc / cfgexpand.c
index bff4897..3e9ecbf 100644 (file)
@@ -36,6 +36,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "except.h"
 #include "flags.h"
 #include "diagnostic.h"
+#include "tree-pretty-print.h"
+#include "gimple-pretty-print.h"
 #include "toplev.h"
 #include "debug.h"
 #include "params.h"
@@ -43,7 +45,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "value-prof.h"
 #include "target.h"
 #include "ssaexpand.h"
-
+#include "bitmap.h"
+#include "sbitmap.h"
+#include "insn-attr.h" /* For INSN_SCHEDULING.  */
 
 /* This variable holds information helping the rewriting of SSA trees
    into RTL.  */
@@ -64,7 +68,13 @@ gimple_assign_rhs_to_tree (gimple stmt)
 
   grhs_class = get_gimple_rhs_class (gimple_expr_code (stmt));
 
-  if (grhs_class == GIMPLE_BINARY_RHS)
+  if (grhs_class == GIMPLE_TERNARY_RHS)
+    t = build3 (gimple_assign_rhs_code (stmt),
+               TREE_TYPE (gimple_assign_lhs (stmt)),
+               gimple_assign_rhs1 (stmt),
+               gimple_assign_rhs2 (stmt),
+               gimple_assign_rhs3 (stmt));
+  else if (grhs_class == GIMPLE_BINARY_RHS)
     t = build2 (gimple_assign_rhs_code (stmt),
                TREE_TYPE (gimple_assign_lhs (stmt)),
                gimple_assign_rhs1 (stmt),
@@ -500,12 +510,12 @@ update_alias_info_with_stack_vars (void)
       for (j = i; j != EOC; j = stack_vars[j].next)
        {
          tree decl = stack_vars[j].decl;
-         unsigned int uid = DECL_UID (decl);
+         unsigned int uid = DECL_PT_UID (decl);
          /* We should never end up partitioning SSA names (though they
             may end up on the stack).  Neither should we allocate stack
             space to something that is unused and thus unreferenced.  */
          gcc_assert (DECL_P (decl)
-                     && referenced_var_lookup (uid));
+                     && referenced_var_lookup (DECL_UID (decl)));
          bitmap_set_bit (part, uid);
          *((bitmap *) pointer_map_insert (decls_to_partitions,
                                           (void *)(size_t) uid)) = part;
@@ -515,7 +525,7 @@ update_alias_info_with_stack_vars (void)
 
       /* Make the SSA name point to all partition members.  */
       pi = get_ptr_info (name);
-      pt_solution_set (&pi->pt, part);
+      pt_solution_set (&pi->pt, part, false, false);
     }
 
   /* Make all points-to sets that contain one member of a partition
@@ -540,8 +550,6 @@ update_alias_info_with_stack_vars (void)
 
       add_partitioned_vars_to_ptset (&cfun->gimple_df->escaped,
                                     decls_to_partitions, visited, temp);
-      add_partitioned_vars_to_ptset (&cfun->gimple_df->callused,
-                                    decls_to_partitions, visited, temp);
 
       pointer_set_destroy (visited);
       pointer_map_destroy (decls_to_partitions);
@@ -1887,6 +1895,9 @@ expand_gimple_stmt_1 (gimple stmt)
            ops.type = TREE_TYPE (lhs);
            switch (get_gimple_rhs_class (gimple_expr_code (stmt)))
              {
+               case GIMPLE_TERNARY_RHS:
+                 ops.op2 = gimple_assign_rhs3 (stmt);
+                 /* Fallthru */
                case GIMPLE_BINARY_RHS:
                  ops.op1 = gimple_assign_rhs2 (stmt);
                  /* Fallthru */
@@ -2228,7 +2239,6 @@ expand_debug_expr (tree exp)
   enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
   int unsignedp = TYPE_UNSIGNED (TREE_TYPE (exp));
   addr_space_t as;
-  enum machine_mode address_mode;
 
   switch (TREE_CODE_CLASS (TREE_CODE (exp)))
     {
@@ -2237,6 +2247,8 @@ expand_debug_expr (tree exp)
        {
        case COND_EXPR:
        case DOT_PROD_EXPR:
+       case WIDEN_MULT_PLUS_EXPR:
+       case WIDEN_MULT_MINUS_EXPR:
          goto ternary;
 
        case TRUTH_ANDIF_EXPR:
@@ -2425,29 +2437,21 @@ expand_debug_expr (tree exp)
        return op0;
       }
 
+    case MEM_REF:
+      /* ??? FIXME.  */
+      if (!integer_zerop (TREE_OPERAND (exp, 1)))
+       return NULL;
+      /* Fallthru.  */
     case INDIRECT_REF:
-    case ALIGN_INDIRECT_REF:
     case MISALIGNED_INDIRECT_REF:
       op0 = expand_debug_expr (TREE_OPERAND (exp, 0));
       if (!op0)
        return NULL;
 
       if (POINTER_TYPE_P (TREE_TYPE (exp)))
-       {
-         as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp)));
-         address_mode = targetm.addr_space.address_mode (as);
-       }
+       as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp)));
       else
-       {
-         as = ADDR_SPACE_GENERIC;
-         address_mode = Pmode;
-       }
-
-      if (TREE_CODE (exp) == ALIGN_INDIRECT_REF)
-       {
-         int align = TYPE_ALIGN_UNIT (TREE_TYPE (exp));
-         op0 = gen_rtx_AND (address_mode, op0, GEN_INT (-align));
-       }
+       as = ADDR_SPACE_GENERIC;
 
       op0 = gen_rtx_MEM (mode, op0);
 
@@ -2563,13 +2567,14 @@ expand_debug_expr (tree exp)
         if (bitpos < 0)
           return NULL;
 
+       if (GET_MODE (op0) == BLKmode)
+         return NULL;
+
        if ((bitpos % BITS_PER_UNIT) == 0
            && bitsize == GET_MODE_BITSIZE (mode1))
          {
            enum machine_mode opmode = GET_MODE (op0);
 
-           gcc_assert (opmode != BLKmode);
-
            if (opmode == VOIDmode)
              opmode = mode1;
 
@@ -2618,6 +2623,22 @@ expand_debug_expr (tree exp)
        return gen_rtx_FIX (mode, op0);
 
     case POINTER_PLUS_EXPR:
+      /* For the rare target where pointers are not the same size as
+        size_t, we need to check for mis-matched modes and correct
+        the addend.  */
+      if (op0 && op1
+         && GET_MODE (op0) != VOIDmode && GET_MODE (op1) != VOIDmode
+         && GET_MODE (op0) != GET_MODE (op1))
+       {
+         if (GET_MODE_BITSIZE (GET_MODE (op0)) < GET_MODE_BITSIZE (GET_MODE (op1)))
+           op1 = gen_rtx_TRUNCATE (GET_MODE (op0), op1);
+         else
+           /* We always sign-extend, regardless of the signedness of
+              the operand, because the operand is always unsigned
+              here even if the original C expression is signed.  */
+           op1 = gen_rtx_SIGN_EXTEND (GET_MODE (op0), op1);
+       }
+      /* Fall through.  */
     case PLUS_EXPR:
       return gen_rtx_PLUS (mode, op0, op1);
 
@@ -3006,18 +3027,27 @@ expand_debug_expr (tree exp)
       return NULL;
 
     case WIDEN_MULT_EXPR:
+    case WIDEN_MULT_PLUS_EXPR:
+    case WIDEN_MULT_MINUS_EXPR:
       if (SCALAR_INT_MODE_P (GET_MODE (op0))
          && SCALAR_INT_MODE_P (mode))
        {
+         enum machine_mode inner_mode = GET_MODE (op0);
          if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))))
-           op0 = gen_rtx_ZERO_EXTEND (mode, op0);
+           op0 = simplify_gen_unary (ZERO_EXTEND, mode, op0, inner_mode);
          else
-           op0 = gen_rtx_SIGN_EXTEND (mode, op0);
+           op0 = simplify_gen_unary (SIGN_EXTEND, mode, op0, inner_mode);
          if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1))))
-           op1 = gen_rtx_ZERO_EXTEND (mode, op1);
+           op1 = simplify_gen_unary (ZERO_EXTEND, mode, op1, inner_mode);
          else
-           op1 = gen_rtx_SIGN_EXTEND (mode, op1);
-         return gen_rtx_MULT (mode, op0, op1);
+           op1 = simplify_gen_unary (SIGN_EXTEND, mode, op1, inner_mode);
+         op0 = gen_rtx_MULT (mode, op0, op1);
+         if (TREE_CODE (exp) == WIDEN_MULT_EXPR)
+           return op0;
+         else if (TREE_CODE (exp) == WIDEN_MULT_PLUS_EXPR)
+           return gen_rtx_PLUS (mode, op0, op2);
+         else
+           return gen_rtx_MINUS (mode, op2, op0);
        }
       return NULL;
 
@@ -3664,7 +3694,7 @@ expand_stack_alignment (void)
      stack.  We check PREFERRED_STACK_BOUNDARY if there may be non-call
      exceptions since callgraph doesn't collect incoming stack alignment
      in this case.  */
-  if (flag_non_call_exceptions
+  if (cfun->can_throw_non_call_exceptions
       && PREFERRED_STACK_BOUNDARY > crtl->preferred_stack_boundary)
     preferred_stack_boundary = PREFERRED_STACK_BOUNDARY;
   else
@@ -3720,7 +3750,9 @@ gimple_expand_cfg (void)
   edge e;
   unsigned i;
 
+  timevar_push (TV_OUT_OF_SSA);
   rewrite_out_of_ssa (&SA);
+  timevar_pop (TV_OUT_OF_SSA);
   SA.partition_to_pseudo = (rtx *)xcalloc (SA.map->num_partitions,
                                           sizeof (rtx));
 
@@ -3742,6 +3774,10 @@ gimple_expand_cfg (void)
   set_curr_insn_block (DECL_INITIAL (current_function_decl));
   prologue_locator = curr_insn_locator ();
 
+#ifdef INSN_SCHEDULING
+  init_sched_attrs ();
+#endif
+
   /* Make sure first insn is a note even if we don't want linenums.
      This makes sure the first insn will never be deleted.
      Also, final expects a note to appear there.  */
@@ -3759,17 +3795,21 @@ gimple_expand_cfg (void)
 
 
   /* Expand the variables recorded during gimple lowering.  */
+  timevar_push (TV_VAR_EXPAND);
   expand_used_vars ();
+  timevar_pop (TV_VAR_EXPAND);
 
   /* Honor stack protection warnings.  */
   if (warn_stack_protect)
     {
       if (cfun->calls_alloca)
        warning (OPT_Wstack_protector,
-                "not protecting local variables: variable length buffer");
+                "stack protector not protecting local variables: "
+                 "variable length buffer");
       if (has_short_buffer && !crtl->stack_protect_guard)
        warning (OPT_Wstack_protector,
-                "not protecting function: no buffer at least %d bytes long",
+                "stack protector not protecting function: "
+                 "all local arrays are less than %d bytes long",
                 (int) PARAM_VALUE (PARAM_SSP_BUFFER_SIZE));
     }
 
@@ -3837,8 +3877,11 @@ gimple_expand_cfg (void)
     expand_debug_locations ();
 
   execute_free_datastructures ();
+  timevar_push (TV_OUT_OF_SSA);
   finish_out_of_ssa (&SA);
+  timevar_pop (TV_OUT_OF_SSA);
 
+  timevar_push (TV_POST_EXPAND);
   /* We are no longer in SSA form.  */
   cfun->gimple_df->in_ssa_p = false;
 
@@ -3948,6 +3991,7 @@ gimple_expand_cfg (void)
      the common parent easily.  */
   set_block_levels (DECL_INITIAL (cfun->decl), 0);
   default_rtl_profile ();
+  timevar_pop (TV_POST_EXPAND);
   return 0;
 }