OSDN Git Service

* tree.c (cp_valid_lang_attribute): Don't set CLASSTYPE_COM_INTERFACE
[pf3gnuchains/gcc-fork.git] / gcc / explow.c
index 585dafd..a1c6380 100644 (file)
@@ -52,6 +52,10 @@ trunc_int_for_mode (c, mode)
 {
   int width = GET_MODE_BITSIZE (mode);
 
+  /* Canonicalize BImode to 0 and STORE_FLAG_VALUE.  */
+  if (mode == BImode)
+    return c & 1 ? STORE_FLAG_VALUE : 0;
+
   /* We clear out all bits that don't belong in MODE, unless they and our
      sign bit are all one.  So we get either a reasonable negative
      value or a reasonable unsigned value.  */
@@ -125,15 +129,10 @@ plus_constant_wide (x, c)
       if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
          && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))
        {
-         /* Any rtl we create here must go in a saveable obstack, since
-            we might have been called from within combine.  */
-         push_obstacks_nochange ();
-         rtl_in_saveable_obstack ();
          tem
            = force_const_mem (GET_MODE (x),
                               plus_constant (get_pool_constant (XEXP (x, 0)),
                                              c));
-         pop_obstacks ();
          if (memory_address_p (GET_MODE (tem), XEXP (tem, 0)))
            return tem;
        }
@@ -294,7 +293,7 @@ find_next_ref (reg, insn)
            return insn;
          if (GET_CODE (insn) == JUMP_INSN)
            {
-             if (simplejump_p (insn))
+             if (any_uncondjump_p (insn))
                next = JUMP_LABEL (insn);
              else
                return 0;
@@ -396,6 +395,7 @@ convert_memory_address (to_mode, x)
       temp = gen_rtx_SYMBOL_REF (to_mode, XSTR (x, 0));
       SYMBOL_REF_FLAG (temp) = SYMBOL_REF_FLAG (x);
       CONSTANT_POOL_ADDRESS_P (temp) = CONSTANT_POOL_ADDRESS_P (x);
+      STRING_POOL_ADDRESS_P (temp) = STRING_POOL_ADDRESS_P (x);
       return temp;
 
     case CONST:
@@ -628,6 +628,93 @@ validize_mem (ref)
   return change_address (ref, GET_MODE (ref), XEXP (ref, 0));
 }
 \f
+/* Given REF, either a MEM or a REG, and T, either the type of X or
+   the expression corresponding to REF, set RTX_UNCHANGING_P if
+   appropriate.  */
+
+void
+maybe_set_unchanging (ref, t)
+     rtx ref;
+     tree t;
+{
+  /* We can set RTX_UNCHANGING_P from TREE_READONLY for decls whose
+     initialization is only executed once, or whose initializer always
+     has the same value.  Currently we simplify this to PARM_DECLs in the
+     first case, and decls with TREE_CONSTANT initializers in the second.  */
+  if ((TREE_READONLY (t) && DECL_P (t)
+       && (TREE_CODE (t) == PARM_DECL
+          || DECL_INITIAL (t) == NULL_TREE
+          || TREE_CONSTANT (DECL_INITIAL (t))))
+      || TREE_CODE_CLASS (TREE_CODE (t)) == 'c')
+    RTX_UNCHANGING_P (ref) = 1;
+}
+
+/* Given REF, a MEM, and T, either the type of X or the expression
+   corresponding to REF, set the memory attributes.  OBJECTP is nonzero
+   if we are making a new object of this type.  */
+
+void
+set_mem_attributes (ref, t, objectp)
+     rtx ref;
+     tree t;
+     int objectp;
+{
+  tree type;
+
+  /* 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
+     we can see here.  */
+  if (t == NULL_TREE)
+    return;
+
+  type = TYPE_P (t) ? t : TREE_TYPE (t);
+
+  /* Get the alias set from the expression or type (perhaps using a
+     front-end routine) and then copy bits from the type.  */
+
+  /* It is incorrect to set RTX_UNCHANGING_P from TREE_READONLY (type)
+     here, because, in C and C++, the fact that a location is accessed
+     through a const expression does not mean that the value there can
+     never change.  */
+  MEM_ALIAS_SET (ref) = get_alias_set (t);
+  MEM_VOLATILE_P (ref) = TYPE_VOLATILE (type);
+  MEM_IN_STRUCT_P (ref) = AGGREGATE_TYPE_P (type);
+
+  /* If we are making an object of this type, we know that it is a scalar if
+     the type is not an aggregate. */
+  if (objectp && ! AGGREGATE_TYPE_P (type))
+    MEM_SCALAR_P (ref) = 1;
+
+  /* If T is a type, this is all we can do.  Otherwise, we may be able
+     to deduce some more information about the expression.  */
+  if (TYPE_P (t))
+    return;
+
+  maybe_set_unchanging (ref, t);
+  if (TREE_THIS_VOLATILE (t))
+    MEM_VOLATILE_P (ref) = 1;
+
+  /* Now see if we can say more about whether it's an aggregate or
+     scalar.  If we already know it's an aggregate, don't bother.  */
+  if (MEM_IN_STRUCT_P (ref))
+    return;
+
+  /* Now remove any NOPs: they don't change what the underlying object is.
+     Likewise for SAVE_EXPR.  */
+  while (TREE_CODE (t) == NOP_EXPR || TREE_CODE (t) == CONVERT_EXPR
+        || TREE_CODE (t) == NON_LVALUE_EXPR || TREE_CODE (t) == SAVE_EXPR)
+    t = TREE_OPERAND (t, 0);
+
+  /* Since we already know the type isn't an aggregate, if this is a decl,
+     it must be a scalar.  Or if it is a reference into an aggregate,
+     this is part of an aggregate.   Otherwise we don't know.  */
+  if (DECL_P (t))
+    MEM_SCALAR_P (ref) = 1;
+  else if (TREE_CODE (t) == COMPONENT_REF || TREE_CODE (t) == ARRAY_REF
+          || TREE_CODE (t) == BIT_FIELD_REF)
+    MEM_IN_STRUCT_P (ref) = 1;
+}
+\f
 /* Return a modified copy of X with its memory address copied
    into a temporary register to protect it from side effects.
    If X is not a MEM, it is returned unchanged (and not copied).
@@ -638,25 +725,17 @@ stabilize (x)
      rtx x;
 {
   register rtx addr;
+
   if (GET_CODE (x) != MEM)
     return x;
+
   addr = XEXP (x, 0);
   if (rtx_unstable_p (addr))
     {
-      rtx temp = copy_all_regs (addr);
-      rtx mem;
-
-      if (GET_CODE (temp) != REG)
-       temp = copy_to_reg (temp);
-      mem = gen_rtx_MEM (GET_MODE (x), temp);
-
-      /* Mark returned memref with in_struct if it's in an array or
-        structure.  Copy everything else from original memref.  */
+      rtx temp = force_reg (Pmode, copy_all_regs (addr));
+      rtx mem = gen_rtx_MEM (GET_MODE (x), temp);
 
       MEM_COPY_ATTRIBUTES (mem, x);
-      if (GET_CODE (addr) == PLUS)
-       MEM_SET_IN_STRUCT_P (mem, 1);
-
       return mem;
     }
   return x;
@@ -763,8 +842,10 @@ force_not_mem (x)
      rtx x;
 {
   register rtx temp;
+
   if (GET_CODE (x) != MEM || GET_MODE (x) == BLKmode)
     return x;
+
   temp = gen_reg_rtx (GET_MODE (x));
   emit_move_insn (temp, x);
   return temp;