OSDN Git Service

Merge basic-improvements-branch to trunk
[pf3gnuchains/gcc-fork.git] / gcc / explow.c
index 8f0b52f..df5bcf6 100644 (file)
@@ -22,6 +22,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "toplev.h"
 #include "rtl.h"
 #include "tree.h"
@@ -34,6 +36,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "insn-config.h"
 #include "ggc.h"
 #include "recog.h"
+#include "langhooks.h"
 
 static rtx break_out_memory_refs       PARAMS ((rtx));
 static void emit_stack_probe           PARAMS ((rtx));
@@ -48,6 +51,10 @@ trunc_int_for_mode (c, mode)
 {
   int width = GET_MODE_BITSIZE (mode);
 
+  /* You want to truncate to a _what_?  */
+  if (! SCALAR_INT_MODE_P (mode))
+    abort ();
+
   /* Canonicalize BImode to 0 and STORE_FLAG_VALUE.  */
   if (mode == BImode)
     return c & 1 ? STORE_FLAG_VALUE : 0;
@@ -285,20 +292,33 @@ rtx
 expr_size (exp)
      tree exp;
 {
-  tree size;
-
-  if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'd'
-      && DECL_SIZE_UNIT (exp) != 0)
-    size = DECL_SIZE_UNIT (exp);
-  else
-    size = size_in_bytes (TREE_TYPE (exp));
+  tree size = (*lang_hooks.expr_size) (exp);
 
   if (TREE_CODE (size) != INTEGER_CST
       && contains_placeholder_p (size))
     size = build (WITH_RECORD_EXPR, sizetype, size, exp);
 
   return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), 0);
+}
+
+/* Return a wide integer for the size in bytes of the value of EXP, or -1
+   if the size can vary or is larger than an integer.  */
+
+HOST_WIDE_INT
+int_expr_size (exp)
+     tree exp;
+{
+  tree t = (*lang_hooks.expr_size) (exp);
 
+  if (t == 0
+      || TREE_CODE (t) != INTEGER_CST
+      || TREE_OVERFLOW (t)
+      || TREE_INT_CST_HIGH (t) != 0
+      /* If the result would appear negative, it's too big to represent.  */
+      || (HOST_WIDE_INT) TREE_INT_CST_LOW (t) < 0)
+    return -1;
+
+  return TREE_INT_CST_LOW (t);
 }
 \f
 /* Return a copy of X in which all memory references
@@ -353,6 +373,7 @@ convert_memory_address (to_mode, x)
 {
   enum machine_mode from_mode = to_mode == ptr_mode ? Pmode : ptr_mode;
   rtx temp;
+  enum rtx_code code;
 
   /* Here we handle some special cases.  If none of them apply, fall through
      to the default case.  */
@@ -360,55 +381,55 @@ convert_memory_address (to_mode, x)
     {
     case CONST_INT:
     case CONST_DOUBLE:
-      return x;
+      if (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (from_mode))
+       code = TRUNCATE;
+      else if (POINTERS_EXTEND_UNSIGNED < 0)
+       break;
+      else if (POINTERS_EXTEND_UNSIGNED > 0)
+       code = ZERO_EXTEND;
+      else
+       code = SIGN_EXTEND;
+      temp = simplify_unary_operation (code, to_mode, x, from_mode);
+      if (temp)
+       return temp;
+      break;
 
     case SUBREG:
-      if (POINTERS_EXTEND_UNSIGNED >= 0
-         && (SUBREG_PROMOTED_VAR_P (x) || REG_POINTER (SUBREG_REG (x)))
+      if ((SUBREG_PROMOTED_VAR_P (x) || REG_POINTER (SUBREG_REG (x)))
          && GET_MODE (SUBREG_REG (x)) == to_mode)
        return SUBREG_REG (x);
       break;
 
     case LABEL_REF:
-      if (POINTERS_EXTEND_UNSIGNED >= 0)
-       {
-         temp = gen_rtx_LABEL_REF (to_mode, XEXP (x, 0));
-         LABEL_REF_NONLOCAL_P (temp) = LABEL_REF_NONLOCAL_P (x);
-         return temp;
-       }
+      temp = gen_rtx_LABEL_REF (to_mode, XEXP (x, 0));
+      LABEL_REF_NONLOCAL_P (temp) = LABEL_REF_NONLOCAL_P (x);
+      return temp;
       break;
 
     case SYMBOL_REF:
-      if (POINTERS_EXTEND_UNSIGNED >= 0)
-       {
-         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;
-       }
+      temp = shallow_copy_rtx (x);
+      PUT_MODE (temp, to_mode);
+      return temp;
       break;
 
     case CONST:
-      if (POINTERS_EXTEND_UNSIGNED >= 0)
-       return gen_rtx_CONST (to_mode,
-                             convert_memory_address (to_mode, XEXP (x, 0)));
+      return gen_rtx_CONST (to_mode,
+                           convert_memory_address (to_mode, XEXP (x, 0)));
       break;
 
     case PLUS:
     case MULT:
-      /* For addition the second operand is a small constant, we can safely
-        permute the conversion and addition operation.  We can always safely
-        permute them if we are making the address narrower.  In addition,
-        always permute the operations if this is a constant.  */
-      if (POINTERS_EXTEND_UNSIGNED >= 0
-         && (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (from_mode)
-             || (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT
-                 && (INTVAL (XEXP (x, 1)) + 20000 < 40000
-                     || CONSTANT_P (XEXP (x, 0))))))
+      /* For addition we can safely permute the conversion and addition
+        operation if one operand is a constant and converting the constant
+        does not change it.  We can always safely permute them if we are
+        making the address narrower.  */
+      if (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (from_mode)
+         || (GET_CODE (x) == PLUS
+             && GET_CODE (XEXP (x, 1)) == CONST_INT
+             && XEXP (x, 1) == convert_memory_address (to_mode, XEXP (x, 1))))
        return gen_rtx_fmt_ee (GET_CODE (x), to_mode,
                               convert_memory_address (to_mode, XEXP (x, 0)),
-                              convert_memory_address (to_mode, XEXP (x, 1)));
+                              XEXP (x, 1));
       break;
 
     default:
@@ -639,8 +660,7 @@ maybe_set_unchanging (ref, t)
      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))))
+          || (DECL_INITIAL (t) && TREE_CONSTANT (DECL_INITIAL (t)))))
       || TREE_CODE_CLASS (TREE_CODE (t)) == 'c')
     RTX_UNCHANGING_P (ref) = 1;
 }
@@ -802,7 +822,7 @@ copy_to_suggested_reg (x, target, mode)
    PUNSIGNEDP points to the signedness of the type and may be adjusted
    to show what signedness to use on extension operations.
 
-   FOR_CALL is non-zero if this call is promoting args for a call.  */
+   FOR_CALL is nonzero if this call is promoting args for a call.  */
 
 enum machine_mode
 promote_mode (type, mode, punsignedp, for_call)
@@ -1062,7 +1082,17 @@ emit_stack_restore (save_level, sa, after)
     }
 
   if (sa != 0)
-    sa = validize_mem (sa);
+    {
+      sa = validize_mem (sa);
+      /* These clobbers prevent the scheduler from moving
+        references to variable arrays below the code
+        that deletes (pops) the arrays.  */
+      emit_insn (gen_rtx_CLOBBER (VOIDmode,
+                   gen_rtx_MEM (BLKmode, 
+                       gen_rtx_SCRATCH (VOIDmode))));
+      emit_insn (gen_rtx_CLOBBER (VOIDmode,
+                   gen_rtx_MEM (BLKmode, stack_pointer_rtx)));
+    }
 
   if (after)
     {
@@ -1202,7 +1232,7 @@ allocate_dynamic_stack_space (size, target, known_align)
      always know its final value at this point in the compilation (it
      might depend on the size of the outgoing parameter lists, for
      example), so we must align the value to be returned in that case.
-     (Note that STACK_DYNAMIC_OFFSET will have a default non-zero value if
+     (Note that STACK_DYNAMIC_OFFSET will have a default nonzero value if
      STACK_POINTER_OFFSET or ACCUMULATE_OUTGOING_ARGS are defined).
      We must also do an alignment operation on the returned value if
      the stack pointer alignment is less strict that BIGGEST_ALIGNMENT.
@@ -1685,4 +1715,3 @@ rtx_to_tree_code (code)
 }
 
 #include "gt-explow.h"
-