OSDN Git Service

Backport from mainline
[pf3gnuchains/gcc-fork.git] / gcc / emit-rtl.c
index 99b02ba..a95c146 100644 (file)
@@ -93,9 +93,10 @@ static GTY(()) int label_num = 1;
 
 /* We record floating-point CONST_DOUBLEs in each floating-point mode for
    the values of 0, 1, and 2.  For the integer entries and VOIDmode, we
-   record a copy of const[012]_rtx.  */
+   record a copy of const[012]_rtx and constm1_rtx.  CONSTM1_RTX
+   is set only for MODE_INT and MODE_VECTOR_INT modes.  */
 
-rtx const_tiny_rtx[3][(int) MAX_MACHINE_MODE];
+rtx const_tiny_rtx[4][(int) MAX_MACHINE_MODE];
 
 rtx const_true_rtx;
 
@@ -1466,7 +1467,7 @@ get_mem_align_offset (rtx mem, unsigned int align)
   /* This function can't use
      if (!MEM_EXPR (mem) || !MEM_OFFSET_KNOWN_P (mem)
         || (MAX (MEM_ALIGN (mem),
-                 get_object_alignment (MEM_EXPR (mem), align))
+                 MAX (align, get_object_alignment (MEM_EXPR (mem))))
             < align))
        return -1;
      else
@@ -1547,6 +1548,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
   HOST_WIDE_INT apply_bitpos = 0;
   tree type;
   struct mem_attrs attrs, *defattrs, *refattrs;
+  addr_space_t as;
 
   /* It can happen that type_for_mode was given a mode for which there
      is no language-level type.  In which case it returns NULL, which
@@ -1571,17 +1573,8 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
   attrs.alias = get_alias_set (t);
 
   MEM_VOLATILE_P (ref) |= TYPE_VOLATILE (type);
-  MEM_IN_STRUCT_P (ref)
-    = AGGREGATE_TYPE_P (type) || TREE_CODE (type) == COMPLEX_TYPE;
   MEM_POINTER (ref) = POINTER_TYPE_P (type);
 
-  /* If we are making an object of this type, or if this is a DECL, we know
-     that it is a scalar if the type is not an aggregate.  */
-  if ((objectp || DECL_P (t))
-      && ! AGGREGATE_TYPE_P (type)
-      && TREE_CODE (type) != COMPLEX_TYPE)
-    MEM_SCALAR_P (ref) = 1;
-
   /* Default values from pre-existing memory attributes if present.  */
   refattrs = MEM_ATTRS (ref);
   if (refattrs)
@@ -1689,11 +1682,29 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
       MEM_NOTRAP_P (ref) = !tree_could_trap_p (t);
 
       base = get_base_address (t);
-      if (base && DECL_P (base)
-         && TREE_READONLY (base)
-         && (TREE_STATIC (base) || DECL_EXTERNAL (base))
-         && !TREE_THIS_VOLATILE (base))
-       MEM_READONLY_P (ref) = 1;
+      if (base)
+       {
+         if (DECL_P (base)
+             && TREE_READONLY (base)
+             && (TREE_STATIC (base) || DECL_EXTERNAL (base))
+             && !TREE_THIS_VOLATILE (base))
+           MEM_READONLY_P (ref) = 1;
+
+         /* Mark static const strings readonly as well.  */
+         if (TREE_CODE (base) == STRING_CST
+             && TREE_READONLY (base)
+             && TREE_STATIC (base))
+           MEM_READONLY_P (ref) = 1;
+
+         if (TREE_CODE (base) == MEM_REF
+             || TREE_CODE (base) == TARGET_MEM_REF)
+           as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (base,
+                                                                     0))));
+         else
+           as = TYPE_ADDR_SPACE (TREE_TYPE (base));
+       }
+      else
+       as = TYPE_ADDR_SPACE (type);
 
       /* If this expression uses it's parent's alias set, mark it such
         that we won't change it.  */
@@ -1826,12 +1837,14 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
          apply_bitpos = bitpos;
        }
 
-      if (!align_computed && !INDIRECT_REF_P (t))
+      if (!align_computed)
        {
-         unsigned int obj_align = get_object_alignment (t, BIGGEST_ALIGNMENT);
+         unsigned int obj_align = get_object_alignment (t);
          attrs.align = MAX (attrs.align, obj_align);
        }
     }
+  else
+    as = TYPE_ADDR_SPACE (type);
 
   /* If we modified OFFSET based on T, then subtract the outstanding
      bit position offset.  Similarly, increase the size of the accessed
@@ -1845,19 +1858,8 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
     }
 
   /* Now set the attributes we computed above.  */
-  attrs.addrspace = TYPE_ADDR_SPACE (type);
+  attrs.addrspace = as;
   set_mem_attrs (ref, &attrs);
-
-  /* If this is already known to be a scalar or aggregate, we are done.  */
-  if (MEM_IN_STRUCT_P (ref) || MEM_SCALAR_P (ref))
-    return;
-
-  /* If it is a reference into an aggregate, this is part of an aggregate.
-     Otherwise we don't know.  */
-  else if (TREE_CODE (t) == COMPONENT_REF || TREE_CODE (t) == ARRAY_REF
-          || TREE_CODE (t) == ARRAY_RANGE_REF
-          || TREE_CODE (t) == BIT_FIELD_REF)
-    MEM_IN_STRUCT_P (ref) = 1;
 }
 
 void
@@ -2444,6 +2446,8 @@ unshare_all_rtl_again (rtx insn)
       {
        reset_used_flags (PATTERN (p));
        reset_used_flags (REG_NOTES (p));
+       if (CALL_P (p))
+         reset_used_flags (CALL_INSN_FUNCTION_USAGE (p));
       }
 
   /* Make sure that virtual stack slots are not shared.  */
@@ -2518,6 +2522,7 @@ verify_rtx_sharing (rtx orig, rtx insn)
     case PC:
     case CC0:
     case RETURN:
+    case SIMPLE_RETURN:
     case SCRATCH:
       return;
       /* SCRATCH must be shared because they represent distinct values.  */
@@ -2610,6 +2615,8 @@ verify_rtl_sharing (void)
       {
        reset_used_flags (PATTERN (p));
        reset_used_flags (REG_NOTES (p));
+       if (CALL_P (p))
+         reset_used_flags (CALL_INSN_FUNCTION_USAGE (p));
        if (GET_CODE (PATTERN (p)) == SEQUENCE)
          {
            int i;
@@ -2621,6 +2628,8 @@ verify_rtl_sharing (void)
                gcc_assert (INSN_P (q));
                reset_used_flags (PATTERN (q));
                reset_used_flags (REG_NOTES (q));
+               if (CALL_P (q))
+                 reset_used_flags (CALL_INSN_FUNCTION_USAGE (q));
              }
          }
       }
@@ -2630,6 +2639,8 @@ verify_rtl_sharing (void)
       {
        verify_rtx_sharing (PATTERN (p), p);
        verify_rtx_sharing (REG_NOTES (p), p);
+       if (CALL_P (p))
+         verify_rtx_sharing (CALL_INSN_FUNCTION_USAGE (p), p);
       }
 
   timevar_pop (TV_VERIFY_RTL_SHARING);
@@ -2646,6 +2657,9 @@ unshare_all_rtl_in_chain (rtx insn)
       {
        PATTERN (insn) = copy_rtx_if_shared (PATTERN (insn));
        REG_NOTES (insn) = copy_rtx_if_shared (REG_NOTES (insn));
+       if (CALL_P (insn))
+         CALL_INSN_FUNCTION_USAGE (insn)
+           = copy_rtx_if_shared (CALL_INSN_FUNCTION_USAGE (insn));
       }
 }
 
@@ -2724,6 +2738,8 @@ repeat:
     case CODE_LABEL:
     case PC:
     case CC0:
+    case RETURN:
+    case SIMPLE_RETURN:
     case SCRATCH:
       /* SCRATCH must be shared because they represent distinct values.  */
       return;
@@ -2843,6 +2859,8 @@ repeat:
     case CODE_LABEL:
     case PC:
     case CC0:
+    case RETURN:
+    case SIMPLE_RETURN:
       return;
 
     case DEBUG_INSN:
@@ -3307,21 +3325,6 @@ next_label (rtx insn)
   return insn;
 }
 
-/* Return the last CODE_LABEL before the insn INSN, or 0 if there is none.  */
-
-rtx
-prev_label (rtx insn)
-{
-  while (insn)
-    {
-      insn = PREV_INSN (insn);
-      if (insn == 0 || LABEL_P (insn))
-       break;
-    }
-
-  return insn;
-}
-
 /* Return the last label to mark the same position as LABEL.  Return LABEL
    itself if it is null or any return rtx.  */
 
@@ -3587,6 +3590,7 @@ try_split (rtx pat, rtx trial, int last)
 
        case REG_NORETURN:
        case REG_SETJMP:
+       case REG_TM:
          for (insn = insn_last; insn != NULL_RTX; insn = PREV_INSN (insn))
            {
              if (CALL_P (insn))
@@ -3614,6 +3618,10 @@ try_split (rtx pat, rtx trial, int last)
          break;
 #endif
 
+       case REG_ARGS_SIZE:
+         fixup_args_size_notes (NULL_RTX, insn_last, INTVAL (XEXP (note, 0)));
+         break;
+
        default:
          break;
        }
@@ -4991,6 +4999,17 @@ set_unique_reg_note (rtx insn, enum reg_note kind, rtx datum)
 
   return REG_NOTES (insn);
 }
+
+/* Like set_unique_reg_note, but don't do anything unless INSN sets DST.  */
+rtx
+set_dst_reg_note (rtx insn, enum reg_note kind, rtx datum, rtx dst)
+{
+  rtx set = single_set (insn);
+
+  if (set && SET_DEST (set) == dst)
+    return set_unique_reg_note (insn, kind, datum);
+  return NULL_RTX;
+}
 \f
 /* Return an indication of which type of insn should have X as a body.
    The value is CODE_LABEL, INSN, CALL_INSN or JUMP_INSN.  */
@@ -5002,7 +5021,7 @@ classify_insn (rtx x)
     return CODE_LABEL;
   if (GET_CODE (x) == CALL)
     return CALL_INSN;
-  if (GET_CODE (x) == RETURN)
+  if (ANY_RETURN_P (x))
     return JUMP_INSN;
   if (GET_CODE (x) == SET)
     {
@@ -5249,6 +5268,7 @@ copy_insn_1 (rtx orig)
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -5257,6 +5277,8 @@ copy_insn_1 (rtx orig)
     case CODE_LABEL:
     case PC:
     case CC0:
+    case RETURN:
+    case SIMPLE_RETURN:
       return orig;
     case CLOBBER:
       if (REG_P (XEXP (orig, 0)) && REGNO (XEXP (orig, 0)) < FIRST_PSEUDO_REGISTER)
@@ -5491,6 +5513,8 @@ gen_rtx_CONST_VECTOR (enum machine_mode mode, rtvec v)
        return CONST0_RTX (mode);
       else if (x == CONST1_RTX (inner))
        return CONST1_RTX (mode);
+      else if (x == CONSTM1_RTX (inner))
+       return CONSTM1_RTX (mode);
     }
 
   return gen_rtx_raw_CONST_VECTOR (mode, v);
@@ -5514,6 +5538,7 @@ init_emit_regs (void)
   /* Assign register numbers to the globally defined register rtx.  */
   pc_rtx = gen_rtx_fmt_ (PC, VOIDmode);
   ret_rtx = gen_rtx_fmt_ (RETURN, VOIDmode);
+  simple_return_rtx = gen_rtx_fmt_ (SIMPLE_RETURN, VOIDmode);
   cc0_rtx = gen_rtx_fmt_ (CC0, VOIDmode);
   stack_pointer_rtx = gen_raw_REG (Pmode, STACK_POINTER_REGNUM);
   frame_pointer_rtx = gen_raw_REG (Pmode, FRAME_POINTER_REGNUM);
@@ -5650,7 +5675,7 @@ init_emit_once (void)
   dconsthalf = dconst1;
   SET_REAL_EXP (&dconsthalf, REAL_EXP (&dconsthalf) - 1);
 
-  for (i = 0; i < (int) ARRAY_SIZE (const_tiny_rtx); i++)
+  for (i = 0; i < 3; i++)
     {
       const REAL_VALUE_TYPE *const r =
        (i == 0 ? &dconst0 : i == 1 ? &dconst1 : &dconst2);
@@ -5680,6 +5705,18 @@ init_emit_once (void)
        const_tiny_rtx[i][(int) mode] = GEN_INT (i);
     }
 
+  const_tiny_rtx[3][(int) VOIDmode] = constm1_rtx;
+
+  for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
+       mode != VOIDmode;
+       mode = GET_MODE_WIDER_MODE (mode))
+    const_tiny_rtx[3][(int) mode] = constm1_rtx;
+
+  for (mode = GET_CLASS_NARROWEST_MODE (MODE_PARTIAL_INT);
+       mode != VOIDmode;
+       mode = GET_MODE_WIDER_MODE (mode))
+    const_tiny_rtx[3][(int) mode] = constm1_rtx;
+      
   for (mode = GET_CLASS_NARROWEST_MODE (MODE_COMPLEX_INT);
        mode != VOIDmode;
        mode = GET_MODE_WIDER_MODE (mode))
@@ -5702,6 +5739,7 @@ init_emit_once (void)
     {
       const_tiny_rtx[0][(int) mode] = gen_const_vector (mode, 0);
       const_tiny_rtx[1][(int) mode] = gen_const_vector (mode, 1);
+      const_tiny_rtx[3][(int) mode] = gen_const_vector (mode, 3);
     }
 
   for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT);