diff options
author | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-07-14 07:46:23 +0000 |
---|---|---|
committer | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-07-14 07:46:23 +0000 |
commit | 70e9546799274a3efa8e96e77dc681a62082bb9e (patch) | |
tree | e23fe4eb2d1a570d31a48f2d2648f10e107f2e10 /gcc | |
parent | 46b3ff29296568882d5ec4f6796ae9a28879971b (diff) | |
download | gcc-70e9546799274a3efa8e96e77dc681a62082bb9e.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@102014 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 21 | ||||
-rw-r--r-- | gcc/config/i386/i386-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 47 | ||||
-rw-r--r-- | gcc/config/i386/i386.h | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/sseregparm-3.c | 14 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/sseregparm-4.c | 14 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/sseregparm-5.c | 14 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/sseregparm-6.c | 13 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/sseregparm-7.c | 13 |
9 files changed, 124 insertions, 21 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 126409f6247..b0ca4f999ed 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,26 @@ 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. diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 15c52b090c2..957876c4c7b 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -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 ix86_function_value (tree, tree); +extern rtx ix86_function_value (tree, tree, bool); #endif #endif diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index da2b8e61acc..17d8ea0b0c5 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -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 *); -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); @@ -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_FUNCTION_VALUE +#define TARGET_FUNCTION_VALUE ix86_function_value + struct gcc_target targetm = TARGET_INITIALIZER; @@ -1705,6 +1708,7 @@ static bool 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, @@ -1715,16 +1719,23 @@ ix86_function_ok_for_sibcall (tree decl, tree exp) 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 - 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 @@ -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 -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); @@ -3205,7 +3217,15 @@ ix86_function_value (tree valtype, tree func) 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. */ @@ -3321,13 +3341,13 @@ ix86_libcall_value (enum machine_mode mode) } } 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 -ix86_value_regno (enum machine_mode mode, tree func) +ix86_value_regno (enum machine_mode mode, tree func, tree fntype) { 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. */ - 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; diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 11e0a3c14cd..7a54cba9e84 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -1433,13 +1433,6 @@ enum reg_class #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) diff --git a/gcc/testsuite/gcc.target/i386/sseregparm-3.c b/gcc/testsuite/gcc.target/i386/sseregparm-3.c new file mode 100644 index 00000000000..9ee82af44ae --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/sseregparm-3.c @@ -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 index 00000000000..a29cf06bf5c --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/sseregparm-4.c @@ -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 index 00000000000..7423722d694 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/sseregparm-5.c @@ -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 index 00000000000..6203b6b5971 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/sseregparm-6.c @@ -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 index 00000000000..61267df9853 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/sseregparm-7.c @@ -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" } } */ |