OSDN Git Service

* config/xtensa/xtensa-protos.h (xtensa_copy_incoming_a7): Declare.
authorbwilson <bwilson@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 22 Nov 2002 00:23:31 +0000 (00:23 +0000)
committerbwilson <bwilson@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 22 Nov 2002 00:23:31 +0000 (00:23 +0000)
        * 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@59364 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/xtensa/xtensa-protos.h
gcc/config/xtensa/xtensa.c
gcc/config/xtensa/xtensa.md

index e3672f9..ab62b50 100644 (file)
@@ -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.
index 051c81e..195d71d 100644 (file)
@@ -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 *));
index ae7c994..babb5b0 100644 (file)
@@ -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
index d4f8c84..5db5c0c 100644 (file)
          && !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;
     }
 }")
 
              && 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;
     }
 }")
 
          && !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;
     }
 }")