re PR middle-end/24003 (17 ACATS regressions (fixed point or decimal artihmetic))
authorEric Botcazou <ebotcazou@adacore.com>
Sun, 13 Nov 2005 09:55:11 +0000 (09:55 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Sun, 13 Nov 2005 09:55:11 +0000 (09:55 +0000)
PR middle-end/24003
* calls.c (expand_call): If TARGET is a MEM and some part of the
argument area has been saved, force TARGET to a register.

Co-Authored-By: Ian Lance Taylor <ian@airs.com>
From-SVN: r106860

gcc/ChangeLog
gcc/calls.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/nested-calls-1.c [new file with mode: 0644]

index 85753792d852b168ff4f5de834c334ef66688c35..dcd74dae752c2b90e2a802a5e916f8a6b1ddb18d 100644 (file)
@@ -1,3 +1,10 @@
+2005-11-13  Eric Botcazou  <ebotcazou@adacore.com>
+            Ian Lance Taylor  <ian@airs.com>
+
+       PR middle-end/24003
+       * calls.c (expand_call): If TARGET is a MEM and some part of the
+       argument area has been saved, force TARGET to a register.
+
 2005-11-13  Razya Ladelsky <razya@il.ibm.com>
 
         * ipa-prop.c (ipa_callsite_compute_param ): Removed obsolete type 
index 920c81575e0a1830cc1d40c43277d4e8bea6e832..2cc15fc2e819e7087158258cddff0ffbc296354f 100644 (file)
@@ -2857,6 +2857,8 @@ expand_call (tree exp, rtx target, int ignore)
               && GET_MODE (target) == TYPE_MODE (TREE_TYPE (exp))
               && GET_MODE (target) == GET_MODE (valreg))
        {
+         bool may_overlap = false;
+
          /* We have to copy a return value in a CLASS_LIKELY_SPILLED hard
             reg to a plain register.  */
          if (REG_P (valreg)
@@ -2865,19 +2867,40 @@ expand_call (tree exp, rtx target, int ignore)
              && !(REG_P (target) && !HARD_REGISTER_P (target)))
            valreg = copy_to_reg (valreg);
 
-         /* TARGET and VALREG cannot be equal at this point because the
-            latter would not have REG_FUNCTION_VALUE_P true, while the
-            former would if it were referring to the same register.
-
-            If they refer to the same register, this move will be a no-op,
-            except when function inlining is being done.  */
-         emit_move_insn (target, valreg);
+         /* If TARGET is a MEM in the argument area, and we have
+            saved part of the argument area, then we can't store
+            directly into TARGET as it may get overwritten when we
+            restore the argument save area below.  Don't work too
+            hard though and simply force TARGET to a register if it
+            is a MEM; the optimizer is quite likely to sort it out.  */
+         if (ACCUMULATE_OUTGOING_ARGS && pass && MEM_P (target))
+           for (i = 0; i < num_actuals; i++)
+             if (args[i].save_area)
+               {
+                 may_overlap = true;
+                 break;
+               }
 
-         /* If we are setting a MEM, this code must be executed.  Since it is
-            emitted after the call insn, sibcall optimization cannot be
-            performed in that case.  */
-         if (MEM_P (target))
-           sibcall_failure = 1;
+         if (may_overlap)
+           target = copy_to_reg (valreg);
+         else
+           {
+             /* TARGET and VALREG cannot be equal at this point
+                because the latter would not have
+                REG_FUNCTION_VALUE_P true, while the former would if
+                it were referring to the same register.
+
+                If they refer to the same register, this move will be
+                a no-op, except when function inlining is being
+                done.  */
+             emit_move_insn (target, valreg);
+
+             /* If we are setting a MEM, this code must be executed.
+                Since it is emitted after the call insn, sibcall
+                optimization cannot be performed in that case.  */
+             if (MEM_P (target))
+               sibcall_failure = 1;
+           }
        }
       else if (TYPE_MODE (TREE_TYPE (exp)) == BLKmode)
        {
index ae3265f36e1c7b4e0c1734f4aada24eb0186738f..e6f9757c0ea58ba8cc700aae858a205831a039d5 100644 (file)
@@ -1,3 +1,7 @@
+2005-11-13  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gcc.dg/nested-calls-1.c: New test.
+
 2005-11-13  Francois-Xavier Coudert  <coudert@clipper.ens.fr>
 
        * gfortran.dg/complex_intrinsic_1.f90: New test.
diff --git a/gcc/testsuite/gcc.dg/nested-calls-1.c b/gcc/testsuite/gcc.dg/nested-calls-1.c
new file mode 100644 (file)
index 0000000..b3f08be
--- /dev/null
@@ -0,0 +1,42 @@
+/* PR middle-end/24003 */
+/* Contributed by Eric Botcazou <ebotcazou@adacore.com> */
+
+/* { dg-do run } */
+/* { dg-options "-std=c99 -O -fno-inline" } */
+/* { dg-options "-std=c99 -O -fno-inline -mtune=i686" { target { i?86-*-* && ilp32 } } } */
+
+#include <limits.h>
+
+typedef unsigned long uns32_t;
+typedef unsigned long long uns64_t;
+
+extern void abort(void);
+
+uns32_t lo (uns64_t p)
+{
+  return (uns32_t)p;
+}
+
+uns64_t concat (uns32_t p1, uns32_t p2)
+{
+#if LLONG_MAX > 2147483647L
+  return ((uns64_t)p1 << 32) | p2;
+#else
+  return 0;
+#endif
+}
+
+uns64_t lshift32 (uns64_t p1, uns32_t p2)
+{
+  return concat (lo (p1), p2);
+}
+
+int main(void)
+{
+#if LLONG_MAX > 2147483647L
+  if (lshift32 (0xFFFFFFFF12345678ULL, 0x90ABCDEFUL) != 0x1234567890ABCDEFULL)
+    abort ();
+#endif
+
+  return 0;
+}