From e1deeb725bfd3bee9f4540cb965b59f89aa56535 Mon Sep 17 00:00:00 2001 From: Bob Wilson Date: Fri, 22 Nov 2002 19:27:42 +0000 Subject: [PATCH] xtensa-protos.h (xtensa_copy_incoming_a7): Declare. * config/xtensa/xtensa-protos.h (xtensa_copy_incoming_a7): Declare. * config/xtensa/xtensa.c (struct machine_function): Add incoming_a7_copied flag. (xtensa_copy_incoming_a7): Define. (xtensa_emit_move_sequence): Use xtensa_copy_incoming_a7. * config/xtensa/xtensa.md (movdi, movsf, movdf): Ditto. From-SVN: r59382 --- gcc/ChangeLog | 9 +++ gcc/config/xtensa/xtensa-protos.h | 1 + gcc/config/xtensa/xtensa.c | 110 +++++++++++++++++++----------- gcc/config/xtensa/xtensa.md | 24 ++----- 4 files changed, 87 insertions(+), 57 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e74c1ef20f2b..212a6b4ef6ca 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2002-11-21 Bob Wilson + + * config/xtensa/xtensa-protos.h (xtensa_copy_incoming_a7): Declare. + * config/xtensa/xtensa.c (struct machine_function): Add + incoming_a7_copied flag. + (xtensa_copy_incoming_a7): Define. + (xtensa_emit_move_sequence): Use xtensa_copy_incoming_a7. + * config/xtensa/xtensa.md (movdi, movsf, movdf): Ditto. + 2002-11-19 Release Manager * GCC 3.2.1 Released. diff --git a/gcc/config/xtensa/xtensa-protos.h b/gcc/config/xtensa/xtensa-protos.h index 01d4a6142a5e..9cda5e625dea 100644 --- a/gcc/config/xtensa/xtensa-protos.h +++ b/gcc/config/xtensa/xtensa-protos.h @@ -70,6 +70,7 @@ extern int xtensa_expand_conditional_move PARAMS ((rtx *, int)); extern int xtensa_expand_scc PARAMS ((rtx *)); extern int xtensa_expand_block_move PARAMS ((rtx *)); extern int xtensa_emit_move_sequence PARAMS ((rtx *, enum machine_mode)); +extern bool xtensa_copy_incoming_a7 PARAMS ((rtx *, enum machine_mode)); extern void xtensa_emit_block_move PARAMS ((rtx *, rtx *, int)); extern void xtensa_expand_nonlocal_goto PARAMS ((rtx *)); extern void xtensa_emit_loop_end PARAMS ((rtx, rtx *)); diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c index 5fe2a9b484cf..a3490430f624 100644 --- a/gcc/config/xtensa/xtensa.c +++ b/gcc/config/xtensa/xtensa.c @@ -87,6 +87,7 @@ const char *xtensa_st_opcodes[(int) MAX_MACHINE_MODE]; struct machine_function { int accesses_prev_frame; + bool incoming_a7_copied; }; /* Vector, indexed by hard register number, which contains 1 for a @@ -1262,45 +1263,8 @@ xtensa_emit_move_sequence (operands, mode) if (!xtensa_valid_move (mode, operands)) operands[1] = force_reg (mode, operands[1]); - /* Check if this move is copying an incoming argument in a7. If - so, emit the move, followed by the special "set_frame_ptr" - unspec_volatile insn, at the very beginning of the function. - This is necessary because the register allocator will ignore - conflicts with a7 and may assign some other pseudo to a7. If - that pseudo was assigned prior to this move, it would clobber - the incoming argument in a7. By copying the argument out of - a7 as the very first thing, and then immediately following - that with an unspec_volatile to keep the scheduler away, we - should avoid any problems. */ - - if (a7_overlap_mentioned_p (operands[1])) - { - rtx mov; - switch (mode) - { - case SImode: - mov = gen_movsi_internal (operands[0], operands[1]); - break; - case HImode: - mov = gen_movhi_internal (operands[0], operands[1]); - break; - case QImode: - mov = gen_movqi_internal (operands[0], operands[1]); - break; - default: - abort (); - } - - /* Insert the instructions before any other argument copies. - (The set_frame_ptr insn comes _after_ the move, so push it - out first.) */ - push_topmost_sequence (); - emit_insn_after (gen_set_frame_ptr (), get_insns ()); - emit_insn_after (mov, get_insns ()); - pop_topmost_sequence (); - - return 1; - } + if (xtensa_copy_incoming_a7 (operands, mode)) + return 1; } /* During reload we don't want to emit (subreg:X (mem:Y)) since that @@ -1332,6 +1296,74 @@ fixup_subreg_mem (x) } +/* Check if this move is copying an incoming argument in a7. If so, + emit the move, followed by the special "set_frame_ptr" + unspec_volatile insn, at the very beginning of the function. This + is necessary because the register allocator will ignore conflicts + with a7 and may assign some other pseudo to a7. If that pseudo was + assigned prior to this move, it would clobber the incoming argument + in a7. By copying the argument out of a7 as the very first thing, + and then immediately following that with an unspec_volatile to keep + the scheduler away, we should avoid any problems. */ + +bool +xtensa_copy_incoming_a7 (operands, mode) + rtx *operands; + enum machine_mode mode; +{ + if (a7_overlap_mentioned_p (operands[1]) + && !cfun->machine->incoming_a7_copied) + { + rtx mov; + switch (mode) + { + case DFmode: + mov = gen_movdf_internal (operands[0], operands[1]); + break; + case SFmode: + mov = gen_movsf_internal (operands[0], operands[1]); + break; + case DImode: + mov = gen_movdi_internal (operands[0], operands[1]); + break; + case SImode: + mov = gen_movsi_internal (operands[0], operands[1]); + break; + case HImode: + mov = gen_movhi_internal (operands[0], operands[1]); + break; + case QImode: + mov = gen_movqi_internal (operands[0], operands[1]); + break; + default: + abort (); + } + + /* Insert the instructions before any other argument copies. + (The set_frame_ptr insn comes _after_ the move, so push it + out first.) */ + push_topmost_sequence (); + emit_insn_after (gen_set_frame_ptr (), get_insns ()); + emit_insn_after (mov, get_insns ()); + pop_topmost_sequence (); + + /* Ideally the incoming argument in a7 would only be copied + once, since propagating a7 into the body of a function + will almost certainly lead to errors. However, there is + at least one harmless case (in GCSE) where the original + copy from a7 is changed to copy into a new pseudo. Thus, + we use a flag to only do this special treatment for the + first copy of a7. */ + + cfun->machine->incoming_a7_copied = true; + + return 1; + } + + return 0; +} + + /* Try to expand a block move operation to an RTL block move instruction. If not optimizing or if the block size is not a constant or if the block is small, the expansion fails and GCC falls back to calling diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md index 95d50d04a848..b0cf9a1724ff 100644 --- a/gcc/config/xtensa/xtensa.md +++ b/gcc/config/xtensa/xtensa.md @@ -929,12 +929,8 @@ && !register_operand (operands[1], DImode)) operands[1] = force_reg (DImode, operands[1]); - if (a7_overlap_mentioned_p (operands[1])) - { - emit_insn (gen_movdi_internal (operands[0], operands[1])); - emit_insn (gen_set_frame_ptr ()); - DONE; - } + if (xtensa_copy_incoming_a7 (operands, DImode)) + DONE; } }") @@ -1107,12 +1103,8 @@ && constantpool_mem_p (operands[1])))) operands[1] = force_reg (SFmode, operands[1]); - if (a7_overlap_mentioned_p (operands[1])) - { - emit_insn (gen_movsf_internal (operands[0], operands[1])); - emit_insn (gen_set_frame_ptr ()); - DONE; - } + if (xtensa_copy_incoming_a7 (operands, SFmode)) + DONE; } }") @@ -1195,12 +1187,8 @@ && !register_operand (operands[1], DFmode)) operands[1] = force_reg (DFmode, operands[1]); - if (a7_overlap_mentioned_p (operands[1])) - { - emit_insn (gen_movdf_internal (operands[0], operands[1])); - emit_insn (gen_set_frame_ptr ()); - DONE; - } + if (xtensa_copy_incoming_a7 (operands, DFmode)) + DONE; } }") -- 2.47.2