OSDN Git Service

2005-06-14 Pascal Obry <obry@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / explow.c
index 62ca87c..fed0872 100644 (file)
@@ -1,6 +1,6 @@
 /* Subroutines for manipulating rtx's in semantically interesting ways.
    Copyright (C) 1987, 1991, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -313,6 +313,7 @@ convert_memory_address (enum machine_mode to_mode ATTRIBUTE_UNUSED,
                        rtx x)
 {
 #ifndef POINTERS_EXTEND_UNSIGNED
+  gcc_assert (GET_MODE (x) == to_mode || GET_MODE (x) == VOIDmode);
   return x;
 #else /* defined(POINTERS_EXTEND_UNSIGNED) */
   enum machine_mode from_mode;
@@ -390,44 +391,6 @@ convert_memory_address (enum machine_mode to_mode ATTRIBUTE_UNUSED,
                        x, POINTERS_EXTEND_UNSIGNED);
 #endif /* defined(POINTERS_EXTEND_UNSIGNED) */
 }
-
-/* Given a memory address or facsimile X, construct a new address,
-   currently equivalent, that is stable: future stores won't change it.
-
-   X must be composed of constants, register and memory references
-   combined with addition, subtraction and multiplication:
-   in other words, just what you can get from expand_expr if sum_ok is 1.
-
-   Works by making copies of all regs and memory locations used
-   by X and combining them the same way X does.
-   You could also stabilize the reference to this address
-   by copying the address to a register with copy_to_reg;
-   but then you wouldn't get indexed addressing in the reference.  */
-
-rtx
-copy_all_regs (rtx x)
-{
-  if (REG_P (x))
-    {
-      if (REGNO (x) != FRAME_POINTER_REGNUM
-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
-         && REGNO (x) != HARD_FRAME_POINTER_REGNUM
-#endif
-         )
-       x = copy_to_reg (x);
-    }
-  else if (MEM_P (x))
-    x = copy_to_reg (x);
-  else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
-          || GET_CODE (x) == MULT)
-    {
-      rtx op0 = copy_all_regs (XEXP (x, 0));
-      rtx op1 = copy_all_regs (XEXP (x, 1));
-      if (op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
-       x = gen_rtx_fmt_ee (GET_CODE (x), Pmode, op0, op1);
-    }
-  return x;
-}
 \f
 /* Return something equivalent to X but valid as a memory address
    for something of mode MODE.  When X is not itself valid, this
@@ -576,22 +539,6 @@ validize_mem (rtx ref)
   return replace_equiv_address (ref, XEXP (ref, 0));
 }
 \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).
-   Perhaps even if it is a MEM, if there is no need to change it.  */
-
-rtx
-stabilize (rtx x)
-{
-  if (!MEM_P (x)
-      || ! rtx_unstable_p (XEXP (x, 0)))
-    return x;
-
-  return
-    replace_equiv_address (x, force_reg (Pmode, copy_all_regs (XEXP (x, 0))));
-}
-\f
 /* Copy the value or contents of X to a new temp reg and return that reg.  */
 
 rtx
@@ -875,7 +822,7 @@ anti_adjust_stack (rtx adjust)
 /* Round the size of a block to be pushed up to the boundary required
    by this machine.  SIZE is the desired size, which need not be constant.  */
 
-rtx
+static rtx
 round_push (rtx size)
 {
   int align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
@@ -965,6 +912,7 @@ emit_stack_save (enum save_level save_level, rtx *psave, rtx after)
       rtx seq;
 
       start_sequence ();
+      do_pending_stack_adjust ();
       /* We must validize inside the sequence, to ensure that any instructions
         created by the validize call also get moved to the right place.  */
       if (sa != 0)
@@ -976,6 +924,7 @@ emit_stack_save (enum save_level save_level, rtx *psave, rtx after)
     }
   else
     {
+      do_pending_stack_adjust ();
       if (sa != 0)
        sa = validize_mem (sa);
       emit_insn (fcn (sa, stack_pointer_rtx));
@@ -1032,6 +981,8 @@ emit_stack_restore (enum save_level save_level, rtx sa, rtx after)
                    gen_rtx_MEM (BLKmode, stack_pointer_rtx)));
     }
 
+  discard_pending_stack_adjust ();
+
   if (after)
     {
       rtx seq;
@@ -1067,83 +1018,6 @@ update_nonlocal_goto_save_area (void)
   emit_stack_save (SAVE_NONLOCAL, &r_save, NULL_RTX);
 }
 \f
-#ifdef SETJMP_VIA_SAVE_AREA
-/* Optimize RTL generated by allocate_dynamic_stack_space for targets
-   where SETJMP_VIA_SAVE_AREA is true.  The problem is that on these
-   platforms, the dynamic stack space used can corrupt the original
-   frame, thus causing a crash if a longjmp unwinds to it.  */
-
-void
-optimize_save_area_alloca (void)
-{
-  rtx insn;
-
-  for (insn = get_insns (); insn; insn = NEXT_INSN(insn))
-    {
-      rtx note;
-
-      if (!NONJUMP_INSN_P (insn))
-       continue;
-
-      for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
-       {
-         if (REG_NOTE_KIND (note) != REG_SAVE_AREA)
-           continue;
-
-         if (!current_function_calls_setjmp)
-           {
-             rtx pat = PATTERN (insn);
-
-             /* If we do not see the note in a pattern matching
-                these precise characteristics, we did something
-                entirely wrong in allocate_dynamic_stack_space.
-
-                Note, one way this could happen is if SETJMP_VIA_SAVE_AREA
-                was defined on a machine where stacks grow towards higher
-                addresses.
-
-                Right now only supported port with stack that grow upward
-                is the HPPA and it does not define SETJMP_VIA_SAVE_AREA.  */
-             gcc_assert (GET_CODE (pat) == SET
-                         && SET_DEST (pat) == stack_pointer_rtx
-                         && GET_CODE (SET_SRC (pat)) == MINUS
-                         && XEXP (SET_SRC (pat), 0) == stack_pointer_rtx);
-
-             /* This will now be transformed into a (set REG REG)
-                so we can just blow away all the other notes.  */
-             XEXP (SET_SRC (pat), 1) = XEXP (note, 0);
-             REG_NOTES (insn) = NULL_RTX;
-           }
-         else
-           {
-             /* setjmp was called, we must remove the REG_SAVE_AREA
-                note so that later passes do not get confused by its
-                presence.  */
-             if (note == REG_NOTES (insn))
-               {
-                 REG_NOTES (insn) = XEXP (note, 1);
-               }
-             else
-               {
-                 rtx srch;
-
-                 for (srch = REG_NOTES (insn); srch; srch = XEXP (srch, 1))
-                   if (XEXP (srch, 1) == note)
-                     break;
-
-                 gcc_assert (srch);
-
-                 XEXP (srch, 1) = XEXP (note, 1);
-               }
-           }
-         /* Once we've seen the note of interest, we need not look at
-            the rest of them.  */
-         break;
-       }
-    }
-}
-#endif /* SETJMP_VIA_SAVE_AREA */
-
 /* Return an rtx representing the address of an area of memory dynamically
    pushed on the stack.  This region of memory is always aligned to
    a multiple of BIGGEST_ALIGNMENT.
@@ -1158,10 +1032,6 @@ optimize_save_area_alloca (void)
 rtx
 allocate_dynamic_stack_space (rtx size, rtx target, int known_align)
 {
-#ifdef SETJMP_VIA_SAVE_AREA
-  rtx setjmpless_size = NULL_RTX;
-#endif
-
   /* If we're asking for zero bytes, it doesn't matter what we point
      to since we can't dereference it.  But return a reasonable
      address anyway.  */
@@ -1210,51 +1080,47 @@ allocate_dynamic_stack_space (rtx size, rtx target, int known_align)
      avoid clobbering the reg save area.  Note that the offset of
      virtual_incoming_args_rtx includes the preallocated stack args space.
      It would be no problem to clobber that, but it's on the wrong side
-     of the old save area.  */
-  {
-    rtx dynamic_offset
-      = expand_binop (Pmode, sub_optab, virtual_stack_dynamic_rtx,
-                     stack_pointer_rtx, NULL_RTX, 1, OPTAB_LIB_WIDEN);
+     of the old save area.
+
+     What used to happen is that, since we did not know for sure
+     whether setjmp() was invoked until after RTL generation, we
+     would use reg notes to store the "optimized" size and fix things
+     up later.  These days we know this information before we ever
+     start building RTL so the reg notes are unnecessary.  */
+  if (!current_function_calls_setjmp)
+    {
+      int align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
 
-    if (!current_function_calls_setjmp)
-      {
-       int align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
-
-       /* See optimize_save_area_alloca to understand what is being
-          set up here.  */
-
-       /* ??? Code below assumes that the save area needs maximal
-          alignment.  This constraint may be too strong.  */
-       gcc_assert (PREFERRED_STACK_BOUNDARY == BIGGEST_ALIGNMENT);
-
-       if (GET_CODE (size) == CONST_INT)
-         {
-           HOST_WIDE_INT new = INTVAL (size) / align * align;
-
-           if (INTVAL (size) != new)
-             setjmpless_size = GEN_INT (new);
-           else
-             setjmpless_size = size;
-         }
-       else
-         {
-           /* Since we know overflow is not possible, we avoid using
-              CEIL_DIV_EXPR and use TRUNC_DIV_EXPR instead.  */
-           setjmpless_size = expand_divmod (0, TRUNC_DIV_EXPR, Pmode, size,
-                                            GEN_INT (align), NULL_RTX, 1);
-           setjmpless_size = expand_mult (Pmode, setjmpless_size,
-                                          GEN_INT (align), NULL_RTX, 1);
-         }
-       /* Our optimization works based upon being able to perform a simple
-          transformation of this RTL into a (set REG REG) so make sure things
-          did in fact end up in a REG.  */
-       if (!register_operand (setjmpless_size, Pmode))
-         setjmpless_size = force_reg (Pmode, setjmpless_size);
-      }
+      /* ??? Code below assumes that the save area needs maximal
+        alignment.  This constraint may be too strong.  */
+      gcc_assert (PREFERRED_STACK_BOUNDARY == BIGGEST_ALIGNMENT);
 
-    size = expand_binop (Pmode, add_optab, size, dynamic_offset,
-                        NULL_RTX, 1, OPTAB_LIB_WIDEN);
-  }
+      if (GET_CODE (size) == CONST_INT)
+       {
+         HOST_WIDE_INT new = INTVAL (size) / align * align;
+
+         if (INTVAL (size) != new)
+           size = GEN_INT (new);
+       }
+      else
+       {
+         /* Since we know overflow is not possible, we avoid using
+            CEIL_DIV_EXPR and use TRUNC_DIV_EXPR instead.  */
+         size = expand_divmod (0, TRUNC_DIV_EXPR, Pmode, size,
+                               GEN_INT (align), NULL_RTX, 1);
+         size = expand_mult (Pmode, size,
+                             GEN_INT (align), NULL_RTX, 1);
+       }
+    }
+  else
+    {
+      rtx dynamic_offset
+       = expand_binop (Pmode, sub_optab, virtual_stack_dynamic_rtx,
+                       stack_pointer_rtx, NULL_RTX, 1, OPTAB_LIB_WIDEN);
+
+      size = expand_binop (Pmode, add_optab, size, dynamic_offset,
+                          NULL_RTX, 1, OPTAB_LIB_WIDEN);
+    }
 #endif /* SETJMP_VIA_SAVE_AREA */
 
   /* Round the size to a multiple of the required stack alignment.
@@ -1354,16 +1220,6 @@ allocate_dynamic_stack_space (rtx size, rtx target, int known_align)
        }
 
       anti_adjust_stack (size);
-#ifdef SETJMP_VIA_SAVE_AREA
-      if (setjmpless_size != NULL_RTX)
-       {
-         rtx note_target = get_last_insn ();
-
-         REG_NOTES (note_target)
-           = gen_rtx_EXPR_LIST (REG_SAVE_AREA, setjmpless_size,
-                                REG_NOTES (note_target));
-       }
-#endif /* SETJMP_VIA_SAVE_AREA */
 
 #ifdef STACK_GROWS_DOWNWARD
       emit_move_insn (target, virtual_stack_dynamic_rtx);
@@ -1575,8 +1431,8 @@ hard_function_value (tree valtype, tree func ATTRIBUTE_UNUSED,
       enum machine_mode tmpmode;
 
       /* int_size_in_bytes can return -1.  We don't need a check here
-        since the value of bytes will be large enough that no mode
-        will match and we will abort later in this function.  */
+        since the value of bytes will then be large enough that no
+        mode will match anyway.  */
 
       for (tmpmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
           tmpmode != VOIDmode;