OSDN Git Service

* config/xtensa/xtensa.c (xtensa_copy_incoming_a7): Remove SUBREG
authorbwilson <bwilson@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 27 Jan 2004 20:24:59 +0000 (20:24 +0000)
committerbwilson <bwilson@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 27 Jan 2004 20:24:59 +0000 (20:24 +0000)
on CQImode and CHImode incoming arguments in register a7.
(function_arg): Wrap BLKmode argument in register a7 in a PARALLEL.
* config/xtensa/xtensa.h (BLOCK_REG_PADDING): Define.
* config/xtensa/xtensa.md (movdi, movdf): Only call force_reg or
xtensa_copy_incoming_a7 before reload.

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

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

index fa55296..2bd5d7d 100644 (file)
@@ -1,3 +1,12 @@
+2004-01-27  Bob Wilson  <bob.wilson@acm.org>
+       
+       * config/xtensa/xtensa.c (xtensa_copy_incoming_a7): Remove SUBREG
+       on CQImode and CHImode incoming arguments in register a7.
+       (function_arg): Wrap BLKmode argument in register a7 in a PARALLEL.
+       * config/xtensa/xtensa.h (BLOCK_REG_PADDING): Define.
+       * config/xtensa/xtensa.md (movdi, movdf): Only call force_reg or
+       xtensa_copy_incoming_a7 before reload.
+       
 2004-01-27  J"orn Rennecke <joern.rennecke@superh.com>
 
        * coverage.c (get_coverage_counts): Give a different message
index d508728..7e7b03a 100644 (file)
@@ -1327,7 +1327,27 @@ xtensa_copy_incoming_a7 (rtx *operands, enum machine_mode mode)
   if (a7_overlap_mentioned_p (operands[1])
       && !cfun->machine->incoming_a7_copied)
     {
-      rtx mov;
+      rtx mov, src;
+
+      /* Despite defining SPLIT_COMPLEX_ARGS, complex function
+        arguments may still appear if they are wrapped in a struct.
+        For CQImode and CHImode arguments, this results in a move
+        with a source operand of the form: "(subreg:SI (reg:CHI a7)
+        0)".  The subreg is later removed by the reload pass,
+        resulting in the RTL for a7 being regenerated using
+        hard_frame_pointer_rtx, and making it impossible for us to
+        distinguish the function argument.  Detect this here when
+        generating the RTL and remove the subreg immediately so that
+        reload won't mess it up.  */
+      src = operands[1];
+      if (GET_CODE (src) == SUBREG
+         && GET_CODE (SUBREG_REG (src)) == REG
+         && REGNO (SUBREG_REG (src)) == A7_REG
+         && SUBREG_BYTE (src) == 0
+         && (GET_MODE (SUBREG_REG (src)) == CHImode
+             || GET_MODE (SUBREG_REG (src)) == CQImode))
+       operands[1] = gen_raw_REG (mode, A7_REG);
+
       switch (mode)
        {
        case DFmode:
@@ -1773,11 +1793,15 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
      rtx that is not equal to hard_frame_pointer_rtx.  For multi-word
      modes for which we don't define move patterns, we can't control
      the expansion unless we explicitly list the individual registers
-     in a PARALLEL.  */
-
-  if (mode != DImode && mode != DFmode
-      && regno < A7_REG
-      && regno + words > A7_REG)
+     in a PARALLEL.  Likewise, a single-word BLKmode argument passed
+     in a7 must be wrapped in a PARALLEL to avoid code that takes the
+     register number and builds a new REG.  This is extremely fragile
+     but seems to be the best solution for now.  */
+
+  if ((mode != DImode && mode != DFmode
+       && regno < A7_REG
+       && regno + words > A7_REG)
+      || (mode == BLKmode && regno == A7_REG))
     {
       rtx result;
       int n;
index f650bcd..677a526 100644 (file)
@@ -799,6 +799,12 @@ typedef struct xtensa_args {
 /* Pass complex arguments independently.  */
 #define SPLIT_COMPLEX_ARGS 1
 
+/* Because Xtensa's function_arg() wraps BLKmode arguments passed in
+   a7 inside a PARALLEL, BLOCK_REG_PADDING needs to be defined
+   to get emit_group_store to do the right thing.  */
+#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
+  FUNCTION_ARG_PADDING (MODE, TYPE)
+
 /* Profiling Xtensa code is typically done with the built-in profiling
    feature of Tensilica's instruction set simulator, which does not
    require any compiler support.  Profiling code on a real (i.e.,
index 01ec40d..d0c4474 100644 (file)
@@ -1,5 +1,5 @@
 ;; GCC machine description for Tensilica's Xtensa architecture.
-;; Copyright (C) 2001 Free Software Foundation, Inc.
+;; Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 ;; Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica.
 
 ;; This file is part of GCC.
   if (CONSTANT_P (operands[1]) && !TARGET_CONST16)
     operands[1] = force_const_mem (DImode, operands[1]);
 
-  if (!register_operand (operands[0], DImode)
-      && !register_operand (operands[1], DImode))
-    operands[1] = force_reg (DImode, operands[1]);
+  if (!(reload_in_progress | reload_completed))
+    {
+      if (!register_operand (operands[0], DImode)
+         && !register_operand (operands[1], DImode))
+       operands[1] = force_reg (DImode, operands[1]);
 
-  if (xtensa_copy_incoming_a7 (operands, DImode))
-    DONE;
+      if (xtensa_copy_incoming_a7 (operands, DImode))
+       DONE;
+    }
 })
 
 (define_insn_and_split "movdi_internal"
   if (CONSTANT_P (operands[1]) && !TARGET_CONST16)
     operands[1] = force_const_mem (DFmode, operands[1]);
 
-  if (!register_operand (operands[0], DFmode)
-      && !register_operand (operands[1], DFmode))
-    operands[1] = force_reg (DFmode, operands[1]);
+  if (!(reload_in_progress | reload_completed))
+    {
+      if (!register_operand (operands[0], DFmode)
+         && !register_operand (operands[1], DFmode))
+       operands[1] = force_reg (DFmode, operands[1]);
 
-  if (xtensa_copy_incoming_a7 (operands, DFmode))
-    DONE;
+      if (xtensa_copy_incoming_a7 (operands, DFmode))
+       DONE;
+    }
 })
 
 (define_insn_and_split "movdf_internal"