OSDN Git Service

optimize
[pf3gnuchains/gcc-fork.git] / gcc / expr.c
index 9bc7721..a3e64f4 100644 (file)
@@ -77,14 +77,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #endif
 #endif
 
-/* Convert defined/undefined to boolean.  */
-#ifdef TARGET_MEM_FUNCTIONS
-#undef TARGET_MEM_FUNCTIONS
-#define TARGET_MEM_FUNCTIONS 1
-#else
-#define TARGET_MEM_FUNCTIONS 0
-#endif
-
 
 /* If this is nonzero, we do not bother generating VOLATILE
    around volatile memory references, and we are willing to
@@ -1349,11 +1341,6 @@ emit_block_move (rtx x, rtx y, rtx size, enum block_op_methods method)
 
   align = MIN (MEM_ALIGN (x), MEM_ALIGN (y));
 
-  if (GET_MODE (x) != BLKmode)
-    abort ();
-  if (GET_MODE (y) != BLKmode)
-    abort ();
-
   x = protect_from_queue (x, 1);
   y = protect_from_queue (y, 0);
   size = protect_from_queue (size, 0);
@@ -1365,6 +1352,11 @@ emit_block_move (rtx x, rtx y, rtx size, enum block_op_methods method)
   if (size == 0)
     abort ();
 
+  /* Make sure we've got BLKmode addresses; store_one_arg can decide that
+     block copy is more efficient for other large modes, e.g. DCmode.  */
+  x = adjust_address (x, BLKmode, 0);
+  y = adjust_address (y, BLKmode, 0);
+
   /* Set MEM_SIZE as appropriate for this block copy.  The main place this
      can be incorrect is coming from __builtin_memcpy.  */
   if (GET_CODE (size) == CONST_INT)
@@ -1511,7 +1503,7 @@ emit_block_move_via_movstr (rtx x, rtx y, rtx size, unsigned int align)
   return false;
 }
 
-/* A subroutine of emit_block_move.  Expand a call to memcpy or bcopy.
+/* A subroutine of emit_block_move.  Expand a call to memcpy.
    Return the return value from memcpy, 0 otherwise.  */
 
 static rtx
@@ -1533,9 +1525,7 @@ emit_block_move_via_libcall (rtx dst, rtx src, rtx size)
      could get the wrong value for an argument.
 
      To avoid this problem we go ahead and emit code to copy the addresses of
-     DST and SRC and SIZE into new pseudos.  We can then place those new
-     pseudos into an RTL_EXPR and use them later, even after a call to
-     emit_queue.
+     DST and SRC and SIZE into new pseudos.
 
      Note this is not strictly needed for library calls since they do not call
      emit_queue before loading their arguments.  However, we may need to have
@@ -1552,10 +1542,7 @@ emit_block_move_via_libcall (rtx dst, rtx src, rtx size)
   dst_tree = make_tree (ptr_type_node, dst_addr);
   src_tree = make_tree (ptr_type_node, src_addr);
 
-  if (TARGET_MEM_FUNCTIONS)
-    size_mode = TYPE_MODE (sizetype);
-  else
-    size_mode = TYPE_MODE (unsigned_type_node);
+  size_mode = TYPE_MODE (sizetype);
 
   size = convert_to_mode (size_mode, size, 1);
   size = copy_to_mode_reg (size_mode, size);
@@ -1564,27 +1551,14 @@ emit_block_move_via_libcall (rtx dst, rtx src, rtx size)
      memcpy in this context.  This could be a user call to memcpy and
      the user may wish to examine the return value from memcpy.  For
      targets where libcalls and normal calls have different conventions
-     for returning pointers, we could end up generating incorrect code.
+     for returning pointers, we could end up generating incorrect code.  */
 
-     For convenience, we generate the call to bcopy this way as well.  */
-
-  if (TARGET_MEM_FUNCTIONS)
-    size_tree = make_tree (sizetype, size);
-  else
-    size_tree = make_tree (unsigned_type_node, size);
+  size_tree = make_tree (sizetype, size);
 
   fn = emit_block_move_libcall_fn (true);
   arg_list = tree_cons (NULL_TREE, size_tree, NULL_TREE);
-  if (TARGET_MEM_FUNCTIONS)
-    {
-      arg_list = tree_cons (NULL_TREE, src_tree, arg_list);
-      arg_list = tree_cons (NULL_TREE, dst_tree, arg_list);
-    }
-  else
-    {
-      arg_list = tree_cons (NULL_TREE, dst_tree, arg_list);
-      arg_list = tree_cons (NULL_TREE, src_tree, arg_list);
-    }
+  arg_list = tree_cons (NULL_TREE, src_tree, arg_list);
+  arg_list = tree_cons (NULL_TREE, dst_tree, arg_list);
 
   /* Now we have to build up the CALL_EXPR itself.  */
   call_expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
@@ -1603,7 +1577,7 @@ emit_block_move_via_libcall (rtx dst, rtx src, rtx size)
                                             gen_rtx_CLOBBER (VOIDmode, dst),
                                             NULL_RTX));
 
-  return TARGET_MEM_FUNCTIONS ? retval : NULL_RTX;
+  return retval;
 }
 
 /* A subroutine of emit_block_move_via_libcall.  Create the tree node
@@ -1619,20 +1593,10 @@ init_block_move_fn (const char *asmspec)
     {
       tree args, fn;
 
-      if (TARGET_MEM_FUNCTIONS)
-       {
-         fn = get_identifier ("memcpy");
-         args = build_function_type_list (ptr_type_node, ptr_type_node,
-                                          const_ptr_type_node, sizetype,
-                                          NULL_TREE);
-       }
-      else
-       {
-         fn = get_identifier ("bcopy");
-         args = build_function_type_list (void_type_node, const_ptr_type_node,
-                                          ptr_type_node, unsigned_type_node,
-                                          NULL_TREE);
-       }
+      fn = get_identifier ("memcpy");
+      args = build_function_type_list (ptr_type_node, ptr_type_node,
+                                      const_ptr_type_node, sizetype,
+                                      NULL_TREE);
 
       fn = build_decl (FUNCTION_DECL, fn, args);
       DECL_EXTERNAL (fn) = 1;
@@ -1959,8 +1923,8 @@ emit_group_load (rtx dst, rtx orig_src, tree type ATTRIBUTE_UNUSED, int ssize)
                                     mode, mode, ssize);
 
       if (shift)
-       expand_binop (mode, ashl_optab, tmps[i], GEN_INT (shift),
-                     tmps[i], 0, OPTAB_WIDEN);
+       tmps[i] = expand_shift (LSHIFT_EXPR, mode, tmps[i],
+                               build_int_2 (shift, 0), tmps[i], 0);
     }
 
   emit_queue ();
@@ -2073,8 +2037,8 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
              )
            {
              int shift = (bytelen - (ssize - bytepos)) * BITS_PER_UNIT;
-             expand_binop (mode, ashr_optab, tmps[i], GEN_INT (shift),
-                           tmps[i], 0, OPTAB_WIDEN);
+             tmps[i] = expand_shift (RSHIFT_EXPR, mode, tmps[i],
+                                     build_int_2 (shift, 0), tmps[i], 0);
            }
          bytelen = ssize - bytepos;
        }
@@ -2644,7 +2608,7 @@ clear_storage_via_clrstr (rtx object, rtx size, unsigned int align)
   return false;
 }
 
-/* A subroutine of clear_storage.  Expand a call to memset or bzero.
+/* A subroutine of clear_storage.  Expand a call to memset.
    Return the return value of memset, 0 otherwise.  */
 
 static rtx
@@ -2665,9 +2629,7 @@ clear_storage_via_libcall (rtx object, rtx size)
      not careful we could get the wrong value for an argument.
 
      To avoid this problem we go ahead and emit code to copy OBJECT
-     and SIZE into new pseudos.  We can then place those new pseudos
-     into an RTL_EXPR and use them later, even after a call to
-     emit_queue.
+     and SIZE into new pseudos.
 
      Note this is not strictly needed for library calls since they
      do not call emit_queue before loading their arguments.  However,
@@ -2677,10 +2639,7 @@ clear_storage_via_libcall (rtx object, rtx size)
 
   object = copy_to_mode_reg (Pmode, XEXP (object, 0));
 
-  if (TARGET_MEM_FUNCTIONS)
-    size_mode = TYPE_MODE (sizetype);
-  else
-    size_mode = TYPE_MODE (unsigned_type_node);
+  size_mode = TYPE_MODE (sizetype);
   size = convert_to_mode (size_mode, size, 1);
   size = copy_to_mode_reg (size_mode, size);
 
@@ -2688,20 +2647,14 @@ clear_storage_via_libcall (rtx object, rtx size)
      memset in this context.  This could be a user call to memset and
      the user may wish to examine the return value from memset.  For
      targets where libcalls and normal calls have different conventions
-     for returning pointers, we could end up generating incorrect code.
-
-     For convenience, we generate the call to bzero this way as well.  */
+     for returning pointers, we could end up generating incorrect code.  */
 
   object_tree = make_tree (ptr_type_node, object);
-  if (TARGET_MEM_FUNCTIONS)
-    size_tree = make_tree (sizetype, size);
-  else
-    size_tree = make_tree (unsigned_type_node, size);
+  size_tree = make_tree (sizetype, size);
 
   fn = clear_storage_libcall_fn (true);
   arg_list = tree_cons (NULL_TREE, size_tree, NULL_TREE);
-  if (TARGET_MEM_FUNCTIONS)
-    arg_list = tree_cons (NULL_TREE, integer_zero_node, arg_list);
+  arg_list = tree_cons (NULL_TREE, integer_zero_node, arg_list);
   arg_list = tree_cons (NULL_TREE, object_tree, arg_list);
 
   /* Now we have to build up the CALL_EXPR itself.  */
@@ -2717,7 +2670,7 @@ clear_storage_via_libcall (rtx object, rtx size)
   if (RTX_UNCHANGING_P (object))
     emit_insn (gen_rtx_CLOBBER (VOIDmode, object));
 
-  return (TARGET_MEM_FUNCTIONS ? retval : NULL_RTX);
+  return retval;
 }
 
 /* A subroutine of clear_storage_via_libcall.  Create the tree node
@@ -2733,19 +2686,10 @@ init_block_clear_fn (const char *asmspec)
     {
       tree fn, args;
 
-      if (TARGET_MEM_FUNCTIONS)
-       {
-         fn = get_identifier ("memset");
-         args = build_function_type_list (ptr_type_node, ptr_type_node,
-                                          integer_type_node, sizetype,
-                                          NULL_TREE);
-       }
-      else
-       {
-         fn = get_identifier ("bzero");
-         args = build_function_type_list (void_type_node, ptr_type_node,
-                                          unsigned_type_node, NULL_TREE);
-       }
+      fn = get_identifier ("memset");
+      args = build_function_type_list (ptr_type_node, ptr_type_node,
+                                      integer_type_node, sizetype,
+                                      NULL_TREE);
 
       fn = build_decl (FUNCTION_DECL, fn, args);
       DECL_EXTERNAL (fn) = 1;
@@ -3858,23 +3802,38 @@ expand_assignment (tree to, tree from, int want_value)
          MEM_KEEP_ALIAS_SET_P (to_rtx) = 1;
        }
 
-      if (mode1 == VOIDmode && !want_value
-         && bitpos + bitsize <= BITS_PER_WORD
-         && bitsize < BITS_PER_WORD
-         && GET_MODE_BITSIZE (GET_MODE (to_rtx)) <= BITS_PER_WORD
-         && !TREE_SIDE_EFFECTS (to)
-         && TREE_CODE (TREE_TYPE (from)) == INTEGER_TYPE
-         && TREE_CODE_CLASS (TREE_CODE (from)) == '2'
-         && operand_equal_p (to, TREE_OPERAND (from, 0), 0))
+      /* Disabled temporarily.  GET_MODE (to_rtx) is often not the right
+        mode.  */
+      while (0 && mode1 == VOIDmode && !want_value
+            && bitpos + bitsize <= BITS_PER_WORD
+            && bitsize < BITS_PER_WORD
+            && GET_MODE_BITSIZE (GET_MODE (to_rtx)) <= BITS_PER_WORD
+            && !TREE_SIDE_EFFECTS (to)
+            && !TREE_THIS_VOLATILE (to))
        {
+         tree src, op0, op1;
          rtx value;
          HOST_WIDE_INT count = bitpos;
+         optab binop;
+
+         src = from;
+         STRIP_NOPS (src);
+         if (TREE_CODE (TREE_TYPE (src)) != INTEGER_TYPE
+             || TREE_CODE_CLASS (TREE_CODE (src)) != '2')
+           break;
+
+         op0 = TREE_OPERAND (src, 0);
+         op1 = TREE_OPERAND (src, 1);
+         STRIP_NOPS (op0);
+
+         if (! operand_equal_p (to, op0, 0))
+           break;
 
          if (BYTES_BIG_ENDIAN)
            count = GET_MODE_BITSIZE (GET_MODE (to_rtx)) - bitpos - bitsize;
 
          /* Special case some bitfield op= exp.  */
-         switch (TREE_CODE (from))
+         switch (TREE_CODE (src))
            {
            case PLUS_EXPR:
            case MINUS_EXPR:
@@ -3882,22 +3841,29 @@ expand_assignment (tree to, tree from, int want_value)
                break;
 
              /* For now, just optimize the case of the topmost bitfield
-                where we don't need to do any masking.
+                where we don't need to do any masking and also
+                1 bit bitfields where xor can be used.
                 We might win by one instruction for the other bitfields
                 too if insv/extv instructions aren't used, so that
                 can be added later.  */
-             if (count + bitsize != GET_MODE_BITSIZE (GET_MODE (to_rtx)))
+             if (count + bitsize != GET_MODE_BITSIZE (GET_MODE (to_rtx))
+                 && (bitsize != 1 || TREE_CODE (op1) != INTEGER_CST))
                break;
-             value = expand_expr (TREE_OPERAND (from, 1), NULL_RTX,
-                                  VOIDmode, 0);
+             value = expand_expr (op1, NULL_RTX, VOIDmode, 0);
              value = protect_from_queue (value, 0);
              to_rtx = protect_from_queue (to_rtx, 1);
+             binop = TREE_CODE (src) == PLUS_EXPR ? add_optab : sub_optab;
+             if (bitsize == 1
+                 && count + bitsize != GET_MODE_BITSIZE (GET_MODE (to_rtx)))
+               {
+                 value = expand_and (GET_MODE (to_rtx), value, const1_rtx,
+                                     NULL_RTX);
+                 binop = xor_optab;
+               }
              value = expand_shift (LSHIFT_EXPR, GET_MODE (to_rtx),
                                    value, build_int_2 (count, 0),
                                    NULL_RTX, 1);
-             result = expand_binop (GET_MODE (to_rtx),
-                                    TREE_CODE (from) == PLUS_EXPR
-                                    ? add_optab : sub_optab, to_rtx,
+             result = expand_binop (GET_MODE (to_rtx), binop, to_rtx,
                                     value, to_rtx, 1, OPTAB_WIDEN);
              if (result != to_rtx)
                emit_move_insn (to_rtx, result);
@@ -3907,6 +3873,8 @@ expand_assignment (tree to, tree from, int want_value)
            default:
              break;
            }
+
+         break;
        }
 
       result = store_field (to_rtx, bitsize, bitpos, mode1, from,
@@ -4011,21 +3979,12 @@ expand_assignment (tree to, tree from, int want_value)
       size = expr_size (from);
       from_rtx = expand_expr (from, NULL_RTX, VOIDmode, 0);
 
-      if (TARGET_MEM_FUNCTIONS)
-       emit_library_call (memmove_libfunc, LCT_NORMAL,
-                          VOIDmode, 3, XEXP (to_rtx, 0), Pmode,
-                          XEXP (from_rtx, 0), Pmode,
-                          convert_to_mode (TYPE_MODE (sizetype),
-                                           size, TYPE_UNSIGNED (sizetype)),
-                          TYPE_MODE (sizetype));
-      else
-        emit_library_call (bcopy_libfunc, LCT_NORMAL,
-                          VOIDmode, 3, XEXP (from_rtx, 0), Pmode,
-                          XEXP (to_rtx, 0), Pmode,
-                          convert_to_mode (TYPE_MODE (integer_type_node),
-                                           size,
-                                           TYPE_UNSIGNED (integer_type_node)),
-                          TYPE_MODE (integer_type_node));
+      emit_library_call (memmove_libfunc, LCT_NORMAL,
+                        VOIDmode, 3, XEXP (to_rtx, 0), Pmode,
+                        XEXP (from_rtx, 0), Pmode,
+                        convert_to_mode (TYPE_MODE (sizetype),
+                                         size, TYPE_UNSIGNED (sizetype)),
+                        TYPE_MODE (sizetype));
 
       preserve_temp_slots (to_rtx);
       free_temp_slots ();
@@ -4538,11 +4497,11 @@ count_type_elements (tree type)
        tree telts = array_type_nelts (type);
        if (telts && host_integerp (telts, 1))
          {
-           HOST_WIDE_INT n = tree_low_cst (telts, 1);
+           HOST_WIDE_INT n = tree_low_cst (telts, 1) + 1;
            HOST_WIDE_INT m = count_type_elements (TREE_TYPE (type));
            if (n == 0)
              return 0;
-           if (max / n < m)
+           else if (max / n > m)
              return n * m;
          }
        return -1;
@@ -5072,14 +5031,6 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
                    = gen_reg_rtx (promote_mode (domain, DECL_MODE (index),
                                                 &unsignedp, 0));
                  SET_DECL_RTL (index, index_r);
-                 if (TREE_CODE (value) == SAVE_EXPR
-                     && SAVE_EXPR_RTL (value) == 0)
-                   {
-                     /* Make sure value gets expanded once before the
-                         loop.  */
-                     expand_expr (value, const0_rtx, VOIDmode, 0);
-                     emit_queue ();
-                   }
                  store_expr (lo_index, index_r, 0);
 
                  /* Build the head of the loop.  */
@@ -5197,10 +5148,10 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
         and then "or" in whatever non-constant ranges we need in addition.
 
         If a large set is all zero or all ones, it is
-        probably better to set it using memset (if available) or bzero.
+        probably better to set it using memset.
         Also, if a large set has just a single range, it may also be
         better to first clear all the first clear the set (using
-        bzero/memset), and set the bits we want.  */
+        memset), and set the bits we want.  */
 
       /* Check for all zeros.  */
       if (elt == NULL_TREE && size > 0)
@@ -5332,8 +5283,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
 
          /* Optimization:  If startbit and endbit are constants divisible
             by BITS_PER_UNIT, call memset instead.  */
-         if (TARGET_MEM_FUNCTIONS
-             && TREE_CODE (startbit) == INTEGER_CST
+         if (TREE_CODE (startbit) == INTEGER_CST
              && TREE_CODE (endbit) == INTEGER_CST
              && (startb = TREE_INT_CST_LOW (startbit)) % BITS_PER_UNIT == 0
              && (endb = TREE_INT_CST_LOW (endbit) + 1) % BITS_PER_UNIT == 0)
@@ -5968,7 +5918,6 @@ safe_from_p (rtx x, tree exp, int top_p)
 {
   rtx exp_rtl = 0;
   int i, nops;
-  static tree save_expr_list;
 
   if (x == 0
       /* If EXP has varying size, we MUST use a target since we currently
@@ -6000,30 +5949,6 @@ safe_from_p (rtx x, tree exp, int top_p)
        return 0;
     }
 
-  /* A SAVE_EXPR might appear many times in the expression passed to the
-     top-level safe_from_p call, and if it has a complex subexpression,
-     examining it multiple times could result in a combinatorial explosion.
-     E.g. on an Alpha running at least 200MHz, a Fortran testcase compiled
-     with optimization took about 28 minutes to compile -- even though it was
-     only a few lines long.  So we mark each SAVE_EXPR we see with TREE_PRIVATE
-     and turn that off when we are done.  We keep a list of the SAVE_EXPRs
-     we have processed.  Note that the only test of top_p was above.  */
-
-  if (top_p)
-    {
-      int rtn;
-      tree t;
-
-      save_expr_list = 0;
-
-      rtn = safe_from_p (x, exp, 0);
-
-      for (t = save_expr_list; t != 0; t = TREE_CHAIN (t))
-       TREE_PRIVATE (TREE_PURPOSE (t)) = 0;
-
-      return rtn;
-    }
-
   /* Now look at our tree code and possibly recurse.  */
   switch (TREE_CODE_CLASS (TREE_CODE (exp)))
     {
@@ -6116,43 +6041,13 @@ safe_from_p (rtx x, tree exp, int top_p)
            return 0;
          break;
 
-       case RTL_EXPR:
-         /* If a sequence exists, we would have to scan every instruction
-            in the sequence to see if it was safe.  This is probably not
-            worthwhile.  */
-         if (RTL_EXPR_SEQUENCE (exp))
-           return 0;
-
-         exp_rtl = RTL_EXPR_RTL (exp);
-         break;
-
        case WITH_CLEANUP_EXPR:
          exp_rtl = WITH_CLEANUP_EXPR_RTL (exp);
          break;
 
        case CLEANUP_POINT_EXPR:
-         return safe_from_p (x, TREE_OPERAND (exp, 0), 0);
-
        case SAVE_EXPR:
-         exp_rtl = SAVE_EXPR_RTL (exp);
-         if (exp_rtl)
-           break;
-
-         /* If we've already scanned this, don't do it again.  Otherwise,
-            show we've scanned it and record for clearing the flag if we're
-            going on.  */
-         if (TREE_PRIVATE (exp))
-           return 1;
-
-         TREE_PRIVATE (exp) = 1;
-         if (! safe_from_p (x, TREE_OPERAND (exp, 0), 0))
-           {
-             TREE_PRIVATE (exp) = 0;
-             return 0;
-           }
-
-         save_expr_list = tree_cons (exp, NULL_TREE, save_expr_list);
-         return 1;
+         return safe_from_p (x, TREE_OPERAND (exp, 0), 0);
 
        case BIND_EXPR:
          /* The only operand we look at is operand 1.  The rest aren't
@@ -6548,8 +6443,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
   original_target = target;
   ignore = (target == const0_rtx
            || ((code == NON_LVALUE_EXPR || code == NOP_EXPR
-                || code == CONVERT_EXPR || code == REFERENCE_EXPR
-                || code == COND_EXPR || code == VIEW_CONVERT_EXPR)
+                || code == CONVERT_EXPR || code == COND_EXPR 
+     || code == VIEW_CONVERT_EXPR)
                && TREE_CODE (type) == VOID_TYPE));
 
   /* If we are going to ignore this result, we need only do something
@@ -6833,88 +6728,30 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
       return temp;
 
     case SAVE_EXPR:
-      context = decl_function_context (exp);
-
-      /* If this SAVE_EXPR was at global context, assume we are an
-        initialization function and move it into our context.  */
-      if (context == 0)
-       SAVE_EXPR_CONTEXT (exp) = current_function_decl;
-
-      if (context == current_function_decl)
-       context = 0;
-
-      /* If this is non-local, handle it.  */
-      if (context)
-       {
-         /* The following call just exists to abort if the context is
-            not of a containing function.  */
-         find_function_data (context);
-
-         temp = SAVE_EXPR_RTL (exp);
-         if (temp && REG_P (temp))
-           {
-             put_var_into_stack (exp, /*rescan=*/true);
-             temp = SAVE_EXPR_RTL (exp);
-           }
-         if (temp == 0 || !MEM_P (temp))
-           abort ();
-         return
-           replace_equiv_address (temp,
-                                  fix_lexical_addr (XEXP (temp, 0), exp));
-       }
-      if (SAVE_EXPR_RTL (exp) == 0)
-       {
-         if (mode == VOIDmode)
-           temp = const0_rtx;
-         else
-           temp = assign_temp (build_qualified_type (type,
-                                                     (TYPE_QUALS (type)
-                                                      | TYPE_QUAL_CONST)),
-                               3, 0, 0);
-
-         SAVE_EXPR_RTL (exp) = temp;
-         if (!optimize && REG_P (temp))
-           save_expr_regs = gen_rtx_EXPR_LIST (VOIDmode, temp,
-                                               save_expr_regs);
-
-         /* If the mode of TEMP does not match that of the expression, it
-            must be a promoted value.  We pass store_expr a SUBREG of the
-            wanted mode but mark it so that we know that it was already
-            extended.  */
-
-         if (REG_P (temp) && GET_MODE (temp) != mode)
-           {
-             temp = gen_lowpart_SUBREG (mode, SAVE_EXPR_RTL (exp));
-             promote_mode (type, mode, &unsignedp, 0);
-             SUBREG_PROMOTED_VAR_P (temp) = 1;
-             SUBREG_PROMOTED_UNSIGNED_SET (temp, unsignedp);
-           }
-
-         if (temp == const0_rtx)
-           expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
-         else
-           store_expr (TREE_OPERAND (exp, 0), temp,
-                       modifier == EXPAND_STACK_PARM ? 2 : 0);
+      {
+       tree val = TREE_OPERAND (exp, 0);
+       rtx ret = expand_expr_real_1 (val, target, tmode, modifier, alt_rtl);
 
-         TREE_USED (exp) = 1;
-       }
+       if (TREE_CODE (val) != VAR_DECL || !DECL_ARTIFICIAL (val))
+         {
+           /* We can indeed still hit this case, typically via builtin
+              expanders calling save_expr immediately before expanding
+              something.  Assume this means that we only have to deal
+              with non-BLKmode values.  */
+           if (GET_MODE (ret) == BLKmode)
+             abort ();
 
-      /* If the mode of SAVE_EXPR_RTL does not match that of the expression, it
-        must be a promoted value.  We return a SUBREG of the wanted mode,
-        but mark it so that we know that it was already extended.  */
+           val = build_decl (VAR_DECL, NULL, TREE_TYPE (exp));
+           DECL_ARTIFICIAL (val) = 1;
+           TREE_OPERAND (exp, 0) = val;
 
-      if (REG_P (SAVE_EXPR_RTL (exp))
-         && GET_MODE (SAVE_EXPR_RTL (exp)) != mode)
-       {
-         /* Compute the signedness and make the proper SUBREG.  */
-         promote_mode (type, mode, &unsignedp, 0);
-         temp = gen_lowpart_SUBREG (mode, SAVE_EXPR_RTL (exp));
-         SUBREG_PROMOTED_VAR_P (temp) = 1;
-         SUBREG_PROMOTED_UNSIGNED_SET (temp, unsignedp);
-         return temp;
-       }
+           if (!CONSTANT_P (ret))
+             ret = copy_to_reg (ret);
+           SET_DECL_RTL (val, ret);
+         }
 
-      return SAVE_EXPR_RTL (exp);
+        return ret;
+      }
 
     case UNSAVE_EXPR:
       {
@@ -6940,7 +6777,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
 
     case LABELED_BLOCK_EXPR:
       if (LABELED_BLOCK_BODY (exp))
-       expand_expr_stmt_value (LABELED_BLOCK_BODY (exp), 0, 1);
+       expand_expr_stmt (LABELED_BLOCK_BODY (exp));
       /* Should perhaps use expand_label, but this is simpler and safer.  */
       do_pending_stack_adjust ();
       emit_label (label_rtx (LABELED_BLOCK_LABEL (exp)));
@@ -6957,32 +6794,10 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        tree block = BIND_EXPR_BLOCK (exp);
        int mark_ends;
 
-       if (TREE_CODE (BIND_EXPR_BODY (exp)) != RTL_EXPR)
-         {
-           /* If we're in functions-as-trees mode, this BIND_EXPR represents
-              the block, so we need to emit NOTE_INSN_BLOCK_* notes.  */
-           mark_ends = (block != NULL_TREE);
-           expand_start_bindings_and_block (mark_ends ? 0 : 2, block);
-         }
-       else
-         {
-           /* If we're not in functions-as-trees mode, we've already emitted
-              those notes into our RTL_EXPR, so we just want to splice our BLOCK
-              into the enclosing one.  */
-           mark_ends = 0;
-
-           /* Need to open a binding contour here because
-              if there are any cleanups they must be contained here.  */
-           expand_start_bindings_and_block (2, NULL_TREE);
-
-           /* Mark the corresponding BLOCK for output in its proper place.  */
-           if (block)
-             {
-               if (TREE_USED (block))
-                 abort ();
-               lang_hooks.decls.insert_block (block);
-             }
-         }
+       /* If we're in functions-as-trees mode, this BIND_EXPR represents
+          the block, so we need to emit NOTE_INSN_BLOCK_* notes.  */
+       mark_ends = (block != NULL_TREE);
+       expand_start_bindings_and_block (mark_ends ? 0 : 2, block);
 
        /* If VARS have not yet been expanded, expand them now.  */
        expand_vars (BIND_EXPR_VARS (exp));
@@ -6999,20 +6814,6 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
        return temp;
       }
 
-    case RTL_EXPR:
-      if (RTL_EXPR_SEQUENCE (exp))
-       {
-         if (RTL_EXPR_SEQUENCE (exp) == const0_rtx)
-           abort ();
-         emit_insn (RTL_EXPR_SEQUENCE (exp));
-         RTL_EXPR_SEQUENCE (exp) = const0_rtx;
-       }
-      preserve_rtl_expr_result (RTL_EXPR_RTL (exp));
-      free_temps_for_rtl_expr (exp);
-      if (alt_rtl)
-       *alt_rtl = RTL_EXPR_ALT_RTL (exp);
-      return RTL_EXPR_RTL (exp);
-
     case CONSTRUCTOR:
       /* If we don't need the result, just ensure we evaluate any
         subexpressions.  */
@@ -7329,25 +7130,13 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                 && (offset != 0
                     || (code == ARRAY_RANGE_REF && mode == BLKmode)))
          {
-           /* If the operand is a SAVE_EXPR, we can deal with this by
-              forcing the SAVE_EXPR into memory.  */
-           if (TREE_CODE (TREE_OPERAND (exp, 0)) == SAVE_EXPR)
-             {
-               put_var_into_stack (TREE_OPERAND (exp, 0),
-                                   /*rescan=*/true);
-               op0 = SAVE_EXPR_RTL (TREE_OPERAND (exp, 0));
-             }
-           else
-             {
-               tree nt
-                 = build_qualified_type (TREE_TYPE (tem),
-                                         (TYPE_QUALS (TREE_TYPE (tem))
-                                          | TYPE_QUAL_CONST));
-               rtx memloc = assign_temp (nt, 1, 1, 1);
+           tree nt = build_qualified_type (TREE_TYPE (tem),
+                                           (TYPE_QUALS (TREE_TYPE (tem))
+                                            | TYPE_QUAL_CONST));
+           rtx memloc = assign_temp (nt, 1, 1, 1);
 
-               emit_move_insn (memloc, op0);
-               op0 = memloc;
-             }
+           emit_move_insn (memloc, op0);
+           op0 = memloc;
          }
 
        if (offset != 0)
@@ -7714,7 +7503,6 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
     case NON_LVALUE_EXPR:
     case NOP_EXPR:
     case CONVERT_EXPR:
-    case REFERENCE_EXPR:
       if (TREE_OPERAND (exp, 0) == error_mark_node)
        return const0_rtx;
 
@@ -7891,7 +7679,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                    && (GET_MODE_CLASS (mode) == MODE_INT)
                    ? addv_optab : add_optab;
 
-      /* If we are adding a constant, an RTL_EXPR that is sp, fp, or ap, and
+      /* If we are adding a constant, a VAR_DECL that is sp, fp, or ap, and
         something else, make sure we add the register to the constant and
         then to the other thing.  This case can occur during strength
         reduction and doing it this way will produce better code if the
@@ -7904,10 +7692,10 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
 
       if (TREE_CODE (TREE_OPERAND (exp, 0)) == PLUS_EXPR
          && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 1)) == INTEGER_CST
-         && TREE_CODE (TREE_OPERAND (exp, 1)) == RTL_EXPR
-         && (RTL_EXPR_RTL (TREE_OPERAND (exp, 1)) == frame_pointer_rtx
-             || RTL_EXPR_RTL (TREE_OPERAND (exp, 1)) == stack_pointer_rtx
-             || RTL_EXPR_RTL (TREE_OPERAND (exp, 1)) == arg_pointer_rtx))
+         && TREE_CODE (TREE_OPERAND (exp, 1)) == VAR_DECL
+         && (DECL_RTL (TREE_OPERAND (exp, 1)) == frame_pointer_rtx
+             || DECL_RTL (TREE_OPERAND (exp, 1)) == stack_pointer_rtx
+             || DECL_RTL (TREE_OPERAND (exp, 1)) == arg_pointer_rtx))
        {
          tree t = TREE_OPERAND (exp, 1);
 
@@ -8891,8 +8679,6 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
              {
                target = assign_temp (type, 2, 0, 1);
                SET_DECL_RTL (slot, target);
-               if (TREE_ADDRESSABLE (slot))
-                 put_var_into_stack (slot, /*rescan=*/false);
 
                /* Since SLOT is not known to the called function
                   to belong to its stack frame, we must build an explicit
@@ -8926,13 +8712,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                  return target;
              }
            else
-             {
-               SET_DECL_RTL (slot, target);
-               /* If we must have an addressable slot, then make sure that
-                  the RTL that we just stored in slot is OK.  */
-               if (TREE_ADDRESSABLE (slot))
-                 put_var_into_stack (slot, /*rescan=*/true);
-             }
+             SET_DECL_RTL (slot, target);
          }
 
        exp1 = TREE_OPERAND (exp, 3) = TREE_OPERAND (exp, 1);
@@ -9070,34 +8850,23 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
            op0 = force_const_mem (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))),
                                   op0);
          else if (REG_P (op0) || GET_CODE (op0) == SUBREG
-                  || GET_CODE (op0) == CONCAT || GET_CODE (op0) == ADDRESSOF
-                  || GET_CODE (op0) == PARALLEL || GET_CODE (op0) == LO_SUM)
+                  || GET_CODE (op0) == CONCAT || GET_CODE (op0) == PARALLEL
+                  || GET_CODE (op0) == LO_SUM)
            {
-             /* If the operand is a SAVE_EXPR, we can deal with this by
-                forcing the SAVE_EXPR into memory.  */
-             if (TREE_CODE (TREE_OPERAND (exp, 0)) == SAVE_EXPR)
-               {
-                 put_var_into_stack (TREE_OPERAND (exp, 0),
-                                     /*rescan=*/true);
-                 op0 = SAVE_EXPR_RTL (TREE_OPERAND (exp, 0));
-               }
+             /* If this object is in a register, it can't be BLKmode.  */
+             tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
+             rtx memloc = assign_temp (inner_type, 1, 1, 1);
+
+             if (GET_CODE (op0) == PARALLEL)
+               /* Handle calls that pass values in multiple
+                  non-contiguous locations.  The Irix 6 ABI has examples
+                  of this.  */
+               emit_group_store (memloc, op0, inner_type,
+                                 int_size_in_bytes (inner_type));
              else
-               {
-                 /* If this object is in a register, it can't be BLKmode.  */
-                 tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
-                 rtx memloc = assign_temp (inner_type, 1, 1, 1);
-
-                 if (GET_CODE (op0) == PARALLEL)
-                   /* Handle calls that pass values in multiple
-                      non-contiguous locations.  The Irix 6 ABI has examples
-                      of this.  */
-                   emit_group_store (memloc, op0, inner_type,
-                                     int_size_in_bytes (inner_type));
-                 else
-                   emit_move_insn (memloc, op0);
+               emit_move_insn (memloc, op0);
 
-                 op0 = memloc;
-               }
+             op0 = memloc;
            }
 
          if (!MEM_P (op0))
@@ -9391,8 +9160,9 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
              if (case_low && case_high)
                {
                  /* Case label is less than minimum for type.  */
-                 if ((tree_int_cst_compare (case_low, min_value) < 0)
-                     && (tree_int_cst_compare (case_high, min_value) < 0))
+                 if (TREE_CODE (min_value) == INTEGER_CST
+                     && tree_int_cst_compare (case_low, min_value) < 0
+                     && tree_int_cst_compare (case_high, min_value) < 0)
                    {
                      warning ("case label value %d is less than minimum value for type",
                               TREE_INT_CST (case_low));
@@ -9400,8 +9170,9 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                    }
                  
                  /* Case value is greater than maximum for type.  */
-                 if ((tree_int_cst_compare (case_low, max_value) > 0)
-                     && (tree_int_cst_compare (case_high, max_value) > 0))
+                 if (TREE_CODE (max_value) == INTEGER_CST
+                     && tree_int_cst_compare (case_low, max_value) > 0
+                     && tree_int_cst_compare (case_high, max_value) > 0)
                    {
                      warning ("case label value %d exceeds maximum value for type",
                               TREE_INT_CST (case_high));
@@ -9409,8 +9180,9 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                    }
                  
                  /* Saturate lower case label value to minimum.  */
-                 if ((tree_int_cst_compare (case_high, min_value) >= 0)
-                     && (tree_int_cst_compare (case_low, min_value) < 0))
+                 if (TREE_CODE (min_value) == INTEGER_CST
+                     && tree_int_cst_compare (case_high, min_value) >= 0
+                     && tree_int_cst_compare (case_low, min_value) < 0)
                    {
                      warning ("lower value %d in case label range less than minimum value for type",
                               TREE_INT_CST (case_low));
@@ -9418,8 +9190,9 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
                    }
                  
                  /* Saturate upper case label value to maximum.  */
-                 if ((tree_int_cst_compare (case_low, max_value) <= 0)
-                     && (tree_int_cst_compare (case_high, max_value) > 0))
+                 if (TREE_CODE (max_value) == INTEGER_CST
+                     && tree_int_cst_compare (case_low, max_value) <= 0
+                     && tree_int_cst_compare (case_high, max_value) > 0)
                    {
                      warning ("upper value %d in case label range exceeds maximum value for type",
                               TREE_INT_CST (case_high));