diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-07-04 08:07:15 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-07-04 08:07:15 +0000 |
commit | e8825bb05c80adfdb34722fab0d3030ef5ef4823 (patch) | |
tree | d8e587b078a6e56d763f14d68c29fef196cd5322 | |
parent | 3f56a1abd3114c6a4d08bd7602b88c7d4170b1f2 (diff) | |
download | gcc-e8825bb05c80adfdb34722fab0d3030ef5ef4823.tar.gz |
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@84072 138bc75d-0d04-0410-961f-82ee72b054a4
44 files changed, 203 insertions, 2866 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index cf04490f855..e9f7ce28e17 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index a398e01b140..12669bec532 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -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. diff --git a/gcc/ada/utils2.c b/gcc/ada/utils2.c index 0a563a55d68..85b0a7452ff 100644 --- a/gcc/ada/utils2.c +++ b/gcc/ada/utils2.c @@ -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; diff --git a/gcc/alias.c b/gcc/alias.c index b8443e8c02d..9e53d9bb07f 100644 --- a/gcc/alias.c +++ b/gcc/alias.c @@ -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) diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 57a718f4dbf..e5f94915cf2 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -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: diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index 23f35ebf4f1..0fe8b000514 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -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. */ diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 7cd1573a03c..37b13fe4c36 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -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 diff --git a/gcc/config/c4x/c4x.c b/gcc/config/c4x/c4x.c index ceaa7dfcb98..62f8679997c 100644 --- a/gcc/config/c4x/c4x.c +++ b/gcc/config/c4x/c4x.c @@ -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)) diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c index 92e0dd213fa..99e8cb9c7e2 100644 --- a/gcc/config/frv/frv.c +++ b/gcc/config/frv/frv.c @@ -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); } diff --git a/gcc/config/h8300/h8300.h b/gcc/config/h8300/h8300.h index d78669babac..eeafd84a24e 100644 --- a/gcc/config/h8300/h8300.h +++ b/gcc/config/h8300/h8300.h @@ -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}}, \ diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index 90d4a1f9302..2c7e36d511e 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -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; } diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index e22e1699f75..ab008e494c7 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -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}}, \ diff --git a/gcc/config/mn10300/mn10300.c b/gcc/config/mn10300/mn10300.c index 95078d62da4..da235e39a29 100644 --- a/gcc/config/mn10300/mn10300.c +++ b/gcc/config/mn10300/mn10300.c @@ -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 (); diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 537148e1764..470425bc72e 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -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) diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index e2a02621522..8e2c458e5df 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -1338,8 +1338,7 @@ 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]); @@ -1386,8 +1385,7 @@ 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]); diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h index 0cf64b84a0d..595a0f5fa88 100644 --- a/gcc/config/sparc/sparc.h +++ b/gcc/config/sparc/sparc.h @@ -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}}, \ diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8baadc015a2..4703ed85be2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,10 +1,14 @@ -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-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> diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index d099980e486..4f473508c38 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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: diff --git a/gcc/cse.c b/gcc/cse.c index c50b28aaba7..ef99bc6cb78 100644 --- 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; } diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 13f9c087356..625a6789672 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -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}. diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 2fb962ce63a..282ccab41d1 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -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: diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index 53edf2c25d8..45abfe320be 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -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) diff --git a/gcc/explow.c b/gcc/explow.c index 99d39362bb3..2223ca6e2bc 100644 --- a/gcc/explow.c +++ b/gcc/explow.c @@ -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 diff --git a/gcc/expmed.c b/gcc/expmed.c index ad1d88367da..6ee291370d0 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -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) { diff --git a/gcc/expr.c b/gcc/expr.c index d3951fed769..b44309ded60 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -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)); diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index a477814081b..0b4026aa4ec 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -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. diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c index fd4fe5c2616..43eb87d1be3 100644 --- a/gcc/fortran/f95-lang.c +++ b/gcc/fortran/f95-lang.c @@ -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: diff --git a/gcc/function.c b/gcc/function.c index c3ab96dbae3..0bab2b6c44d 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -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; }; -/* 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; @@ -1291,1461 +1210,6 @@ init_temp_slots (void) target_temp_slot_level = 0; } -/* 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); -} - -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; -} - -/* 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); - } -} - -/* 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); - } - } -} - -/* 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; -} - -/* 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; -} - -/* 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); - } - } -} - /* These routines are responsible for converting virtual register references to the actual hard register references once RTL generation is complete. @@ -2799,640 +1263,6 @@ static int 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; - } - - seq = get_insns (); - end_sequence (); - emit_insn_before (seq, insn); - compute_insns_for_mem (p ? NEXT_INSN (p) : get_insns (), - insn, ht); - } - - /* 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)); - - /* We replaced with a reg -- all done. */ - return true; - } - } - - else if (validate_change (insn, loc, sub, 0)) - { - /* Remember the replacement so that the same one can be done - on the REG_NOTES. */ - if (REG_P (sub) || GET_CODE (sub) == SUBREG) - { - rtx tem; - - 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; - } - goto restart; - } - } - - give_up: - /* Scan all subexpressions. */ - fmt = GET_RTX_FORMAT (code); - for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++) - { - 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. */ - -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); -} - -/* Return nonzero if K1 and K2 (two REGs) are the same. */ - -static int -insns_for_mem_comp (const void *k1, const void *k2) -{ - 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 insns_for_mem_walk_info -{ - /* The hash table that we are using to record which INSNs use which - MEMs. */ - htab_t ht; - - /* The INSN we are currently processing. */ - rtx insn; - - /* 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; -}; - -/* 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). */ - -static int -insns_for_mem_walk (rtx *r, void *data) -{ - 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; -} - -/* Walk the INSNS, until we reach LAST_INSN, recording which INSNs use - which REGs in HT. */ - -static void -compute_insns_for_mem (rtx insns, rtx last_insn, htab_t ht) -{ - rtx insn; - struct insns_for_mem_walk_info ifmwi; - ifmwi.ht = ht; - - 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); - } -} - -/* Helper function for purge_addressof called through for_each_rtx. - Returns true iff the rtl is an ADDRESSOF. */ - -static int -is_addressof (rtx *rtl, void *data ATTRIBUTE_UNUSED) -{ - return GET_CODE (*rtl) == ADDRESSOF; -} - -/* Eliminate all occurrences of ADDRESSOF from INSNS. Elide any remaining - (MEM (ADDRESSOF)) patterns, and force any needed registers into the - stack. */ - -void -purge_addressof (rtx insns) -{ - rtx insn, tmp; - htab_t ht; - - /* 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); - - postponed_insns = NULL; - - 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 (); - - if (! purge_addressof_1 (®_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; - - 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 (¬e, is_addressof, NULL)) - remove_note (insn, note); - } - } - } - - /* 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); - - if (! purge_addressof_1 (&PATTERN (insn), insn, - asm_noperands (PATTERN (insn)) > 0, 0, 0, ht)) - abort (); - } - - /* Clean up. */ - purge_bitfield_addressof_replacements = 0; - purge_addressof_replacements = 0; - - /* REGs are shared. purge_addressof will destructively replace a REG - with a MEM, which creates shared MEMs. - - 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). - - So, we have to do another unsharing pass after we have flushed any - REGs that had their address taken into the stack. - - 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 ()); -} /* 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; } +/* 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); -} - -/* 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); -} /* 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. */ diff --git a/gcc/function.h b/gcc/function.h index 4a057625bcf..a90a5009325 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -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) diff --git a/gcc/genrecog.c b/gcc/genrecog.c index 6dc10840c74..2694e839383 100644 --- a/gcc/genrecog.c +++ b/gcc/genrecog.c @@ -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) diff --git a/gcc/integrate.c b/gcc/integrate.c index 3b587ab8d2b..03711d9baf0 100644 --- a/gcc/integrate.c +++ b/gcc/integrate.c @@ -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)) diff --git a/gcc/passes.c b/gcc/passes.c index c564f687adf..822e4db8f8d 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -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) diff --git a/gcc/recog.c b/gcc/recog.c index 2d9e472d6cf..9220f4dc6b3 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -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; diff --git a/gcc/reload1.c b/gcc/reload1.c index a7eafa3382a..35fe9ca009f 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -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)); diff --git a/gcc/rtl.c b/gcc/rtl.c index 59d77999c2b..f1aa85b64dc 100644 --- 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) diff --git a/gcc/rtl.def b/gcc/rtl.def index 6881b6fdb6f..25b5ee90610 100644 --- a/gcc/rtl.def +++ b/gcc/rtl.def @@ -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. diff --git a/gcc/rtl.h b/gcc/rtl.h index 8e673049e60..4de6b82391c 100644 --- 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 */ diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index 3329d8bf07c..0eaf1c0df2e 100644 --- a/gcc/rtlanal.c +++ b/gcc/rtlanal.c @@ -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. */ diff --git a/gcc/rtlhooks.c b/gcc/rtlhooks.c index cabb1b7ead3..5cb14efd140 100644 --- a/gcc/rtlhooks.c +++ b/gcc/rtlhooks.c @@ -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 (); } diff --git a/gcc/stmt.c b/gcc/stmt.c index 543c92a09dc..77bc32ae734 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -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 diff --git a/gcc/tree.h b/gcc/tree.h index eff90686c73..3d2f1880b97 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -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); diff --git a/gcc/treelang/ChangeLog b/gcc/treelang/ChangeLog index 06a962bdae5..fb70e8aeb2b 100644 --- a/gcc/treelang/ChangeLog +++ b/gcc/treelang/ChangeLog @@ -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, diff --git a/gcc/treelang/treetree.c b/gcc/treelang/treetree.c index c8be057ddac..1819ad91e53 100644 --- a/gcc/treelang/treetree.c +++ b/gcc/treelang/treetree.c @@ -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: diff --git a/gcc/web.c b/gcc/web.c index 91dbb90e3c3..01b54254450 100644 --- 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); } |