OSDN Git Service

2010-12-09 Yao Qi <yao@codesourcery.com>
[pf3gnuchains/gcc-fork.git] / gcc / emit-rtl.c
index bb9f63a..4a5b290 100644 (file)
@@ -39,7 +39,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "diagnostic-core.h"
-#include "toplev.h"
 #include "rtl.h"
 #include "tree.h"
 #include "tm_p.h"
@@ -589,12 +588,12 @@ gen_rtx_REG (enum machine_mode mode, unsigned int regno)
       if (regno == FRAME_POINTER_REGNUM
          && (!reload_completed || frame_pointer_needed))
        return frame_pointer_rtx;
-#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
+#if !HARD_FRAME_POINTER_IS_FRAME_POINTER
       if (regno == HARD_FRAME_POINTER_REGNUM
          && (!reload_completed || frame_pointer_needed))
        return hard_frame_pointer_rtx;
 #endif
-#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM && HARD_FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
+#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM && !HARD_FRAME_POINTER_IS_ARG_POINTER
       if (regno == ARG_POINTER_REGNUM)
        return arg_pointer_rtx;
 #endif
@@ -603,6 +602,7 @@ gen_rtx_REG (enum machine_mode mode, unsigned int regno)
        return return_address_pointer_rtx;
 #endif
       if (regno == (unsigned) PIC_OFFSET_TABLE_REGNUM
+         && PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
          && fixed_regs[PIC_OFFSET_TABLE_REGNUM])
        return pic_offset_table_rtx;
       if (regno == STACK_POINTER_REGNUM)
@@ -1459,7 +1459,8 @@ get_mem_align_offset (rtx mem, unsigned int align)
   /* This function can't use
      if (!MEM_EXPR (mem) || !MEM_OFFSET (mem)
         || !CONST_INT_P (MEM_OFFSET (mem))
-        || (get_object_alignment (MEM_EXPR (mem), MEM_ALIGN (mem), align)
+        || (MAX (MEM_ALIGN (mem),
+                 get_object_alignment (MEM_EXPR (mem), align))
             < align))
        return -1;
      else
@@ -1587,39 +1588,37 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
   else if (TREE_CODE (t) == MEM_REF)
     {
       tree op0 = TREE_OPERAND (t, 0);
-      unsigned HOST_WIDE_INT aoff = BITS_PER_UNIT;
-      if (host_integerp (TREE_OPERAND (t, 1), 1))
+      if (TREE_CODE (op0) == ADDR_EXPR
+         && (DECL_P (TREE_OPERAND (op0, 0))
+             || CONSTANT_CLASS_P (TREE_OPERAND (op0, 0))))
        {
-         unsigned HOST_WIDE_INT ioff = TREE_INT_CST_LOW (TREE_OPERAND (t, 1));
-         aoff = (ioff & -ioff) * BITS_PER_UNIT;
-       }
-      if (TREE_CODE (op0) == ADDR_EXPR && DECL_P (TREE_OPERAND (op0, 0)))
-       align = MAX (align, DECL_ALIGN (TREE_OPERAND (op0, 0)));
-      else if (TREE_CODE (op0) == ADDR_EXPR
-              && CONSTANT_CLASS_P (TREE_OPERAND (op0, 0)))
-       {
-         align = TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (op0, 0)));
+         if (DECL_P (TREE_OPERAND (op0, 0)))
+           align = DECL_ALIGN (TREE_OPERAND (op0, 0));
+         else if (CONSTANT_CLASS_P (TREE_OPERAND (op0, 0)))
+           {
+             align = TYPE_ALIGN (TREE_TYPE (TREE_OPERAND (op0, 0)));
 #ifdef CONSTANT_ALIGNMENT
-         align = CONSTANT_ALIGNMENT (TREE_OPERAND (op0, 0), align);
+             align = CONSTANT_ALIGNMENT (TREE_OPERAND (op0, 0), align);
 #endif
+           }
+         if (TREE_INT_CST_LOW (TREE_OPERAND (t, 1)) != 0)
+           {
+             unsigned HOST_WIDE_INT ioff
+               = TREE_INT_CST_LOW (TREE_OPERAND (t, 1));
+             unsigned HOST_WIDE_INT aoff = (ioff & -ioff) * BITS_PER_UNIT;
+             align = MIN (aoff, align);
+           }
        }
       else
        /* ??? This isn't fully correct, we can't set the alignment from the
           type in all cases.  */
        align = MAX (align, TYPE_ALIGN (type));
-
-      if (!integer_zerop (TREE_OPERAND (t, 1)) && aoff < align)
-       align = aoff;
     }
 
-  else if (TREE_CODE (t) == MISALIGNED_INDIRECT_REF)
-    {
-      if (integer_zerop (TREE_OPERAND (t, 1)))
-       /* We don't know anything about the alignment.  */
-       align = BITS_PER_UNIT;
-      else
-       align = tree_low_cst (TREE_OPERAND (t, 1), 1);
-    }
+  else if (TREE_CODE (t) == TARGET_MEM_REF)
+    /* ??? This isn't fully correct, we can't set the alignment from the
+       type in all cases.  */
+    align = MAX (align, TYPE_ALIGN (type));
 
   /* If the size is known, we can set that.  */
   if (TYPE_SIZE_UNIT (type) && host_integerp (TYPE_SIZE_UNIT (type), 1))
@@ -1661,7 +1660,11 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
          else
            MEM_NOTRAP_P (ref) = 1;
        }
-      else
+      else if (TREE_CODE (base) == INDIRECT_REF
+              || TREE_CODE (base) == MEM_REF
+              || TREE_CODE (base) == TARGET_MEM_REF
+              || TREE_CODE (base) == ARRAY_REF
+              || TREE_CODE (base) == ARRAY_RANGE_REF)
        MEM_NOTRAP_P (ref) = TREE_THIS_NOTRAP (base);
 
       base = get_base_address (base);
@@ -1774,8 +1777,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
            }
 
          /* If this is an indirect reference, record it.  */
-         else if (TREE_CODE (t) == MEM_REF 
-                  || TREE_CODE (t) == MISALIGNED_INDIRECT_REF)
+         else if (TREE_CODE (t) == MEM_REF)
            {
              expr = t;
              offset = const0_rtx;
@@ -1785,7 +1787,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
 
       /* If this is an indirect reference, record it.  */
       else if (TREE_CODE (t) == MEM_REF 
-              || TREE_CODE (t) == MISALIGNED_INDIRECT_REF)
+              || TREE_CODE (t) == TARGET_MEM_REF)
        {
          expr = t;
          offset = const0_rtx;
@@ -1794,8 +1796,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
 
       if (!align_computed && !INDIRECT_REF_P (t))
        {
-         unsigned int obj_align
-           = get_object_alignment (t, align, BIGGEST_ALIGNMENT);
+         unsigned int obj_align = get_object_alignment (t, BIGGEST_ALIGNMENT);
          align = MAX (align, obj_align);
        }
     }
@@ -1838,10 +1839,8 @@ set_mem_attributes (rtx ref, tree t, int objectp)
 void
 set_mem_alias_set (rtx mem, alias_set_type set)
 {
-#ifdef ENABLE_CHECKING
   /* If the new and old alias sets don't conflict, something is wrong.  */
-  gcc_assert (alias_sets_conflict_p (set, MEM_ALIAS_SET (mem)));
-#endif
+  gcc_checking_assert (alias_sets_conflict_p (set, MEM_ALIAS_SET (mem)));
 
   MEM_ATTRS (mem) = get_mem_attrs (set, MEM_EXPR (mem), MEM_OFFSET (mem),
                                   MEM_SIZE (mem), MEM_ALIGN (mem),
@@ -2239,7 +2238,6 @@ get_spill_slot_decl (bool force_build_p)
   DECL_ARTIFICIAL (d) = 1;
   DECL_IGNORED_P (d) = 1;
   TREE_USED (d) = 1;
-  TREE_THIS_NOTRAP (d) = 1;
   spill_slot_decl = d;
 
   rd = gen_rtx_MEM (BLKmode, frame_pointer_rtx);
@@ -2375,7 +2373,7 @@ unshare_all_rtl_again (rtx insn)
   set_used_decls (DECL_INITIAL (cfun->decl));
 
   /* Make sure that virtual parameters are not shared.  */
-  for (decl = DECL_ARGUMENTS (cfun->decl); decl; decl = TREE_CHAIN (decl))
+  for (decl = DECL_ARGUMENTS (cfun->decl); decl; decl = DECL_CHAIN (decl))
     set_used_flags (DECL_RTL (decl));
 
   reset_used_flags (stack_slot_list);
@@ -2527,6 +2525,8 @@ verify_rtl_sharing (void)
 {
   rtx p;
 
+  timevar_push (TV_VERIFY_RTL_SHARING);
+
   for (p = get_insns (); p; p = NEXT_INSN (p))
     if (INSN_P (p))
       {
@@ -2553,6 +2553,8 @@ verify_rtl_sharing (void)
        verify_rtx_sharing (PATTERN (p), p);
        verify_rtx_sharing (REG_NOTES (p), p);
       }
+
+  timevar_pop (TV_VERIFY_RTL_SHARING);
 }
 
 /* Go through all the RTL insn bodies and copy any invalid shared structure.
@@ -2585,7 +2587,7 @@ set_used_decls (tree blk)
   tree t;
 
   /* Mark decls.  */
-  for (t = BLOCK_VARS (blk); t; t = TREE_CHAIN (t))
+  for (t = BLOCK_VARS (blk); t; t = DECL_CHAIN (t))
     if (DECL_RTL_SET_P (t))
       set_used_flags (DECL_RTL (t));
 
@@ -2730,11 +2732,10 @@ repeat:
   return;
 }
 
-/* Clear all the USED bits in X to allow copy_rtx_if_shared to be used
-   to look for shared sub-parts.  */
+/* Set the USED bit in X and its non-shareable subparts to FLAG.  */
 
-void
-reset_used_flags (rtx x)
+static void
+mark_used_flags (rtx x, int flag)
 {
   int i, j;
   enum rtx_code code;
@@ -2780,7 +2781,7 @@ repeat:
       break;
     }
 
-  RTX_FLAG (x, used) = 0;
+  RTX_FLAG (x, used) = flag;
 
   format_ptr = GET_RTX_FORMAT (code);
   length = GET_RTX_LENGTH (code);
@@ -2795,81 +2796,33 @@ repeat:
               x = XEXP (x, i);
              goto repeat;
             }
-         reset_used_flags (XEXP (x, i));
+         mark_used_flags (XEXP (x, i), flag);
          break;
 
        case 'E':
          for (j = 0; j < XVECLEN (x, i); j++)
-           reset_used_flags (XVECEXP (x, i, j));
+           mark_used_flags (XVECEXP (x, i, j), flag);
          break;
        }
     }
 }
 
-/* Set all the USED bits in X to allow copy_rtx_if_shared to be used
+/* Clear all the USED bits in X to allow copy_rtx_if_shared to be used
    to look for shared sub-parts.  */
 
 void
-set_used_flags (rtx x)
+reset_used_flags (rtx x)
 {
-  int i, j;
-  enum rtx_code code;
-  const char *format_ptr;
-
-  if (x == 0)
-    return;
-
-  code = GET_CODE (x);
-
-  /* These types may be freely shared so we needn't do any resetting
-     for them.  */
-
-  switch (code)
-    {
-    case REG:
-    case DEBUG_EXPR:
-    case VALUE:
-    case CONST_INT:
-    case CONST_DOUBLE:
-    case CONST_FIXED:
-    case CONST_VECTOR:
-    case SYMBOL_REF:
-    case CODE_LABEL:
-    case PC:
-    case CC0:
-      return;
-
-    case DEBUG_INSN:
-    case INSN:
-    case JUMP_INSN:
-    case CALL_INSN:
-    case NOTE:
-    case LABEL_REF:
-    case BARRIER:
-      /* The chain of insns is not being copied.  */
-      return;
-
-    default:
-      break;
-    }
-
-  RTX_FLAG (x, used) = 1;
+  mark_used_flags (x, 0);
+}
 
-  format_ptr = GET_RTX_FORMAT (code);
-  for (i = 0; i < GET_RTX_LENGTH (code); i++)
-    {
-      switch (*format_ptr++)
-       {
-       case 'e':
-         set_used_flags (XEXP (x, i));
-         break;
+/* Set all the USED bits in X to allow copy_rtx_if_shared to be used
+   to look for shared sub-parts.  */
 
-       case 'E':
-         for (j = 0; j < XVECLEN (x, i); j++)
-           set_used_flags (XVECEXP (x, i, j));
-         break;
-       }
-    }
+void
+set_used_flags (rtx x)
+{
+  mark_used_flags (x, 1);
 }
 \f
 /* Copy X if necessary so that it won't be altered by changes in OTHER.
@@ -3135,6 +3088,38 @@ prev_nondebug_insn (rtx insn)
   return insn;
 }
 
+/* Return the next insn after INSN that is not a NOTE nor DEBUG_INSN.
+   This routine does not look inside SEQUENCEs.  */
+
+rtx
+next_nonnote_nondebug_insn (rtx insn)
+{
+  while (insn)
+    {
+      insn = NEXT_INSN (insn);
+      if (insn == 0 || (!NOTE_P (insn) && !DEBUG_INSN_P (insn)))
+       break;
+    }
+
+  return insn;
+}
+
+/* Return the previous insn before INSN that is not a NOTE nor DEBUG_INSN.
+   This routine does not look inside SEQUENCEs.  */
+
+rtx
+prev_nonnote_nondebug_insn (rtx insn)
+{
+  while (insn)
+    {
+      insn = PREV_INSN (insn);
+      if (insn == 0 || (!NOTE_P (insn) && !DEBUG_INSN_P (insn)))
+       break;
+    }
+
+  return insn;
+}
+
 /* Return the next INSN, CALL_INSN or JUMP_INSN after INSN;
    or 0, if there is none.  This routine does not look inside
    SEQUENCEs.  */
@@ -3885,7 +3870,7 @@ remove_insn (rtx insn)
   if (!BARRIER_P (insn)
       && (bb = BLOCK_FOR_INSN (insn)))
     {
-      if (INSN_P (insn))
+      if (NONDEBUG_INSN_P (insn))
        df_set_bb_dirty (bb);
       if (BB_HEAD (bb) == insn)
        {
@@ -3948,6 +3933,13 @@ delete_insns_since (rtx from)
 void
 reorder_insns_nobb (rtx from, rtx to, rtx after)
 {
+#ifdef ENABLE_CHECKING
+  rtx x;
+  for (x = from; x != to; x = NEXT_INSN (x))
+    gcc_assert (after != x);
+  gcc_assert (after != to);
+#endif
+
   /* Splice this bunch out of where it is now.  */
   if (PREV_INSN (from))
     NEXT_INSN (PREV_INSN (from)) = NEXT_INSN (to);
@@ -5347,6 +5339,8 @@ init_virtual_regs (void)
   regno_reg_rtx[VIRTUAL_STACK_DYNAMIC_REGNUM] = virtual_stack_dynamic_rtx;
   regno_reg_rtx[VIRTUAL_OUTGOING_ARGS_REGNUM] = virtual_outgoing_args_rtx;
   regno_reg_rtx[VIRTUAL_CFA_REGNUM] = virtual_cfa_rtx;
+  regno_reg_rtx[VIRTUAL_PREFERRED_STACK_BOUNDARY_REGNUM]
+    = virtual_preferred_stack_boundary_rtx;
 }
 
 \f
@@ -5669,6 +5663,8 @@ init_emit_regs (void)
   virtual_outgoing_args_rtx =
     gen_raw_REG (Pmode, VIRTUAL_OUTGOING_ARGS_REGNUM);
   virtual_cfa_rtx = gen_raw_REG (Pmode, VIRTUAL_CFA_REGNUM);
+  virtual_preferred_stack_boundary_rtx =
+    gen_raw_REG (Pmode, VIRTUAL_PREFERRED_STACK_BOUNDARY_REGNUM);
 
   /* Initialize RTL for commonly used hard registers.  These are
      copied into regno_reg_rtx as we begin to compile each function.  */