OSDN Git Service

ObjC NeXT, split encode-support code from next-mapping.h
[pf3gnuchains/gcc-fork.git] / gcc / cfgexpand.c
index de686b5..81e988b 100644 (file)
@@ -1,5 +1,5 @@
 /* A pass for lowering trees to RTL.
-   Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -253,6 +253,8 @@ alloc_stack_frame_space (HOST_WIDE_INT size, unsigned HOST_WIDE_INT align)
 static void
 add_stack_var (tree decl)
 {
+  struct stack_var *v;
+
   if (stack_vars_num >= stack_vars_alloc)
     {
       if (stack_vars_alloc)
@@ -262,17 +264,23 @@ add_stack_var (tree decl)
       stack_vars
        = XRESIZEVEC (struct stack_var, stack_vars, stack_vars_alloc);
     }
-  stack_vars[stack_vars_num].decl = decl;
-  stack_vars[stack_vars_num].offset = 0;
-  stack_vars[stack_vars_num].size = tree_low_cst (DECL_SIZE_UNIT (SSAVAR (decl)), 1);
-  stack_vars[stack_vars_num].alignb = get_decl_align_unit (SSAVAR (decl));
+  v = &stack_vars[stack_vars_num];
+
+  v->decl = decl;
+  v->offset = 0;
+  v->size = tree_low_cst (DECL_SIZE_UNIT (SSAVAR (decl)), 1);
+  /* Ensure that all variables have size, so that &a != &b for any two
+     variables that are simultaneously live.  */
+  if (v->size == 0)
+    v->size = 1;
+  v->alignb = get_decl_align_unit (SSAVAR (decl));
 
   /* All variables are initially in their own partition.  */
-  stack_vars[stack_vars_num].representative = stack_vars_num;
-  stack_vars[stack_vars_num].next = EOC;
+  v->representative = stack_vars_num;
+  v->next = EOC;
 
   /* All variables initially conflict with no other.  */
-  stack_vars[stack_vars_num].conflicts = NULL;
+  v->conflicts = NULL;
 
   /* Ensure that this decl doesn't get put onto the list twice.  */
   set_rtl (decl, pc_rtx);
@@ -508,9 +516,11 @@ update_alias_info_with_stack_vars (void)
          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.  */
+            space to something that is unused and thus unreferenced, except
+            for -O0 where we are preserving even unreferenced variables.  */
          gcc_assert (DECL_P (decl)
-                     && referenced_var_lookup (DECL_UID (decl)));
+                     && (!optimize
+                         || referenced_var_lookup (DECL_UID (decl))));
          bitmap_set_bit (part, uid);
          *((bitmap *) pointer_map_insert (decls_to_partitions,
                                           (void *)(size_t) uid)) = part;
@@ -676,8 +686,7 @@ partition_stack_vars (void)
        }
     }
 
-  if (optimize)
-    update_alias_info_with_stack_vars ();
+  update_alias_info_with_stack_vars ();
 }
 
 /* A debugging aid for expand_used_vars.  Dump the generated partitions.  */
@@ -839,6 +848,7 @@ expand_stack_vars (bool (*pred) (tree))
          /* Large alignment is only processed in the last pass.  */
          if (pred)
            continue;
+         gcc_assert (large_base != NULL);
 
          large_alloc += alignb - 1;
          large_alloc &= -(HOST_WIDE_INT)alignb;
@@ -1684,7 +1694,14 @@ maybe_cleanup_end_of_block (edge e, rtx last)
        {
          insn = PREV_INSN (insn);
          if (JUMP_P (NEXT_INSN (insn)))
-           delete_insn (NEXT_INSN (insn));
+           {
+             if (!any_condjump_p (NEXT_INSN (insn)))
+               {
+                 gcc_assert (BARRIER_P (NEXT_INSN (NEXT_INSN (insn))));
+                 delete_insn (NEXT_INSN (NEXT_INSN (insn)));
+               }
+             delete_insn (NEXT_INSN (insn));
+           }
        }
     }
 }
@@ -2351,6 +2368,7 @@ expand_debug_expr (tree exp)
        case DOT_PROD_EXPR:
        case WIDEN_MULT_PLUS_EXPR:
        case WIDEN_MULT_MINUS_EXPR:
+       case FMA_EXPR:
          goto ternary;
 
        case TRUTH_ANDIF_EXPR:
@@ -2542,15 +2560,20 @@ expand_debug_expr (tree exp)
       }
 
     case MEM_REF:
-      /* ??? FIXME.  */
-      if (!integer_zerop (TREE_OPERAND (exp, 1)))
-       return NULL;
-      /* Fallthru.  */
     case INDIRECT_REF:
       op0 = expand_debug_expr (TREE_OPERAND (exp, 0));
       if (!op0)
        return NULL;
 
+      if (TREE_CODE (exp) == MEM_REF)
+       {
+         op1 = expand_debug_expr (TREE_OPERAND (exp, 1));
+         if (!op1 || !CONST_INT_P (op1))
+           return NULL;
+
+         op0 = plus_constant (op0, INTVAL (op1));
+       }
+
       if (POINTER_TYPE_P (TREE_TYPE (exp)))
        as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp)));
       else
@@ -2680,7 +2703,7 @@ expand_debug_expr (tree exp)
            enum machine_mode opmode = GET_MODE (op0);
 
            if (opmode == VOIDmode)
-             opmode = mode1;
+             opmode = TYPE_MODE (TREE_TYPE (tem));
 
            /* This condition may hold if we're expanding the address
               right past the end of an array that turned out not to
@@ -2701,7 +2724,8 @@ expand_debug_expr (tree exp)
                                     ? SIGN_EXTRACT
                                     : ZERO_EXTRACT, mode,
                                     GET_MODE (op0) != VOIDmode
-                                    ? GET_MODE (op0) : mode1,
+                                    ? GET_MODE (op0)
+                                    : TYPE_MODE (TREE_TYPE (tem)),
                                     op0, GEN_INT (bitsize), GEN_INT (bitpos));
       }
 
@@ -3064,7 +3088,7 @@ expand_debug_expr (tree exp)
          if (i < TYPE_VECTOR_SUBPARTS (TREE_TYPE (exp)))
            {
              op1 = expand_debug_expr
-               (fold_convert (TREE_TYPE (TREE_TYPE (exp)), integer_zero_node));
+               (build_zero_cst (TREE_TYPE (TREE_TYPE (exp))));
 
              if (!op1)
                return NULL;
@@ -3192,6 +3216,9 @@ expand_debug_expr (tree exp)
        }
       return NULL;
 
+    case FMA_EXPR:
+      return gen_rtx_FMA (mode, op0, op1, op2);
+
     default:
     flag_unsupported:
 #ifdef ENABLE_CHECKING
@@ -3901,6 +3928,8 @@ gimple_expand_cfg (void)
       else
        set_curr_insn_source_location (cfun->function_start_locus);
     }
+  else
+    set_curr_insn_source_location (UNKNOWN_LOCATION);
   set_curr_insn_block (DECL_INITIAL (current_function_decl));
   prologue_locator = curr_insn_locator ();
 
@@ -3923,6 +3952,10 @@ gimple_expand_cfg (void)
   crtl->preferred_stack_boundary = STACK_BOUNDARY;
   cfun->cfg->max_jumptable_ents = 0;
 
+  /* Resovle the function section.  Some targets, like ARM EABI rely on knowledge
+     of the function section at exapnsion time to predict distance of calls.  */
+  resolve_unique_section (current_function_decl, 0, flag_function_sections);
+
   /* Expand the variables recorded during gimple lowering.  */
   timevar_push (TV_VAR_EXPAND);
   start_sequence ();
@@ -4052,7 +4085,19 @@ gimple_expand_cfg (void)
       for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
        {
          if (e->insns.r)
-           commit_one_edge_insertion (e);
+           {
+             /* Avoid putting insns before parm_birth_insn.  */
+             if (e->src == ENTRY_BLOCK_PTR
+                 && single_succ_p (ENTRY_BLOCK_PTR)
+                 && parm_birth_insn)
+               {
+                 rtx insns = e->insns.r;
+                 e->insns.r = NULL_RTX;
+                 emit_insn_after_noloc (insns, parm_birth_insn, e->dest);
+               }
+             else
+               commit_one_edge_insertion (e);
+           }
          else
            ei_next (&ei);
        }