OSDN Git Service

2005-07-14 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 14 Jul 2005 07:46:23 +0000 (07:46 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 14 Jul 2005 07:46:23 +0000 (07:46 +0000)
PR middle-end/22347
* config/i386/i386-protos.h (ix86_function_value): Change
prototype to match new target hook.
* config/i386/i386.c (ix86_value_regno): Change prototype
to take extra type argument.
(TARGET_FUNCTION_VALUE): Define.
(ix86_function_ok_for_sibcall): Pass extra argument to
ix86_value_regno, check return slot rtx for exact match.
(ix86_function_value): Take extra parameter.  Dispatch to
ix86_value_regno with fndecl/fntype as provided.
(ix86_value_regno): Handle extra type argument.
* config/i386/i386.h (FUNCTION_VALUE): No longer define.

* testsuite/gcc.target/i386/sseregparm-3.c: New testcase.
* testsuite/gcc.target/i386/sseregparm-4.c: New testcase.
* testsuite/gcc.target/i386/sseregparm-5.c: New testcase.
* testsuite/gcc.target/i386/sseregparm-6.c: New testcase.
* testsuite/gcc.target/i386/sseregparm-7.c: New testcase.

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

gcc/ChangeLog
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.c
gcc/config/i386/i386.h
gcc/testsuite/gcc.target/i386/sseregparm-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/sseregparm-4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/sseregparm-5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/sseregparm-6.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/sseregparm-7.c [new file with mode: 0644]

index 126409f..b0ca4f9 100644 (file)
@@ -1,5 +1,26 @@
 2005-07-14  Richard Guenther  <rguenther@suse.de>
 
 2005-07-14  Richard Guenther  <rguenther@suse.de>
 
+       PR middle-end/22347
+       * config/i386/i386-protos.h (ix86_function_value): Change
+       prototype to match new target hook.
+       * config/i386/i386.c (ix86_value_regno): Change prototype
+       to take extra type argument.
+       (TARGET_FUNCTION_VALUE): Define.
+       (ix86_function_ok_for_sibcall): Pass extra argument to
+       ix86_value_regno, check return slot rtx for exact match.
+       (ix86_function_value): Take extra parameter.  Dispatch to
+       ix86_value_regno with fndecl/fntype as provided.
+       (ix86_value_regno): Handle extra type argument.
+       * config/i386/i386.h (FUNCTION_VALUE): No longer define.
+
+       * testsuite/gcc.target/i386/sseregparm-3.c: New testcase.
+       * testsuite/gcc.target/i386/sseregparm-4.c: New testcase.
+       * testsuite/gcc.target/i386/sseregparm-5.c: New testcase.
+       * testsuite/gcc.target/i386/sseregparm-6.c: New testcase.
+       * testsuite/gcc.target/i386/sseregparm-7.c: New testcase.
+
+2005-07-14  Richard Guenther  <rguenther@suse.de>
+
        * Makefile.in (explow.o, reg-stack.o): Depend on target.h.
        * calls.c (expand_call): Pass fntype to hard_function_value.
        (emit_library_call_value_1): Likewise.
        * Makefile.in (explow.o, reg-stack.o): Depend on target.h.
        * calls.c (expand_call): Pass fntype to hard_function_value.
        (emit_library_call_value_1): Likewise.
index 15c52b0..957876c 100644 (file)
@@ -206,7 +206,7 @@ extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree);
 extern rtx function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
 extern void function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
                                  tree, int);
 extern rtx function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
 extern void function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
                                  tree, int);
-extern rtx ix86_function_value (tree, tree);
+extern rtx ix86_function_value (tree, tree, bool);
 #endif
 
 #endif
 #endif
 
 #endif
index da2b8e6..17d8ea0 100644 (file)
@@ -891,7 +891,7 @@ static int ix86_function_regparm (tree, tree);
 const struct attribute_spec ix86_attribute_table[];
 static bool ix86_function_ok_for_sibcall (tree, tree);
 static tree ix86_handle_cconv_attribute (tree *, tree, tree, int, bool *);
 const struct attribute_spec ix86_attribute_table[];
 static bool ix86_function_ok_for_sibcall (tree, tree);
 static tree ix86_handle_cconv_attribute (tree *, tree, tree, int, bool *);
-static int ix86_value_regno (enum machine_mode, tree);
+static int ix86_value_regno (enum machine_mode, tree, tree);
 static bool contains_128bit_aligned_vector_p (tree);
 static rtx ix86_struct_value_rtx (tree, int);
 static bool ix86_ms_bitfield_layout_p (tree);
 static bool contains_128bit_aligned_vector_p (tree);
 static rtx ix86_struct_value_rtx (tree, int);
 static bool ix86_ms_bitfield_layout_p (tree);
@@ -1085,6 +1085,9 @@ static void init_ext_80387_constants (void);
 #undef TARGET_STACK_PROTECT_FAIL
 #define TARGET_STACK_PROTECT_FAIL ix86_stack_protect_fail
 
 #undef TARGET_STACK_PROTECT_FAIL
 #define TARGET_STACK_PROTECT_FAIL ix86_stack_protect_fail
 
+#undef TARGET_FUNCTION_VALUE
+#define TARGET_FUNCTION_VALUE ix86_function_value
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 \f
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 \f
@@ -1705,6 +1708,7 @@ static bool
 ix86_function_ok_for_sibcall (tree decl, tree exp)
 {
   tree func;
 ix86_function_ok_for_sibcall (tree decl, tree exp)
 {
   tree func;
+  rtx a, b;
 
   /* If we are generating position-independent code, we cannot sibcall
      optimize any indirect call, or a direct call to a global function,
 
   /* If we are generating position-independent code, we cannot sibcall
      optimize any indirect call, or a direct call to a global function,
@@ -1715,16 +1719,23 @@ ix86_function_ok_for_sibcall (tree decl, tree exp)
   if (decl)
     func = decl;
   else
   if (decl)
     func = decl;
   else
-    func = NULL;
+    {
+      func = TREE_TYPE (TREE_OPERAND (exp, 0));
+      if (POINTER_TYPE_P (func))
+        func = TREE_TYPE (func);
+    }
 
 
-  /* If we are returning floats on the 80387 register stack, we cannot
+  /* Check that the return value locations are the same.  Like
+     if we are returning floats on the 80387 register stack, we cannot
      make a sibcall from a function that doesn't return a float to a
      function that does or, conversely, from a function that does return
      a float to a function that doesn't; the necessary stack adjustment
      make a sibcall from a function that doesn't return a float to a
      function that does or, conversely, from a function that does return
      a float to a function that doesn't; the necessary stack adjustment
-     would not be executed.  */
-  if (STACK_REG_P (ix86_function_value (TREE_TYPE (exp), func))
-      != STACK_REG_P (ix86_function_value (TREE_TYPE (DECL_RESULT (cfun->decl)),
-                                          cfun->decl)))
+     would not be executed.  This is also the place we notice
+     differences in the return value ABI.  */
+  a = ix86_function_value (TREE_TYPE (exp), func, false);
+  b = ix86_function_value (TREE_TYPE (DECL_RESULT (cfun->decl)),
+                          cfun->decl, false);
+  if (! rtx_equal_p (a, b))
     return false;
 
   /* If this call is indirect, we'll need to be able to use a call-clobbered
     return false;
 
   /* If this call is indirect, we'll need to be able to use a call-clobbered
@@ -3189,7 +3200,8 @@ ix86_function_value_regno_p (int regno)
    If the precise function being called is known, FUNC is its FUNCTION_DECL;
    otherwise, FUNC is 0.  */
 rtx
    If the precise function being called is known, FUNC is its FUNCTION_DECL;
    otherwise, FUNC is 0.  */
 rtx
-ix86_function_value (tree valtype, tree func)
+ix86_function_value (tree valtype, tree fntype_or_decl,
+                    bool outgoing ATTRIBUTE_UNUSED)
 {
   enum machine_mode natmode = type_natural_mode (valtype);
 
 {
   enum machine_mode natmode = type_natural_mode (valtype);
 
@@ -3205,7 +3217,15 @@ ix86_function_value (tree valtype, tree func)
       return ret;
     }
   else
       return ret;
     }
   else
-    return gen_rtx_REG (TYPE_MODE (valtype), ix86_value_regno (natmode, func));
+    {
+      tree fn = NULL_TREE, fntype;
+      if (fntype_or_decl
+         && DECL_P (fntype_or_decl))
+        fn = fntype_or_decl;
+      fntype = fn ? TREE_TYPE (fn) : fntype_or_decl;
+      return gen_rtx_REG (TYPE_MODE (valtype),
+                         ix86_value_regno (natmode, fn, fntype));
+    }
 }
 
 /* Return false iff type is returned in memory.  */
 }
 
 /* Return false iff type is returned in memory.  */
@@ -3321,13 +3341,13 @@ ix86_libcall_value (enum machine_mode mode)
        }
     }
   else
        }
     }
   else
-    return gen_rtx_REG (mode, ix86_value_regno (mode, NULL));
+    return gen_rtx_REG (mode, ix86_value_regno (mode, NULL, NULL));
 }
 
 /* Given a mode, return the register to use for a return value.  */
 
 static int
 }
 
 /* Given a mode, return the register to use for a return value.  */
 
 static int
-ix86_value_regno (enum machine_mode mode, tree func)
+ix86_value_regno (enum machine_mode mode, tree func, tree fntype)
 {
   gcc_assert (!TARGET_64BIT);
 
 {
   gcc_assert (!TARGET_64BIT);
 
@@ -3347,9 +3367,10 @@ ix86_value_regno (enum machine_mode mode, tree func)
 
   /* Floating point return values in %st(0), except for local functions when
      SSE math is enabled or for functions with sseregparm attribute.  */
 
   /* Floating point return values in %st(0), except for local functions when
      SSE math is enabled or for functions with sseregparm attribute.  */
-  if (func && (mode == SFmode || mode == DFmode))
+  if ((func || fntype)
+      && (mode == SFmode || mode == DFmode))
     {
     {
-      int sse_level = ix86_function_sseregparm (TREE_TYPE (func), func);
+      int sse_level = ix86_function_sseregparm (fntype, func);
       if ((sse_level >= 1 && mode == SFmode)
          || (sse_level == 2 && mode == DFmode))
         return FIRST_SSE_REG;
       if ((sse_level >= 1 && mode == SFmode)
          || (sse_level == 2 && mode == DFmode))
         return FIRST_SSE_REG;
index 11e0a3c..7a54cba 100644 (file)
@@ -1433,13 +1433,6 @@ enum reg_class
 #define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, SIZE) \
   ix86_return_pops_args ((FUNDECL), (FUNTYPE), (SIZE))
 
 #define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, SIZE) \
   ix86_return_pops_args ((FUNDECL), (FUNTYPE), (SIZE))
 
-/* Define how to find the value returned by a function.
-   VALTYPE is the data type of the value (as a tree).
-   If the precise function being called is known, FUNC is its FUNCTION_DECL;
-   otherwise, FUNC is 0.  */
-#define FUNCTION_VALUE(VALTYPE, FUNC)  \
-   ix86_function_value (VALTYPE, FUNC)
-
 #define FUNCTION_VALUE_REGNO_P(N) \
   ix86_function_value_regno_p (N)
 
 #define FUNCTION_VALUE_REGNO_P(N) \
   ix86_function_value_regno_p (N)
 
diff --git a/gcc/testsuite/gcc.target/i386/sseregparm-3.c b/gcc/testsuite/gcc.target/i386/sseregparm-3.c
new file mode 100644 (file)
index 0000000..9ee82af
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-msse2 -O2" } */
+/* { dg-require-effective-target ilp32 } */
+
+/* Make sure we know that mysinfp returns in %xmm0.  */
+
+double __attribute__((sseregparm)) mysin(double x);
+double __attribute__((sseregparm)) (*mysinfp)(double) = mysin;
+double bar(double x)
+{
+  return 1.0+mysinfp(x);
+}
+
+/* { dg-final { scan-assembler "fldl" } } */
diff --git a/gcc/testsuite/gcc.target/i386/sseregparm-4.c b/gcc/testsuite/gcc.target/i386/sseregparm-4.c
new file mode 100644 (file)
index 0000000..a29cf06
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-msse2 -O2" } */
+/* { dg-require-effective-target ilp32 } */
+
+/* Make sure we know that mysinfp returns in %xmm0.  */
+
+double __attribute__((sseregparm)) mysin(double x);
+double __attribute__((sseregparm)) (*mysinfp)(double) = mysin;
+double bar(double x)
+{
+  return mysinfp(x);
+}
+
+/* { dg-final { scan-assembler "fldl" } } */
diff --git a/gcc/testsuite/gcc.target/i386/sseregparm-5.c b/gcc/testsuite/gcc.target/i386/sseregparm-5.c
new file mode 100644 (file)
index 0000000..7423722
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-msse2 -O2" } */
+/* { dg-require-effective-target ilp32 } */
+
+/* Make sure we know that mysinfp returns in %xmm0.  */
+
+double __attribute__((sseregparm)) mysin(void);
+double __attribute__((sseregparm)) (*mysinfp)(void) = mysin;
+double bar(double x)
+{
+  return mysinfp();
+}
+
+/* { dg-final { scan-assembler "fldl" } } */
diff --git a/gcc/testsuite/gcc.target/i386/sseregparm-6.c b/gcc/testsuite/gcc.target/i386/sseregparm-6.c
new file mode 100644 (file)
index 0000000..6203b6b
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-msse2 -O2" } */
+/* { dg-require-effective-target ilp32 } */
+
+/* Make sure we know that mysinfp returns in %xmm0.  */
+
+double __attribute__((sseregparm)) mysin(double x);
+double bar(double x)
+{
+  return mysin(x);
+}
+
+/* { dg-final { scan-assembler "fldl" } } */
diff --git a/gcc/testsuite/gcc.target/i386/sseregparm-7.c b/gcc/testsuite/gcc.target/i386/sseregparm-7.c
new file mode 100644 (file)
index 0000000..61267df
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-msse2 -O2" } */
+/* { dg-require-effective-target ilp32 } */
+
+/* Make sure we know that mysinfp returns in %xmm0.  */
+
+double __attribute__((sseregparm)) mysin(void);
+double bar(double x)
+{
+  return mysin();
+}
+
+/* { dg-final { scan-assembler "fldl" } } */