]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
rtl.def (ADDRESSOF): Remove.
authorRichard Henderson <rth@gcc.gnu.org>
Sun, 4 Jul 2004 08:07:15 +0000 (01:07 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Sun, 4 Jul 2004 08:07:15 +0000 (01:07 -0700)
* rtl.def (ADDRESSOF): Remove.
* alias.c (rtx_equal_for_memref_p): Don't handle addressof.
(find_base_term, memrefs_conflict_p): Likewise.
* cse.c (fixed_base_plus_p, find_best_addr: Likewise.
(fold_rtx, cse_insn, set_live_p): Likewise.
* dwarf2out.c (mem_loc_descriptor): Likewise.
(add_location_or_const_value_attribute): Likewise.
* emit-rtl.c (copy_insn_1): Likewise.
* explow.c (memory_address): Likewise.
* expmed.c (store_split_bit_field): Likewise.
* expr.c (expand_expr_real_1): Likewise.
* function.c (instantiate_decl
(instantiate_virtual_regs_1, fix_lexical_addr): Likewise.
* genrecog.c (preds, validate_pattern): Likewise.
* integrate.c (copy_rtx_and_substitute): Likewise.
* recog.c (general_operand, register_operand): Likewise.
(memory_address_p): Likwise.
* reload1.c (eliminate_regs, elimination_effects): Likewise.
* rtl.c (copy_rtx): Likewise.
* rtlanal.c (rtx_unstable_p, rtx_varies_p): Likewise.
(rtx_addr_can_trap_p, nonzero_address_p, address_cost): Likewise.
* rtlhooks.c (gen_lowpart_general): Likewise.
* stmt.c (expand_asm_operands): Likewise.
* web.c (entry_register, replace_ref, web_main): Likewise.
* config/alpha/alpha.c (input_operand, alpha_legitimate_address_p,
alpha_expand_block_move, alpha_expand_block_clear): Likewise.
* config/arm/arm.c (thumb_rtx_costs): Likewise.
* config/c4x/c4x.c (c4x_valid_operands): Likewise.
* config/frv/frv.c (move_destination_operand, move_source_operand,
condexec_dest_operand, condexec_source_operand,
condexec_memory_operand): Likewise.
* config/h8300/h8300.h (PREDICATE_CODES): Likewise.
* config/ia64/ia64.c (general_xfmode_operand): Likewise.
(destination_xfmode_operand): Likewise.
* config/mips/mips.h (PREDICATE_CODES): Likewise.
* config/mn10300/mn10300.c (mn10300_address_cost_1): Likewise.
* config/s390/s390.c (general_s_operand): Likewise.
* config/s390/s390.md (mov*): Likewise.
* config/sparc/sparc.h (PREDICATE_CODES): Likewise.

* c-typeck.c (c_mark_addressable): Don't put_var_into_stack.
* expr.c (expand_expr_real_1): Likewise.
* stmt.c (expand_decl): Likewise.
* config/c4x/c4x.c (c4x_expand_builtin): Likewise.

* function.c (struct fixup_replacement, struct insns_for_mem_entry,
postponed_insns, put_var_into_stack, put_reg_into_stack,
schedule_fixup_var_refs, fixup_var_refs, find_fixup_replacement,
fixup_var_refs_insns, fixup_var_refs_insns_with_hash,
fixup_var_refs_insn, fixup_var_refs_1, fixup_memory_subreg,
walk_fixup_memory_subreg, fixup_stack_1, optimize_bit_field,
gen_mem_addressof, flush_addressof, put_addressof_into_stack,
purge_bitfield_addressof_replacements, purge_addressof_replacements,
purge_addressof_1, insns_for_mem_hash, insns_for_mem_comp,
struct insns_for_mem_walk_info, insns_for_mem_walk,
compute_insns_for_mem, is_addressof, purge_addressof, setjmp_protect,
setjmp_protect_args): Remove.
(push_function_context_to): Don't handle var_refs_queue.
(pop_function_context_from, free_after_compilation): Likewise.
(instantiate_virtual_regs): Don't handle parm_reg_stack_loc.
(assign_parms, allocate_struct_function): Likewise.
(use_register_for_decl): New.
(expand_function_end): Don't setjmp_protect.
* function.h (struct emit_status): Update commentary.
(struct function): Remove x_max_parm_reg, x_parm_reg_stack_loc.
(max_parm_reg, parm_reg_stack_loc): Remove.
* passes.c (DFI_addressof): Remove.
(dump_file_info): Remove addressof.
(rest_of_handle_addressof): Remove.
(rest_of_compilation): Don't call it.
* rtl.h (ADDRESSOF_REGNO, ADDRESSOF_DECL): Remove.
* stmt.c (expand_decl): Use use_register_for_decl.
* tree.h: Update decls.
* web.c (mark_addressof): Remove.
* doc/invoke.texi (-dF): Remove.

ada/
        * utils2.c (gnat_mark_addressable): Don't put_var_into_stack.
cp/
        * typeck.c (cxx_mark_addressable): Don't put_var_into_stack.
fortran/
        * f95-lang.c (gfc_mark_addressable): Don't put_var_into_stack.
treelang/
        * treetree.c (tree_mark_addressable):  Don't put_var_into_stack.

From-SVN: r84072

44 files changed:
gcc/ChangeLog
gcc/ada/ChangeLog
gcc/ada/utils2.c
gcc/alias.c
gcc/c-typeck.c
gcc/config/alpha/alpha.c
gcc/config/arm/arm.c
gcc/config/c4x/c4x.c
gcc/config/frv/frv.c
gcc/config/h8300/h8300.h
gcc/config/ia64/ia64.c
gcc/config/mips/mips.h
gcc/config/mn10300/mn10300.c
gcc/config/s390/s390.c
gcc/config/s390/s390.md
gcc/config/sparc/sparc.h
gcc/cp/ChangeLog
gcc/cp/typeck.c
gcc/cse.c
gcc/doc/invoke.texi
gcc/dwarf2out.c
gcc/emit-rtl.c
gcc/explow.c
gcc/expmed.c
gcc/expr.c
gcc/fortran/ChangeLog
gcc/fortran/f95-lang.c
gcc/function.c
gcc/function.h
gcc/genrecog.c
gcc/integrate.c
gcc/passes.c
gcc/recog.c
gcc/reload1.c
gcc/rtl.c
gcc/rtl.def
gcc/rtl.h
gcc/rtlanal.c
gcc/rtlhooks.c
gcc/stmt.c
gcc/tree.h
gcc/treelang/ChangeLog
gcc/treelang/treetree.c
gcc/web.c

index cf04490f85537751e59d3ba2902bc582021452b4..e9f7ce28e170497b7df35229e09300a10ff1044e 100644 (file)
@@ -1,3 +1,81 @@
+2004-07-04  Richard Henderson  <rth@redhat.com>
+
+       * rtl.def (ADDRESSOF): Remove.
+       * alias.c (rtx_equal_for_memref_p): Don't handle addressof.
+       (find_base_term, memrefs_conflict_p): Likewise.
+       * cse.c (fixed_base_plus_p, find_best_addr: Likewise.
+       (fold_rtx, cse_insn, set_live_p): Likewise.
+       * dwarf2out.c (mem_loc_descriptor): Likewise.
+       (add_location_or_const_value_attribute): Likewise.
+       * emit-rtl.c (copy_insn_1): Likewise.
+       * explow.c (memory_address): Likewise.
+       * expmed.c (store_split_bit_field): Likewise.
+       * expr.c (expand_expr_real_1): Likewise.
+       * function.c (instantiate_decl
+       (instantiate_virtual_regs_1, fix_lexical_addr): Likewise.
+       * genrecog.c (preds, validate_pattern): Likewise.
+       * integrate.c (copy_rtx_and_substitute): Likewise.
+       * recog.c (general_operand, register_operand): Likewise.
+       (memory_address_p): Likwise.
+       * reload1.c (eliminate_regs, elimination_effects): Likewise.
+       * rtl.c (copy_rtx): Likewise.
+       * rtlanal.c (rtx_unstable_p, rtx_varies_p): Likewise.
+       (rtx_addr_can_trap_p, nonzero_address_p, address_cost): Likewise.
+       * rtlhooks.c (gen_lowpart_general): Likewise.
+       * stmt.c (expand_asm_operands): Likewise.
+       * web.c (entry_register, replace_ref, web_main): Likewise.
+       * config/alpha/alpha.c (input_operand, alpha_legitimate_address_p,
+       alpha_expand_block_move, alpha_expand_block_clear): Likewise.
+       * config/arm/arm.c (thumb_rtx_costs): Likewise.
+       * config/c4x/c4x.c (c4x_valid_operands): Likewise.
+       * config/frv/frv.c (move_destination_operand, move_source_operand,
+       condexec_dest_operand, condexec_source_operand,
+       condexec_memory_operand): Likewise.
+       * config/h8300/h8300.h (PREDICATE_CODES): Likewise.
+       * config/ia64/ia64.c (general_xfmode_operand): Likewise.
+       (destination_xfmode_operand): Likewise.
+       * config/mips/mips.h (PREDICATE_CODES): Likewise.
+       * config/mn10300/mn10300.c (mn10300_address_cost_1): Likewise.
+       * config/s390/s390.c (general_s_operand): Likewise.
+       * config/s390/s390.md (mov*): Likewise.
+       * config/sparc/sparc.h (PREDICATE_CODES): Likewise.
+
+       * c-typeck.c (c_mark_addressable): Don't put_var_into_stack.
+       * expr.c (expand_expr_real_1): Likewise.
+       * stmt.c (expand_decl): Likewise.
+       * config/c4x/c4x.c (c4x_expand_builtin): Likewise.
+
+       * function.c (struct fixup_replacement, struct insns_for_mem_entry,
+       postponed_insns, put_var_into_stack, put_reg_into_stack,
+       schedule_fixup_var_refs, fixup_var_refs, find_fixup_replacement,
+       fixup_var_refs_insns, fixup_var_refs_insns_with_hash,
+       fixup_var_refs_insn, fixup_var_refs_1, fixup_memory_subreg,
+       walk_fixup_memory_subreg, fixup_stack_1, optimize_bit_field,
+       gen_mem_addressof, flush_addressof, put_addressof_into_stack,
+       purge_bitfield_addressof_replacements, purge_addressof_replacements,
+       purge_addressof_1, insns_for_mem_hash, insns_for_mem_comp,
+       struct insns_for_mem_walk_info, insns_for_mem_walk, 
+       compute_insns_for_mem, is_addressof, purge_addressof, setjmp_protect,
+       setjmp_protect_args): Remove.
+       (push_function_context_to): Don't handle var_refs_queue.
+       (pop_function_context_from, free_after_compilation): Likewise.
+       (instantiate_virtual_regs): Don't handle parm_reg_stack_loc.
+       (assign_parms, allocate_struct_function): Likewise.
+       (use_register_for_decl): New.
+       (expand_function_end): Don't setjmp_protect.
+       * function.h (struct emit_status): Update commentary.
+       (struct function): Remove x_max_parm_reg, x_parm_reg_stack_loc.
+       (max_parm_reg, parm_reg_stack_loc): Remove.
+       * passes.c (DFI_addressof): Remove.
+       (dump_file_info): Remove addressof.
+       (rest_of_handle_addressof): Remove.
+       (rest_of_compilation): Don't call it.
+       * rtl.h (ADDRESSOF_REGNO, ADDRESSOF_DECL): Remove.
+       * stmt.c (expand_decl): Use use_register_for_decl.
+       * tree.h: Update decls.
+       * web.c (mark_addressof): Remove.
+       * doc/invoke.texi (-dF): Remove.
+
 2004-07-03  Richard Henderson  <rth@redhat.com>
 
        * config/ia64/ia64.c (spill_xfmode_operand): Use assign_stack_temp
index a398e01b1403e836b1cda3e4bfe92fd438063f58..12669bec53227d60122347986f89f0b5164c701e 100644 (file)
@@ -1,3 +1,7 @@
+2004-07-04  Richard Henderson  <rth@redhat.com>
+
+       * utils2.c (gnat_mark_addressable): Don't put_var_into_stack.
+
 2004-07-01  Richard Henderson  <rth@redhat.com>
 
        * trans.c (gnat_stabilize_reference): Don't handle RTL_EXPR.
index 0a563a55d686c5ec1c7a73edd94af002878824be..85b0a7452fff4117bb29d197d96fabff4955e530 100644 (file)
@@ -1987,7 +1987,6 @@ gnat_mark_addressable (tree expr_node)
       case VAR_DECL:
       case PARM_DECL:
       case RESULT_DECL:
-       put_var_into_stack (expr_node, 1);
        TREE_ADDRESSABLE (expr_node) = 1;
        return true;
 
index b8443e8c02deaffbf74193b83c9a58aedf29ba75..9e53d9bb07f4d4b52b1df7d3050981b5a2b74894 100644 (file)
@@ -1256,11 +1256,6 @@ rtx_equal_for_memref_p (rtx x, rtx y)
         comparison for these nodes.  */
       return 0;
 
-    case ADDRESSOF:
-      return (XINT (x, 1) == XINT (y, 1)
-             && rtx_equal_for_memref_p (XEXP (x, 0),
-                                        XEXP (y, 0)));
-
     default:
       break;
     }
@@ -1502,9 +1497,6 @@ find_base_term (rtx x)
     case LABEL_REF:
       return x;
 
-    case ADDRESSOF:
-      return REG_BASE_VALUE (frame_pointer_rtx);
-
     default:
       return 0;
     }
@@ -1826,18 +1818,6 @@ memrefs_conflict_p (int xsize, rtx x, int ysize, rtx y, HOST_WIDE_INT c)
       return memrefs_conflict_p (xsize, x, ysize, canon_rtx (XEXP (y, 0)), c);
     }
 
-  if (GET_CODE (x) == ADDRESSOF)
-    {
-      if (y == frame_pointer_rtx
-         || GET_CODE (y) == ADDRESSOF)
-       return xsize <= 0 || ysize <= 0;
-    }
-  if (GET_CODE (y) == ADDRESSOF)
-    {
-      if (x == frame_pointer_rtx)
-       return xsize <= 0 || ysize <= 0;
-    }
-
   if (CONSTANT_P (x))
     {
       if (GET_CODE (x) == CONST_INT && GET_CODE (y) == CONST_INT)
index 57a718f4dbf87eb01caa28ae2609c1d0400d03f4..e5f94915cf2327295e5d375a912d2151e79d6b91 100644 (file)
@@ -2714,7 +2714,6 @@ c_mark_addressable (tree exp)
            pedwarn ("address of register variable `%s' requested",
                     IDENTIFIER_POINTER (DECL_NAME (x)));
          }
-       put_var_into_stack (x, /*rescan=*/true);
 
        /* drops in */
       case FUNCTION_DECL:
index 23f35ebf4f1034434e2a71f82b1bdc14569f9b69..0fe8b000514744a832957d7606b650709c659db3 100644 (file)
@@ -806,7 +806,6 @@ input_operand (rtx op, enum machine_mode mode)
              && local_symbolic_operand (XEXP (op, 0), mode));
 
     case REG:
-    case ADDRESSOF:
       return 1;
 
     case SUBREG:
@@ -1725,9 +1724,6 @@ alpha_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
              && CONSTANT_ADDRESS_P (ofs))
            return true;
        }
-      else if (GET_CODE (x) == ADDRESSOF
-              && GET_CODE (ofs) == CONST_INT)
-       return true;
     }
 
   /* If we're managing explicit relocations, LO_SUM is valid, as
@@ -4486,39 +4482,6 @@ alpha_expand_block_move (rtx operands[])
        }
     }
 
-  /* Load the entire block into registers.  */
-  if (GET_CODE (XEXP (orig_src, 0)) == ADDRESSOF)
-    {
-      enum machine_mode mode;
-
-      tmp = XEXP (XEXP (orig_src, 0), 0);
-
-      /* Don't use the existing register if we're reading more than
-        is held in the register.  Nor if there is not a mode that
-        handles the exact size.  */
-      mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 1);
-      if (GET_CODE (tmp) == REG
-         && mode != BLKmode
-         && GET_MODE_SIZE (GET_MODE (tmp)) >= bytes)
-       {
-         if (mode == TImode)
-           {
-             data_regs[nregs] = gen_lowpart (DImode, tmp);
-             data_regs[nregs + 1] = gen_highpart (DImode, tmp);
-             nregs += 2;
-           }
-         else
-           data_regs[nregs++] = gen_lowpart (mode, tmp);
-
-         goto src_done;
-       }
-
-      /* No appropriate mode; fall back on memory.  */
-      orig_src = replace_equiv_address (orig_src,
-                                       copy_addr_to_reg (XEXP (orig_src, 0)));
-      src_align = GET_MODE_BITSIZE (GET_MODE (tmp));
-    }
-
   ofs = 0;
   if (src_align >= 64 && bytes >= 8)
     {
@@ -4603,8 +4566,6 @@ alpha_expand_block_move (rtx operands[])
       ofs += 1;
     }
 
- src_done:
-
   if (nregs > ARRAY_SIZE (data_regs))
     abort ();
 
@@ -4612,57 +4573,6 @@ alpha_expand_block_move (rtx operands[])
 
   i = 0, ofs = 0;
 
-  if (GET_CODE (XEXP (orig_dst, 0)) == ADDRESSOF)
-    {
-      enum machine_mode mode;
-      tmp = XEXP (XEXP (orig_dst, 0), 0);
-
-      mode = mode_for_size (orig_bytes * BITS_PER_UNIT, MODE_INT, 1);
-      if (GET_CODE (tmp) == REG && GET_MODE (tmp) == mode)
-       {
-         if (nregs == 1)
-           {
-             emit_move_insn (tmp, data_regs[0]);
-             i = 1;
-             goto dst_done;
-           }
-
-         else if (nregs == 2 && mode == TImode)
-           {
-             /* Undo the subregging done above when copying between
-                two TImode registers.  */
-             if (GET_CODE (data_regs[0]) == SUBREG
-                 && GET_MODE (SUBREG_REG (data_regs[0])) == TImode)
-               emit_move_insn (tmp, SUBREG_REG (data_regs[0]));
-             else
-               {
-                 rtx seq;
-
-                 start_sequence ();
-                 emit_move_insn (gen_lowpart (DImode, tmp), data_regs[0]);
-                 emit_move_insn (gen_highpart (DImode, tmp), data_regs[1]);
-                 seq = get_insns ();
-                 end_sequence ();
-
-                 emit_no_conflict_block (seq, tmp, data_regs[0],
-                                         data_regs[1], NULL_RTX);
-               }
-
-             i = 2;
-             goto dst_done;
-           }
-       }
-
-      /* ??? If nregs > 1, consider reconstructing the word in regs.  */
-      /* ??? Optimize mode < dst_mode with strict_low_part.  */
-
-      /* No appropriate mode; fall back on memory.  We can speed things
-        up by recognizing extra alignment information.  */
-      orig_dst = replace_equiv_address (orig_dst,
-                                       copy_addr_to_reg (XEXP (orig_dst, 0)));
-      dst_align = GET_MODE_BITSIZE (GET_MODE (tmp));
-    }
-
   /* Write out the data in whatever chunks reading the source allowed.  */
   if (dst_align >= 64)
     {
@@ -4751,8 +4661,6 @@ alpha_expand_block_move (rtx operands[])
       ofs += 1;
     }
 
- dst_done:
-
   if (i != nregs)
     abort ();
 
@@ -4798,21 +4706,6 @@ alpha_expand_block_clear (rtx operands[])
            align = a, alignofs = 2 - c % 2;
        }
     }
-  else if (GET_CODE (tmp) == ADDRESSOF)
-    {
-      enum machine_mode mode;
-
-      mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 1);
-      if (GET_MODE (XEXP (tmp, 0)) == mode)
-       {
-         emit_move_insn (XEXP (tmp, 0), const0_rtx);
-         return 1;
-       }
-
-      /* No appropriate mode; fall back on memory.  */
-      orig_dst = replace_equiv_address (orig_dst, copy_addr_to_reg (tmp));
-      align = GET_MODE_BITSIZE (GET_MODE (XEXP (tmp, 0)));
-    }
 
   /* Handle an unaligned prefix first.  */
 
index 7cd1573a03c91dad3b69e78e560554c00ff6e1e1..37b13fe4c363f7fd40fa5dbbf0ac8b6bb9e980e8 100644 (file)
@@ -3550,7 +3550,6 @@ thumb_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer)
       /* XXX guess.  */
       return 8;
 
-    case ADDRESSOF:
     case MEM:
       /* XXX another guess.  */
       /* Memory costs quite a lot for the first word, but subsequent words
index ceaa7dfcb9890bef1767d491d2552f96420aef00..62f8679997c5e92160eb77cdd576c70e3bc193bf 100644 (file)
@@ -3812,12 +3812,6 @@ c4x_valid_operands (enum rtx_code code, rtx *operands,
        case MEM:
          break;
          
-         /* After CSE, any remaining (ADDRESSOF:P reg) gets converted
-            into a stack slot memory address comprising a PLUS and a
-            constant.  */
-       case ADDRESSOF:
-         break;
-         
        default:
          fatal_insn ("c4x_valid_operands: Internal error", op2);
          break;
@@ -3862,12 +3856,6 @@ c4x_valid_operands (enum rtx_code code, rtx *operands,
        case MEM:
          break;
          
-         /* After CSE, any remaining (ADDRESSOF:P reg) gets converted
-            into a stack slot memory address comprising a PLUS and a
-            constant.  */
-       case ADDRESSOF:
-         break;
-         
        default:
          abort ();
          break;
@@ -4863,8 +4851,6 @@ c4x_expand_builtin (tree exp, rtx target,
       if (TARGET_C3X)
        break;
       arg0 = TREE_VALUE (arglist);
-      if (TREE_CODE (arg0) == VAR_DECL || TREE_CODE (arg0) == PARM_DECL)
-       put_var_into_stack (arg0, /*rescan=*/true);
       r0 = expand_expr (arg0, NULL_RTX, QFmode, 0);
       r0 = protect_from_queue (r0, 0);
       if (register_operand (r0, QFmode))
index 92e0dd213fa5afdde9c4e30af33faa679cba6979..99e8cb9c7e24bb2e86aa48b1c8ea73b927f644ed 100644 (file)
@@ -4370,9 +4370,6 @@ move_destination_operand (rtx op, enum machine_mode mode)
       return TRUE;
 
     case MEM:
-      if (GET_CODE (XEXP (op, 0)) == ADDRESSOF)
-        return TRUE;
-
       return frv_legitimate_memory_operand (op, mode, FALSE);
     }
 
@@ -4463,9 +4460,6 @@ move_source_operand (rtx op, enum machine_mode mode)
       return TRUE;
 
     case MEM:
-      if (GET_CODE (XEXP (op, 0)) == ADDRESSOF)
-        return TRUE;
-
       return frv_legitimate_memory_operand (op, mode, FALSE);
     }
 
@@ -4505,9 +4499,6 @@ condexec_dest_operand (rtx op, enum machine_mode mode)
       return TRUE;
 
     case MEM:
-      if (GET_CODE (XEXP (op, 0)) == ADDRESSOF)
-        return TRUE;
-
       return frv_legitimate_memory_operand (op, mode, TRUE);
     }
 
@@ -4551,9 +4542,6 @@ condexec_source_operand (rtx op, enum machine_mode mode)
       return TRUE;
 
     case MEM:
-      if (GET_CODE (XEXP (op, 0)) == ADDRESSOF)
-        return TRUE;
-
       return frv_legitimate_memory_operand (op, mode, TRUE);
     }
 
@@ -5237,9 +5225,6 @@ condexec_memory_operand (rtx op, enum machine_mode mode)
     return FALSE;
 
   addr = XEXP (op, 0);
-  if (GET_CODE (addr) == ADDRESSOF)
-    return TRUE;
-
   return frv_legitimate_address_p (mode, addr, reload_completed, TRUE, FALSE);
 }
 
index d78669babac172c1462e050368ac903631524ad1..eeafd84a24e50e84925f71c5ad5c0f494e8433c9 100644 (file)
@@ -1150,9 +1150,9 @@ struct cum_arg
 
 #define PREDICATE_CODES                                                        \
   {"general_operand_src", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, \
-                          LABEL_REF, SUBREG, REG, MEM, ADDRESSOF}},    \
+                          LABEL_REF, SUBREG, REG, MEM}},               \
   {"general_operand_dst", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, \
-                          LABEL_REF, SUBREG, REG, MEM, ADDRESSOF}},    \
+                          LABEL_REF, SUBREG, REG, MEM}},               \
   {"single_one_operand", {CONST_INT}},                                 \
   {"single_zero_operand", {CONST_INT}},                                        \
   {"call_insn_operand", {MEM}},                                                \
index 90d4a1f9302096fca8df6a16e4a22355895a181b..2c7e36d511e7e0882ba6ef47f7999e22bd6bc6a1 100644 (file)
@@ -958,8 +958,6 @@ general_xfmode_operand (rtx op, enum machine_mode mode)
 {
   if (! general_operand (op, mode))
     return 0;
-  if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == ADDRESSOF)
-    return 0;
   return 1;
 }
 
@@ -970,8 +968,6 @@ destination_xfmode_operand (rtx op, enum machine_mode mode)
 {
   if (! destination_operand (op, mode))
     return 0;
-  if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == ADDRESSOF)
-    return 0;
   return 1;
 }
 
index e22e1699f75b3fc8d1a9779bc0d5754a856839c0..ab008e494c7b56a492f5471f67b6058bd58b2432 100644 (file)
@@ -2743,7 +2743,7 @@ typedef struct mips_args {
    macro are thoses used in the most insn patterns.  */
 
 #define PREDICATE_CODES                                                        \
-  {"uns_arith_operand",                { REG, CONST_INT, SUBREG, ADDRESSOF }}, \
+  {"uns_arith_operand",                { REG, CONST_INT, SUBREG }},            \
   {"symbolic_operand",         { CONST, SYMBOL_REF, LABEL_REF }},      \
   {"general_symbolic_operand", { CONST, SYMBOL_REF, LABEL_REF }},      \
   {"global_got_operand",       { CONST, SYMBOL_REF, LABEL_REF }},      \
@@ -2751,8 +2751,8 @@ typedef struct mips_args {
   {"const_arith_operand",      { CONST_INT }},                         \
   {"small_data_pattern",       { SET, PARALLEL, UNSPEC,                \
                                  UNSPEC_VOLATILE }},                   \
-  {"arith_operand",            { REG, CONST_INT, CONST, SUBREG, ADDRESSOF }},  \
-  {"reg_or_0_operand",         { REG, CONST_INT, CONST_DOUBLE, SUBREG, ADDRESSOF }}, \
+  {"arith_operand",            { REG, CONST_INT, CONST, SUBREG }},     \
+  {"reg_or_0_operand",         { REG, CONST_INT, CONST_DOUBLE, SUBREG }}, \
   {"small_int",                        { CONST_INT }},                         \
   {"const_float_1_operand",    { CONST_DOUBLE }},                      \
   {"reg_or_const_float_1_operand", { CONST_DOUBLE, REG}},               \
index 95078d62da41b195e24218a4758fd5e465b048b4..da235e39a29400953295f9cae0f2c6278ec36877 100644 (file)
@@ -1974,19 +1974,6 @@ mn10300_address_cost_1 (rtx x, int *unsig)
     case LABEL_REF:
       return 8;
 
-    case ADDRESSOF:
-      switch (GET_CODE (XEXP (x, 0)))
-       {
-       case MEM:
-         return mn10300_address_cost (XEXP (x, 0));
-
-       case REG:
-         return 1;
-
-       default:
-         abort ();
-       }
-
     default:
       abort ();
 
index 537148e17643d54b8a84fa1a874e636a8ccbce27..470425bc72e90cd0022ed632eb6ab95f4d2f13ae 100644 (file)
@@ -1181,8 +1181,6 @@ general_s_operand (register rtx op, enum machine_mode mode,
       /* Memory operands are OK unless they already use an
         index register.  */
       case MEM:
-       if (GET_CODE (XEXP (op, 0)) == ADDRESSOF)
-         return 1;
        if (!s390_decompose_address (XEXP (op, 0), &addr))
          return 0;
        if (addr.indx)
index e2a026215227ada2831c976275ac4d73168298ad..8e2c458e5df8304885f61528455ae2c1c06e0b79 100644 (file)
      always sign-extends (at least) to SImode.  */
   if (optimize && !no_new_pseudos
       && register_operand (operands[0], VOIDmode)
-      && GET_CODE (operands[1]) == MEM
-      && GET_CODE (XEXP (operands[1], 0)) != ADDRESSOF)
+      && GET_CODE (operands[1]) == MEM)
     {
       rtx tmp = gen_reg_rtx (SImode);
       rtx ext = gen_rtx_SIGN_EXTEND (SImode, operands[1]);
      is just as fast as a QImode load.  */
   if (TARGET_ZARCH && optimize && !no_new_pseudos
       && register_operand (operands[0], VOIDmode)
-      && GET_CODE (operands[1]) == MEM
-      && GET_CODE (XEXP (operands[1], 0)) != ADDRESSOF)
+      && GET_CODE (operands[1]) == MEM)
     {
       rtx tmp = gen_reg_rtx (word_mode);
       rtx ext = gen_rtx_ZERO_EXTEND (word_mode, operands[1]);
index 0cf64b84a0df6a973f20701ad0b2b03e5ea534b6..595a0f5fa88b1a44d3f568ca7471b667f8bb567e 100644 (file)
@@ -2578,7 +2578,7 @@ do {                                                                      \
 {"icc_or_fcc_reg_operand", {REG}},                                     \
 {"call_operand", {MEM}},                                               \
 {"call_operand_address", {SYMBOL_REF, LABEL_REF, CONST, CONST_DOUBLE,  \
-       ADDRESSOF, SUBREG, REG, PLUS, LO_SUM, CONST_INT}},              \
+       SUBREG, REG, PLUS, LO_SUM, CONST_INT}},                         \
 {"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST}},                  \
 {"symbolic_memory_operand", {SUBREG, MEM}},                            \
 {"label_ref_operand", {LABEL_REF}},                                    \
index 8baadc015a2d83f654dc14e28cd86a1d859d08a7..4703ed85be26e641c7a0226bdcea53cb2db1a37b 100644 (file)
@@ -1,10 +1,14 @@
-2004-07-03  Scott Brumbaugh  <scottb.lists@verizon.net>\r
-\r
-       PR c++/3761\r
-       * name-lookup.c (push_class_level_binding): Don't pass a\r
-       TREE_LIST of ambiguous names to check_template_shadow as it\r
-       only handles declarations. Instead, pull the declaration \r
-       out and pass that.\r
+2004-07-04  Richard Henderson  <rth@redhat.com>
+
+       * typeck.c (cxx_mark_addressable): Don't put_var_into_stack.
+
+2004-07-03  Scott Brumbaugh  <scottb.lists@verizon.net>
+
+       PR c++/3761
+       * name-lookup.c (push_class_level_binding): Don't pass a
+       TREE_LIST of ambiguous names to check_template_shadow as it
+       only handles declarations. Instead, pull the declaration
+       out and pass that.
 
 2004-07-03  Giovanni Bajo  <giovannibajo@gcc.gnu.org>
 
index d099980e486aa841e2f2dcfeca07910d507e4fad..4f473508c389b6497122f749265517dca9754201 100644 (file)
@@ -4295,7 +4295,6 @@ cxx_mark_addressable (tree exp)
          warning ("address requested for `%D', which is declared `register'",
                      x);
        TREE_ADDRESSABLE (x) = 1;
-       put_var_into_stack (x, /*rescan=*/true);
        return true;
 
       case FUNCTION_DECL:
index c50b28aaba76d0d1c00db4fb3fcb24c8c153ae8c..ef99bc6cb78254de682d65a1e283782c9dd6886a 100644 (file)
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -695,9 +695,6 @@ fixed_base_plus_p (rtx x)
        return false;
       return fixed_base_plus_p (XEXP (x, 0));
 
-    case ADDRESSOF:
-      return true;
-
     default:
       return false;
     }
@@ -2769,7 +2766,6 @@ find_best_addr (rtx insn, rtx *loc, enum machine_mode mode)
          && (regno = REGNO (addr), regno == FRAME_POINTER_REGNUM
              || regno == HARD_FRAME_POINTER_REGNUM
              || regno == ARG_POINTER_REGNUM))
-      || GET_CODE (addr) == ADDRESSOF
       || CONSTANT_ADDRESS_P (addr))
     return;
 
@@ -3188,10 +3184,6 @@ fold_rtx (rtx x, rtx insn)
         since they are used only for lists of args
         in a function call's REG_EQUAL note.  */
     case EXPR_LIST:
-      /* Changing anything inside an ADDRESSOF is incorrect; we don't
-        want to (e.g.,) make (addressof (const_int 0)) just because
-        the location is known to be zero.  */
-    case ADDRESSOF:
       return x;
 
 #ifdef HAVE_cc0
@@ -3444,8 +3436,6 @@ fold_rtx (rtx x, rtx insn)
        else if (GET_CODE (addr) == LO_SUM
                 && GET_CODE (XEXP (addr, 1)) == SYMBOL_REF)
          base = XEXP (addr, 1);
-       else if (GET_CODE (addr) == ADDRESSOF)
-         return change_address (x, VOIDmode, addr);
 
        /* If this is a constant pool reference, we can fold it into its
           constant to allow better value tracking.  */
@@ -5924,7 +5914,6 @@ cse_insn (rtx insn, rtx libcall_insn)
     if (sets[i].rtl)
       {
        rtx dest = SET_DEST (sets[i].rtl);
-       rtx inner_dest = sets[i].inner_dest;
        struct table_elt *elt;
 
        /* Don't record value if we are not supposed to risk allocating
@@ -5973,17 +5962,8 @@ cse_insn (rtx insn, rtx libcall_insn)
              sets[i].dest_hash = HASH (dest, GET_MODE (dest));
            }
 
-       if (MEM_P (inner_dest)
-           && GET_CODE (XEXP (inner_dest, 0)) == ADDRESSOF)
-         /* Given (SET (MEM (ADDRESSOF (X))) Y) we don't want to say
-            that (MEM (ADDRESSOF (X))) is equivalent to Y.
-            Consider the case in which the address of the MEM is
-            passed to a function, which alters the MEM.  Then, if we
-            later use Y instead of the MEM we'll miss the update.  */
-         elt = insert (dest, 0, sets[i].dest_hash, GET_MODE (dest));
-       else
-         elt = insert (dest, sets[i].src_elt,
-                       sets[i].dest_hash, GET_MODE (dest));
+       elt = insert (dest, sets[i].src_elt,
+                     sets[i].dest_hash, GET_MODE (dest));
 
        elt->in_memory = (MEM_P (sets[i].inner_dest)
                          && (! RTX_UNCHANGING_P (sets[i].inner_dest)
@@ -7402,12 +7382,7 @@ set_live_p (rtx set, rtx insn ATTRIBUTE_UNUSED, /* Only used with HAVE_cc0.  */
   else if (!REG_P (SET_DEST (set))
           || REGNO (SET_DEST (set)) < FIRST_PSEUDO_REGISTER
           || counts[REGNO (SET_DEST (set))] != 0
-          || side_effects_p (SET_SRC (set))
-          /* An ADDRESSOF expression can turn into a use of the
-             internal arg pointer, so always consider the
-             internal arg pointer live.  If it is truly dead,
-             flow will delete the initializing insn.  */
-          || (SET_DEST (set) == current_function_internal_arg_pointer))
+          || side_effects_p (SET_SRC (set)))
     return true;
   return false;
 }
index 13f9c0873569201850f7d5adfab83325bbd2a556..625a6789672e25d8dd7b69dcff4aa959f818a655 100644 (file)
@@ -3315,9 +3315,6 @@ Dump after the third if conversion, to @file{@var{file}.31.ce3}.
 @opindex df
 Dump after control and data flow analysis, to @file{@var{file}.11.cfg}.
 Also dump after life analysis, to @file{@var{file}.19.life}.
-@item F
-@opindex dF
-Dump after purging @code{ADDRESSOF} codes, to @file{@var{file}.07.addressof}.
 @item g
 @opindex dg
 Dump after global register allocation, to @file{@var{file}.26.greg}.
index 2fb962ce63a5ff30071df95e2ce34f9509a07633..282ccab41d1b4be826169561c43c166237c94818 100644 (file)
@@ -8736,15 +8736,6 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode, bool can_use_fbreg)
       mem_loc_result = int_loc_descriptor (INTVAL (rtl));
       break;
 
-    case ADDRESSOF:
-      /* If this is a MEM, return its address.  Otherwise, we can't
-        represent this.  */
-      if (MEM_P (XEXP (rtl, 0)))
-       return mem_loc_descriptor (XEXP (XEXP (rtl, 0), 0), mode,
-                                  can_use_fbreg);
-      else
-       return 0;
-
     default:
       abort ();
     }
@@ -10093,11 +10084,6 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl,
 
   switch (GET_CODE (rtl))
     {
-    case ADDRESSOF:
-      /* The address of a variable that was optimized away;
-        don't emit anything.  */
-      break;
-
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_VECTOR:
index 53edf2c25d8a818b3d71083b43f4282ae12179d0..45abfe320bee1923ddb85ff966882c600f66806c 100644 (file)
@@ -5013,7 +5013,6 @@ copy_insn_1 (rtx orig)
     case CODE_LABEL:
     case PC:
     case CC0:
-    case ADDRESSOF:
       return orig;
     case CLOBBER:
       if (REG_P (XEXP (orig, 0)) && REGNO (XEXP (orig, 0)) < FIRST_PSEUDO_REGISTER)
index 99d39362bb3f971478fce48d29ae4eca98c46372..2223ca6e2bc2b4a9de1bbee4fbdbbf3a8ded43f5 100644 (file)
@@ -436,9 +436,6 @@ memory_address (enum machine_mode mode, rtx x)
 {
   rtx oldx = x;
 
-  if (GET_CODE (x) == ADDRESSOF)
-    return x;
-
   x = convert_memory_address (Pmode, x);
 
   /* By passing constant addresses through registers
index ad1d88367da030bdb71217b0b31f40f65a17ce3f..6ee291370d0b81dd88094a1e281a7cdae0e43479 100644 (file)
@@ -945,8 +945,6 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
                                               ? GET_MODE (value)
                                               : word_mode, value));
     }
-  else if (GET_CODE (value) == ADDRESSOF)
-    value = copy_to_reg (value);
 
   while (bitsdone < bitsize)
     {
index d3951fed769a6db1551b3bfd861a4c36988ac406..b44309ded60acb267f6d0b6fdb2216be3571ef41 100644 (file)
@@ -8740,8 +8740,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
@@ -8775,13 +8773,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);
@@ -8919,8 +8911,8 @@ 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 this object is in a register, it can't be BLKmode.  */
              tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
index a477814081ba56caa01353360120ec20291f6e43..0b4026aa4ecf8ea017172d8bb8bd7c3a8dc7e848 100644 (file)
@@ -1,3 +1,7 @@
+2004-07-04  Richard Henderson  <rth@redhat.com>
+
+       * f95-lang.c (gfc_mark_addressable): Don't put_var_into_stack.
+
 2004-07-04  Paul Brook  <paul@codesourcery.com>
 
        * decl.c (gfc_match_implicit_range): Don't use typespec.
index fd4fe5c2616d6873acf11f7447809ed82a543caa..43eb87d1be323f05e591af7aa61f76eaf0d806ef 100644 (file)
@@ -668,7 +668,6 @@ gfc_mark_addressable (tree exp)
            pedwarn ("address of register variable `%s' requested",
                     IDENTIFIER_POINTER (DECL_NAME (x)));
          }
-       put_var_into_stack (x, /*rescan=*/true);
 
        /* drops in */
       case FUNCTION_DECL:
index c3ab96dbae3a6e83f18a0327bf39ca194a41537c..0bab2b6c44d74b893ba0ed338af103d75d6625f1 100644 (file)
@@ -31,12 +31,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    Call `assign_stack_local' to allocate a stack slot for a local variable.
    This is usually done during the RTL generation for the function body,
    but it can also be done in the reload pass when a pseudo-register does
-   not get a hard register.
-
-   Call `put_var_into_stack' when you learn, belatedly, that a variable
-   previously given a pseudo-register must in fact go in the stack.
-   This function changes the DECL_RTL to be a stack slot instead of a reg
-   then scans all the RTL instructions so far generated to correct them.  */
+   not get a hard register.  */
 
 #include "config.h"
 #include "system.h"
@@ -202,47 +197,11 @@ struct temp_slot GTY(())
   HOST_WIDE_INT full_size;
 };
 \f
-/* This structure is used to record MEMs or pseudos used to replace VAR, any
-   SUBREGs of VAR, and any MEMs containing VAR as an address.  We need to
-   maintain this list in case two operands of an insn were required to match;
-   in that case we must ensure we use the same replacement.  */
-
-struct fixup_replacement GTY(())
-{
-  rtx old;
-  rtx new;
-  struct fixup_replacement *next;
-};
-
-struct insns_for_mem_entry
-{
-  /* A MEM.  */
-  rtx key;
-  /* These are the INSNs which reference the MEM.  */
-  rtx insns;
-};
-
 /* Forward declarations.  */
 
 static rtx assign_stack_local_1 (enum machine_mode, HOST_WIDE_INT, int,
                                 struct function *);
 static struct temp_slot *find_temp_slot_from_address (rtx);
-static void put_reg_into_stack (struct function *, rtx, tree, enum machine_mode,
-                               unsigned int, bool, bool, bool, htab_t);
-static void schedule_fixup_var_refs (struct function *, rtx, tree, enum machine_mode,
-                                    htab_t);
-static void fixup_var_refs (rtx, enum machine_mode, int, rtx, htab_t);
-static struct fixup_replacement
-  *find_fixup_replacement (struct fixup_replacement **, rtx);
-static void fixup_var_refs_insns (rtx, rtx, enum machine_mode, int, int, rtx);
-static void fixup_var_refs_insns_with_hash (htab_t, rtx, enum machine_mode, int, rtx);
-static void fixup_var_refs_insn (rtx, rtx, enum machine_mode, int, int, rtx);
-static void fixup_var_refs_1 (rtx, enum machine_mode, rtx *, rtx,
-                             struct fixup_replacement **, rtx);
-static rtx fixup_memory_subreg (rtx, rtx, enum machine_mode, int);
-static rtx walk_fixup_memory_subreg (rtx, rtx, rtx, enum machine_mode, int);
-static rtx fixup_stack_1 (rtx, rtx);
-static void optimize_bit_field (rtx, rtx, rtx *);
 static void instantiate_decls (tree, int);
 static void instantiate_decls_1 (tree, int);
 static void instantiate_decl (rtx, HOST_WIDE_INT, int);
@@ -262,17 +221,10 @@ static int contains (rtx, varray_type);
 #ifdef HAVE_return
 static void emit_return_into_block (basic_block, rtx);
 #endif
-static void put_addressof_into_stack (rtx, htab_t);
-static bool purge_addressof_1 (rtx *, rtx, int, int, int, htab_t);
 static void purge_single_hard_subreg_set (rtx);
 #if defined(HAVE_epilogue) && defined(INCOMING_RETURN_ADDR_RTX)
 static rtx keep_stack_depressed (rtx);
 #endif
-static int is_addressof (rtx *, void *);
-static hashval_t insns_for_mem_hash (const void *);
-static int insns_for_mem_comp (const void *, const void *);
-static int insns_for_mem_walk (rtx *, void *);
-static void compute_insns_for_mem (rtx, rtx, htab_t);
 static void prepare_function_start (tree);
 static void do_clobber_return_reg (rtx, void *);
 static void do_use_return_reg (rtx, void *);
@@ -283,9 +235,6 @@ static void set_insn_locators (rtx, int) ATTRIBUTE_UNUSED;
 /* Pointer to chain of `struct function' for containing functions.  */
 struct function *outer_function_chain;
 
-/* List of insns that were postponed by purge_addressof_1.  */
-static rtx postponed_insns;
-
 /* Given a function decl for a containing function,
    return the `struct function' for it.  */
 
@@ -329,7 +278,6 @@ push_function_context_to (tree context)
 
   p->outer = outer_function_chain;
   outer_function_chain = p;
-  p->fixup_var_refs_queue = 0;
 
   lang_hooks.function.enter_nested (p);
 
@@ -349,7 +297,6 @@ void
 pop_function_context_from (tree context ATTRIBUTE_UNUSED)
 {
   struct function *p = outer_function_chain;
-  struct var_refs_queue *queue;
 
   cfun = p;
   outer_function_chain = p->outer;
@@ -361,32 +308,6 @@ pop_function_context_from (tree context ATTRIBUTE_UNUSED)
 
   lang_hooks.function.leave_nested (p);
 
-  /* Finish doing put_var_into_stack for any of our variables which became
-     addressable during the nested function.  If only one entry has to be
-     fixed up, just do that one.  Otherwise, first make a list of MEMs that
-     are not to be unshared.  */
-  if (p->fixup_var_refs_queue == 0)
-    ;
-  else if (p->fixup_var_refs_queue->next == 0)
-    fixup_var_refs (p->fixup_var_refs_queue->modified,
-                   p->fixup_var_refs_queue->promoted_mode,
-                   p->fixup_var_refs_queue->unsignedp,
-                   p->fixup_var_refs_queue->modified, 0);
-  else
-    {
-      rtx list = 0;
-
-      for (queue = p->fixup_var_refs_queue; queue; queue = queue->next)
-       list = gen_rtx_EXPR_LIST (VOIDmode, queue->modified, list);
-
-      for (queue = p->fixup_var_refs_queue; queue; queue = queue->next)
-       fixup_var_refs (queue->modified, queue->promoted_mode,
-                       queue->unsignedp, list, 0);
-
-    }
-
-  p->fixup_var_refs_queue = 0;
-
   /* Reset variables that have known state during rtx generation.  */
   rtx_equal_function_value_matters = 1;
   virtuals_instantiated = 0;
@@ -440,8 +361,6 @@ free_after_compilation (struct function *f)
   f->x_tail_recursion_reentry = NULL;
   f->x_arg_pointer_save_area = NULL;
   f->x_parm_birth_insn = NULL;
-  f->x_parm_reg_stack_loc = NULL;
-  f->fixup_var_refs_queue = NULL;
   f->original_arg_vector = NULL;
   f->original_decl_initial = NULL;
   f->epilogue_delay_list = NULL;
@@ -1170,2269 +1089,180 @@ preserve_temp_slots (rtx x)
            move_slot_to_level (p, temp_slot_level - 1);
        }
 
-      return;
-    }
-
-  /* If X is a register that is being used as a pointer, see if we have
-     a temporary slot we know it points to.  To be consistent with
-     the code below, we really should preserve all non-kept slots
-     if we can't find a match, but that seems to be much too costly.  */
-  if (REG_P (x) && REG_POINTER (x))
-    p = find_temp_slot_from_address (x);
-
-  /* If X is not in memory or is at a constant address, it cannot be in
-     a temporary slot, but it can contain something whose address was
-     taken.  */
-  if (p == 0 && (!MEM_P (x) || CONSTANT_P (XEXP (x, 0))))
-    {
-      for (p = *temp_slots_at_level (temp_slot_level); p; p = next)
-       {
-         next = p->next;
-
-         if (p->addr_taken)
-           move_slot_to_level (p, temp_slot_level - 1);
-       }
-
-      return;
-    }
-
-  /* First see if we can find a match.  */
-  if (p == 0)
-    p = find_temp_slot_from_address (XEXP (x, 0));
-
-  if (p != 0)
-    {
-      /* Move everything at our level whose address was taken to our new
-        level in case we used its address.  */
-      struct temp_slot *q;
-
-      if (p->level == temp_slot_level)
-       {
-         for (q = *temp_slots_at_level (temp_slot_level); q; q = next)
-           {
-             next = q->next;
-
-             if (p != q && q->addr_taken)
-               move_slot_to_level (q, temp_slot_level - 1);
-           }
-
-         move_slot_to_level (p, temp_slot_level - 1);
-         p->addr_taken = 0;
-       }
-      return;
-    }
-
-  /* Otherwise, preserve all non-kept slots at this level.  */
-  for (p = *temp_slots_at_level (temp_slot_level); p; p = next)
-    {
-      next = p->next;
-
-      if (!p->keep)
-       move_slot_to_level (p, temp_slot_level - 1);
-    }
-}
-
-/* Free all temporaries used so far.  This is normally called at the
-   end of generating code for a statement.  */
-
-void
-free_temp_slots (void)
-{
-  struct temp_slot *p, *next;
-
-  for (p = *temp_slots_at_level (temp_slot_level); p; p = next)
-    {
-      next = p->next;
-
-      if (!p->keep)
-       make_slot_available (p);
-    }
-
-  combine_temp_slots ();
-}
-
-/* Push deeper into the nesting level for stack temporaries.  */
-
-void
-push_temp_slots (void)
-{
-  temp_slot_level++;
-}
-
-/* Pop a temporary nesting level.  All slots in use in the current level
-   are freed.  */
-
-void
-pop_temp_slots (void)
-{
-  struct temp_slot *p, *next;
-
-  for (p = *temp_slots_at_level (temp_slot_level); p; p = next)
-    {
-      next = p->next;
-      make_slot_available (p);
-    }
-
-  combine_temp_slots ();
-
-  temp_slot_level--;
-}
-
-/* Initialize temporary slots.  */
-
-void
-init_temp_slots (void)
-{
-  /* We have not allocated any temporaries yet.  */
-  avail_temp_slots = 0;
-  used_temp_slots = 0;
-  temp_slot_level = 0;
-  var_temp_slot_level = 0;
-  target_temp_slot_level = 0;
-}
-\f
-/* Retroactively move an auto variable from a register to a stack
-   slot.  This is done when an address-reference to the variable is
-   seen.  If RESCAN is true, all previously emitted instructions are
-   examined and modified to handle the fact that DECL is now
-   addressable.  */
-
-void
-put_var_into_stack (tree decl, int rescan)
-{
-  rtx orig_reg, reg;
-  enum machine_mode promoted_mode, decl_mode;
-  struct function *function = 0;
-  tree context;
-  bool can_use_addressof_p;
-  bool volatile_p = TREE_CODE (decl) != SAVE_EXPR && TREE_THIS_VOLATILE (decl);
-  bool used_p = (TREE_USED (decl)
-              || (TREE_CODE (decl) != SAVE_EXPR && DECL_INITIAL (decl) != 0));
-
-  context = decl_function_context (decl);
-
-  /* Get the current rtl used for this object and its original mode.  */
-  orig_reg = reg = DECL_RTL_IF_SET (decl);
-
-  /* No need to do anything if decl has no rtx yet
-     since in that case caller is setting TREE_ADDRESSABLE
-     and a stack slot will be assigned when the rtl is made.  */
-  if (reg == 0)
-    return;
-
-  /* Get the declared mode for this object.  */
-  decl_mode = (TREE_CODE (decl) == SAVE_EXPR ? TYPE_MODE (TREE_TYPE (decl))
-              : DECL_MODE (decl));
-  /* Get the mode it's actually stored in.  */
-  promoted_mode = GET_MODE (reg);
-
-  /* If this variable comes from an outer function, find that
-     function's saved context.  Don't use find_function_data here,
-     because it might not be in any active function.
-     FIXME: Is that really supposed to happen?
-     It does in ObjC at least.  */
-  if (context != current_function_decl)
-    for (function = outer_function_chain; function; function = function->outer)
-      if (function->decl == context)
-       break;
-
-  /* If this is a variable-sized object or a structure passed by invisible
-     reference, with a pseudo to address it, put that pseudo into the stack
-     if the var is non-local.  */
-  if (TREE_CODE (decl) != SAVE_EXPR && DECL_NONLOCAL (decl)
-      && MEM_P (reg)
-      && REG_P (XEXP (reg, 0))
-      && REGNO (XEXP (reg, 0)) > LAST_VIRTUAL_REGISTER)
-    {
-      orig_reg = reg = XEXP (reg, 0);
-      decl_mode = promoted_mode = GET_MODE (reg);
-    }
-
-  /* If this variable lives in the current function and we don't need to put it
-     in the stack for the sake of setjmp or the non-locality, try to keep it in
-     a register until we know we actually need the address.  */
-  can_use_addressof_p
-    = (function == 0
-       && ! (TREE_CODE (decl) != SAVE_EXPR && DECL_NONLOCAL (decl))
-       && optimize > 0
-       /* FIXME make it work for promoted modes too */
-       && decl_mode == promoted_mode
-#ifdef NON_SAVING_SETJMP
-       && ! (NON_SAVING_SETJMP && current_function_calls_setjmp)
-#endif
-       );
-
-  /* If we can't use ADDRESSOF, make sure we see through one we already
-     generated.  */
-  if (! can_use_addressof_p
-      && MEM_P (reg)
-      && GET_CODE (XEXP (reg, 0)) == ADDRESSOF)
-    reg = XEXP (XEXP (reg, 0), 0);
-
-  /* Now we should have a value that resides in one or more pseudo regs.  */
-
-  if (REG_P (reg))
-    {
-      if (can_use_addressof_p)
-       gen_mem_addressof (reg, decl, rescan);
-      else
-       put_reg_into_stack (function, reg, TREE_TYPE (decl), decl_mode,
-                           0, volatile_p, used_p, false, 0);
-
-         /* If this was previously a MEM but we've removed the ADDRESSOF,
-            set this address into that MEM so we always use the same
-            rtx for this variable.  */
-         if (orig_reg != reg && MEM_P (orig_reg))
-           XEXP (orig_reg, 0) = XEXP (reg, 0);
-    }
-  else if (GET_CODE (reg) == CONCAT)
-    {
-      /* A CONCAT contains two pseudos; put them both in the stack.
-        We do it so they end up consecutive.
-        We fixup references to the parts only after we fixup references
-        to the whole CONCAT, lest we do double fixups for the latter
-        references.  */
-      enum machine_mode part_mode = GET_MODE (XEXP (reg, 0));
-      tree part_type = lang_hooks.types.type_for_mode (part_mode, 0);
-      rtx lopart = XEXP (reg, 0);
-      rtx hipart = XEXP (reg, 1);
-#ifdef FRAME_GROWS_DOWNWARD
-      /* Since part 0 should have a lower address, do it second.  */
-      put_reg_into_stack (function, hipart, part_type, part_mode,
-                         0, volatile_p, false, false, 0);
-      put_reg_into_stack (function, lopart, part_type, part_mode,
-                         0, volatile_p, false, true, 0);
-#else
-      put_reg_into_stack (function, lopart, part_type, part_mode,
-                         0, volatile_p, false, false, 0);
-      put_reg_into_stack (function, hipart, part_type, part_mode,
-                         0, volatile_p, false, true, 0);
-#endif
-
-      /* Change the CONCAT into a combined MEM for both parts.  */
-      PUT_CODE (reg, MEM);
-      MEM_ATTRS (reg) = 0;
-
-      /* set_mem_attributes uses DECL_RTL to avoid re-generating of
-         already computed alias sets.  Here we want to re-generate.  */
-      if (DECL_P (decl))
-       SET_DECL_RTL (decl, NULL);
-      set_mem_attributes (reg, decl, 1);
-      if (DECL_P (decl))
-       SET_DECL_RTL (decl, reg);
-
-      /* The two parts are in memory order already.
-        Use the lower parts address as ours.  */
-      XEXP (reg, 0) = XEXP (XEXP (reg, 0), 0);
-      /* Prevent sharing of rtl that might lose.  */
-      if (GET_CODE (XEXP (reg, 0)) == PLUS)
-       XEXP (reg, 0) = copy_rtx (XEXP (reg, 0));
-      if (used_p && rescan)
-       {
-         schedule_fixup_var_refs (function, reg, TREE_TYPE (decl),
-                                  promoted_mode, 0);
-         schedule_fixup_var_refs (function, lopart, part_type, part_mode, 0);
-         schedule_fixup_var_refs (function, hipart, part_type, part_mode, 0);
-       }
-    }
-  else
-    return;
-}
-
-/* Subroutine of put_var_into_stack.  This puts a single pseudo reg REG
-   into the stack frame of FUNCTION (0 means the current function).
-   TYPE is the user-level data type of the value hold in the register.
-   DECL_MODE is the machine mode of the user-level data type.
-   ORIGINAL_REGNO must be set if the real regno is not visible in REG.
-   VOLATILE_P is true if this is for a "volatile" decl.
-   USED_P is true if this reg might have already been used in an insn.
-   CONSECUTIVE_P is true if the stack slot assigned to reg must be
-   consecutive with the previous stack slot.  */
-
-static void
-put_reg_into_stack (struct function *function, rtx reg, tree type,
-                   enum machine_mode decl_mode, unsigned int original_regno,
-                   bool volatile_p, bool used_p, bool consecutive_p,
-                   htab_t ht)
-{
-  struct function *func = function ? function : cfun;
-  enum machine_mode mode = GET_MODE (reg);
-  unsigned int regno = original_regno;
-  rtx new = 0;
-
-  if (regno == 0)
-    regno = REGNO (reg);
-
-  if (regno < func->x_max_parm_reg)
-    {
-      if (!func->x_parm_reg_stack_loc)
-       abort ();
-      new = func->x_parm_reg_stack_loc[regno];
-    }
-
-  if (new == 0)
-    new = assign_stack_local_1 (decl_mode, GET_MODE_SIZE (decl_mode),
-                               consecutive_p ? -2 : 0, func);
-
-  PUT_CODE (reg, MEM);
-  PUT_MODE (reg, decl_mode);
-  XEXP (reg, 0) = XEXP (new, 0);
-  MEM_ATTRS (reg) = 0;
-  /* `volatil' bit means one thing for MEMs, another entirely for REGs.  */
-  MEM_VOLATILE_P (reg) = volatile_p;
-
-  /* If this is a memory ref that contains aggregate components,
-     mark it as such for cse and loop optimize.  If we are reusing a
-     previously generated stack slot, then we need to copy the bit in
-     case it was set for other reasons.  For instance, it is set for
-     __builtin_va_alist.  */
-  if (type)
-    {
-      MEM_SET_IN_STRUCT_P (reg,
-                          AGGREGATE_TYPE_P (type) || MEM_IN_STRUCT_P (new));
-      set_mem_alias_set (reg, get_alias_set (type));
-    }
-
-  if (used_p)
-    schedule_fixup_var_refs (function, reg, type, mode, ht);
-}
-
-/* Make sure that all refs to the variable, previously made
-   when it was a register, are fixed up to be valid again.
-   See function above for meaning of arguments.  */
-
-static void
-schedule_fixup_var_refs (struct function *function, rtx reg, tree type,
-                        enum machine_mode promoted_mode, htab_t ht)
-{
-  int unsigned_p = type ? TYPE_UNSIGNED (type) : 0;
-
-  if (function != 0)
-    {
-      struct var_refs_queue *temp;
-
-      temp = ggc_alloc (sizeof (struct var_refs_queue));
-      temp->modified = reg;
-      temp->promoted_mode = promoted_mode;
-      temp->unsignedp = unsigned_p;
-      temp->next = function->fixup_var_refs_queue;
-      function->fixup_var_refs_queue = temp;
-    }
-  else
-    /* Variable is local; fix it up now.  */
-    fixup_var_refs (reg, promoted_mode, unsigned_p, reg, ht);
-}
-\f
-static void
-fixup_var_refs (rtx var, enum machine_mode promoted_mode, int unsignedp,
-               rtx may_share, htab_t ht)
-{
-  rtx first_insn = get_insns ();
-  struct sequence_stack *stack = seq_stack;
-  int save_volatile_ok = volatile_ok;
-
-  /* If there's a hash table, it must record all uses of VAR.  */
-  if (ht)
-    {
-      if (stack != 0)
-       abort ();
-      fixup_var_refs_insns_with_hash (ht, var, promoted_mode, unsignedp,
-                                     may_share);
-      return;
-    }
-
-  /* Volatile is valid in MEMs because all we're doing in changing the
-     address inside.  */
-  volatile_ok = 1;
-  fixup_var_refs_insns (first_insn, var, promoted_mode, unsignedp,
-                       stack == 0, may_share);
-
-  /* Scan all pending sequences too.  */
-  for (; stack; stack = stack->next)
-    {
-      push_to_full_sequence (stack->first, stack->last);
-      fixup_var_refs_insns (stack->first, var, promoted_mode, unsignedp,
-                           stack->next != 0, may_share);
-      /* Update bounds of sequence in case we added insns.  */
-      stack->first = get_insns ();
-      stack->last = get_last_insn ();
-      end_sequence ();
-    }
-
-  volatile_ok = save_volatile_ok;
-}
-\f
-/* REPLACEMENTS is a pointer to a list of the struct fixup_replacement and X is
-   some part of an insn.  Return a struct fixup_replacement whose OLD
-   value is equal to X.  Allocate a new structure if no such entry exists.  */
-
-static struct fixup_replacement *
-find_fixup_replacement (struct fixup_replacement **replacements, rtx x)
-{
-  struct fixup_replacement *p;
-
-  /* See if we have already replaced this.  */
-  for (p = *replacements; p != 0 && ! rtx_equal_p (p->old, x); p = p->next)
-    ;
-
-  if (p == 0)
-    {
-      p = xmalloc (sizeof (struct fixup_replacement));
-      p->old = x;
-      p->new = 0;
-      p->next = *replacements;
-      *replacements = p;
-    }
-
-  return p;
-}
-
-/* Scan the insn-chain starting with INSN for refs to VAR and fix them
-   up.  TOPLEVEL is nonzero if this chain is the main chain of insns
-   for the current function.  MAY_SHARE is either a MEM that is not
-   to be unshared or a list of them.  */
-
-static void
-fixup_var_refs_insns (rtx insn, rtx var, enum machine_mode promoted_mode,
-                     int unsignedp, int toplevel, rtx may_share)
-{
-  while (insn)
-    {
-      /* fixup_var_refs_insn might modify insn, so save its next
-         pointer now.  */
-      rtx next = NEXT_INSN (insn);
-
-      if (INSN_P (insn))
-       fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, toplevel,
-                            may_share);
-
-      insn = next;
-    }
-}
-
-/* Look up the insns which reference VAR in HT and fix them up.  Other
-   arguments are the same as fixup_var_refs_insns.  */
-
-static void
-fixup_var_refs_insns_with_hash (htab_t ht, rtx var, enum machine_mode promoted_mode,
-                               int unsignedp, rtx may_share)
-{
-  struct insns_for_mem_entry tmp;
-  struct insns_for_mem_entry *ime;
-  rtx insn_list;
-
-  tmp.key = var;
-  ime = htab_find (ht, &tmp);
-  for (insn_list = ime->insns; insn_list != 0; insn_list = XEXP (insn_list, 1))
-    if (INSN_P (XEXP (insn_list, 0)))
-      fixup_var_refs_insn (XEXP (insn_list, 0), var, promoted_mode,
-                          unsignedp, 1, may_share);
-}
-
-
-/* Per-insn processing by fixup_var_refs_insns(_with_hash).  INSN is
-   the insn under examination, VAR is the variable to fix up
-   references to, PROMOTED_MODE and UNSIGNEDP describe VAR, and
-   TOPLEVEL is nonzero if this is the main insn chain for this
-   function.  */
-
-static void
-fixup_var_refs_insn (rtx insn, rtx var, enum machine_mode promoted_mode,
-                    int unsignedp, int toplevel, rtx no_share)
-{
-  rtx call_dest = 0;
-  rtx set, prev, prev_set;
-  rtx note;
-
-  /* Remember the notes in case we delete the insn.  */
-  note = REG_NOTES (insn);
-
-  /* If this is a CLOBBER of VAR, delete it.
-
-     If it has a REG_LIBCALL note, delete the REG_LIBCALL
-     and REG_RETVAL notes too.  */
-  if (GET_CODE (PATTERN (insn)) == CLOBBER
-      && (XEXP (PATTERN (insn), 0) == var
-         || (GET_CODE (XEXP (PATTERN (insn), 0)) == CONCAT
-             && (XEXP (XEXP (PATTERN (insn), 0), 0) == var
-                 || XEXP (XEXP (PATTERN (insn), 0), 1) == var))))
-    {
-      if ((note = find_reg_note (insn, REG_LIBCALL, NULL_RTX)) != 0)
-       /* The REG_LIBCALL note will go away since we are going to
-          turn INSN into a NOTE, so just delete the
-          corresponding REG_RETVAL note.  */
-       remove_note (XEXP (note, 0),
-                    find_reg_note (XEXP (note, 0), REG_RETVAL,
-                                   NULL_RTX));
-
-      delete_insn (insn);
-    }
-
-  /* The insn to load VAR from a home in the arglist
-     is now a no-op.  When we see it, just delete it.
-     Similarly if this is storing VAR from a register from which
-     it was loaded in the previous insn.  This will occur
-     when an ADDRESSOF was made for an arglist slot.  */
-  else if (toplevel
-          && (set = single_set (insn)) != 0
-          && SET_DEST (set) == var
-          /* If this represents the result of an insn group,
-             don't delete the insn.  */
-          && find_reg_note (insn, REG_RETVAL, NULL_RTX) == 0
-          && (rtx_equal_p (SET_SRC (set), var)
-              || (REG_P (SET_SRC (set))
-                  && (prev = prev_nonnote_insn (insn)) != 0
-                  && (prev_set = single_set (prev)) != 0
-                  && SET_DEST (prev_set) == SET_SRC (set)
-                  && rtx_equal_p (SET_SRC (prev_set), var))))
-    {
-      delete_insn (insn);
-    }
-  else
-    {
-      struct fixup_replacement *replacements = 0;
-
-      if (SMALL_REGISTER_CLASSES)
-       {
-         /* If the insn that copies the results of a CALL_INSN
-            into a pseudo now references VAR, we have to use an
-            intermediate pseudo since we want the life of the
-            return value register to be only a single insn.
-
-            If we don't use an intermediate pseudo, such things as
-            address computations to make the address of VAR valid
-            if it is not can be placed between the CALL_INSN and INSN.
-
-            To make sure this doesn't happen, we record the destination
-            of the CALL_INSN and see if the next insn uses both that
-            and VAR.  */
-
-         if (call_dest != 0 && GET_CODE (insn) == INSN
-             && reg_mentioned_p (var, PATTERN (insn))
-             && reg_mentioned_p (call_dest, PATTERN (insn)))
-           {
-             rtx temp = gen_reg_rtx (GET_MODE (call_dest));
-
-             emit_insn_before (gen_move_insn (temp, call_dest), insn);
-
-             PATTERN (insn) = replace_rtx (PATTERN (insn),
-                                           call_dest, temp);
-           }
-
-         if (GET_CODE (insn) == CALL_INSN
-             && GET_CODE (PATTERN (insn)) == SET)
-           call_dest = SET_DEST (PATTERN (insn));
-         else if (GET_CODE (insn) == CALL_INSN
-                  && GET_CODE (PATTERN (insn)) == PARALLEL
-                  && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET)
-           call_dest = SET_DEST (XVECEXP (PATTERN (insn), 0, 0));
-         else
-           call_dest = 0;
-       }
-
-      /* See if we have to do anything to INSN now that VAR is in
-        memory.  If it needs to be loaded into a pseudo, use a single
-        pseudo for the entire insn in case there is a MATCH_DUP
-        between two operands.  We pass a pointer to the head of
-        a list of struct fixup_replacements.  If fixup_var_refs_1
-        needs to allocate pseudos or replacement MEMs (for SUBREGs),
-        it will record them in this list.
-
-        If it allocated a pseudo for any replacement, we copy into
-        it here.  */
-
-      fixup_var_refs_1 (var, promoted_mode, &PATTERN (insn), insn,
-                       &replacements, no_share);
-
-      while (replacements)
-       {
-         struct fixup_replacement *next;
-
-         if (REG_P (replacements->new))
-           {
-             rtx insert_before;
-             rtx seq;
-
-             /* OLD might be a (subreg (mem)).  */
-             if (GET_CODE (replacements->old) == SUBREG)
-               replacements->old
-                 = fixup_memory_subreg (replacements->old, insn,
-                                        promoted_mode, 0);
-             else
-               replacements->old
-                 = fixup_stack_1 (replacements->old, insn);
-
-             insert_before = insn;
-
-             /* If we are changing the mode, do a conversion.
-                This might be wasteful, but combine.c will
-                eliminate much of the waste.  */
-
-             if (GET_MODE (replacements->new)
-                 != GET_MODE (replacements->old))
-               {
-                 start_sequence ();
-                 convert_move (replacements->new,
-                               replacements->old, unsignedp);
-                 seq = get_insns ();
-                 end_sequence ();
-               }
-             else
-               seq = gen_move_insn (replacements->new,
-                                    replacements->old);
-
-             emit_insn_before (seq, insert_before);
-           }
-
-         next = replacements->next;
-         free (replacements);
-         replacements = next;
-       }
-    }
-
-  /* Also fix up any invalid exprs in the REG_NOTES of this insn.
-     But don't touch other insns referred to by reg-notes;
-     we will get them elsewhere.  */
-  while (note)
-    {
-      if (GET_CODE (note) != INSN_LIST)
-       XEXP (note, 0)
-         = walk_fixup_memory_subreg (XEXP (note, 0), insn, var,
-                                     promoted_mode, 1);
-      note = XEXP (note, 1);
-    }
-}
-\f
-/* VAR is a MEM that used to be a pseudo register with mode PROMOTED_MODE.
-   See if the rtx expression at *LOC in INSN needs to be changed.
-
-   REPLACEMENTS is a pointer to a list head that starts out zero, but may
-   contain a list of original rtx's and replacements. If we find that we need
-   to modify this insn by replacing a memory reference with a pseudo or by
-   making a new MEM to implement a SUBREG, we consult that list to see if
-   we have already chosen a replacement. If none has already been allocated,
-   we allocate it and update the list.  fixup_var_refs_insn will copy VAR
-   or the SUBREG, as appropriate, to the pseudo.  */
-
-static void
-fixup_var_refs_1 (rtx var, enum machine_mode promoted_mode, rtx *loc, rtx insn,
-                 struct fixup_replacement **replacements, rtx no_share)
-{
-  int i;
-  rtx x = *loc;
-  RTX_CODE code = GET_CODE (x);
-  const char *fmt;
-  rtx tem, tem1;
-  struct fixup_replacement *replacement;
-
-  switch (code)
-    {
-    case ADDRESSOF:
-      if (XEXP (x, 0) == var)
-       {
-         /* Prevent sharing of rtl that might lose.  */
-         rtx sub = copy_rtx (XEXP (var, 0));
-
-         if (! validate_change (insn, loc, sub, 0))
-           {
-             rtx y = gen_reg_rtx (GET_MODE (sub));
-             rtx seq, new_insn;
-
-             /* We should be able to replace with a register or all is lost.
-                Note that we can't use validate_change to verify this, since
-                we're not caring for replacing all dups simultaneously.  */
-             if (! validate_replace_rtx (*loc, y, insn))
-               abort ();
-
-             /* Careful!  First try to recognize a direct move of the
-                value, mimicking how things are done in gen_reload wrt
-                PLUS.  Consider what happens when insn is a conditional
-                move instruction and addsi3 clobbers flags.  */
-
-             start_sequence ();
-             new_insn = emit_insn (gen_rtx_SET (VOIDmode, y, sub));
-             seq = get_insns ();
-             end_sequence ();
-
-             if (recog_memoized (new_insn) < 0)
-               {
-                 /* That failed.  Fall back on force_operand and hope.  */
-
-                 start_sequence ();
-                 sub = force_operand (sub, y);
-                 if (sub != y)
-                   emit_insn (gen_move_insn (y, sub));
-                 seq = get_insns ();
-                 end_sequence ();
-               }
-
-#ifdef HAVE_cc0
-             /* Don't separate setter from user.  */
-             if (PREV_INSN (insn) && sets_cc0_p (PREV_INSN (insn)))
-               insn = PREV_INSN (insn);
-#endif
-
-             emit_insn_before (seq, insn);
-           }
-       }
-      return;
-
-    case MEM:
-      if (var == x)
-       {
-         /* If we already have a replacement, use it.  Otherwise,
-            try to fix up this address in case it is invalid.  */
-
-         replacement = find_fixup_replacement (replacements, var);
-         if (replacement->new)
-           {
-             *loc = replacement->new;
-             return;
-           }
-
-         *loc = replacement->new = x = fixup_stack_1 (x, insn);
-
-         /* Unless we are forcing memory to register or we changed the mode,
-            we can leave things the way they are if the insn is valid.  */
-
-         INSN_CODE (insn) = -1;
-         if (! flag_force_mem && GET_MODE (x) == promoted_mode
-             && recog_memoized (insn) >= 0)
-           return;
-
-         *loc = replacement->new = gen_reg_rtx (promoted_mode);
-         return;
-       }
-
-      /* If X contains VAR, we need to unshare it here so that we update
-        each occurrence separately.  But all identical MEMs in one insn
-        must be replaced with the same rtx because of the possibility of
-        MATCH_DUPs.  */
-
-      if (reg_mentioned_p (var, x))
-       {
-         replacement = find_fixup_replacement (replacements, x);
-         if (replacement->new == 0)
-           replacement->new = copy_most_rtx (x, no_share);
-
-         *loc = x = replacement->new;
-         code = GET_CODE (x);
-       }
-      break;
-
-    case REG:
-    case CC0:
-    case PC:
-    case CONST_INT:
-    case CONST:
-    case SYMBOL_REF:
-    case LABEL_REF:
-    case CONST_DOUBLE:
-    case CONST_VECTOR:
-      return;
-
-    case SIGN_EXTRACT:
-    case ZERO_EXTRACT:
-      /* Note that in some cases those types of expressions are altered
-        by optimize_bit_field, and do not survive to get here.  */
-      if (XEXP (x, 0) == var
-         || (GET_CODE (XEXP (x, 0)) == SUBREG
-             && SUBREG_REG (XEXP (x, 0)) == var))
-       {
-         /* Get TEM as a valid MEM in the mode presently in the insn.
-
-            We don't worry about the possibility of MATCH_DUP here; it
-            is highly unlikely and would be tricky to handle.  */
-
-         tem = XEXP (x, 0);
-         if (GET_CODE (tem) == SUBREG)
-           {
-             if (GET_MODE_BITSIZE (GET_MODE (tem))
-                 > GET_MODE_BITSIZE (GET_MODE (var)))
-               {
-                 replacement = find_fixup_replacement (replacements, var);
-                 if (replacement->new == 0)
-                   replacement->new = gen_reg_rtx (GET_MODE (var));
-                 SUBREG_REG (tem) = replacement->new;
-
-                 /* The following code works only if we have a MEM, so we
-                    need to handle the subreg here.  We directly substitute
-                    it assuming that a subreg must be OK here.  We already
-                    scheduled a replacement to copy the mem into the
-                    subreg.  */
-                 XEXP (x, 0) = tem;
-                 return;
-               }
-             else
-               tem = fixup_memory_subreg (tem, insn, promoted_mode, 0);
-           }
-         else
-           tem = fixup_stack_1 (tem, insn);
-
-         /* Unless we want to load from memory, get TEM into the proper mode
-            for an extract from memory.  This can only be done if the
-            extract is at a constant position and length.  */
-
-         if (! flag_force_mem && GET_CODE (XEXP (x, 1)) == CONST_INT
-             && GET_CODE (XEXP (x, 2)) == CONST_INT
-             && ! mode_dependent_address_p (XEXP (tem, 0))
-             && ! MEM_VOLATILE_P (tem))
-           {
-             enum machine_mode wanted_mode = VOIDmode;
-             enum machine_mode is_mode = GET_MODE (tem);
-             HOST_WIDE_INT pos = INTVAL (XEXP (x, 2));
-
-             if (GET_CODE (x) == ZERO_EXTRACT)
-               {
-                 enum machine_mode new_mode
-                   = mode_for_extraction (EP_extzv, 1);
-                 if (new_mode != MAX_MACHINE_MODE)
-                   wanted_mode = new_mode;
-               }
-             else if (GET_CODE (x) == SIGN_EXTRACT)
-               {
-                 enum machine_mode new_mode
-                   = mode_for_extraction (EP_extv, 1);
-                 if (new_mode != MAX_MACHINE_MODE)
-                   wanted_mode = new_mode;
-               }
-
-             /* If we have a narrower mode, we can do something.  */
-             if (wanted_mode != VOIDmode
-                 && GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode))
-               {
-                 HOST_WIDE_INT offset = pos / BITS_PER_UNIT;
-                 rtx old_pos = XEXP (x, 2);
-                 rtx newmem;
-
-                 /* If the bytes and bits are counted differently, we
-                    must adjust the offset.  */
-                 if (BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN)
-                   offset = (GET_MODE_SIZE (is_mode)
-                             - GET_MODE_SIZE (wanted_mode) - offset);
-
-                 pos %= GET_MODE_BITSIZE (wanted_mode);
-
-                 newmem = adjust_address_nv (tem, wanted_mode, offset);
-
-                 /* Make the change and see if the insn remains valid.  */
-                 INSN_CODE (insn) = -1;
-                 XEXP (x, 0) = newmem;
-                 XEXP (x, 2) = GEN_INT (pos);
-
-                 if (recog_memoized (insn) >= 0)
-                   return;
-
-                 /* Otherwise, restore old position.  XEXP (x, 0) will be
-                    restored later.  */
-                 XEXP (x, 2) = old_pos;
-               }
-           }
-
-         /* If we get here, the bitfield extract insn can't accept a memory
-            reference.  Copy the input into a register.  */
-
-         tem1 = gen_reg_rtx (GET_MODE (tem));
-         emit_insn_before (gen_move_insn (tem1, tem), insn);
-         XEXP (x, 0) = tem1;
-         return;
-       }
-      break;
-
-    case SUBREG:
-      if (SUBREG_REG (x) == var)
-       {
-         /* If this is a special SUBREG made because VAR was promoted
-            from a wider mode, replace it with VAR and call ourself
-            recursively, this time saying that the object previously
-            had its current mode (by virtue of the SUBREG).  */
-
-         if (SUBREG_PROMOTED_VAR_P (x))
-           {
-             *loc = var;
-             fixup_var_refs_1 (var, GET_MODE (var), loc, insn, replacements,
-                               no_share);
-             return;
-           }
-
-         /* If this SUBREG makes VAR wider, it has become a paradoxical
-            SUBREG with VAR in memory, but these aren't allowed at this
-            stage of the compilation.  So load VAR into a pseudo and take
-            a SUBREG of that pseudo.  */
-         if (GET_MODE_SIZE (GET_MODE (x)) > GET_MODE_SIZE (GET_MODE (var)))
-           {
-             replacement = find_fixup_replacement (replacements, var);
-             if (replacement->new == 0)
-               replacement->new = gen_reg_rtx (promoted_mode);
-             SUBREG_REG (x) = replacement->new;
-             return;
-           }
-
-         /* See if we have already found a replacement for this SUBREG.
-            If so, use it.  Otherwise, make a MEM and see if the insn
-            is recognized.  If not, or if we should force MEM into a register,
-            make a pseudo for this SUBREG.  */
-         replacement = find_fixup_replacement (replacements, x);
-         if (replacement->new)
-           {
-             enum machine_mode mode = GET_MODE (x);
-             *loc = replacement->new;
-
-             /* Careful!  We may have just replaced a SUBREG by a MEM, which
-                means that the insn may have become invalid again.  We can't
-                in this case make a new replacement since we already have one
-                and we must deal with MATCH_DUPs.  */
-             if (MEM_P (replacement->new))
-               {
-                 INSN_CODE (insn) = -1;
-                 if (recog_memoized (insn) >= 0)
-                   return;
-
-                 fixup_var_refs_1 (replacement->new, mode, &PATTERN (insn),
-                                   insn, replacements, no_share);
-               }
-
-             return;
-           }
-
-         replacement->new = *loc = fixup_memory_subreg (x, insn,
-                                                        promoted_mode, 0);
-
-         INSN_CODE (insn) = -1;
-         if (! flag_force_mem && recog_memoized (insn) >= 0)
-           return;
-
-         *loc = replacement->new = gen_reg_rtx (GET_MODE (x));
-         return;
-       }
-      break;
-
-    case SET:
-      /* First do special simplification of bit-field references.  */
-      if (GET_CODE (SET_DEST (x)) == SIGN_EXTRACT
-         || GET_CODE (SET_DEST (x)) == ZERO_EXTRACT)
-       optimize_bit_field (x, insn, 0);
-      if (GET_CODE (SET_SRC (x)) == SIGN_EXTRACT
-         || GET_CODE (SET_SRC (x)) == ZERO_EXTRACT)
-       optimize_bit_field (x, insn, 0);
-
-      /* For a paradoxical SUBREG inside a ZERO_EXTRACT, load the object
-        into a register and then store it back out.  */
-      if (GET_CODE (SET_DEST (x)) == ZERO_EXTRACT
-         && GET_CODE (XEXP (SET_DEST (x), 0)) == SUBREG
-         && SUBREG_REG (XEXP (SET_DEST (x), 0)) == var
-         && (GET_MODE_SIZE (GET_MODE (XEXP (SET_DEST (x), 0)))
-             > GET_MODE_SIZE (GET_MODE (var))))
-       {
-         replacement = find_fixup_replacement (replacements, var);
-         if (replacement->new == 0)
-           replacement->new = gen_reg_rtx (GET_MODE (var));
-
-         SUBREG_REG (XEXP (SET_DEST (x), 0)) = replacement->new;
-         emit_insn_after (gen_move_insn (var, replacement->new), insn);
-       }
-
-      /* If SET_DEST is now a paradoxical SUBREG, put the result of this
-        insn into a pseudo and store the low part of the pseudo into VAR.  */
-      if (GET_CODE (SET_DEST (x)) == SUBREG
-         && SUBREG_REG (SET_DEST (x)) == var
-         && (GET_MODE_SIZE (GET_MODE (SET_DEST (x)))
-             > GET_MODE_SIZE (GET_MODE (var))))
-       {
-         SET_DEST (x) = tem = gen_reg_rtx (GET_MODE (SET_DEST (x)));
-         emit_insn_after (gen_move_insn (var, gen_lowpart (GET_MODE (var),
-                                                           tem)),
-                          insn);
-         break;
-       }
-
-      {
-       rtx dest = SET_DEST (x);
-       rtx src = SET_SRC (x);
-       rtx outerdest = dest;
-
-       while (GET_CODE (dest) == SUBREG || GET_CODE (dest) == STRICT_LOW_PART
-              || GET_CODE (dest) == SIGN_EXTRACT
-              || GET_CODE (dest) == ZERO_EXTRACT)
-         dest = XEXP (dest, 0);
-
-       if (GET_CODE (src) == SUBREG)
-         src = SUBREG_REG (src);
-
-       /* If VAR does not appear at the top level of the SET
-          just scan the lower levels of the tree.  */
-
-       if (src != var && dest != var)
-         break;
-
-       /* We will need to rerecognize this insn.  */
-       INSN_CODE (insn) = -1;
-
-       if (GET_CODE (outerdest) == ZERO_EXTRACT && dest == var
-           && mode_for_extraction (EP_insv, -1) != MAX_MACHINE_MODE)
-         {
-           /* Since this case will return, ensure we fixup all the
-              operands here.  */
-           fixup_var_refs_1 (var, promoted_mode, &XEXP (outerdest, 1),
-                             insn, replacements, no_share);
-           fixup_var_refs_1 (var, promoted_mode, &XEXP (outerdest, 2),
-                             insn, replacements, no_share);
-           fixup_var_refs_1 (var, promoted_mode, &SET_SRC (x),
-                             insn, replacements, no_share);
-
-           tem = XEXP (outerdest, 0);
-
-           /* Clean up (SUBREG:SI (MEM:mode ...) 0)
-              that may appear inside a ZERO_EXTRACT.
-              This was legitimate when the MEM was a REG.  */
-           if (GET_CODE (tem) == SUBREG
-               && SUBREG_REG (tem) == var)
-             tem = fixup_memory_subreg (tem, insn, promoted_mode, 0);
-           else
-             tem = fixup_stack_1 (tem, insn);
-
-           if (GET_CODE (XEXP (outerdest, 1)) == CONST_INT
-               && GET_CODE (XEXP (outerdest, 2)) == CONST_INT
-               && ! mode_dependent_address_p (XEXP (tem, 0))
-               && ! MEM_VOLATILE_P (tem))
-             {
-               enum machine_mode wanted_mode;
-               enum machine_mode is_mode = GET_MODE (tem);
-               HOST_WIDE_INT pos = INTVAL (XEXP (outerdest, 2));
-
-               wanted_mode = mode_for_extraction (EP_insv, 0);
-
-               /* If we have a narrower mode, we can do something.  */
-               if (GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode))
-                 {
-                   HOST_WIDE_INT offset = pos / BITS_PER_UNIT;
-                   rtx old_pos = XEXP (outerdest, 2);
-                   rtx newmem;
-
-                   if (BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN)
-                     offset = (GET_MODE_SIZE (is_mode)
-                               - GET_MODE_SIZE (wanted_mode) - offset);
-
-                   pos %= GET_MODE_BITSIZE (wanted_mode);
-
-                   newmem = adjust_address_nv (tem, wanted_mode, offset);
-
-                   /* Make the change and see if the insn remains valid.  */
-                   INSN_CODE (insn) = -1;
-                   XEXP (outerdest, 0) = newmem;
-                   XEXP (outerdest, 2) = GEN_INT (pos);
-
-                   if (recog_memoized (insn) >= 0)
-                     return;
-
-                   /* Otherwise, restore old position.  XEXP (x, 0) will be
-                      restored later.  */
-                   XEXP (outerdest, 2) = old_pos;
-                 }
-             }
-
-           /* If we get here, the bit-field store doesn't allow memory
-              or isn't located at a constant position.  Load the value into
-              a register, do the store, and put it back into memory.  */
-
-           tem1 = gen_reg_rtx (GET_MODE (tem));
-           emit_insn_before (gen_move_insn (tem1, tem), insn);
-           emit_insn_after (gen_move_insn (tem, tem1), insn);
-           XEXP (outerdest, 0) = tem1;
-           return;
-         }
-
-       /* STRICT_LOW_PART is a no-op on memory references
-          and it can cause combinations to be unrecognizable,
-          so eliminate it.  */
-
-       if (dest == var && GET_CODE (SET_DEST (x)) == STRICT_LOW_PART)
-         SET_DEST (x) = XEXP (SET_DEST (x), 0);
-
-       /* A valid insn to copy VAR into or out of a register
-          must be left alone, to avoid an infinite loop here.
-          If the reference to VAR is by a subreg, fix that up,
-          since SUBREG is not valid for a memref.
-          Also fix up the address of the stack slot.
-
-          Note that we must not try to recognize the insn until
-          after we know that we have valid addresses and no
-          (subreg (mem ...) ...) constructs, since these interfere
-          with determining the validity of the insn.  */
-
-       if ((SET_SRC (x) == var
-            || (GET_CODE (SET_SRC (x)) == SUBREG
-                && SUBREG_REG (SET_SRC (x)) == var))
-           && (REG_P (SET_DEST (x))
-               || (GET_CODE (SET_DEST (x)) == SUBREG
-                   && REG_P (SUBREG_REG (SET_DEST (x)))))
-           && GET_MODE (var) == promoted_mode
-           && x == single_set (insn))
-         {
-           rtx pat, last;
-
-           if (GET_CODE (SET_SRC (x)) == SUBREG
-               && (GET_MODE_SIZE (GET_MODE (SET_SRC (x)))
-                   > GET_MODE_SIZE (GET_MODE (var))))
-             {
-               /* This (subreg VAR) is now a paradoxical subreg.  We need
-                  to replace VAR instead of the subreg.  */
-               replacement = find_fixup_replacement (replacements, var);
-               if (replacement->new == NULL_RTX)
-                 replacement->new = gen_reg_rtx (GET_MODE (var));
-               SUBREG_REG (SET_SRC (x)) = replacement->new;
-             }
-           else
-             {
-               replacement = find_fixup_replacement (replacements, SET_SRC (x));
-               if (replacement->new)
-                 SET_SRC (x) = replacement->new;
-               else if (GET_CODE (SET_SRC (x)) == SUBREG)
-                 SET_SRC (x) = replacement->new
-                   = fixup_memory_subreg (SET_SRC (x), insn, promoted_mode,
-                                          0);
-               else
-                 SET_SRC (x) = replacement->new
-                   = fixup_stack_1 (SET_SRC (x), insn);
-             }
-
-           if (recog_memoized (insn) >= 0)
-             return;
-
-           /* INSN is not valid, but we know that we want to
-              copy SET_SRC (x) to SET_DEST (x) in some way.  So
-              we generate the move and see whether it requires more
-              than one insn.  If it does, we emit those insns and
-              delete INSN.  Otherwise, we can just replace the pattern
-              of INSN; we have already verified above that INSN has
-              no other function that to do X.  */
-
-           pat = gen_move_insn (SET_DEST (x), SET_SRC (x));
-           if (NEXT_INSN (pat) != NULL_RTX)
-             {
-               last = emit_insn_before (pat, insn);
-
-               /* INSN might have REG_RETVAL or other important notes, so
-                  we need to store the pattern of the last insn in the
-                  sequence into INSN similarly to the normal case.  LAST
-                  should not have REG_NOTES, but we allow them if INSN has
-                  no REG_NOTES.  */
-               if (REG_NOTES (last) && REG_NOTES (insn))
-                 abort ();
-               if (REG_NOTES (last))
-                 REG_NOTES (insn) = REG_NOTES (last);
-               PATTERN (insn) = PATTERN (last);
-
-               delete_insn (last);
-             }
-           else
-             PATTERN (insn) = PATTERN (pat);
-
-           return;
-         }
-
-       if ((SET_DEST (x) == var
-            || (GET_CODE (SET_DEST (x)) == SUBREG
-                && SUBREG_REG (SET_DEST (x)) == var))
-           && (REG_P (SET_SRC (x))
-               || (GET_CODE (SET_SRC (x)) == SUBREG
-                   && REG_P (SUBREG_REG (SET_SRC (x)))))
-           && GET_MODE (var) == promoted_mode
-           && x == single_set (insn))
-         {
-           rtx pat, last;
-
-           if (GET_CODE (SET_DEST (x)) == SUBREG)
-             SET_DEST (x) = fixup_memory_subreg (SET_DEST (x), insn,
-                                                 promoted_mode, 0);
-           else
-             SET_DEST (x) = fixup_stack_1 (SET_DEST (x), insn);
-
-           if (recog_memoized (insn) >= 0)
-             return;
-
-           pat = gen_move_insn (SET_DEST (x), SET_SRC (x));
-           if (NEXT_INSN (pat) != NULL_RTX)
-             {
-               last = emit_insn_before (pat, insn);
-
-               /* INSN might have REG_RETVAL or other important notes, so
-                  we need to store the pattern of the last insn in the
-                  sequence into INSN similarly to the normal case.  LAST
-                  should not have REG_NOTES, but we allow them if INSN has
-                  no REG_NOTES.  */
-               if (REG_NOTES (last) && REG_NOTES (insn))
-                 abort ();
-               if (REG_NOTES (last))
-                 REG_NOTES (insn) = REG_NOTES (last);
-               PATTERN (insn) = PATTERN (last);
-
-               delete_insn (last);
-             }
-           else
-             PATTERN (insn) = PATTERN (pat);
-
-           return;
-         }
-
-       /* Otherwise, storing into VAR must be handled specially
-          by storing into a temporary and copying that into VAR
-          with a new insn after this one.  Note that this case
-          will be used when storing into a promoted scalar since
-          the insn will now have different modes on the input
-          and output and hence will be invalid (except for the case
-          of setting it to a constant, which does not need any
-          change if it is valid).  We generate extra code in that case,
-          but combine.c will eliminate it.  */
-
-       if (dest == var)
-         {
-           rtx temp;
-           rtx fixeddest = SET_DEST (x);
-           enum machine_mode temp_mode;
-
-           /* STRICT_LOW_PART can be discarded, around a MEM.  */
-           if (GET_CODE (fixeddest) == STRICT_LOW_PART)
-             fixeddest = XEXP (fixeddest, 0);
-           /* Convert (SUBREG (MEM)) to a MEM in a changed mode.  */
-           if (GET_CODE (fixeddest) == SUBREG)
-             {
-               fixeddest = fixup_memory_subreg (fixeddest, insn,
-                                                promoted_mode, 0);
-               temp_mode = GET_MODE (fixeddest);
-             }
-           else
-             {
-               fixeddest = fixup_stack_1 (fixeddest, insn);
-               temp_mode = promoted_mode;
-             }
-
-           temp = gen_reg_rtx (temp_mode);
-
-           emit_insn_after (gen_move_insn (fixeddest,
-                                           gen_lowpart (GET_MODE (fixeddest),
-                                                        temp)),
-                            insn);
-
-           SET_DEST (x) = temp;
-         }
-      }
-
-    default:
-      break;
-    }
-
-  /* Nothing special about this RTX; fix its operands.  */
-
-  fmt = GET_RTX_FORMAT (code);
-  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
-    {
-      if (fmt[i] == 'e')
-       fixup_var_refs_1 (var, promoted_mode, &XEXP (x, i), insn, replacements,
-                         no_share);
-      else if (fmt[i] == 'E')
-       {
-         int j;
-         for (j = 0; j < XVECLEN (x, i); j++)
-           fixup_var_refs_1 (var, promoted_mode, &XVECEXP (x, i, j),
-                             insn, replacements, no_share);
-       }
-    }
-}
-\f
-/* Previously, X had the form (SUBREG:m1 (REG:PROMOTED_MODE ...)).
-   The REG  was placed on the stack, so X now has the form (SUBREG:m1
-   (MEM:m2 ...)).
-
-   Return an rtx (MEM:m1 newaddr) which is equivalent.  If any insns
-   must be emitted to compute NEWADDR, put them before INSN.
-
-   UNCRITICAL nonzero means accept paradoxical subregs.
-   This is used for subregs found inside REG_NOTES.  */
-
-static rtx
-fixup_memory_subreg (rtx x, rtx insn, enum machine_mode promoted_mode, int uncritical)
-{
-  int offset;
-  rtx mem = SUBREG_REG (x);
-  rtx addr = XEXP (mem, 0);
-  enum machine_mode mode = GET_MODE (x);
-  rtx result, seq;
-
-  /* Paradoxical SUBREGs are usually invalid during RTL generation.  */
-  if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (mem)) && ! uncritical)
-    abort ();
-
-  offset = SUBREG_BYTE (x);
-  if (BYTES_BIG_ENDIAN)
-    /* If the PROMOTED_MODE is wider than the mode of the MEM, adjust
-       the offset so that it points to the right location within the
-       MEM.  */
-    offset -= (GET_MODE_SIZE (promoted_mode) - GET_MODE_SIZE (GET_MODE (mem)));
-
-  if (!flag_force_addr
-      && memory_address_p (mode, plus_constant (addr, offset)))
-    /* Shortcut if no insns need be emitted.  */
-    return adjust_address (mem, mode, offset);
-
-  start_sequence ();
-  result = adjust_address (mem, mode, offset);
-  seq = get_insns ();
-  end_sequence ();
-
-  emit_insn_before (seq, insn);
-  return result;
-}
-
-/* Do fixup_memory_subreg on all (SUBREG (VAR) ...) contained in X.
-   VAR is a MEM that used to be a pseudo register with mode PROMOTED_MODE.
-   Replace subexpressions of X in place.
-   If X itself is a (SUBREG (VAR) ...), return the replacement expression.
-   Otherwise return X, with its contents possibly altered.
-
-   INSN and UNCRITICAL are as for fixup_memory_subreg.  */
-
-static rtx
-walk_fixup_memory_subreg (rtx x, rtx insn, rtx var,
-                         enum machine_mode promoted_mode, int uncritical)
-{
-  enum rtx_code code;
-  const char *fmt;
-  int i;
-
-  if (x == 0)
-    return 0;
-
-  code = GET_CODE (x);
-
-  if (code == SUBREG && SUBREG_REG (x) == var)
-    return fixup_memory_subreg (x, insn, promoted_mode, uncritical);
-
-  /* Nothing special about this RTX; fix its operands.  */
-
-  fmt = GET_RTX_FORMAT (code);
-  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
-    {
-      if (fmt[i] == 'e')
-       XEXP (x, i) = walk_fixup_memory_subreg (XEXP (x, i), insn, var,
-                                               promoted_mode, uncritical);
-      else if (fmt[i] == 'E')
-       {
-         int j;
-         for (j = 0; j < XVECLEN (x, i); j++)
-           XVECEXP (x, i, j)
-             = walk_fixup_memory_subreg (XVECEXP (x, i, j), insn, var,
-                                         promoted_mode, uncritical);
-       }
-    }
-  return x;
-}
-\f
-/* For each memory ref within X, if it refers to a stack slot
-   with an out of range displacement, put the address in a temp register
-   (emitting new insns before INSN to load these registers)
-   and alter the memory ref to use that register.
-   Replace each such MEM rtx with a copy, to avoid clobberage.  */
-
-static rtx
-fixup_stack_1 (rtx x, rtx insn)
-{
-  int i;
-  RTX_CODE code = GET_CODE (x);
-  const char *fmt;
-
-  if (code == MEM)
-    {
-      rtx ad = XEXP (x, 0);
-      /* If we have address of a stack slot but it's not valid
-        (displacement is too large), compute the sum in a register.  */
-      if (GET_CODE (ad) == PLUS
-         && REG_P (XEXP (ad, 0))
-         && ((REGNO (XEXP (ad, 0)) >= FIRST_VIRTUAL_REGISTER
-              && REGNO (XEXP (ad, 0)) <= LAST_VIRTUAL_REGISTER)
-             || REGNO (XEXP (ad, 0)) == FRAME_POINTER_REGNUM
-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
-             || REGNO (XEXP (ad, 0)) == HARD_FRAME_POINTER_REGNUM
-#endif
-             || REGNO (XEXP (ad, 0)) == STACK_POINTER_REGNUM
-             || REGNO (XEXP (ad, 0)) == ARG_POINTER_REGNUM
-             || XEXP (ad, 0) == current_function_internal_arg_pointer)
-         && GET_CODE (XEXP (ad, 1)) == CONST_INT)
-       {
-         rtx temp, seq;
-         if (memory_address_p (GET_MODE (x), ad))
-           return x;
-
-         start_sequence ();
-         temp = copy_to_reg (ad);
-         seq = get_insns ();
-         end_sequence ();
-         emit_insn_before (seq, insn);
-         return replace_equiv_address (x, temp);
-       }
-      return x;
-    }
-
-  fmt = GET_RTX_FORMAT (code);
-  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
-    {
-      if (fmt[i] == 'e')
-       XEXP (x, i) = fixup_stack_1 (XEXP (x, i), insn);
-      else if (fmt[i] == 'E')
-       {
-         int j;
-         for (j = 0; j < XVECLEN (x, i); j++)
-           XVECEXP (x, i, j) = fixup_stack_1 (XVECEXP (x, i, j), insn);
-       }
-    }
-  return x;
-}
-\f
-/* Optimization: a bit-field instruction whose field
-   happens to be a byte or halfword in memory
-   can be changed to a move instruction.
-
-   We call here when INSN is an insn to examine or store into a bit-field.
-   BODY is the SET-rtx to be altered.
-
-   EQUIV_MEM is the table `reg_equiv_mem' if that is available; else 0.
-   (Currently this is called only from function.c, and EQUIV_MEM
-   is always 0.)  */
-
-static void
-optimize_bit_field (rtx body, rtx insn, rtx *equiv_mem)
-{
-  rtx bitfield;
-  int destflag;
-  rtx seq = 0;
-  enum machine_mode mode;
-
-  if (GET_CODE (SET_DEST (body)) == SIGN_EXTRACT
-      || GET_CODE (SET_DEST (body)) == ZERO_EXTRACT)
-    bitfield = SET_DEST (body), destflag = 1;
-  else
-    bitfield = SET_SRC (body), destflag = 0;
-
-  /* First check that the field being stored has constant size and position
-     and is in fact a byte or halfword suitably aligned.  */
-
-  if (GET_CODE (XEXP (bitfield, 1)) == CONST_INT
-      && GET_CODE (XEXP (bitfield, 2)) == CONST_INT
-      && ((mode = mode_for_size (INTVAL (XEXP (bitfield, 1)), MODE_INT, 1))
-         != BLKmode)
-      && INTVAL (XEXP (bitfield, 2)) % INTVAL (XEXP (bitfield, 1)) == 0)
-    {
-      rtx memref = 0;
-
-      /* Now check that the containing word is memory, not a register,
-        and that it is safe to change the machine mode.  */
-
-      if (MEM_P (XEXP (bitfield, 0)))
-       memref = XEXP (bitfield, 0);
-      else if (REG_P (XEXP (bitfield, 0))
-              && equiv_mem != 0)
-       memref = equiv_mem[REGNO (XEXP (bitfield, 0))];
-      else if (GET_CODE (XEXP (bitfield, 0)) == SUBREG
-              && MEM_P (SUBREG_REG (XEXP (bitfield, 0))))
-       memref = SUBREG_REG (XEXP (bitfield, 0));
-      else if (GET_CODE (XEXP (bitfield, 0)) == SUBREG
-              && equiv_mem != 0
-              && REG_P (SUBREG_REG (XEXP (bitfield, 0))))
-       memref = equiv_mem[REGNO (SUBREG_REG (XEXP (bitfield, 0)))];
-
-      if (memref
-         && ! mode_dependent_address_p (XEXP (memref, 0))
-         && ! MEM_VOLATILE_P (memref))
-       {
-         /* Now adjust the address, first for any subreg'ing
-            that we are now getting rid of,
-            and then for which byte of the word is wanted.  */
-
-         HOST_WIDE_INT offset = INTVAL (XEXP (bitfield, 2));
-         rtx insns;
-
-         /* Adjust OFFSET to count bits from low-address byte.  */
-         if (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
-           offset = (GET_MODE_BITSIZE (GET_MODE (XEXP (bitfield, 0)))
-                     - offset - INTVAL (XEXP (bitfield, 1)));
-
-         /* Adjust OFFSET to count bytes from low-address byte.  */
-         offset /= BITS_PER_UNIT;
-         if (GET_CODE (XEXP (bitfield, 0)) == SUBREG)
-           {
-             offset += (SUBREG_BYTE (XEXP (bitfield, 0))
-                        / UNITS_PER_WORD) * UNITS_PER_WORD;
-             if (BYTES_BIG_ENDIAN)
-               offset -= (MIN (UNITS_PER_WORD,
-                               GET_MODE_SIZE (GET_MODE (XEXP (bitfield, 0))))
-                          - MIN (UNITS_PER_WORD,
-                                 GET_MODE_SIZE (GET_MODE (memref))));
-           }
-
-         start_sequence ();
-         memref = adjust_address (memref, mode, offset);
-         insns = get_insns ();
-         end_sequence ();
-         emit_insn_before (insns, insn);
-
-         /* Store this memory reference where
-            we found the bit field reference.  */
-
-         if (destflag)
-           {
-             validate_change (insn, &SET_DEST (body), memref, 1);
-             if (! CONSTANT_ADDRESS_P (SET_SRC (body)))
-               {
-                 rtx src = SET_SRC (body);
-                 while (GET_CODE (src) == SUBREG
-                        && SUBREG_BYTE (src) == 0)
-                   src = SUBREG_REG (src);
-                 if (GET_MODE (src) != GET_MODE (memref))
-                   src = gen_lowpart (GET_MODE (memref), SET_SRC (body));
-                 validate_change (insn, &SET_SRC (body), src, 1);
-               }
-             else if (GET_MODE (SET_SRC (body)) != VOIDmode
-                      && GET_MODE (SET_SRC (body)) != GET_MODE (memref))
-               /* This shouldn't happen because anything that didn't have
-                  one of these modes should have got converted explicitly
-                  and then referenced through a subreg.
-                  This is so because the original bit-field was
-                  handled by agg_mode and so its tree structure had
-                  the same mode that memref now has.  */
-               abort ();
-           }
-         else
-           {
-             rtx dest = SET_DEST (body);
-
-             while (GET_CODE (dest) == SUBREG
-                    && SUBREG_BYTE (dest) == 0
-                    && (GET_MODE_CLASS (GET_MODE (dest))
-                        == GET_MODE_CLASS (GET_MODE (SUBREG_REG (dest))))
-                    && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest)))
-                        <= UNITS_PER_WORD))
-               dest = SUBREG_REG (dest);
-
-             validate_change (insn, &SET_DEST (body), dest, 1);
-
-             if (GET_MODE (dest) == GET_MODE (memref))
-               validate_change (insn, &SET_SRC (body), memref, 1);
-             else
-               {
-                 /* Convert the mem ref to the destination mode.  */
-                 rtx newreg = gen_reg_rtx (GET_MODE (dest));
-
-                 start_sequence ();
-                 convert_move (newreg, memref,
-                               GET_CODE (SET_SRC (body)) == ZERO_EXTRACT);
-                 seq = get_insns ();
-                 end_sequence ();
-
-                 validate_change (insn, &SET_SRC (body), newreg, 1);
-               }
-           }
-
-         /* See if we can convert this extraction or insertion into
-            a simple move insn.  We might not be able to do so if this
-            was, for example, part of a PARALLEL.
-
-            If we succeed, write out any needed conversions.  If we fail,
-            it is hard to guess why we failed, so don't do anything
-            special; just let the optimization be suppressed.  */
-
-         if (apply_change_group () && seq)
-           emit_insn_before (seq, insn);
-       }
-    }
-}
-\f
-/* These routines are responsible for converting virtual register references
-   to the actual hard register references once RTL generation is complete.
-
-   The following four variables are used for communication between the
-   routines.  They contain the offsets of the virtual registers from their
-   respective hard registers.  */
-
-static int in_arg_offset;
-static int var_offset;
-static int dynamic_offset;
-static int out_arg_offset;
-static int cfa_offset;
-
-/* In most machines, the stack pointer register is equivalent to the bottom
-   of the stack.  */
-
-#ifndef STACK_POINTER_OFFSET
-#define STACK_POINTER_OFFSET   0
-#endif
-
-/* If not defined, pick an appropriate default for the offset of dynamically
-   allocated memory depending on the value of ACCUMULATE_OUTGOING_ARGS,
-   REG_PARM_STACK_SPACE, and OUTGOING_REG_PARM_STACK_SPACE.  */
-
-#ifndef STACK_DYNAMIC_OFFSET
-
-/* The bottom of the stack points to the actual arguments.  If
-   REG_PARM_STACK_SPACE is defined, this includes the space for the register
-   parameters.  However, if OUTGOING_REG_PARM_STACK space is not defined,
-   stack space for register parameters is not pushed by the caller, but
-   rather part of the fixed stack areas and hence not included in
-   `current_function_outgoing_args_size'.  Nevertheless, we must allow
-   for it when allocating stack dynamic objects.  */
-
-#if defined(REG_PARM_STACK_SPACE) && ! defined(OUTGOING_REG_PARM_STACK_SPACE)
-#define STACK_DYNAMIC_OFFSET(FNDECL)   \
-((ACCUMULATE_OUTGOING_ARGS                                                   \
-  ? (current_function_outgoing_args_size + REG_PARM_STACK_SPACE (FNDECL)) : 0)\
- + (STACK_POINTER_OFFSET))                                                   \
-
-#else
-#define STACK_DYNAMIC_OFFSET(FNDECL)   \
-((ACCUMULATE_OUTGOING_ARGS ? current_function_outgoing_args_size : 0)        \
- + (STACK_POINTER_OFFSET))
-#endif
-#endif
-
-/* On most machines, the CFA coincides with the first incoming parm.  */
-
-#ifndef ARG_POINTER_CFA_OFFSET
-#define ARG_POINTER_CFA_OFFSET(FNDECL) FIRST_PARM_OFFSET (FNDECL)
-#endif
-
-/* Build up a (MEM (ADDRESSOF (REG))) rtx for a register REG that just
-   had its address taken.  DECL is the decl or SAVE_EXPR for the
-   object stored in the register, for later use if we do need to force
-   REG into the stack.  REG is overwritten by the MEM like in
-   put_reg_into_stack.  RESCAN is true if previously emitted
-   instructions must be rescanned and modified now that the REG has
-   been transformed.  */
-
-rtx
-gen_mem_addressof (rtx reg, tree decl, int rescan)
-{
-  rtx r = gen_rtx_ADDRESSOF (Pmode, gen_reg_rtx (GET_MODE (reg)),
-                            REGNO (reg), decl);
-
-  /* Calculate this before we start messing with decl's RTL.  */
-  HOST_WIDE_INT set = decl ? get_alias_set (decl) : 0;
-
-  /* If the original REG was a user-variable, then so is the REG whose
-     address is being taken.  Likewise for unchanging.  */
-  REG_USERVAR_P (XEXP (r, 0)) = REG_USERVAR_P (reg);
-  RTX_UNCHANGING_P (XEXP (r, 0)) = RTX_UNCHANGING_P (reg);
-
-  PUT_CODE (reg, MEM);
-  MEM_VOLATILE_P (reg) = 0;
-  MEM_ATTRS (reg) = 0;
-  XEXP (reg, 0) = r;
-
-  if (decl)
-    {
-      tree type = TREE_TYPE (decl);
-      enum machine_mode decl_mode = DECL_MODE (decl);
-      rtx decl_rtl = DECL_RTL_IF_SET (decl);
-
-      PUT_MODE (reg, decl_mode);
-
-      /* Clear DECL_RTL momentarily so functions below will work
-        properly, then set it again.  */
-      if (DECL_P (decl) && decl_rtl == reg)
-       SET_DECL_RTL (decl, 0);
-
-      set_mem_attributes (reg, decl, 1);
-      set_mem_alias_set (reg, set);
-
-      if (DECL_P (decl) && decl_rtl == reg)
-       SET_DECL_RTL (decl, reg);
-
-      if (rescan
-         && (TREE_USED (decl) || (DECL_P (decl) && DECL_INITIAL (decl) != 0)))
-       fixup_var_refs (reg, GET_MODE (reg), TYPE_UNSIGNED (type), reg, 0);
-    }
-  else if (rescan)
-    {
-      /* This can only happen during reload.  Clear the same flag bits as
-        reload.  */
-      RTX_UNCHANGING_P (reg) = 0;
-      MEM_IN_STRUCT_P (reg) = 0;
-      MEM_SCALAR_P (reg) = 0;
-
-      fixup_var_refs (reg, GET_MODE (reg), 0, reg, 0);
-    }
-
-  return reg;
-}
-
-/* If DECL has an RTL that is an ADDRESSOF rtx, put it into the stack.  */
-
-void
-flush_addressof (tree decl)
-{
-  if ((TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == VAR_DECL)
-      && DECL_RTL (decl) != 0
-      && MEM_P (DECL_RTL (decl))
-      && GET_CODE (XEXP (DECL_RTL (decl), 0)) == ADDRESSOF
-      && REG_P (XEXP (XEXP (DECL_RTL (decl), 0), 0)))
-    put_addressof_into_stack (XEXP (DECL_RTL (decl), 0), 0);
-}
-
-/* Force the register pointed to by R, an ADDRESSOF rtx, into the stack.  */
-
-static void
-put_addressof_into_stack (rtx r, htab_t ht)
-{
-  tree decl, type;
-  bool volatile_p, used_p;
-
-  rtx reg = XEXP (r, 0);
-
-  if (!REG_P (reg))
-    abort ();
-
-  decl = ADDRESSOF_DECL (r);
-  if (decl)
-    {
-      type = TREE_TYPE (decl);
-      volatile_p = (TREE_CODE (decl) != SAVE_EXPR
-                   && TREE_THIS_VOLATILE (decl));
-      used_p = (TREE_USED (decl)
-               || (DECL_P (decl) && DECL_INITIAL (decl) != 0));
-    }
-  else
-    {
-      type = NULL_TREE;
-      volatile_p = false;
-      used_p = true;
-    }
-
-  put_reg_into_stack (0, reg, type, GET_MODE (reg), ADDRESSOF_REGNO (r),
-                     volatile_p, used_p, false, ht);
-}
-
-/* List of replacements made below in purge_addressof_1 when creating
-   bitfield insertions.  */
-static rtx purge_bitfield_addressof_replacements;
-
-/* List of replacements made below in purge_addressof_1 for patterns
-   (MEM (ADDRESSOF (REG ...))).  The key of the list entry is the
-   corresponding (ADDRESSOF (REG ...)) and value is a substitution for
-   the all pattern.  List PURGE_BITFIELD_ADDRESSOF_REPLACEMENTS is not
-   enough in complex cases, e.g. when some field values can be
-   extracted by usage MEM with narrower mode.  */
-static rtx purge_addressof_replacements;
-
-/* Helper function for purge_addressof.  See if the rtx expression at *LOC
-   in INSN needs to be changed.  If FORCE, always put any ADDRESSOFs into
-   the stack.  If the function returns FALSE then the replacement could not
-   be made.  If MAY_POSTPONE is true and we would not put the addressof
-   to stack, postpone processing of the insn.  */
-
-static bool
-purge_addressof_1 (rtx *loc, rtx insn, int force, int store, int may_postpone,
-                  htab_t ht)
-{
-  rtx x;
-  RTX_CODE code;
-  int i, j;
-  const char *fmt;
-  bool result = true;
-  bool libcall = false;
-
-  /* Re-start here to avoid recursion in common cases.  */
- restart:
-
-  x = *loc;
-  if (x == 0)
-    return true;
-
-  /* Is this a libcall?  */
-  if (!insn)
-    libcall = REG_NOTE_KIND (*loc) == REG_RETVAL;
-
-  code = GET_CODE (x);
-
-  /* If we don't return in any of the cases below, we will recurse inside
-     the RTX, which will normally result in any ADDRESSOF being forced into
-     memory.  */
-  if (code == SET)
-    {
-      result = purge_addressof_1 (&SET_DEST (x), insn, force, 1,
-                                 may_postpone, ht);
-      result &= purge_addressof_1 (&SET_SRC (x), insn, force, 0,
-                                  may_postpone, ht);
-      return result;
-    }
-  else if (code == ADDRESSOF)
-    {
-      rtx sub, insns;
-
-      if (!MEM_P (XEXP (x, 0)))
-       put_addressof_into_stack (x, ht);
-
-      /* We must create a copy of the rtx because it was created by
-        overwriting a REG rtx which is always shared.  */
-      sub = copy_rtx (XEXP (XEXP (x, 0), 0));
-      if (validate_change (insn, loc, sub, 0)
-         || validate_replace_rtx (x, sub, insn))
-       return true;
-
-      start_sequence ();
-
-      /* If SUB is a hard or virtual register, try it as a pseudo-register.
-        Otherwise, perhaps SUB is an expression, so generate code to compute
-        it.  */
-      if (REG_P (sub) && REGNO (sub) <= LAST_VIRTUAL_REGISTER)
-       sub = copy_to_reg (sub);
-      else
-       sub = force_operand (sub, NULL_RTX);
-
-      if (! validate_change (insn, loc, sub, 0)
-         && ! validate_replace_rtx (x, sub, insn))
-       abort ();
-
-      insns = get_insns ();
-      end_sequence ();
-      emit_insn_before (insns, insn);
-      return true;
-    }
-
-  else if (code == MEM && GET_CODE (XEXP (x, 0)) == ADDRESSOF && ! force)
-    {
-      rtx sub = XEXP (XEXP (x, 0), 0);
-
-      if (MEM_P (sub))
-       sub = adjust_address_nv (sub, GET_MODE (x), 0);
-      else if (REG_P (sub)
-              && (MEM_VOLATILE_P (x) || GET_MODE (x) == BLKmode))
-       ;
-      else if (REG_P (sub) && GET_MODE (x) != GET_MODE (sub))
-       {
-         int size_x, size_sub;
-
-         if (may_postpone)
-           {
-             /* Postpone for now, so that we do not emit bitfield arithmetics
-                unless there is some benefit from it.  */
-             if (!postponed_insns || XEXP (postponed_insns, 0) != insn)
-               postponed_insns = alloc_INSN_LIST (insn, postponed_insns);
-             return true;
-           }
-
-         if (!insn)
-           {
-             /* When processing REG_NOTES look at the list of
-                replacements done on the insn to find the register that X
-                was replaced by.  */
-             rtx tem;
-
-             for (tem = purge_bitfield_addressof_replacements;
-                  tem != NULL_RTX;
-                  tem = XEXP (XEXP (tem, 1), 1))
-               if (rtx_equal_p (x, XEXP (tem, 0)))
-                 {
-                   *loc = XEXP (XEXP (tem, 1), 0);
-                   return true;
-                 }
-
-             /* See comment for purge_addressof_replacements.  */
-             for (tem = purge_addressof_replacements;
-                  tem != NULL_RTX;
-                  tem = XEXP (XEXP (tem, 1), 1))
-               if (rtx_equal_p (XEXP (x, 0), XEXP (tem, 0)))
-                 {
-                   rtx z = XEXP (XEXP (tem, 1), 0);
-
-                   if (GET_MODE (x) == GET_MODE (z)
-                       || (!REG_P (XEXP (XEXP (tem, 1), 0))
-                           && GET_CODE (XEXP (XEXP (tem, 1), 0)) != SUBREG))
-                     abort ();
-
-                   /* It can happen that the note may speak of things
-                      in a wider (or just different) mode than the
-                      code did.  This is especially true of
-                      REG_RETVAL.  */
-
-                   if (GET_CODE (z) == SUBREG && SUBREG_BYTE (z) == 0)
-                     z = SUBREG_REG (z);
-
-                   if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD
-                       && (GET_MODE_SIZE (GET_MODE (x))
-                           > GET_MODE_SIZE (GET_MODE (z))))
-                     {
-                       /* This can occur as a result in invalid
-                          pointer casts, e.g. float f; ...
-                          *(long long int *)&f.
-                          ??? We could emit a warning here, but
-                          without a line number that wouldn't be
-                          very helpful.  */
-                       z = gen_rtx_SUBREG (GET_MODE (x), z, 0);
-                     }
-                   else
-                     z = gen_lowpart (GET_MODE (x), z);
-
-                   *loc = z;
-                   return true;
-                 }
-
-             /* When we are processing the REG_NOTES of the last instruction
-                of a libcall, there will be typically no replacements
-                for that insn; the replacements happened before, piecemeal
-                fashion.  OTOH we are not interested in the details of
-                this for the REG_EQUAL note, we want to know the big picture,
-                which can be succinctly described with a simple SUBREG.
-                Note that removing the REG_EQUAL note is not an option
-                on the last insn of a libcall, so we must do a replacement.  */
-
-             /* In compile/990107-1.c:7 compiled at -O1 -m1 for sh-elf,
-                we got
-                (mem:DI (addressof:SI (reg/v:DF 160) 159 0x401c8510)
-                [0 S8 A32]), which can be expressed with a simple
-                same-size subreg  */
-             if ((GET_MODE_SIZE (GET_MODE (x))
-                  <= GET_MODE_SIZE (GET_MODE (sub)))
-                 /* Again, invalid pointer casts (as in
-                    compile/990203-1.c) can require paradoxical
-                    subregs.  */
-                 || (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD
-                     && (GET_MODE_SIZE (GET_MODE (x))
-                         > GET_MODE_SIZE (GET_MODE (sub)))
-                     && libcall))
-               {
-                 *loc = gen_rtx_SUBREG (GET_MODE (x), sub, 0);
-                 return true;
-               }
-             /* ??? Are there other cases we should handle?  */
-
-             /* Sometimes we may not be able to find the replacement.  For
-                example when the original insn was a MEM in a wider mode,
-                and the note is part of a sign extension of a narrowed
-                version of that MEM.  Gcc testcase compile/990829-1.c can
-                generate an example of this situation.  Rather than complain
-                we return false, which will prompt our caller to remove the
-                offending note.  */
-             return false;
-           }
-
-         size_x = GET_MODE_BITSIZE (GET_MODE (x));
-         size_sub = GET_MODE_BITSIZE (GET_MODE (sub));
-
-         /* Do not frob unchanging MEMs.  If a later reference forces the
-            pseudo to the stack, we can wind up with multiple writes to
-            an unchanging memory, which is invalid.  */
-         if (RTX_UNCHANGING_P (x) && size_x != size_sub)
-           ;
-
-         /* Don't even consider working with paradoxical subregs,
-            or the moral equivalent seen here.  */
-         else if (size_x <= size_sub
-                  && int_mode_for_mode (GET_MODE (sub)) != BLKmode)
-           {
-             /* Do a bitfield insertion to mirror what would happen
-                in memory.  */
-
-             rtx val, seq;
-
-             if (store)
-               {
-                 rtx p = PREV_INSN (insn);
-
-                 start_sequence ();
-                 val = gen_reg_rtx (GET_MODE (x));
-                 if (! validate_change (insn, loc, val, 0))
-                   {
-                     /* Discard the current sequence and put the
-                        ADDRESSOF on stack.  */
-                     end_sequence ();
-                     goto give_up;
-                   }
-                 seq = get_insns ();
-                 end_sequence ();
-                 emit_insn_before (seq, insn);
-                 compute_insns_for_mem (p ? NEXT_INSN (p) : get_insns (),
-                                        insn, ht);
-
-                 start_sequence ();
-                 store_bit_field (sub, size_x, 0, GET_MODE (x),
-                                  val, GET_MODE_SIZE (GET_MODE (sub)));
-
-                 /* Make sure to unshare any shared rtl that store_bit_field
-                    might have created.  */
-                 unshare_all_rtl_again (get_insns ());
-
-                 seq = get_insns ();
-                 end_sequence ();
-                 p = emit_insn_after (seq, insn);
-                 if (NEXT_INSN (insn))
-                   compute_insns_for_mem (NEXT_INSN (insn),
-                                          p ? NEXT_INSN (p) : NULL_RTX,
-                                          ht);
-               }
-             else
-               {
-                 rtx p = PREV_INSN (insn);
-
-                 start_sequence ();
-                 val = extract_bit_field (sub, size_x, 0, 1, NULL_RTX,
-                                          GET_MODE (x), GET_MODE (x),
-                                          GET_MODE_SIZE (GET_MODE (sub)));
-
-                 if (! validate_change (insn, loc, val, 0))
-                   {
-                     /* Discard the current sequence and put the
-                        ADDRESSOF on stack.  */
-                     end_sequence ();
-                     goto give_up;
-                   }
+      return;
+    }
 
-                 seq = get_insns ();
-                 end_sequence ();
-                 emit_insn_before (seq, insn);
-                 compute_insns_for_mem (p ? NEXT_INSN (p) : get_insns (),
-                                        insn, ht);
-               }
+  /* If X is a register that is being used as a pointer, see if we have
+     a temporary slot we know it points to.  To be consistent with
+     the code below, we really should preserve all non-kept slots
+     if we can't find a match, but that seems to be much too costly.  */
+  if (REG_P (x) && REG_POINTER (x))
+    p = find_temp_slot_from_address (x);
 
-             /* Remember the replacement so that the same one can be done
-                on the REG_NOTES.  */
-             purge_bitfield_addressof_replacements
-               = gen_rtx_EXPR_LIST (VOIDmode, x,
-                                    gen_rtx_EXPR_LIST
-                                    (VOIDmode, val,
-                                     purge_bitfield_addressof_replacements));
+  /* If X is not in memory or is at a constant address, it cannot be in
+     a temporary slot, but it can contain something whose address was
+     taken.  */
+  if (p == 0 && (!MEM_P (x) || CONSTANT_P (XEXP (x, 0))))
+    {
+      for (p = *temp_slots_at_level (temp_slot_level); p; p = next)
+       {
+         next = p->next;
 
-             /* We replaced with a reg -- all done.  */
-             return true;
-           }
+         if (p->addr_taken)
+           move_slot_to_level (p, temp_slot_level - 1);
        }
 
-      else if (validate_change (insn, loc, sub, 0))
+      return;
+    }
+
+  /* First see if we can find a match.  */
+  if (p == 0)
+    p = find_temp_slot_from_address (XEXP (x, 0));
+
+  if (p != 0)
+    {
+      /* Move everything at our level whose address was taken to our new
+        level in case we used its address.  */
+      struct temp_slot *q;
+
+      if (p->level == temp_slot_level)
        {
-         /* Remember the replacement so that the same one can be done
-            on the REG_NOTES.  */
-         if (REG_P (sub) || GET_CODE (sub) == SUBREG)
+         for (q = *temp_slots_at_level (temp_slot_level); q; q = next)
            {
-             rtx tem;
+             next = q->next;
 
-             for (tem = purge_addressof_replacements;
-                  tem != NULL_RTX;
-                  tem = XEXP (XEXP (tem, 1), 1))
-               if (rtx_equal_p (XEXP (x, 0), XEXP (tem, 0)))
-                 {
-                   XEXP (XEXP (tem, 1), 0) = sub;
-                   return true;
-                 }
-             purge_addressof_replacements
-               = gen_rtx_EXPR_LIST (VOIDmode, XEXP (x, 0),
-                                    gen_rtx_EXPR_LIST (VOIDmode, sub,
-                                                       purge_addressof_replacements));
-             return true;
+             if (p != q && q->addr_taken)
+               move_slot_to_level (q, temp_slot_level - 1);
            }
-         goto restart;
+
+         move_slot_to_level (p, temp_slot_level - 1);
+         p->addr_taken = 0;
        }
+      return;
     }
 
- give_up:
-  /* Scan all subexpressions.  */
-  fmt = GET_RTX_FORMAT (code);
-  for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
+  /* Otherwise, preserve all non-kept slots at this level.  */
+  for (p = *temp_slots_at_level (temp_slot_level); p; p = next)
     {
-      if (*fmt == 'e')
-       result &= purge_addressof_1 (&XEXP (x, i), insn, force, 0,
-                                    may_postpone, ht);
-      else if (*fmt == 'E')
-       for (j = 0; j < XVECLEN (x, i); j++)
-         result &= purge_addressof_1 (&XVECEXP (x, i, j), insn, force, 0,
-                                      may_postpone, ht);
-    }
-
-  return result;
-}
-
-/* Return a hash value for K, a REG.  */
+      next = p->next;
 
-static hashval_t
-insns_for_mem_hash (const void *k)
-{
-  /* Use the address of the key for the hash value.  */
-  struct insns_for_mem_entry *m = (struct insns_for_mem_entry *) k;
-  return htab_hash_pointer (m->key);
+      if (!p->keep)
+       move_slot_to_level (p, temp_slot_level - 1);
+    }
 }
 
-/* Return nonzero if K1 and K2 (two REGs) are the same.  */
+/* Free all temporaries used so far.  This is normally called at the
+   end of generating code for a statement.  */
 
-static int
-insns_for_mem_comp (const void *k1, const void *k2)
+void
+free_temp_slots (void)
 {
-  struct insns_for_mem_entry *m1 = (struct insns_for_mem_entry *) k1;
-  struct insns_for_mem_entry *m2 = (struct insns_for_mem_entry *) k2;
-  return m1->key == m2->key;
-}
+  struct temp_slot *p, *next;
 
-struct insns_for_mem_walk_info
-{
-  /* The hash table that we are using to record which INSNs use which
-     MEMs.  */
-  htab_t ht;
+  for (p = *temp_slots_at_level (temp_slot_level); p; p = next)
+    {
+      next = p->next;
 
-  /* The INSN we are currently processing.  */
-  rtx insn;
+      if (!p->keep)
+       make_slot_available (p);
+    }
 
-  /* Zero if we are walking to find ADDRESSOFs, one if we are walking
-     to find the insns that use the REGs in the ADDRESSOFs.  */
-  int pass;
-};
+  combine_temp_slots ();
+}
 
-/* Called from compute_insns_for_mem via for_each_rtx.  If R is a REG
-   that might be used in an ADDRESSOF expression, record this INSN in
-   the hash table given by DATA (which is really a pointer to an
-   insns_for_mem_walk_info structure).  */
+/* Push deeper into the nesting level for stack temporaries.  */
 
-static int
-insns_for_mem_walk (rtx *r, void *data)
+void
+push_temp_slots (void)
 {
-  struct insns_for_mem_walk_info *ifmwi
-    = (struct insns_for_mem_walk_info *) data;
-  struct insns_for_mem_entry tmp;
-  tmp.insns = NULL_RTX;
-
-  if (ifmwi->pass == 0 && *r && GET_CODE (*r) == ADDRESSOF
-      && REG_P (XEXP (*r, 0)))
-    {
-      void **e;
-      tmp.key = XEXP (*r, 0);
-      e = htab_find_slot (ifmwi->ht, &tmp, INSERT);
-      if (*e == NULL)
-       {
-         *e = ggc_alloc (sizeof (tmp));
-         memcpy (*e, &tmp, sizeof (tmp));
-       }
-    }
-  else if (ifmwi->pass == 1 && *r && REG_P (*r))
-    {
-      struct insns_for_mem_entry *ifme;
-      tmp.key = *r;
-      ifme = htab_find (ifmwi->ht, &tmp);
-
-      /* If we have not already recorded this INSN, do so now.  Since
-        we process the INSNs in order, we know that if we have
-        recorded it it must be at the front of the list.  */
-      if (ifme && (!ifme->insns || XEXP (ifme->insns, 0) != ifmwi->insn))
-       ifme->insns = gen_rtx_EXPR_LIST (VOIDmode, ifmwi->insn,
-                                        ifme->insns);
-    }
-
-  return 0;
+  temp_slot_level++;
 }
 
-/* Walk the INSNS, until we reach LAST_INSN, recording which INSNs use
-   which REGs in HT.  */
+/* Pop a temporary nesting level.  All slots in use in the current level
+   are freed.  */
 
-static void
-compute_insns_for_mem (rtx insns, rtx last_insn, htab_t ht)
+void
+pop_temp_slots (void)
 {
-  rtx insn;
-  struct insns_for_mem_walk_info ifmwi;
-  ifmwi.ht = ht;
+  struct temp_slot *p, *next;
 
-  for (ifmwi.pass = 0; ifmwi.pass < 2; ++ifmwi.pass)
-    for (insn = insns; insn != last_insn; insn = NEXT_INSN (insn))
-      if (INSN_P (insn))
-       {
-         ifmwi.insn = insn;
-         for_each_rtx (&insn, insns_for_mem_walk, &ifmwi);
-       }
-}
+  for (p = *temp_slots_at_level (temp_slot_level); p; p = next)
+    {
+      next = p->next;
+      make_slot_available (p);
+    }
 
-/* Helper function for purge_addressof called through for_each_rtx.
-   Returns true iff the rtl is an ADDRESSOF.  */
+  combine_temp_slots ();
 
-static int
-is_addressof (rtx *rtl, void *data ATTRIBUTE_UNUSED)
-{
-  return GET_CODE (*rtl) == ADDRESSOF;
+  temp_slot_level--;
 }
 
-/* Eliminate all occurrences of ADDRESSOF from INSNS.  Elide any remaining
-   (MEM (ADDRESSOF)) patterns, and force any needed registers into the
-   stack.  */
+/* Initialize temporary slots.  */
 
 void
-purge_addressof (rtx insns)
+init_temp_slots (void)
 {
-  rtx insn, tmp;
-  htab_t ht;
+  /* We have not allocated any temporaries yet.  */
+  avail_temp_slots = 0;
+  used_temp_slots = 0;
+  temp_slot_level = 0;
+  var_temp_slot_level = 0;
+  target_temp_slot_level = 0;
+}
+\f
+/* These routines are responsible for converting virtual register references
+   to the actual hard register references once RTL generation is complete.
 
-  /* When we actually purge ADDRESSOFs, we turn REGs into MEMs.  That
-     requires a fixup pass over the instruction stream to correct
-     INSNs that depended on the REG being a REG, and not a MEM.  But,
-     these fixup passes are slow.  Furthermore, most MEMs are not
-     mentioned in very many instructions.  So, we speed up the process
-     by pre-calculating which REGs occur in which INSNs; that allows
-     us to perform the fixup passes much more quickly.  */
-  ht = htab_create_ggc (1000, insns_for_mem_hash, insns_for_mem_comp, NULL);
-  compute_insns_for_mem (insns, NULL_RTX, ht);
+   The following four variables are used for communication between the
+   routines.  They contain the offsets of the virtual registers from their
+   respective hard registers.  */
 
-  postponed_insns = NULL;
+static int in_arg_offset;
+static int var_offset;
+static int dynamic_offset;
+static int out_arg_offset;
+static int cfa_offset;
 
-  for (insn = insns; insn; insn = NEXT_INSN (insn))
-    if (INSN_P (insn))
-      {
-       if (! purge_addressof_1 (&PATTERN (insn), insn,
-                                asm_noperands (PATTERN (insn)) > 0, 0, 1, ht))
-         /* If we could not replace the ADDRESSOFs in the insn,
-            something is wrong.  */
-         abort ();
+/* In most machines, the stack pointer register is equivalent to the bottom
+   of the stack.  */
 
-       if (! purge_addressof_1 (&REG_NOTES (insn), NULL_RTX, 0, 0, 0, ht))
-         {
-           /* If we could not replace the ADDRESSOFs in the insn's notes,
-              we can just remove the offending notes instead.  */
-           rtx note;
+#ifndef STACK_POINTER_OFFSET
+#define STACK_POINTER_OFFSET   0
+#endif
 
-           for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
-             {
-               /* If we find a REG_RETVAL note then the insn is a libcall.
-                  Such insns must have REG_EQUAL notes as well, in order
-                  for later passes of the compiler to work.  So it is not
-                  safe to delete the notes here, and instead we abort.  */
-               if (REG_NOTE_KIND (note) == REG_RETVAL)
-                 abort ();
-               if (for_each_rtx (&note, is_addressof, NULL))
-                 remove_note (insn, note);
-             }
-         }
-      }
+/* If not defined, pick an appropriate default for the offset of dynamically
+   allocated memory depending on the value of ACCUMULATE_OUTGOING_ARGS,
+   REG_PARM_STACK_SPACE, and OUTGOING_REG_PARM_STACK_SPACE.  */
 
-  /* Process the postponed insns.  */
-  while (postponed_insns)
-    {
-      insn = XEXP (postponed_insns, 0);
-      tmp = postponed_insns;
-      postponed_insns = XEXP (postponed_insns, 1);
-      free_INSN_LIST_node (tmp);
+#ifndef STACK_DYNAMIC_OFFSET
 
-      if (! purge_addressof_1 (&PATTERN (insn), insn,
-                              asm_noperands (PATTERN (insn)) > 0, 0, 0, ht))
-       abort ();
-    }
+/* The bottom of the stack points to the actual arguments.  If
+   REG_PARM_STACK_SPACE is defined, this includes the space for the register
+   parameters.  However, if OUTGOING_REG_PARM_STACK space is not defined,
+   stack space for register parameters is not pushed by the caller, but
+   rather part of the fixed stack areas and hence not included in
+   `current_function_outgoing_args_size'.  Nevertheless, we must allow
+   for it when allocating stack dynamic objects.  */
 
-  /* Clean up.  */
-  purge_bitfield_addressof_replacements = 0;
-  purge_addressof_replacements = 0;
+#if defined(REG_PARM_STACK_SPACE) && ! defined(OUTGOING_REG_PARM_STACK_SPACE)
+#define STACK_DYNAMIC_OFFSET(FNDECL)   \
+((ACCUMULATE_OUTGOING_ARGS                                                   \
+  ? (current_function_outgoing_args_size + REG_PARM_STACK_SPACE (FNDECL)) : 0)\
+ + (STACK_POINTER_OFFSET))                                                   \
 
-  /* REGs are shared.  purge_addressof will destructively replace a REG
-     with a MEM, which creates shared MEMs.
+#else
+#define STACK_DYNAMIC_OFFSET(FNDECL)   \
+((ACCUMULATE_OUTGOING_ARGS ? current_function_outgoing_args_size : 0)        \
+ + (STACK_POINTER_OFFSET))
+#endif
+#endif
 
-     Unfortunately, the children of put_reg_into_stack assume that MEMs
-     referring to the same stack slot are shared (fixup_var_refs and
-     the associated hash table code).
+/* On most machines, the CFA coincides with the first incoming parm.  */
 
-     So, we have to do another unsharing pass after we have flushed any
-     REGs that had their address taken into the stack.
+#ifndef ARG_POINTER_CFA_OFFSET
+#define ARG_POINTER_CFA_OFFSET(FNDECL) FIRST_PARM_OFFSET (FNDECL)
+#endif
 
-     It may be worth tracking whether or not we converted any REGs into
-     MEMs to avoid this overhead when it is not needed.  */
-  unshare_all_rtl_again (get_insns ());
-}
 \f
 /* Convert a SET of a hard subreg to a set of the appropriate hard
    register.  A subroutine of purge_hard_subreg_sets.  */
@@ -3509,7 +1339,6 @@ void
 instantiate_virtual_regs (void)
 {
   rtx insn;
-  unsigned int i;
 
   /* Compute the offsets to use for this function.  */
   in_arg_offset = FIRST_PARM_OFFSET (current_function_decl);
@@ -3549,12 +1378,6 @@ instantiate_virtual_regs (void)
           instantiate_virtual_regs_lossage (insn);
       }
 
-  /* Instantiate the stack slots for the parm registers, for later use in
-     addressof elimination.  */
-  for (i = 0; i < max_parm_reg; ++i)
-    if (parm_reg_stack_loc[i])
-      instantiate_virtual_regs_1 (&parm_reg_stack_loc[i], NULL_RTX, 0);
-
   /* Now instantiate the remaining register equivalences for debugging info.
      These will not be valid addresses.  */
   instantiate_decls (current_function_decl, 0);
@@ -3634,7 +1457,6 @@ instantiate_decl (rtx x, HOST_WIDE_INT size, int valid_only)
 
   addr = XEXP (x, 0);
   if (CONSTANT_P (addr)
-      || (GET_CODE (addr) == ADDRESSOF && REG_P (XEXP (addr, 0)))
       || (REG_P (addr)
          && (REGNO (addr) < FIRST_VIRTUAL_REGISTER
              || REGNO (addr) > LAST_VIRTUAL_REGISTER)))
@@ -4088,20 +1910,6 @@ instantiate_virtual_regs_1 (rtx *loc, rtx object, int extra_insns)
 
       return 1;
 
-    case ADDRESSOF:
-      if (REG_P (XEXP (x, 0)))
-       return 1;
-
-      else if (MEM_P (XEXP (x, 0)))
-       {
-         /* If we have a (addressof (mem ..)), do any instantiation inside
-            since we know we'll be making the inside valid when we finally
-            remove the ADDRESSOF.  */
-         instantiate_virtual_regs_1 (&XEXP (XEXP (x, 0), 0), NULL_RTX, 0);
-         return 1;
-       }
-      break;
-
     default:
       break;
     }
@@ -4184,6 +1992,46 @@ aggregate_value_p (tree exp, tree fntype)
   return 0;
 }
 \f
+/* Return true if we should assign DECL a pseudo register; false if it
+   should live on the local stack.  */
+
+bool
+use_register_for_decl (tree decl)
+{
+  /* Honor volatile.  */
+  if (TREE_SIDE_EFFECTS (decl))
+    return false;
+
+  /* Honor addressability.  */
+  if (TREE_ADDRESSABLE (decl))
+    return false;
+
+  /* Only register-like things go in registers.  */
+  if (DECL_MODE (decl) == BLKmode)
+    return false;
+
+  /* If -ffloat-store specified, don't put explicit float variables
+     into registers.  */
+  /* ??? This should be checked after DECL_ARTIFICIAL, but tree-ssa
+     propagates values across these stores, and it probably shouldn't.  */
+  if (flag_float_store && FLOAT_TYPE_P (TREE_TYPE (decl)))
+    return false;
+
+  /* Compiler-generated temporaries can always go in registers.  */
+  if (DECL_ARTIFICIAL (decl))
+    return true;
+
+#ifdef NON_SAVING_SETJMP
+  /* Protect variables not declared "register" from setjmp.  */
+  if (NON_SAVING_SETJMP
+      && current_function_calls_setjmp
+      && !DECL_REGISTER (decl))
+    return false;
+#endif
+
+  return (optimize || DECL_REGISTER (decl));
+}
+
 /* Assign RTL expressions to the function's parameters.
    This may involve copying them into registers and using
    those registers as the RTL for them.  */
@@ -4247,9 +2095,6 @@ assign_parms (tree fndecl)
 
   orig_fnargs = fnargs;
 
-  max_parm_reg = LAST_VIRTUAL_REGISTER + 1;
-  parm_reg_stack_loc = ggc_alloc_cleared (max_parm_reg * sizeof (rtx));
-
   /* If the target wants to split complex arguments into scalars, do so.  */
   if (targetm.calls.split_complex_arg)
     fnargs = split_complex_args (fnargs);
@@ -4653,7 +2498,8 @@ assign_parms (tree fndecl)
 
         Set DECL_RTL to that place.  */
 
-      if (GET_CODE (entry_parm) == PARALLEL && nominal_mode != BLKmode
+      if (GET_CODE (entry_parm) == PARALLEL
+         && nominal_mode != BLKmode
          && XVECLEN (entry_parm, 0) > 1)
        {
          /* Reconstitute objects the size of a register or larger using
@@ -4662,29 +2508,10 @@ assign_parms (tree fndecl)
 
          if (REG_P (parmreg))
            {
-             unsigned int regno = REGNO (parmreg);
-
              emit_group_store (parmreg, entry_parm, TREE_TYPE (parm),
                                int_size_in_bytes (TREE_TYPE (parm)));
              SET_DECL_RTL (parm, parmreg);
              loaded_in_reg = 1;
-
-             if (regno >= max_parm_reg)
-               {
-                 rtx *new;
-                 int old_max_parm_reg = max_parm_reg;
-
-                 /* It's slow to expand this one register at a time,
-                    but it's also rare and we need max_parm_reg to be
-                    precisely correct.  */
-                 max_parm_reg = regno + 1;
-                 new = ggc_realloc (parm_reg_stack_loc,
-                                    max_parm_reg * sizeof (rtx));
-                 memset (new + old_max_parm_reg, 0,
-                         (max_parm_reg - old_max_parm_reg) * sizeof (rtx));
-                 parm_reg_stack_loc = new;
-                 parm_reg_stack_loc[regno] = stack_parm;
-               }
            }
        }
 
@@ -4790,13 +2617,7 @@ assign_parms (tree fndecl)
          if (! DECL_RTL_SET_P (parm))
            SET_DECL_RTL (parm, stack_parm);
        }
-      else if (! ((! optimize
-                  && ! DECL_REGISTER (parm))
-                 || TREE_SIDE_EFFECTS (parm)
-                 /* If -ffloat-store specified, don't put explicit
-                    float variables into registers.  */
-                 || (flag_float_store
-                     && TREE_CODE (TREE_TYPE (parm)) == REAL_TYPE))
+      else if (use_register_for_decl (parm)
               /* Always assign pseudo to structure return or item passed
                  by invisible reference.  */
               || passed_pointer || parm == function_result_decl)
@@ -4805,7 +2626,6 @@ assign_parms (tree fndecl)
             may need to do it in a wider mode.  */
 
          rtx parmreg;
-         unsigned int regno, regnoi = 0, regnor = 0;
 
          unsignedp = TYPE_UNSIGNED (TREE_TYPE (parm));
 
@@ -4889,16 +2709,10 @@ assign_parms (tree fndecl)
 
          /* If we were passed a pointer but the actual value
             can safely live in a register, put it in one.  */
-         if (passed_pointer && TYPE_MODE (TREE_TYPE (parm)) != BLKmode
+         if (passed_pointer
+             && use_register_for_decl (parm)
              /* If by-reference argument was promoted, demote it.  */
-             && (TYPE_MODE (TREE_TYPE (parm)) != GET_MODE (DECL_RTL (parm))
-                 || ! ((! optimize
-                        && ! DECL_REGISTER (parm))
-                       || TREE_SIDE_EFFECTS (parm)
-                       /* If -ffloat-store specified, don't put explicit
-                          float variables into registers.  */
-                       || (flag_float_store
-                           && TREE_CODE (TREE_TYPE (parm)) == REAL_TYPE))))
+             && TYPE_MODE (TREE_TYPE (parm)) != GET_MODE (DECL_RTL (parm)))
            {
              /* We can't use nominal_mode, because it will have been set to
                 Pmode above.  We must use the actual mode of the parm.  */
@@ -4970,56 +2784,6 @@ assign_parms (tree fndecl)
            }
 #endif /* FUNCTION_ARG_CALLEE_COPIES */
 
-         /* In any case, record the parm's desired stack location
-            in case we later discover it must live in the stack.
-
-            If it is a COMPLEX value, store the stack location for both
-            halves.  */
-
-         if (GET_CODE (parmreg) == CONCAT)
-           regno = MAX (REGNO (XEXP (parmreg, 0)), REGNO (XEXP (parmreg, 1)));
-         else
-           regno = REGNO (parmreg);
-
-         if (regno >= max_parm_reg)
-           {
-             rtx *new;
-             int old_max_parm_reg = max_parm_reg;
-
-             /* It's slow to expand this one register at a time,
-                but it's also rare and we need max_parm_reg to be
-                precisely correct.  */
-             max_parm_reg = regno + 1;
-             new = ggc_realloc (parm_reg_stack_loc,
-                                max_parm_reg * sizeof (rtx));
-             memset (new + old_max_parm_reg, 0,
-                     (max_parm_reg - old_max_parm_reg) * sizeof (rtx));
-             parm_reg_stack_loc = new;
-           }
-
-         if (GET_CODE (parmreg) == CONCAT)
-           {
-             enum machine_mode submode = GET_MODE (XEXP (parmreg, 0));
-
-             regnor = REGNO (gen_realpart (submode, parmreg));
-             regnoi = REGNO (gen_imagpart (submode, parmreg));
-
-             if (stack_parm != 0)
-               {
-                 parm_reg_stack_loc[regnor]
-                   = gen_realpart (submode, stack_parm);
-                 parm_reg_stack_loc[regnoi]
-                   = gen_imagpart (submode, stack_parm);
-               }
-             else
-               {
-                 parm_reg_stack_loc[regnor] = 0;
-                 parm_reg_stack_loc[regnoi] = 0;
-               }
-           }
-         else
-           parm_reg_stack_loc[REGNO (parmreg)] = stack_parm;
-
          /* Mark the register as eliminable if we did no conversion
             and it was copied from memory at a fixed offset,
             and the arg pointer was not copied to a pseudo-reg.
@@ -5039,25 +2803,33 @@ assign_parms (tree fndecl)
 
              /* Mark complex types separately.  */
              if (GET_CODE (parmreg) == CONCAT)
-               /* Scan backwards for the set of the real and
-                  imaginary parts.  */
-               for (sinsn = linsn; sinsn != 0;
-                    sinsn = prev_nonnote_insn (sinsn))
-                 {
-                   set = single_set (sinsn);
-                   if (set != 0
-                       && SET_DEST (set) == regno_reg_rtx [regnoi])
-                     REG_NOTES (sinsn)
-                       = gen_rtx_EXPR_LIST (REG_EQUIV,
-                                            parm_reg_stack_loc[regnoi],
-                                            REG_NOTES (sinsn));
-                   else if (set != 0
-                            && SET_DEST (set) == regno_reg_rtx [regnor])
-                     REG_NOTES (sinsn)
-                       = gen_rtx_EXPR_LIST (REG_EQUIV,
-                                            parm_reg_stack_loc[regnor],
-                                            REG_NOTES (sinsn));
-                 }
+               {
+                 enum machine_mode submode
+                   = GET_MODE_INNER (GET_MODE (parmreg));
+                 int regnor = REGNO (gen_realpart (submode, parmreg));
+                 int regnoi = REGNO (gen_imagpart (submode, parmreg));
+                 rtx stackr = gen_realpart (submode, stack_parm);
+                 rtx stacki = gen_imagpart (submode, stack_parm);
+
+                 /* Scan backwards for the set of the real and
+                    imaginary parts.  */
+                 for (sinsn = linsn; sinsn != 0;
+                      sinsn = prev_nonnote_insn (sinsn))
+                   {
+                     set = single_set (sinsn);
+                     if (set == 0)
+                       continue;
+
+                     if (SET_DEST (set) == regno_reg_rtx [regnoi])
+                       REG_NOTES (sinsn)
+                         = gen_rtx_EXPR_LIST (REG_EQUIV, stacki,
+                                              REG_NOTES (sinsn));
+                     else if (SET_DEST (set) == regno_reg_rtx [regnor])
+                       REG_NOTES (sinsn)
+                         = gen_rtx_EXPR_LIST (REG_EQUIV, stackr,
+                                              REG_NOTES (sinsn));
+                   }
+               }
              else if ((set = single_set (linsn)) != 0
                       && SET_DEST (set) == parmreg)
                REG_NOTES (linsn)
@@ -5069,22 +2841,6 @@ assign_parms (tree fndecl)
          if (POINTER_TYPE_P (TREE_TYPE (parm)))
            mark_reg_pointer (parmreg,
                              TYPE_ALIGN (TREE_TYPE (TREE_TYPE (parm))));
-
-         /* If something wants our address, try to use ADDRESSOF.  */
-         if (TREE_ADDRESSABLE (parm))
-           {
-             /* If we end up putting something into the stack,
-                fixup_var_refs_insns will need to make a pass over
-                all the instructions.  It looks through the pending
-                sequences -- but it can't see the ones in the
-                CONVERSION_INSNS, if they're not on the sequence
-                stack.  So, we go back to that sequence, just so that
-                the fixups will happen.  */
-             push_to_sequence (conversion_insns);
-             put_var_into_stack (parm, /*rescan=*/true);
-             conversion_insns = get_insns ();
-             end_sequence ();
-           }
        }
       else
        {
@@ -5648,63 +3404,6 @@ setjmp_args_warning (void)
               decl, decl);
 }
 
-/* If this function call setjmp, put all vars into the stack
-   unless they were declared `register'.  */
-
-void
-setjmp_protect (tree block)
-{
-  tree decl, sub;
-  for (decl = BLOCK_VARS (block); decl; decl = TREE_CHAIN (decl))
-    if ((TREE_CODE (decl) == VAR_DECL
-        || TREE_CODE (decl) == PARM_DECL)
-       && DECL_RTL (decl) != 0
-       && (REG_P (DECL_RTL (decl))
-           || (MEM_P (DECL_RTL (decl))
-               && GET_CODE (XEXP (DECL_RTL (decl), 0)) == ADDRESSOF))
-       /* If this variable came from an inline function, it must be
-          that its life doesn't overlap the setjmp.  If there was a
-          setjmp in the function, it would already be in memory.  We
-          must exclude such variable because their DECL_RTL might be
-          set to strange things such as virtual_stack_vars_rtx.  */
-       && ! DECL_FROM_INLINE (decl)
-       && (
-#ifdef NON_SAVING_SETJMP
-           /* If longjmp doesn't restore the registers,
-              don't put anything in them.  */
-           NON_SAVING_SETJMP
-           ||
-#endif
-           ! DECL_REGISTER (decl)))
-      put_var_into_stack (decl, /*rescan=*/true);
-  for (sub = BLOCK_SUBBLOCKS (block); sub; sub = TREE_CHAIN (sub))
-    setjmp_protect (sub);
-}
-\f
-/* Like the previous function, but for args instead of local variables.  */
-
-void
-setjmp_protect_args (void)
-{
-  tree decl;
-  for (decl = DECL_ARGUMENTS (current_function_decl);
-       decl; decl = TREE_CHAIN (decl))
-    if ((TREE_CODE (decl) == VAR_DECL
-        || TREE_CODE (decl) == PARM_DECL)
-       && DECL_RTL (decl) != 0
-       && (REG_P (DECL_RTL (decl))
-           || (MEM_P (DECL_RTL (decl))
-               && GET_CODE (XEXP (DECL_RTL (decl), 0)) == ADDRESSOF))
-       && (
-           /* If longjmp doesn't restore the registers,
-              don't put anything in them.  */
-#ifdef NON_SAVING_SETJMP
-           NON_SAVING_SETJMP
-           ||
-#endif
-           ! DECL_REGISTER (decl)))
-      put_var_into_stack (decl, /*rescan=*/true);
-}
 \f
 /* Convert a stack slot address ADDR for variable VAR
    (from a containing function)
@@ -5725,9 +3424,6 @@ fix_lexical_addr (rtx addr, tree var)
 
   fp = find_function_data (context);
 
-  if (GET_CODE (addr) == ADDRESSOF && MEM_P (XEXP (addr, 0)))
-    addr = XEXP (XEXP (addr, 0), 0);
-
   /* Decode given address as base reg plus displacement.  */
   if (REG_P (addr))
     basereg = addr, displacement = 0;
@@ -6027,8 +3723,6 @@ allocate_struct_function (tree fndecl)
 
   cfun = ggc_alloc_cleared (sizeof (struct function));
 
-  max_parm_reg = LAST_VIRTUAL_REGISTER + 1;
-
   cfun->stack_alignment_needed = STACK_BOUNDARY;
   cfun->preferred_stack_boundary = STACK_BOUNDARY;
 
@@ -6488,18 +4182,6 @@ expand_function_end (void)
   if (arg_pointer_save_area && ! cfun->arg_pointer_save_area_init)
     get_arg_pointer_save_area (cfun);
 
-#ifdef NON_SAVING_SETJMP
-  /* Don't put any variables in registers if we call setjmp
-     on a machine that fails to restore the registers.  */
-  if (NON_SAVING_SETJMP && current_function_calls_setjmp)
-    {
-      if (DECL_INITIAL (current_function_decl) != error_mark_node)
-       setjmp_protect (DECL_INITIAL (current_function_decl));
-
-      setjmp_protect_args ();
-    }
-#endif
-
   /* If we are doing stack checking and this function makes calls,
      do a stack probe at the start of the function to ensure we have enough
      space for another stack frame.  */
index 4a057625bcfdbe784f3fa16b2d24a011f648dec7..a90a5009325bc3067dfc22e0c5922b62f10f5ac9 100644 (file)
@@ -97,10 +97,7 @@ struct emit_status GTY(())
     regno_pointer_align;
 
   /* Indexed by pseudo register number, gives the rtx for that pseudo.
-     Allocated in parallel with regno_pointer_align.
-
-     Note MEM expressions can appear in this array due to the actions
-     of put_var_into_stack.  */
+     Allocated in parallel with regno_pointer_align.  */
   rtx * GTY ((length ("%h.x_reg_rtx_no"))) x_regno_reg_rtx;
 };
 
@@ -273,16 +270,6 @@ struct function GTY(())
   /* Insn after which register parms and SAVE_EXPRs are born, if nonopt.  */
   rtx x_parm_birth_insn;
 
-  /* 1 + last pseudo register number possibly used for loading a copy
-     of a parameter of this function.  */
-  unsigned int x_max_parm_reg;
-
-  /* Vector indexed by REGNO, containing location on stack in which
-     to put the parm which is nominally in pseudo register REGNO,
-     if we discover that that parm must go in the stack.  The highest
-     element in this vector is one less than MAX_PARM_REG, above.  */
-  rtx * GTY ((length ("%h.x_max_parm_reg"))) x_parm_reg_stack_loc;
-
   /* List of all used temporaries allocated, by level.  */
   struct varray_head_tag * GTY((param_is (struct temp_slot))) x_used_temp_slots;
 
@@ -498,8 +485,6 @@ extern int trampolines_created;
 #define current_function_has_nonlocal_label (cfun->has_nonlocal_label)
 #define current_function_has_nonlocal_goto (cfun->has_nonlocal_goto)
 
-#define max_parm_reg (cfun->x_max_parm_reg)
-#define parm_reg_stack_loc (cfun->x_parm_reg_stack_loc)
 #define return_label (cfun->x_return_label)
 #define naked_return_label (cfun->x_naked_return_label)
 #define stack_slot_list (cfun->x_stack_slot_list)
index 6dc10840c74574a3630b9ae440e2bb6f46414ee5..2694e839383d5c3f6de2a588d8088c6b89e7e14a 100644 (file)
@@ -190,23 +190,23 @@ static const struct pred_table
   const RTX_CODE codes[NUM_RTX_CODE];
 } preds[] = {
   {"general_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
-                      LABEL_REF, SUBREG, REG, MEM, ADDRESSOF}},
+                      LABEL_REF, SUBREG, REG, MEM }},
 #ifdef PREDICATE_CODES
   PREDICATE_CODES
 #endif
   {"address_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
-                      LABEL_REF, SUBREG, REG, MEM, ADDRESSOF,
+                      LABEL_REF, SUBREG, REG, MEM,
                       PLUS, MINUS, MULT}},
-  {"register_operand", {SUBREG, REG, ADDRESSOF}},
-  {"pmode_register_operand", {SUBREG, REG, ADDRESSOF}},
+  {"register_operand", {SUBREG, REG}},
+  {"pmode_register_operand", {SUBREG, REG}},
   {"scratch_operand", {SCRATCH, REG}},
   {"immediate_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
                         LABEL_REF}},
   {"const_int_operand", {CONST_INT}},
   {"const_double_operand", {CONST_INT, CONST_DOUBLE}},
-  {"nonimmediate_operand", {SUBREG, REG, MEM, ADDRESSOF}},
+  {"nonimmediate_operand", {SUBREG, REG, MEM}},
   {"nonmemory_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
-                        LABEL_REF, SUBREG, REG, ADDRESSOF}},
+                        LABEL_REF, SUBREG, REG}},
   {"push_operand", {MEM}},
   {"pop_operand", {MEM}},
   {"memory_operand", {SUBREG, MEM}},
@@ -519,7 +519,6 @@ validate_pattern (rtx pattern, rtx insn, rtx set, int set_code)
                    if (c != REG
                        && c != SUBREG
                        && c != MEM
-                       && c != ADDRESSOF
                        && c != CONCAT
                        && c != PARALLEL
                        && c != STRICT_LOW_PART)
index 3b587ab8d2b05893e6ce37f7069ca4d753b4155f..03711d9baf09301ffe7f8442ea80ac201463c301 100644 (file)
@@ -364,41 +364,6 @@ copy_rtx_and_substitute (rtx orig, struct inline_remap *map, int for_lhs)
                                  GET_MODE (SUBREG_REG (orig)),
                                  SUBREG_BYTE (orig));
 
-    case ADDRESSOF:
-      copy = gen_rtx_ADDRESSOF (mode,
-                               copy_rtx_and_substitute (XEXP (orig, 0),
-                                                        map, for_lhs),
-                               0, ADDRESSOF_DECL (orig));
-      regno = ADDRESSOF_REGNO (orig);
-      if (map->reg_map[regno])
-       regno = REGNO (map->reg_map[regno]);
-      else if (regno > LAST_VIRTUAL_REGISTER)
-       {
-         temp = XEXP (orig, 0);
-         map->reg_map[regno] = gen_reg_rtx (GET_MODE (temp));
-         REG_USERVAR_P (map->reg_map[regno]) = REG_USERVAR_P (temp);
-         REG_LOOP_TEST_P (map->reg_map[regno]) = REG_LOOP_TEST_P (temp);
-         RTX_UNCHANGING_P (map->reg_map[regno]) = RTX_UNCHANGING_P (temp);
-         /* A reg with REG_FUNCTION_VALUE_P true will never reach here.  */
-
-         /* Objects may initially be represented as registers, but
-            but turned into a MEM if their address is taken by
-            put_var_into_stack.  Therefore, the register table may have
-            entries which are MEMs.
-
-            We briefly tried to clear such entries, but that ended up
-            cascading into many changes due to the optimizers not being
-            prepared for empty entries in the register table.  So we've
-            decided to allow the MEMs in the register table for now.  */
-         if (REG_P (map->x_regno_reg_rtx[regno])
-             && REG_POINTER (map->x_regno_reg_rtx[regno]))
-           mark_reg_pointer (map->reg_map[regno],
-                             map->regno_pointer_align[regno]);
-         regno = REGNO (map->reg_map[regno]);
-       }
-      ADDRESSOF_REGNO (copy) = regno;
-      return copy;
-
     case USE:
     case CLOBBER:
       /* USE and CLOBBER are ordinary, but we convert (use (subreg foo))
index c564f687adfea54dd6a1e30d198f5ae2c2ab7b2f..822e4db8f8ddfd1b57c971ad25000625da3d0086 100644 (file)
@@ -139,7 +139,6 @@ enum dump_file_index
   DFI_jump,
   DFI_null,
   DFI_cse,
-  DFI_addressof,
   DFI_gcse,
   DFI_loop,
   DFI_bypass,
@@ -181,7 +180,7 @@ enum dump_file_index
    Remaining -d letters:
 
        "   e            q         "
-       "          K   O Q     WXY "
+       "    F     K   O Q     WXY "
 */
 
 static struct dump_file_info dump_file_tbl[DFI_MAX] =
@@ -193,7 +192,6 @@ static struct dump_file_info dump_file_tbl[DFI_MAX] =
   { "jump",    'j', 0, 0, 0 },
   { "null",    'u', 0, 0, 0 },
   { "cse",     's', 0, 0, 0 },
-  { "addressof", 'F', 0, 0, 0 },
   { "gcse",    'G', 1, 0, 0 },
   { "loop",    'L', 1, 0, 0 },
   { "bypass",   'G', 1, 0, 0 }, /* Yes, duplicate enable switch.  */
@@ -989,20 +987,6 @@ rest_of_handle_cfg (void)
   close_dump_file (DFI_cfg, print_rtl_with_bb, get_insns ());
 }
 
-/* Purge addressofs.  */
-static void
-rest_of_handle_addressof (void)
-{
-  open_dump_file (DFI_addressof, current_function_decl);
-
-  purge_addressof (get_insns ());
-  if (optimize && purge_all_dead_edges (0))
-    delete_unreachable_blocks ();
-  reg_scan (get_insns (), max_reg_num (), 1);
-
-  close_dump_file (DFI_addressof, print_rtl, get_insns ());
-}
-
 /* Perform jump bypassing and control flow optimizations.  */
 static void
 rest_of_handle_jump_bypass (void)
@@ -1543,8 +1527,6 @@ rest_of_compilation (void)
   if (optimize > 0)
     rest_of_handle_cse ();
 
-  rest_of_handle_addressof ();
-
   ggc_collect ();
 
   if (optimize > 0)
index 2d9e472d6cf2ff053c061d551281d85e3fbdc6fa..9220f4dc6b31c15c5b6b0426f3b8c5d66a216f02 100644 (file)
@@ -978,19 +978,11 @@ general_operand (rtx op, enum machine_mode mode)
       if (! volatile_ok && MEM_VOLATILE_P (op))
        return 0;
 
-      if (GET_CODE (y) == ADDRESSOF)
-       return 1;
-
       /* Use the mem's mode, since it will be reloaded thus.  */
       mode = GET_MODE (op);
       GO_IF_LEGITIMATE_ADDRESS (mode, y, win);
     }
 
-  /* Pretend this is an operand for now; we'll run force_operand
-     on its replacement in fixup_var_refs_1.  */
-  if (code == ADDRESSOF)
-    return 1;
-
   return 0;
 
  win:
@@ -1060,11 +1052,6 @@ register_operand (rtx op, enum machine_mode mode)
       op = sub;
     }
 
-  /* If we have an ADDRESSOF, consider it valid since it will be
-     converted into something that will not be a MEM.  */
-  if (GET_CODE (op) == ADDRESSOF)
-    return 1;
-
   /* We don't consider registers whose class is NO_REGS
      to be a register operand.  */
   return (REG_P (op)
@@ -1288,9 +1275,6 @@ pop_operand (rtx op, enum machine_mode mode)
 int
 memory_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx addr)
 {
-  if (GET_CODE (addr) == ADDRESSOF)
-    return 1;
-
   GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
   return 0;
 
index a7eafa3382a97cf4390777651bfa716a52e26ecd..35fe9ca009f7c1fe3e77d212a712ee78e802f3b7 100644 (file)
@@ -2282,15 +2282,6 @@ eliminate_regs (rtx x, enum machine_mode mem_mode, rtx insn)
     case RETURN:
       return x;
 
-    case ADDRESSOF:
-      /* This is only for the benefit of the debugging backends, which call
-        eliminate_regs on DECL_RTL; any ADDRESSOFs in the actual insns are
-        removed after CSE.  */
-      new = eliminate_regs (XEXP (x, 0), 0, insn);
-      if (MEM_P (new))
-       return XEXP (new, 0);
-      return x;
-
     case REG:
       regno = REGNO (x);
 
@@ -2553,12 +2544,6 @@ eliminate_regs (rtx x, enum machine_mode mem_mode, rtx insn)
       return x;
 
     case MEM:
-      /* This is only for the benefit of the debugging backends, which call
-        eliminate_regs on DECL_RTL; any ADDRESSOFs in the actual insns are
-        removed after CSE.  */
-      if (GET_CODE (XEXP (x, 0)) == ADDRESSOF)
-       return eliminate_regs (XEXP (XEXP (x, 0), 0), 0, insn);
-
       /* Our only special processing is to pass the mode of the MEM to our
         recursive call and copy the flags.  While we are here, handle this
         case more efficiently.  */
@@ -2657,9 +2642,6 @@ elimination_effects (rtx x, enum machine_mode mem_mode)
     case RETURN:
       return;
 
-    case ADDRESSOF:
-      abort ();
-
     case REG:
       regno = REGNO (x);
 
@@ -2802,9 +2784,6 @@ elimination_effects (rtx x, enum machine_mode mem_mode)
       return;
 
     case MEM:
-      if (GET_CODE (XEXP (x, 0)) == ADDRESSOF)
-       abort ();
-
       /* Our only special processing is to pass the mode of the MEM to our
         recursive call.  */
       elimination_effects (XEXP (x, 0), GET_MODE (x));
index 59d77999c2b717804ed51fde803783db0998cd9c..f1aa85b64dcd9de8883bc3f25e8bd4ae5a9d75e3 100644 (file)
--- a/gcc/rtl.c
+++ b/gcc/rtl.c
@@ -224,7 +224,6 @@ copy_rtx (rtx orig)
     case CC0:
     case SCRATCH:
       /* SCRATCH must be shared because they represent distinct values.  */
-    case ADDRESSOF:
       return orig;
     case CLOBBER:
       if (REG_P (XEXP (orig, 0)) && REGNO (XEXP (orig, 0)) < FIRST_PSEUDO_REGISTER)
index 6881b6fdb6ff3aed535958703c2b43415e52a1f4..25b5ee90610ba0e79eab6e10df1271c77e105804 100644 (file)
@@ -906,15 +906,6 @@ DEF_RTL_EXPR(SYMBOL_REF, "symbol_ref", "s00", RTX_CONST_OBJ)
    pretend to be looking at the entire value and comparing it.  */
 DEF_RTL_EXPR(CC0, "cc0", "", RTX_OBJ)
 
-/* Reference to the address of a register.  Removed by purge_addressof after
-   CSE has elided as many as possible.
-   1st operand: the register we may need the address of.
-   2nd operand: the original pseudo regno we were generated for.
-   3rd operand: the decl for the object in the register, for
-     put_reg_in_stack.  */
-
-DEF_RTL_EXPR(ADDRESSOF, "addressof", "eit", RTX_OBJ)
-
 /* =====================================================================
    A QUEUED expression really points to a member of the queue of instructions
    to be output later for postincrement/postdecrement.
index 8e673049e60fa0665101a5b0658aef8dae789d65..4de6b82391c3c79b83721b54a837a46b78df1e67 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1115,12 +1115,6 @@ enum label_kind
 
 #define LABEL_ALT_ENTRY_P(LABEL) (LABEL_KIND (LABEL) != LABEL_NORMAL)
 
-/* The original regno this ADDRESSOF was built for.  */
-#define ADDRESSOF_REGNO(RTX) XCUINT (RTX, 1, ADDRESSOF)
-
-/* The variable in the register we took the address of.  */
-#define ADDRESSOF_DECL(RTX) XCTREE (RTX, 2, ADDRESSOF)
-
 /* In jump.c, each JUMP_INSN can point to a label that it can jump to,
    so that if the JUMP_INSN is deleted, the label's LABEL_NUSES can
    be decremented and possibly the label can be deleted.  */
@@ -1801,9 +1795,6 @@ extern rtx simplify_replace_rtx (rtx, rtx, rtx);
 extern rtx simplify_rtx (rtx);
 extern rtx avoid_constant_pool_reference (rtx);
 
-/* In function.c  */
-extern rtx gen_mem_addressof (rtx, tree, int);
-
 /* In regclass.c  */
 extern enum machine_mode choose_hard_reg_mode (unsigned int, unsigned int,
                                               bool);
@@ -2280,7 +2271,6 @@ extern int prologue_epilogue_contains (rtx);
 extern int sibcall_epilogue_contains (rtx);
 extern void mark_temp_addr_taken (rtx);
 extern void update_temp_slot_address (rtx, rtx);
-extern void purge_addressof (rtx);
 extern void purge_hard_subreg_sets (rtx);
 
 /* In stmt.c */
index 3329d8bf07c63b4fe9ab9e81ab9b2cdd3630fd5e..0eaf1c0df2e775d48c660ac465c0c4a8aba78099 100644 (file)
@@ -86,7 +86,6 @@ rtx_unstable_p (rtx x)
     case QUEUED:
       return 1;
 
-    case ADDRESSOF:
     case CONST:
     case CONST_INT:
     case CONST_DOUBLE:
@@ -173,10 +172,6 @@ rtx_varies_p (rtx x, int for_alias)
     case LABEL_REF:
       return 0;
 
-    case ADDRESSOF:
-      /* This will resolve to some offset from the frame pointer.  */
-      return 0;
-
     case REG:
       /* Note that we have to test for the actual rtx used for the frame
         and arg pointers and not just the register number in case we have
@@ -248,10 +243,6 @@ rtx_addr_can_trap_p (rtx x)
     case LABEL_REF:
       return 0;
 
-    case ADDRESSOF:
-      /* This will resolve to some offset from the frame pointer.  */
-      return 0;
-
     case REG:
       /* As in rtx_varies_p, we have to use the actual rtx, not reg number.  */
       if (x == frame_pointer_rtx || x == hard_frame_pointer_rtx
@@ -311,10 +302,6 @@ nonzero_address_p (rtx x)
     case LABEL_REF:
       return true;
 
-    case ADDRESSOF:
-      /* This will resolve to some offset from the frame pointer.  */
-      return true;
-
     case REG:
       /* As in rtx_varies_p, we have to use the actual rtx, not reg number.  */
       if (x == frame_pointer_rtx || x == hard_frame_pointer_rtx
@@ -3838,14 +3825,6 @@ rtx_cost (rtx x, enum rtx_code outer_code ATTRIBUTE_UNUSED)
 int
 address_cost (rtx x, enum machine_mode mode)
 {
-  /* The address_cost target hook does not deal with ADDRESSOF nodes.  But,
-     during CSE, such nodes are present.  Using an ADDRESSOF node which
-     refers to the address of a REG is a good thing because we can then
-     turn (MEM (ADDRESSOF (REG))) into just plain REG.  */
-
-  if (GET_CODE (x) == ADDRESSOF && REG_P (XEXP ((x), 0)))
-    return -1;
-
   /* We may be asked for cost of various unusual addresses, such as operands
      of push instruction.  It is not worthwhile to complicate writing
      of the target hook by such cases.  */
index cabb1b7ead321e238bcd47a379c6ebd013692d2e..5cb14efd14008b2f04b7ee209e0a922d9e5659a4 100644 (file)
@@ -76,8 +76,6 @@ gen_lowpart_general (enum machine_mode mode, rtx x)
 
       return adjust_address (x, mode, offset);
     }
-  else if (GET_CODE (x) == ADDRESSOF)
-    return gen_lowpart_general (mode, force_reg (GET_MODE (x), x));
   else
     abort ();
 }
index 543c92a09dc84adae0d8d7f8edc45f664c292bc9..77bc32ae734e1539d1dac07c8ba46b51471b8d23 100644 (file)
@@ -1600,7 +1600,6 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
                }
              if (REG_P (op)
                  || GET_CODE (op) == SUBREG
-                 || GET_CODE (op) == ADDRESSOF
                  || GET_CODE (op) == CONCAT)
                {
                  tree qual_type = build_qualified_type (type,
@@ -3070,14 +3069,7 @@ expand_decl (tree decl)
       set_mem_attributes (x, decl, 1);
       SET_DECL_RTL (decl, x);
     }
-  else if (DECL_MODE (decl) != BLKmode
-          /* If -ffloat-store, don't put explicit float vars
-             into regs.  */
-          && !(flag_float_store
-               && TREE_CODE (type) == REAL_TYPE)
-          && ! TREE_THIS_VOLATILE (decl)
-          && ! DECL_NONLOCAL (decl)
-          && (DECL_REGISTER (decl) || DECL_ARTIFICIAL (decl) || optimize))
+  else if (use_register_for_decl (decl))
     {
       /* Automatic variable that can go in a register.  */
       int unsignedp = TYPE_UNSIGNED (type);
@@ -3103,10 +3095,6 @@ expand_decl (tree decl)
        }
 
       maybe_set_unchanging (DECL_RTL (decl), decl);
-
-      /* If something wants our address, try to use ADDRESSOF.  */
-      if (TREE_ADDRESSABLE (decl))
-       put_var_into_stack (decl, /*rescan=*/false);
     }
 
   else if (TREE_CODE (DECL_SIZE_UNIT (decl)) == INTEGER_CST
index eff90686c73eed922d7d1861f36beb03bdcff632..3d2f1880b97c0dae5abe715fb9f4d16c95dfc3bd 100644 (file)
@@ -3465,17 +3465,14 @@ extern void build_common_tree_nodes_2 (int);
 extern tree build_range_type (tree, tree, tree);
 
 /* In function.c */
-extern void setjmp_protect_args (void);
-extern void setjmp_protect (tree);
 extern void expand_main_function (void);
 extern void init_dummy_function_start (void);
 extern void expand_dummy_function_end (void);
 extern void init_function_for_compilation (void);
 extern void allocate_struct_function (tree);
 extern void init_function_start (tree);
+extern bool use_register_for_decl (tree);
 extern void assign_parms (tree);
-extern void put_var_into_stack (tree, int);
-extern void flush_addressof (tree);
 extern void setjmp_vars_warning (tree);
 extern void setjmp_args_warning (void);
 extern void init_temp_slots (void);
index 06a962bdae5c7d535a32b742e884ead8f79a1c26..fb70e8aeb2b1d6309c48a29d05265d64df2bd023 100644 (file)
@@ -1,3 +1,7 @@
+2004-04-07  Richard Henderson  <rth@redhat.com>
+
+       * treetree.c (tree_mark_addressable):  Don't put_var_into_stack.
+
 2004-03-31  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
 
        * treetree.c (tree_lang_signed_or_unsigned_type): Use TYPE_UNSIGNED,
index c8be057ddacffe9ff023d5ef7ad6dc3a52d95143..1819ad91e53d684cc6d5b01b048b87a6d72134ee 100644 (file)
@@ -962,7 +962,6 @@ tree_mark_addressable (tree exp)
            pedwarn ("address of register variable `%s' requested",
                     IDENTIFIER_POINTER (DECL_NAME (x)));
          }
-       put_var_into_stack (x, /*rescan=*/ true);
 
        /* drops in */
       case FUNCTION_DECL:
index 91dbb90e3c386b0a37e9f142cb90b832c07ba060..01b54254450d5a8716b6cfcf3158335ea80ca67e 100644 (file)
--- a/gcc/web.c
+++ b/gcc/web.c
@@ -70,9 +70,8 @@ static struct web_entry *unionfind_root (struct web_entry *);
 static void unionfind_union (struct web_entry *, struct web_entry *);
 static void union_defs (struct df *, struct ref *, struct web_entry *, 
                         struct web_entry *);
-static rtx entry_register (struct web_entry *, struct ref *, char *, char *);
+static rtx entry_register (struct web_entry *, struct ref *, char *);
 static void replace_ref (struct ref *, rtx);
-static int mark_addressof (rtx *, void *);
 
 /* Find the root of unionfind tree (the representative of set).  */
 
@@ -173,8 +172,7 @@ union_defs (struct df *df, struct ref *use, struct web_entry *def_entry,
 /* Find the corresponding register for the given entry.  */
 
 static rtx
-entry_register (struct web_entry *entry, struct ref *ref, char *used, 
-                char *use_addressof)
+entry_register (struct web_entry *entry, struct ref *ref, char *used)
 {
   struct web_entry *root;
   rtx reg, newreg;
@@ -198,14 +196,6 @@ entry_register (struct web_entry *entry, struct ref *ref, char *used,
                 "New web forced to keep reg=%i (user variable)\n",
                 REGNO (reg));
     }
-  else if (use_addressof [REGNO (reg)])
-    {
-      newreg = reg;
-      if (dump_file)
-       fprintf (dump_file,
-                "New web forced to keep reg=%i (address taken)\n",
-                REGNO (reg));
-    }
   else
     {
       newreg = gen_reg_rtx (GET_MODE (reg));
@@ -239,19 +229,6 @@ replace_ref (struct ref *ref, rtx reg)
   *loc = reg;
 }
 
-/* Mark each pseudo whose address is taken.  */
-
-static int
-mark_addressof (rtx *rtl, void *data)
-{
-  if (!*rtl)
-    return 0;
-  if (GET_CODE (*rtl) == ADDRESSOF
-      && REG_P (XEXP (*rtl, 0)))
-    ((char *)data)[REGNO (XEXP (*rtl, 0))] = 1;
-  return 0;
-}
-
 /* Main entry point.  */
 
 void
@@ -263,9 +240,6 @@ web_main (void)
   unsigned int i;
   int max = max_reg_num ();
   char *used;
-  char *use_addressof;
-  basic_block bb;
-  rtx insn;
 
   df = df_init ();
   df_analyze (df, 0, DF_UD_CHAIN | DF_EQUIV_NOTES);
@@ -273,7 +247,6 @@ web_main (void)
   def_entry = xcalloc (df->n_defs, sizeof (struct web_entry));
   use_entry = xcalloc (df->n_uses, sizeof (struct web_entry));
   used = xcalloc (max, sizeof (char));
-  use_addressof = xcalloc (max, sizeof (char));
 
   if (dump_file)
     df_dump (df, DF_UD_CHAIN | DF_DU_CHAIN, dump_file);
@@ -282,22 +255,14 @@ web_main (void)
   for (i = 0; i < df->n_uses; i++)
     union_defs (df, df->uses[i], def_entry, use_entry);
 
-  /* We can not safely rename registers whose address is taken.  */
-  FOR_EACH_BB (bb)
-    FOR_BB_INSNS (bb, insn)
-      {
-       if (INSN_P (insn))
-         for_each_rtx (&PATTERN (insn), mark_addressof, use_addressof);
-      }
-
   /* Update the instruction stream, allocating new registers for split pseudos
      in progress.  */
   for (i = 0; i < df->n_uses; i++)
     replace_ref (df->uses[i], entry_register (use_entry + i, df->uses[i],
-                                             used, use_addressof));
+                                             used));
   for (i = 0; i < df->n_defs; i++)
     replace_ref (df->defs[i], entry_register (def_entry + i, df->defs[i],
-                                             used, use_addressof));
+                                             used));
 
   /* Dataflow information is corrupt here, but it can be easily updated
      by creating new entries for new registers and updates or calling
@@ -305,6 +270,5 @@ web_main (void)
   free (def_entry);
   free (use_entry);
   free (used);
-  free (use_addressof);
   df_finish (df);
 }