aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Wilson <bob.wilson@acm.org>2002-11-22 00:23:31 +0000
committerBob Wilson <bwilson@gcc.gnu.org>2002-11-22 00:23:31 +0000
commit58db834b27756ef397b96597ce0a541d8ae89dec (patch)
tree14dbde98b223724f8db35d54e3274299e7aed2f6
parentc05dbe8131d5d1f1b4cfb1a1f08af5c9e79942e1 (diff)
downloadgcc-58db834b27756ef397b96597ce0a541d8ae89dec.zip
gcc-58db834b27756ef397b96597ce0a541d8ae89dec.tar.gz
gcc-58db834b27756ef397b96597ce0a541d8ae89dec.tar.bz2
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: r59364
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/config/xtensa/xtensa-protos.h1
-rw-r--r--gcc/config/xtensa/xtensa.c110
-rw-r--r--gcc/config/xtensa/xtensa.md24
4 files changed, 87 insertions, 57 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e3672f9..ab62b50 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2002-11-21 Bob Wilson <bob.wilson@acm.org>
+
+ * 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.
+
Thu Nov 21 23:52:04 CET 2002 Jan Hubicka <jH@suse.cz>
* i386-protos.h (x86_64_sign_extended_value): Fix prototype.
diff --git a/gcc/config/xtensa/xtensa-protos.h b/gcc/config/xtensa/xtensa-protos.h
index 051c81e..195d71d 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 ae7c994..babb5b0 100644
--- a/gcc/config/xtensa/xtensa.c
+++ b/gcc/config/xtensa/xtensa.c
@@ -90,6 +90,7 @@ const char *xtensa_st_opcodes[(int) MAX_MACHINE_MODE];
struct machine_function GTY(())
{
int accesses_prev_frame;
+ bool incoming_a7_copied;
};
/* Vector, indexed by hard register number, which contains 1 for a
@@ -1275,45 +1276,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
@@ -1345,6 +1309,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 d4f8c84..5db5c0c 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;
}
}")
@@ -1193,12 +1185,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;
}
}")