OSDN Git Service

(memop_valid): Memory indirection now valid.
[pf3gnuchains/gcc-fork.git] / gcc / explow.c
index 1491217..db0fbc8 100644 (file)
@@ -1,5 +1,5 @@
 /* Subroutines for manipulating rtx's in semantically interesting ways.
-   Copyright (C) 1987, 1991, 1994, 1995 Free Software Foundation, Inc.
+   Copyright (C) 1987, 91, 94, 95, 96, 1997 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -304,8 +304,11 @@ convert_memory_address (to_mode, x)
      enum machine_mode to_mode;
      rtx x;
 {
+  enum machine_mode from_mode = to_mode == ptr_mode ? Pmode : ptr_mode;
   rtx temp;
 
+  /* Here we handle some special cases.  If none of them apply, fall through
+     to the default case.  */
   switch (GET_CODE (x))
     {
     case CONST_INT:
@@ -318,23 +321,30 @@ convert_memory_address (to_mode, x)
     case SYMBOL_REF:
       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);
       return temp;
 
-    case PLUS:
-    case MULT:
-      return gen_rtx (GET_CODE (x), to_mode, 
-                     convert_memory_address (to_mode, XEXP (x, 0)),
-                     convert_memory_address (to_mode, XEXP (x, 1)));
-
     case CONST:
       return gen_rtx (CONST, to_mode, 
                      convert_memory_address (to_mode, XEXP (x, 0)));
 
-    default:
-      return convert_modes (to_mode,
-                           to_mode == ptr_mode ? Pmode : ptr_mode,
-                           x, POINTERS_EXTEND_UNSIGNED);
+    case PLUS:
+    case MULT:
+      /* For addition the second operand is a small constant, we can safely
+        permute the converstion 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 (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)))))
+       return gen_rtx (GET_CODE (x), to_mode, 
+                       convert_memory_address (to_mode, XEXP (x, 0)),
+                       convert_memory_address (to_mode, XEXP (x, 1)));
     }
+
+  return convert_modes (to_mode, from_mode,
+                       x, POINTERS_EXTEND_UNSIGNED);
 }
 #endif
 
@@ -493,11 +503,11 @@ memory_address (mode, x)
   if (oldx == x)
     return x;
   else if (GET_CODE (x) == REG)
-    mark_reg_pointer (x);
+    mark_reg_pointer (x, 1);
   else if (GET_CODE (x) == PLUS
           && GET_CODE (XEXP (x, 0)) == REG
           && GET_CODE (XEXP (x, 1)) == CONST_INT)
-    mark_reg_pointer (XEXP (x, 0));
+    mark_reg_pointer (XEXP (x, 0), 1);
 
   /* OLDX may have been the address on a temporary.  Update the address
      to indicate that X is now used.  */
@@ -723,6 +733,7 @@ promote_mode (type, mode, punsignedp, for_call)
 #endif
 
 #ifdef POINTERS_EXTEND_UNSIGNED
+    case REFERENCE_TYPE:
     case POINTER_TYPE:
       mode = Pmode;
       unsignedp = POINTERS_EXTEND_UNSIGNED;
@@ -806,7 +817,8 @@ round_push (size)
   else
     {
       /* CEIL_DIV_EXPR needs to worry about the addition overflowing,
-        but we know it can't.  So add ourselves and then do TRUNC_DIV_EXPR. */
+        but we know it can't.  So add ourselves and then do
+        TRUNC_DIV_EXPR.  */
       size = expand_binop (Pmode, add_optab, size, GEN_INT (align - 1),
                           NULL_RTX, 1, OPTAB_LIB_WIDEN);
       size = expand_divmod (0, TRUNC_DIV_EXPR, Pmode, size, GEN_INT (align),
@@ -1008,7 +1020,7 @@ allocate_dynamic_stack_space (size, target, known_align)
      If we have to align, we must leave space in SIZE for the hole
      that might result from the alignment operation.  */
 
-#if defined (STACK_DYNAMIC_OFFSET) || defined (STACK_POINTER_OFFSET) || defined (ALLOCATE_OUTGOING_ARGS) || ! defined (STACK_BOUNDARY)
+#if defined (STACK_DYNAMIC_OFFSET) || defined (STACK_POINTER_OFFSET) || ! defined (STACK_BOUNDARY)
 #define MUST_ALIGN 1
 #else
 #define MUST_ALIGN (STACK_BOUNDARY < BIGGEST_ALIGNMENT)
@@ -1070,7 +1082,7 @@ allocate_dynamic_stack_space (size, target, known_align)
       || REGNO (target) < FIRST_PSEUDO_REGISTER)
     target = gen_reg_rtx (Pmode);
 
-  mark_reg_pointer (target);
+  mark_reg_pointer (target, known_align / BITS_PER_UNIT);
 
 #ifndef STACK_GROWS_DOWNWARD
   emit_move_insn (target, virtual_stack_dynamic_rtx);
@@ -1108,7 +1120,8 @@ allocate_dynamic_stack_space (size, target, known_align)
   if (MUST_ALIGN)
     {
       /* CEIL_DIV_EXPR needs to worry about the addition overflowing,
-        but we know it can't.  So add ourselves and then do TRUNC_DIV_EXPR. */
+        but we know it can't.  So add ourselves and then do
+        TRUNC_DIV_EXPR.  */
       target = expand_binop (Pmode, add_optab, target,
                             GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1),
                             NULL_RTX, 1, OPTAB_LIB_WIDEN);