OSDN Git Service

Empty patch as it has already been committed to trunk.
[pf3gnuchains/gcc-fork.git] / gcc / cfgexpand.c
index 4f317d9..3f7b1d2 100644 (file)
@@ -49,6 +49,10 @@ along with GCC; see the file COPYING3.  If not see
    into RTL.  */
 struct ssaexpand SA;
 
+/* This variable holds the currently expanded gimple statement for purposes
+   of comminucating the profile info to the builtin expanders.  */
+gimple currently_expanding_gimple_stmt;
+
 /* Return an expression tree corresponding to the RHS of GIMPLE
    statement STMT.  */
 
@@ -1756,7 +1760,6 @@ expand_call_stmt (gimple stmt)
 {
   tree exp;
   tree lhs = gimple_call_lhs (stmt);
-  tree fndecl = gimple_call_fndecl (stmt);
   size_t i;
 
   exp = build_vl_exp (CALL_EXPR, gimple_call_num_args (stmt) + 3);
@@ -1768,10 +1771,10 @@ expand_call_stmt (gimple stmt)
   for (i = 0; i < gimple_call_num_args (stmt); i++)
     CALL_EXPR_ARG (exp, i) = gimple_call_arg (stmt, i);
 
-  if (!(gimple_call_flags (stmt) & (ECF_CONST | ECF_PURE)))
+  if (gimple_has_side_effects (stmt))
     TREE_SIDE_EFFECTS (exp) = 1;
 
-  if (gimple_call_flags (stmt) & ECF_NOTHROW)
+  if (gimple_call_nothrow_p (stmt))
     TREE_NOTHROW (exp) = 1;
 
   CALL_EXPR_TAILCALL (exp) = gimple_call_tail_p (stmt);
@@ -1782,15 +1785,6 @@ expand_call_stmt (gimple stmt)
   SET_EXPR_LOCATION (exp, gimple_location (stmt));
   TREE_BLOCK (exp) = gimple_block (stmt);
 
-  /* Record the original call statement, as it may be used
-     to retrieve profile information during expansion.  */
-
-  if (fndecl && DECL_BUILT_IN (fndecl))
-    {
-      tree_ann_common_t ann = get_tree_common_ann (exp);
-      ann->stmt = stmt;
-    }
-
   if (lhs)
     expand_assignment (lhs, exp, false);
   else
@@ -2194,46 +2188,6 @@ round_udiv_adjust (enum machine_mode mode, rtx mod, rtx op1)
      const1_rtx, const0_rtx);
 }
 
-/* Wrap modeless constants in CONST:MODE.  */
-rtx
-wrap_constant (enum machine_mode mode, rtx x)
-{
-  if (GET_MODE (x) != VOIDmode)
-    return x;
-
-  if (CONST_INT_P (x)
-      || GET_CODE (x) == CONST_FIXED
-      || GET_CODE (x) == CONST_DOUBLE
-      || GET_CODE (x) == LABEL_REF)
-    {
-      gcc_assert (mode != VOIDmode);
-
-      x = gen_rtx_CONST (mode, x);
-    }
-
-  return x;
-}
-
-/* Remove CONST wrapper added by wrap_constant().  */
-rtx
-unwrap_constant (rtx x)
-{
-  rtx ret = x;
-
-  if (GET_CODE (x) != CONST)
-    return x;
-
-  x = XEXP (x, 0);
-
-  if (CONST_INT_P (x)
-      || GET_CODE (x) == CONST_FIXED
-      || GET_CODE (x) == CONST_DOUBLE
-      || GET_CODE (x) == LABEL_REF)
-    ret = x;
-
-  return ret;
-}
-
 /* Convert X to MODE, that must be Pmode or ptr_mode, without emitting
    any rtl.  */
 
@@ -2275,6 +2229,9 @@ expand_debug_expr (tree exp)
   rtx op0 = NULL_RTX, op1 = NULL_RTX, op2 = NULL_RTX;
   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;
+  enum machine_mode pointer_mode;
 
   switch (TREE_CODE_CLASS (TREE_CODE (exp)))
     {
@@ -2356,9 +2313,7 @@ expand_debug_expr (tree exp)
     case COMPLEX_CST:
       gcc_assert (COMPLEX_MODE_P (mode));
       op0 = expand_debug_expr (TREE_REALPART (exp));
-      op0 = wrap_constant (GET_MODE_INNER (mode), op0);
       op1 = expand_debug_expr (TREE_IMAGPART (exp));
-      op1 = wrap_constant (GET_MODE_INNER (mode), op1);
       return gen_rtx_CONCAT (mode, op0, op1);
 
     case DEBUG_EXPR_DECL:
@@ -2388,7 +2343,8 @@ expand_debug_expr (tree exp)
              || DECL_EXTERNAL (exp)
              || !TREE_STATIC (exp)
              || !DECL_NAME (exp)
-             || DECL_HARD_REGISTER (exp))
+             || DECL_HARD_REGISTER (exp)
+             || mode == VOIDmode)
            return NULL;
 
          op0 = DECL_RTL (exp);
@@ -2470,20 +2426,29 @@ expand_debug_expr (tree exp)
       if (!op0)
        return NULL;
 
-      gcc_assert (GET_MODE (op0) == Pmode
-                 || GET_MODE (op0) == ptr_mode
+      if (POINTER_TYPE_P (TREE_TYPE (exp)))
+       as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp)));
+      else
+       as = ADDR_SPACE_GENERIC;
+
+      address_mode = targetm.addr_space.address_mode (as);
+      pointer_mode = targetm.addr_space.pointer_mode (as);
+
+      gcc_assert (GET_MODE (op0) == address_mode
+                 || GET_MODE (op0) == pointer_mode
                  || GET_CODE (op0) == CONST_INT
                  || GET_CODE (op0) == CONST_DOUBLE);
 
       if (TREE_CODE (exp) == ALIGN_INDIRECT_REF)
        {
          int align = TYPE_ALIGN_UNIT (TREE_TYPE (exp));
-         op0 = gen_rtx_AND (Pmode, op0, GEN_INT (-align));
+         op0 = gen_rtx_AND (address_mode, op0, GEN_INT (-align));
        }
 
       op0 = gen_rtx_MEM (mode, op0);
 
       set_mem_attributes (op0, exp, 0);
+      set_mem_addr_space (op0, as);
 
       return op0;
 
@@ -2497,14 +2462,19 @@ expand_debug_expr (tree exp)
       if (!op0)
        return NULL;
 
-      gcc_assert (GET_MODE (op0) == Pmode
-                 || GET_MODE (op0) == ptr_mode
+      as = TYPE_ADDR_SPACE (TREE_TYPE (exp));
+      address_mode = targetm.addr_space.address_mode (as);
+      pointer_mode = targetm.addr_space.pointer_mode (as);
+
+      gcc_assert (GET_MODE (op0) == address_mode
+                 || GET_MODE (op0) == pointer_mode
                  || GET_CODE (op0) == CONST_INT
                  || GET_CODE (op0) == CONST_DOUBLE);
 
       op0 = gen_rtx_MEM (mode, op0);
 
       set_mem_attributes (op0, exp, 0);
+      set_mem_addr_space (op0, as);
 
       return op0;
 
@@ -2593,6 +2563,9 @@ expand_debug_expr (tree exp)
        if (bitpos == 0 && mode == GET_MODE (op0))
          return op0;
 
+        if (bitpos < 0)
+          return NULL;
+
        if ((bitpos % BITS_PER_UNIT) == 0
            && bitsize == GET_MODE_BITSIZE (mode1))
          {
@@ -2869,6 +2842,46 @@ expand_debug_expr (tree exp)
        op1 = gen_rtx_CONST (GET_MODE_INNER (mode), op1);
       return gen_rtx_CONCAT (mode, op0, op1);
 
+    case CONJ_EXPR:
+      if (GET_CODE (op0) == CONCAT)
+       return gen_rtx_CONCAT (mode, XEXP (op0, 0),
+                              gen_rtx_NEG (GET_MODE_INNER (mode),
+                                           XEXP (op0, 1)));
+      else
+       {
+         enum machine_mode imode = GET_MODE_INNER (mode);
+         rtx re, im;
+
+         if (MEM_P (op0))
+           {
+             re = adjust_address_nv (op0, imode, 0);
+             im = adjust_address_nv (op0, imode, GET_MODE_SIZE (imode));
+           }
+         else
+           {
+             enum machine_mode ifmode = int_mode_for_mode (mode);
+             enum machine_mode ihmode = int_mode_for_mode (imode);
+             rtx halfsize;
+             if (ifmode == BLKmode || ihmode == BLKmode)
+               return NULL;
+             halfsize = GEN_INT (GET_MODE_BITSIZE (ihmode));
+             re = op0;
+             if (mode != ifmode)
+               re = gen_rtx_SUBREG (ifmode, re, 0);
+             re = gen_rtx_ZERO_EXTRACT (ihmode, re, halfsize, const0_rtx);
+             if (imode != ihmode)
+               re = gen_rtx_SUBREG (imode, re, 0);
+             im = copy_rtx (op0);
+             if (mode != ifmode)
+               im = gen_rtx_SUBREG (ifmode, im, 0);
+             im = gen_rtx_ZERO_EXTRACT (ihmode, im, halfsize, halfsize);
+             if (imode != ihmode)
+               im = gen_rtx_SUBREG (imode, im, 0);
+           }
+         im = gen_rtx_NEG (imode, im);
+         return gen_rtx_CONCAT (mode, re, im);
+       }
+
     case ADDR_EXPR:
       op0 = expand_debug_expr (TREE_OPERAND (exp, 0));
       if (!op0 || !MEM_P (op0))
@@ -3087,6 +3100,7 @@ expand_gimple_basic_block (basic_block bb)
       basic_block new_bb;
 
       stmt = gsi_stmt (gsi);
+      currently_expanding_gimple_stmt = stmt;
 
       /* Expand this statement, then evaluate the resulting RTL and
         fixup the CFG accordingly.  */
@@ -3184,6 +3198,8 @@ expand_gimple_basic_block (basic_block bb)
        }
     }
 
+  currently_expanding_gimple_stmt = NULL;
+
   /* Expand implicit goto and convert goto_locus.  */
   FOR_EACH_EDGE (e, ei, bb->succs)
     {
@@ -3201,6 +3217,18 @@ expand_gimple_basic_block (basic_block bb)
        }
     }
 
+  /* Expanded RTL can create a jump in the last instruction of block.
+     This later might be assumed to be a jump to successor and break edge insertion.
+     We need to insert dummy move to prevent this. PR41440. */
+  if (single_succ_p (bb)
+      && (single_succ_edge (bb)->flags & EDGE_FALLTHRU)
+      && (last = get_last_insn ())
+      && JUMP_P (last))
+    {
+      rtx dummy = gen_reg_rtx (SImode);
+      emit_insn_after_noloc (gen_move_insn (dummy, dummy), last, NULL);
+    }
+
   do_pending_stack_adjust ();
 
   /* Find the block tail.  The last insn in the block is the insn
@@ -3429,8 +3457,18 @@ expand_stack_alignment (void)
       || crtl->has_nonlocal_goto)
     crtl->need_drap = true;
 
-  gcc_assert (crtl->stack_alignment_needed
-             <= crtl->stack_alignment_estimated);
+  /* Call update_stack_boundary here again to update incoming stack
+     boundary.  It may set incoming stack alignment to a different
+     value after RTL expansion.  TARGET_FUNCTION_OK_FOR_SIBCALL may
+     use the minimum incoming stack alignment to check if it is OK
+     to perform sibcall optimization since sibcall optimization will
+     only align the outgoing stack to incoming stack boundary.  */
+  if (targetm.calls.update_stack_boundary)
+    targetm.calls.update_stack_boundary ();
+
+  /* The incoming stack frame has to be aligned at least at
+     parm_stack_boundary.  */
+  gcc_assert (crtl->parm_stack_boundary <= INCOMING_STACK_BOUNDARY);
 
   /* Update crtl->stack_alignment_estimated and use it later to align
      stack.  We check PREFERRED_STACK_BOUNDARY if there may be non-call
@@ -3446,6 +3484,9 @@ expand_stack_alignment (void)
   if (preferred_stack_boundary > crtl->stack_alignment_needed)
     crtl->stack_alignment_needed = preferred_stack_boundary;
 
+  gcc_assert (crtl->stack_alignment_needed
+             <= crtl->stack_alignment_estimated);
+
   crtl->stack_realign_needed
     = INCOMING_STACK_BOUNDARY < crtl->stack_alignment_estimated;
   crtl->stack_realign_tried = crtl->stack_realign_needed;
@@ -3522,7 +3563,7 @@ gimple_expand_cfg (void)
   targetm.expand_to_rtl_hook ();
   crtl->stack_alignment_needed = STACK_BOUNDARY;
   crtl->max_used_stack_slot_alignment = STACK_BOUNDARY;
-  crtl->stack_alignment_estimated = STACK_BOUNDARY;
+  crtl->stack_alignment_estimated = 0;
   crtl->preferred_stack_boundary = STACK_BOUNDARY;
   cfun->cfg->max_jumptable_ents = 0;
 
@@ -3586,23 +3627,6 @@ gimple_expand_cfg (void)
   if (crtl->stack_protect_guard)
     stack_protect_prologue ();
 
-  /* Update stack boundary if needed.  */
-  if (SUPPORTS_STACK_ALIGNMENT)
-    {
-      /* Call update_stack_boundary here to update incoming stack
-        boundary before TARGET_FUNCTION_OK_FOR_SIBCALL is called.
-        TARGET_FUNCTION_OK_FOR_SIBCALL needs to know the accurate
-        incoming stack alignment to check if it is OK to perform
-        sibcall optimization since sibcall optimization will only
-        align the outgoing stack to incoming stack boundary.  */
-      if (targetm.calls.update_stack_boundary)
-       targetm.calls.update_stack_boundary ();
-      
-      /* The incoming stack frame has to be aligned at least at
-        parm_stack_boundary.  */
-      gcc_assert (crtl->parm_stack_boundary <= INCOMING_STACK_BOUNDARY);
-    }
-
   expand_phi_nodes (&SA);
 
   /* Register rtl specific functions for cfg.  */