OSDN Git Service

Fix ICE with long double after float HFA.
authorwilson <wilson@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 18 Jan 2005 03:51:05 +0000 (03:51 +0000)
committerwilson <wilson@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 18 Jan 2005 03:51:05 +0000 (03:51 +0000)
PR target/19357
* config/ia64/ia64.md (movxf): Handle general register source.  Adjust
comment to document why.
* gcc.c-torture/compile/pr19357.c: New test.

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

gcc/ChangeLog
gcc/config/ia64/ia64.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/pr19357.c [new file with mode: 0644]

index 6ef223a..ec637b5 100644 (file)
@@ -1,3 +1,9 @@
+2005-01-17  James E Wilson  <wilson@specifixinc.com>
+
+       PR target/19357
+       * config/ia64/ia64.md (movxf): Handle general register source.  Adjust
+       comment to document why.
+
 2005-01-17  Richard Henderson  <rth@redhat.com>
 
        * config/i386/sse.md (smaxv4sf3_finite, sse_vmsmaxv4sf3_finite,
index c406a79..b22f49e 100644 (file)
   if (GET_CODE (op0) == SUBREG)
     op0 = SUBREG_REG (op0);
 
-  /* We must support XFmode loads into general registers for stdarg/vararg
-     and unprototyped calls.  We split them into DImode loads for convenience.
-     We don't need XFmode stores from general regs, because a stdarg/vararg
-     routine does a block store to memory of unnamed arguments.  */
+  /* We must support XFmode loads into general registers for stdarg/vararg,
+     unprototyped calls, and a rare case where a long double is passed as
+     an argument after a float HFA fills the FP registers.  We split them into
+     DImode loads for convenience.  We also need to support XFmode stores
+     for the last case.  This case does not happen for stdarg/vararg routines,
+     because we do a block store to memory of unnamed arguments.  */
 
   if (GET_CODE (op0) == REG && GR_REGNO_P (REGNO (op0)))
     {
          if (GET_CODE (op1) == SUBREG)
            op1 = SUBREG_REG (op1);
          else
-           /* ??? Maybe we should make a SUBREG here?  */
            op1 = gen_rtx_REG (TImode, REGNO (op1));
 
          emit_move_insn (gen_rtx_REG (TImode, REGNO (op0)), op1);
       abort ();
     }
 
+  if (GET_CODE (operands[1]) == REG && GR_REGNO_P (REGNO (operands[1])))
+    {
+      /* We're hoping to transform everything that deals with XFmode
+        quantities and GR registers early in the compiler.  */
+      if (no_new_pseudos)
+       abort ();
+
+      /* Op0 can't be a GR_REG here, as that case is handled above.
+        If op0 is a register, then we spill op1, so that we now have a
+        MEM operand.  This requires creating an XFmode subreg of a TImode reg
+        to force the spill.  */
+      if (register_operand (operands[0], XFmode))
+       {
+         rtx op1 = gen_rtx_REG (TImode, REGNO (operands[1]));
+         op1 = gen_rtx_SUBREG (XFmode, op1, 0);
+         operands[1] = spill_xfmode_operand (op1, 0);
+       }
+
+      else if (GET_CODE (operands[0]) == MEM)
+       {
+         rtx in[2];
+
+         in[WORDS_BIG_ENDIAN] = gen_rtx_REG (DImode, REGNO (operands[1]));
+         in[!WORDS_BIG_ENDIAN] = gen_rtx_REG (DImode, REGNO (operands[1]) + 1);
+
+         emit_move_insn (adjust_address (operands[0], DImode, 0), in[0]);
+         emit_move_insn (adjust_address (operands[0], DImode, 8), in[1]);
+         DONE;
+       }
+
+      else
+       abort ();
+    }
+
   if (! reload_in_progress && ! reload_completed)
     {
       operands[1] = spill_xfmode_operand (operands[1], 0);
index 9f39f00..5a5a3b8 100644 (file)
@@ -1,3 +1,8 @@
+2005-01-17  James E. Wilson  <wilson@specifixinc.com>
+
+       PR target/19357
+       * gcc.c-torture/compile/pr19357.c: New test.
+
 2005-01-17  Ian Lance Taylor  <ian@airs.com>
 
        PR c/5675
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr19357.c b/gcc/testsuite/gcc.c-torture/compile/pr19357.c
new file mode 100644 (file)
index 0000000..2dc26d7
--- /dev/null
@@ -0,0 +1,8 @@
+/* This generated an ICE for an ia64-linux target.  */
+struct f {
+  float f[8];
+};
+
+long double ftest(struct f arg1, long double arg2) {
+  return arg2;
+}