OSDN Git Service

2008-12-17 Sebastian Pop <sebastian.pop@amd.com>
[pf3gnuchains/gcc-fork.git] / gcc / explow.c
index 2223ca6..498d40e 100644 (file)
@@ -1,12 +1,13 @@
 /* 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, 2006, 2007
+   Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -15,9 +16,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 
 #include "config.h"
@@ -29,6 +29,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "tree.h"
 #include "tm_p.h"
 #include "flags.h"
+#include "except.h"
 #include "function.h"
 #include "expr.h"
 #include "optabs.h"
@@ -37,6 +38,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "ggc.h"
 #include "recog.h"
 #include "langhooks.h"
+#include "target.h"
+#include "output.h"
 
 static rtx break_out_memory_refs (rtx);
 static void emit_stack_probe (rtx);
@@ -50,8 +53,7 @@ trunc_int_for_mode (HOST_WIDE_INT c, enum machine_mode mode)
   int width = GET_MODE_BITSIZE (mode);
 
   /* You want to truncate to a _what_?  */
-  if (! SCALAR_INT_MODE_P (mode))
-    abort ();
+  gcc_assert (SCALAR_INT_MODE_P (mode));
 
   /* Canonicalize BImode to 0 and STORE_FLAG_VALUE.  */
   if (mode == BImode)
@@ -71,12 +73,10 @@ trunc_int_for_mode (HOST_WIDE_INT c, enum machine_mode mode)
   return c;
 }
 
-/* Return an rtx for the sum of X and the integer C.
-
-   This function should be used via the `plus_constant' macro.  */
+/* Return an rtx for the sum of X and the integer C.  */
 
 rtx
-plus_constant_wide (rtx x, HOST_WIDE_INT c)
+plus_constant (rtx x, HOST_WIDE_INT c)
 {
   RTX_CODE code;
   rtx y;
@@ -240,9 +240,18 @@ eliminate_constant_term (rtx x, rtx *constptr)
 rtx
 expr_size (tree exp)
 {
-  tree size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (lang_hooks.expr_size (exp), exp);
+  tree size;
+
+  if (TREE_CODE (exp) == WITH_SIZE_EXPR)
+    size = TREE_OPERAND (exp, 1);
+  else
+    {
+      size = lang_hooks.expr_size (exp);
+      gcc_assert (size);
+      size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (size, exp);
+    }
 
-  return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), 0);
+  return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), EXPAND_NORMAL);
 }
 
 /* Return a wide integer for the size in bytes of the value of EXP, or -1
@@ -251,17 +260,20 @@ expr_size (tree exp)
 HOST_WIDE_INT
 int_expr_size (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)
+  tree size;
+
+  if (TREE_CODE (exp) == WITH_SIZE_EXPR)
+    size = TREE_OPERAND (exp, 1);
+  else
+    {
+      size = lang_hooks.expr_size (exp);
+      gcc_assert (size);
+    }
+
+  if (size == 0 || !host_integerp (size, 0))
     return -1;
 
-  return TREE_INT_CST_LOW (t);
+  return tree_low_cst (size, 0);
 }
 \f
 /* Return a copy of X in which all memory references
@@ -294,7 +306,7 @@ break_out_memory_refs (rtx x)
       rtx op1 = break_out_memory_refs (XEXP (x, 1));
 
       if (op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
-       x = gen_rtx_fmt_ee (GET_CODE (x), Pmode, op0, op1);
+       x = simplify_gen_binary (GET_CODE (x), Pmode, op0, op1);
     }
 
   return x;
@@ -311,6 +323,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;
@@ -369,12 +382,15 @@ convert_memory_address (enum machine_mode to_mode ATTRIBUTE_UNUSED,
     case MULT:
       /* 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.  */
+        does not change it or if one operand is a constant and we are
+        using a ptr_extend instruction  (POINTERS_EXTEND_UNSIGNED < 0).
+        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))))
+             && (XEXP (x, 1) == convert_memory_address (to_mode, XEXP (x, 1))
+                 || POINTERS_EXTEND_UNSIGNED < 0)))
        return gen_rtx_fmt_ee (GET_CODE (x), to_mode,
                               convert_memory_address (to_mode, XEXP (x, 0)),
                               XEXP (x, 1));
@@ -388,44 +404,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
@@ -443,14 +421,6 @@ memory_address (enum machine_mode mode, rtx x)
   if (! cse_not_expected && CONSTANT_P (x) && CONSTANT_ADDRESS_P (x))
     x = force_reg (Pmode, x);
 
-  /* Accept a QUEUED that refers to a REG
-     even though that isn't a valid address.
-     On attempting to put this in an insn we will call protect_from_queue
-     which will turn it into a REG, which is valid.  */
-  else if (GET_CODE (x) == QUEUED
-      && REG_P (QUEUED_VAR (x)))
-    ;
-
   /* We get better cse by rejecting indirect addressing at this stage.
      Let the combiner create indirect addresses where appropriate.
      For now, generate the code so that the subexpressions useful to share
@@ -461,18 +431,22 @@ memory_address (enum machine_mode mode, rtx x)
        x = break_out_memory_refs (x);
 
       /* At this point, any valid address is accepted.  */
-      GO_IF_LEGITIMATE_ADDRESS (mode, x, win);
+      if (memory_address_p (mode, x))
+       goto done;
 
       /* If it was valid before but breaking out memory refs invalidated it,
         use it the old way.  */
       if (memory_address_p (mode, oldx))
-       goto win2;
+       {
+         x = oldx;
+         goto done;
+       }
 
       /* Perform machine-dependent transformations on X
         in certain cases.  This is not necessary since the code
         below can handle all possible cases, but machine-dependent
         transformations can make better code.  */
-      LEGITIMIZE_ADDRESS (x, oldx, mode, win);
+      LEGITIMIZE_ADDRESS (x, oldx, mode, done);
 
       /* PLUS and MULT can appear in special ways
         as the result of attempts to make an address usable for indexing.
@@ -512,27 +486,11 @@ memory_address (enum machine_mode mode, rtx x)
         the register is a valid address.  */
       else
        x = force_reg (Pmode, x);
-
-      goto done;
-
-    win2:
-      x = oldx;
-    win:
-      if (flag_force_addr && ! cse_not_expected && !REG_P (x)
-         /* Don't copy an addr via a reg if it is one of our stack slots.  */
-         && ! (GET_CODE (x) == PLUS
-               && (XEXP (x, 0) == virtual_stack_vars_rtx
-                   || XEXP (x, 0) == virtual_incoming_args_rtx)))
-       {
-         if (general_operand (x, Pmode))
-           x = force_reg (Pmode, x);
-         else
-           x = force_operand (x, NULL_RTX);
-       }
     }
 
  done:
 
+  gcc_assert (memory_address_p (mode, x));
   /* If we didn't change the address, we are done.  Otherwise, mark
      a reg as a pointer if we have REG or REG + CONST_INT.  */
   if (oldx == x)
@@ -551,20 +509,6 @@ memory_address (enum machine_mode mode, rtx x)
   return x;
 }
 
-/* Like `memory_address' but pretend `flag_force_addr' is 0.  */
-
-rtx
-memory_address_noforce (enum machine_mode mode, rtx x)
-{
-  int ambient_force_addr = flag_force_addr;
-  rtx val;
-
-  flag_force_addr = 0;
-  val = memory_address (mode, x);
-  flag_force_addr = ambient_force_addr;
-  return val;
-}
-
 /* Convert a mem ref into one with a valid memory address.
    Pass through anything else unchanged.  */
 
@@ -573,56 +517,67 @@ validize_mem (rtx ref)
 {
   if (!MEM_P (ref))
     return ref;
-  if (! (flag_force_addr && CONSTANT_ADDRESS_P (XEXP (ref, 0)))
-      && memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
+  ref = use_anchored_address (ref);
+  if (memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
     return ref;
 
   /* Don't alter REF itself, since that is probably a stack slot.  */
   return replace_equiv_address (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 (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.
-
-     We cannot do this for non-static aggregates, because of the double
-     writes that can be generated by store_constructor, depending on the
-     contents of the initializer.  Yes, this does eliminate a good fraction
-     of the number of uses of RTX_UNCHANGING_P for a language like Ada.
-     It also eliminates a good quantity of bugs.  Let this be incentive to
-     eliminate RTX_UNCHANGING_P entirely in favor of a more reliable
-     solution, perhaps based on alias sets.  */
-
-  if ((TREE_READONLY (t) && DECL_P (t)
-       && (TREE_STATIC (t) || ! AGGREGATE_TYPE_P (TREE_TYPE (t)))
-       && (TREE_CODE (t) == PARM_DECL
-          || (DECL_INITIAL (t) && TREE_CONSTANT (DECL_INITIAL (t)))))
-      || TREE_CODE_CLASS (TREE_CODE (t)) == 'c')
-    RTX_UNCHANGING_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).
-   Perhaps even if it is a MEM, if there is no need to change it.  */
+/* If X is a memory reference to a member of an object block, try rewriting
+   it to use an anchor instead.  Return the new memory reference on success
+   and the old one on failure.  */
 
 rtx
-stabilize (rtx x)
+use_anchored_address (rtx x)
 {
-  if (!MEM_P (x)
-      || ! rtx_unstable_p (XEXP (x, 0)))
+  rtx base;
+  HOST_WIDE_INT offset;
+
+  if (!flag_section_anchors)
+    return x;
+
+  if (!MEM_P (x))
+    return x;
+
+  /* Split the address into a base and offset.  */
+  base = XEXP (x, 0);
+  offset = 0;
+  if (GET_CODE (base) == CONST
+      && GET_CODE (XEXP (base, 0)) == PLUS
+      && GET_CODE (XEXP (XEXP (base, 0), 1)) == CONST_INT)
+    {
+      offset += INTVAL (XEXP (XEXP (base, 0), 1));
+      base = XEXP (XEXP (base, 0), 0);
+    }
+
+  /* Check whether BASE is suitable for anchors.  */
+  if (GET_CODE (base) != SYMBOL_REF
+      || !SYMBOL_REF_HAS_BLOCK_INFO_P (base)
+      || SYMBOL_REF_ANCHOR_P (base)
+      || SYMBOL_REF_BLOCK (base) == NULL
+      || !targetm.use_anchors_for_symbol_p (base))
     return x;
 
-  return
-    replace_equiv_address (x, force_reg (Pmode, copy_all_regs (XEXP (x, 0))));
+  /* Decide where BASE is going to be.  */
+  place_block_symbol (base);
+
+  /* Get the anchor we need to use.  */
+  offset += SYMBOL_REF_BLOCK_OFFSET (base);
+  base = get_section_anchor (SYMBOL_REF_BLOCK (base), offset,
+                            SYMBOL_REF_TLS_MODEL (base));
+
+  /* Work out the offset from the anchor.  */
+  offset -= SYMBOL_REF_BLOCK_OFFSET (base);
+
+  /* If we're going to run a CSE pass, force the anchor into a register.
+     We will then be able to reuse registers for several accesses, if the
+     target costs say that that's worthwhile.  */
+  if (!cse_not_expected)
+    base = force_reg (GET_MODE (base), base);
+
+  return replace_equiv_address (x, plus_constant (base, offset));
 }
 \f
 /* Copy the value or contents of X to a new temp reg and return that reg.  */
@@ -665,8 +620,7 @@ copy_to_mode_reg (enum machine_mode mode, rtx x)
   if (! general_operand (x, VOIDmode))
     x = force_operand (x, temp);
 
-  if (GET_MODE (x) != mode && GET_MODE (x) != VOIDmode)
-    abort ();
+  gcc_assert (GET_MODE (x) == mode || GET_MODE (x) == VOIDmode);
   if (x != temp)
     emit_move_insn (temp, x);
   return temp;
@@ -745,7 +699,7 @@ force_reg (enum machine_mode mode, rtx x)
        align = MIN (sa, ca);
       }
 
-    if (align)
+    if (align || (MEM_P (x) && MEM_POINTER (x)))
       mark_reg_pointer (temp, align);
   }
 
@@ -801,10 +755,10 @@ copy_to_suggested_reg (rtx x, rtx target, enum machine_mode mode)
 #endif
 
 enum machine_mode
-promote_mode (tree type, enum machine_mode mode, int *punsignedp,
+promote_mode (const_tree type, enum machine_mode mode, int *punsignedp,
              int for_call ATTRIBUTE_UNUSED)
 {
-  enum tree_code code = TREE_CODE (type);
+  const enum tree_code code = TREE_CODE (type);
   int unsignedp = *punsignedp;
 
 #ifndef PROMOTE_MODE
@@ -816,7 +770,7 @@ promote_mode (tree type, enum machine_mode mode, int *punsignedp,
     {
 #ifdef PROMOTE_FUNCTION_MODE
     case INTEGER_TYPE:   case ENUMERAL_TYPE:   case BOOLEAN_TYPE:
-    case CHAR_TYPE:      case REAL_TYPE:       case OFFSET_TYPE:
+    case REAL_TYPE:      case OFFSET_TYPE:     case FIXED_POINT_TYPE:
 #ifdef PROMOTE_MODE
       if (for_call)
        {
@@ -855,7 +809,6 @@ void
 adjust_stack (rtx adjust)
 {
   rtx temp;
-  adjust = protect_from_queue (adjust, 0);
 
   if (adjust == const0_rtx)
     return;
@@ -885,7 +838,6 @@ void
 anti_adjust_stack (rtx adjust)
 {
   rtx temp;
-  adjust = protect_from_queue (adjust, 0);
 
   if (adjust == const0_rtx)
     return;
@@ -911,7 +863,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;
@@ -921,10 +873,10 @@ round_push (rtx size)
 
   if (GET_CODE (size) == CONST_INT)
     {
-      HOST_WIDE_INT new = (INTVAL (size) + align - 1) / align * align;
+      HOST_WIDE_INT new_size = (INTVAL (size) + align - 1) / align * align;
 
-      if (INTVAL (size) != new)
-       size = GEN_INT (new);
+      if (INTVAL (size) != new_size)
+       size = GEN_INT (new_size);
     }
   else
     {
@@ -1001,6 +953,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)
@@ -1012,6 +965,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));
@@ -1061,13 +1015,12 @@ emit_stack_restore (enum save_level save_level, rtx sa, rtx after)
       /* 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)));
+      emit_clobber (gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode)));
+      emit_clobber (gen_rtx_MEM (BLKmode, stack_pointer_rtx));
     }
 
+  discard_pending_stack_adjust ();
+
   if (after)
     {
       rtx seq;
@@ -1096,92 +1049,13 @@ update_nonlocal_goto_save_area (void)
      first one is used for the frame pointer save; the rest are sized by
      STACK_SAVEAREA_MODE.  Create a reference to array index 1, the first
      of the stack save area slots.  */
-  t_save = build (ARRAY_REF, ptr_type_node, cfun->nonlocal_goto_save_area,
-                 integer_one_node, NULL_TREE, NULL_TREE);
+  t_save = build4 (ARRAY_REF, ptr_type_node, cfun->nonlocal_goto_save_area,
+                  integer_one_node, NULL_TREE, NULL_TREE);
   r_save = expand_expr (t_save, NULL_RTX, VOIDmode, EXPAND_WRITE);
 
   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 (rtx insns)
-{
-  rtx insn;
-
-  for (insn = insns; insn; insn = NEXT_INSN(insn))
-    {
-      rtx note;
-
-      if (GET_CODE (insn) != 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.  */
-             if (GET_CODE (pat) != SET
-                 || SET_DEST (pat) != stack_pointer_rtx
-                 || GET_CODE (SET_SRC (pat)) != MINUS
-                 || XEXP (SET_SRC (pat), 0) != stack_pointer_rtx)
-               abort ();
-
-             /* 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;
-
-                 if (srch == NULL_RTX)
-                   abort ();
-
-                 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.
@@ -1196,10 +1070,6 @@ optimize_save_area_alloca (rtx insns)
 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.  */
@@ -1207,7 +1077,7 @@ allocate_dynamic_stack_space (rtx size, rtx target, int known_align)
     return virtual_stack_dynamic_rtx;
 
   /* Otherwise, show we're calling alloca or equivalent.  */
-  current_function_calls_alloca = 1;
+  cfun->calls_alloca = 1;
 
   /* Ensure the size is in the proper mode.  */
   if (GET_MODE (size) != VOIDmode && GET_MODE (size) != Pmode)
@@ -1216,7 +1086,7 @@ allocate_dynamic_stack_space (rtx size, rtx target, int known_align)
   /* We can't attempt to minimize alignment necessary, because we don't
      know the final value of preferred_stack_boundary yet while executing
      this code.  */
-  cfun->preferred_stack_boundary = PREFERRED_STACK_BOUNDARY;
+  crtl->preferred_stack_boundary = PREFERRED_STACK_BOUNDARY;
 
   /* We will need to ensure that the address we return is aligned to
      BIGGEST_ALIGNMENT.  If STACK_DYNAMIC_OFFSET is defined, we don't
@@ -1248,52 +1118,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 (!cfun->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.  */
-       if (PREFERRED_STACK_BOUNDARY != BIGGEST_ALIGNMENT)
-         abort ();
-
-       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_size = INTVAL (size) / align * align;
+
+         if (INTVAL (size) != new_size)
+           size = GEN_INT (new_size);
+       }
+      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.
@@ -1321,13 +1186,16 @@ allocate_dynamic_stack_space (rtx size, rtx target, int known_align)
 
  /* We ought to be called always on the toplevel and stack ought to be aligned
     properly.  */
-  if (stack_pointer_delta % (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT))
-    abort ();
+  gcc_assert (!(stack_pointer_delta
+               % (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT)));
 
-  /* If needed, check that we have the required amount of stack.  Take into
-     account what has already been checked.  */
-  if (flag_stack_check && ! STACK_CHECK_BUILTIN)
-    probe_stack_range (STACK_CHECK_MAX_FRAME_SIZE + STACK_CHECK_PROTECT, size);
+  /* If needed, check that we have the required amount of stack.
+     Take into account what has already been checked.  */
+  if (flag_stack_check == GENERIC_STACK_CHECK)
+    probe_stack_range (STACK_OLD_CHECK_PROTECT + STACK_CHECK_MAX_FRAME_SIZE,
+                      size);
+  else if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK)
+    probe_stack_range (STACK_CHECK_PROTECT, size);
 
   /* Don't use a TARGET that isn't a pseudo or is the wrong mode.  */
   if (target == 0 || !REG_P (target)
@@ -1367,7 +1235,7 @@ allocate_dynamic_stack_space (rtx size, rtx target, int known_align)
 #endif
 
       /* Check stack bounds if necessary.  */
-      if (current_function_limit_stack)
+      if (crtl->limit_stack)
        {
          rtx available;
          rtx space_available = gen_label_rtx ();
@@ -1393,16 +1261,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);
@@ -1573,8 +1431,7 @@ probe_stack_range (HOST_WIDE_INT first, rtx size)
                           1, OPTAB_WIDEN);
 #endif
 
-      if (temp != test_addr)
-       abort ();
+      gcc_assert (temp == test_addr);
 
       emit_label (test_lab);
       emit_cmp_and_jump_insns (test_addr, last_addr, CMP_OPCODE,
@@ -1589,24 +1446,19 @@ probe_stack_range (HOST_WIDE_INT first, rtx size)
 /* Return an rtx representing the register or memory location
    in which a scalar value of data type VALTYPE
    was returned by a function call to function FUNC.
-   FUNC is a FUNCTION_DECL node if the precise function is known,
-   otherwise 0.
+   FUNC is a FUNCTION_DECL, FNTYPE a FUNCTION_TYPE node if the precise
+   function is known, otherwise 0.
    OUTGOING is 1 if on a machine with register windows this function
    should return the register in which the function will put its result
    and 0 otherwise.  */
 
 rtx
-hard_function_value (tree valtype, tree func ATTRIBUTE_UNUSED,
+hard_function_value (const_tree valtype, const_tree func, const_tree fntype,
                     int outgoing ATTRIBUTE_UNUSED)
 {
   rtx val;
 
-#ifdef FUNCTION_OUTGOING_VALUE
-  if (outgoing)
-    val = FUNCTION_OUTGOING_VALUE (valtype, func);
-  else
-#endif
-    val = FUNCTION_VALUE (valtype, func);
+  val = targetm.calls.function_value (valtype, func ? func : fntype, outgoing);
 
   if (REG_P (val)
       && GET_MODE (val) == BLKmode)
@@ -1615,8 +1467,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;
@@ -1628,8 +1480,7 @@ hard_function_value (tree valtype, tree func ATTRIBUTE_UNUSED,
        }
 
       /* No suitable mode found.  */
-      if (tmpmode == VOIDmode)
-       abort ();
+      gcc_assert (tmpmode != VOIDmode);
 
       PUT_MODE (val, tmpmode);
     }