re PR target/30120 (silent miscompilation of argument passing)
PR target/30120 Revert: 2006-11-15 Uros Bizjak <ubizjak@gmail.com> * config/i386/i386.opt: New target option -mx87regparm. * config/i386/i386.h (struct ix86_args): Add x87_nregs, x87_regno, float_in_x87: Add new variables. mmx_words, sse_words: Remove. (X87_REGPARM_MAX): Define. * config/i386/i386.c (override_options): Error out for -mx87regparm but no 80387 support. (ix86_attribute_table): Add x87regparm. (ix86_handle_cconv_attribute): Update comments for x87regparm. (ix86_comp_type_attributes): Check for mismatched x87regparm types. (ix86_function_x87regparm): New function. (ix86_function_arg_regno_p): Add X87_REGPARM_MAX 80387 floating point registers. (init_cumulative_args): Initialize x87_nregs and float_in_x87 variables. (function_arg_advance): Process x87_nregs and x87_regno when floating point argument is to be passed in 80387 register. (function_arg): Pass XFmode arguments in 80387 registers for local functions. Pass SFmode and DFmode arguments to local functions in 80387 registers when flag_unsafe_math_optimizations is set. * reg-stack.c (convert_regs_entry): Disable NaN load for stack registers that are used for argument passing. * doc/extend.texi: Document x87regparm function attribute. * doc/invoke.texi: Document -mx87regparm. testsuite/ChangeLog: PR target/30120 * gcc.target/i386/pr30120.c: New test. Revert: 2006-11-15 Uros Bizjak <ubizjak@gmail.com> * gcc.target/i386/x87regparm-1.c: New test. * gcc.target/i386/x87regparm-2.c: New test. * gcc.target/i386/x87regparm-3.c: New test. * gcc.target/i386/x87regparm-4.c: New test. From-SVN: r119734
This commit is contained in:
parent
c3f824ce13
commit
fa283935de
@ -1,3 +1,37 @@
|
||||
2006-12-11 Uros Bizjak <ubizjak@gmail.com>
|
||||
|
||||
PR target/30120
|
||||
Revert:
|
||||
2006-11-15 Uros Bizjak <ubizjak@gmail.com>
|
||||
|
||||
* config/i386/i386.opt: New target option -mx87regparm.
|
||||
|
||||
* config/i386/i386.h (struct ix86_args): Add x87_nregs, x87_regno,
|
||||
float_in_x87: Add new variables. mmx_words, sse_words: Remove.
|
||||
(X87_REGPARM_MAX): Define.
|
||||
|
||||
* config/i386/i386.c (override_options): Error out for
|
||||
-mx87regparm but no 80387 support.
|
||||
(ix86_attribute_table): Add x87regparm.
|
||||
(ix86_handle_cconv_attribute): Update comments for x87regparm.
|
||||
(ix86_comp_type_attributes): Check for mismatched x87regparm types.
|
||||
(ix86_function_x87regparm): New function.
|
||||
(ix86_function_arg_regno_p): Add X87_REGPARM_MAX 80387 floating
|
||||
point registers.
|
||||
(init_cumulative_args): Initialize x87_nregs and float_in_x87
|
||||
variables.
|
||||
(function_arg_advance): Process x87_nregs and x87_regno when
|
||||
floating point argument is to be passed in 80387 register.
|
||||
(function_arg): Pass XFmode arguments in 80387 registers for local
|
||||
functions. Pass SFmode and DFmode arguments to local functions
|
||||
in 80387 registers when flag_unsafe_math_optimizations is set.
|
||||
|
||||
* reg-stack.c (convert_regs_entry): Disable NaN load for
|
||||
stack registers that are used for argument passing.
|
||||
|
||||
* doc/extend.texi: Document x87regparm function attribute.
|
||||
* doc/invoke.texi: Document -mx87regparm.
|
||||
|
||||
2006-12-11 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
Move all varpool routines out of cgraph/cgraphunit to varpool.c
|
||||
|
@ -2149,11 +2149,6 @@ override_options (void)
|
||||
ix86_preferred_stack_boundary = (1 << i) * BITS_PER_UNIT;
|
||||
}
|
||||
|
||||
/* Accept -mx87regparm only if 80387 support is enabled. */
|
||||
if (TARGET_X87REGPARM
|
||||
&& ! TARGET_80387)
|
||||
error ("-mx87regparm used without 80387 enabled");
|
||||
|
||||
/* Accept -msseregparm only if at least SSE support is enabled. */
|
||||
if (TARGET_SSEREGPARM
|
||||
&& ! TARGET_SSE)
|
||||
@ -2460,9 +2455,6 @@ const struct attribute_spec ix86_attribute_table[] =
|
||||
/* Regparm attribute specifies how many integer arguments are to be
|
||||
passed in registers. */
|
||||
{ "regparm", 1, 1, false, true, true, ix86_handle_cconv_attribute },
|
||||
/* X87regparm attribute says we are passing floating point arguments
|
||||
in 80387 registers. */
|
||||
{ "x87regparm", 0, 0, false, true, true, ix86_handle_cconv_attribute },
|
||||
/* Sseregparm attribute says we are using x86_64 calling conventions
|
||||
for FP arguments. */
|
||||
{ "sseregparm", 0, 0, false, true, true, ix86_handle_cconv_attribute },
|
||||
@ -2565,8 +2557,8 @@ ix86_function_ok_for_sibcall (tree decl, tree exp)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Handle "cdecl", "stdcall", "fastcall", "regparm", "x87regparm"
|
||||
and "sseregparm" calling convention attributes;
|
||||
/* Handle "cdecl", "stdcall", "fastcall", "regparm" and "sseregparm"
|
||||
calling convention attributes;
|
||||
arguments as in struct attribute_spec.handler. */
|
||||
|
||||
static tree
|
||||
@ -2631,8 +2623,7 @@ ix86_handle_cconv_attribute (tree *node, tree name,
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Can combine fastcall with stdcall (redundant), x87regparm
|
||||
and sseregparm. */
|
||||
/* Can combine fastcall with stdcall (redundant) and sseregparm. */
|
||||
if (is_attribute_p ("fastcall", name))
|
||||
{
|
||||
if (lookup_attribute ("cdecl", TYPE_ATTRIBUTES (*node)))
|
||||
@ -2649,8 +2640,8 @@ ix86_handle_cconv_attribute (tree *node, tree name,
|
||||
}
|
||||
}
|
||||
|
||||
/* Can combine stdcall with fastcall (redundant), regparm,
|
||||
x87regparm and sseregparm. */
|
||||
/* Can combine stdcall with fastcall (redundant), regparm and
|
||||
sseregparm. */
|
||||
else if (is_attribute_p ("stdcall", name))
|
||||
{
|
||||
if (lookup_attribute ("cdecl", TYPE_ATTRIBUTES (*node)))
|
||||
@ -2663,7 +2654,7 @@ ix86_handle_cconv_attribute (tree *node, tree name,
|
||||
}
|
||||
}
|
||||
|
||||
/* Can combine cdecl with regparm, x87regparm and sseregparm. */
|
||||
/* Can combine cdecl with regparm and sseregparm. */
|
||||
else if (is_attribute_p ("cdecl", name))
|
||||
{
|
||||
if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (*node)))
|
||||
@ -2676,7 +2667,7 @@ ix86_handle_cconv_attribute (tree *node, tree name,
|
||||
}
|
||||
}
|
||||
|
||||
/* Can combine x87regparm or sseregparm with all attributes. */
|
||||
/* Can combine sseregparm with all attributes. */
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
@ -2701,11 +2692,6 @@ ix86_comp_type_attributes (tree type1, tree type2)
|
||||
!= ix86_function_regparm (type2, NULL)))
|
||||
return 0;
|
||||
|
||||
/* Check for mismatched x87regparm types. */
|
||||
if (!lookup_attribute ("x87regparm", TYPE_ATTRIBUTES (type1))
|
||||
!= !lookup_attribute ("x87regparm", TYPE_ATTRIBUTES (type2)))
|
||||
return 0;
|
||||
|
||||
/* Check for mismatched sseregparm types. */
|
||||
if (!lookup_attribute ("sseregparm", TYPE_ATTRIBUTES (type1))
|
||||
!= !lookup_attribute ("sseregparm", TYPE_ATTRIBUTES (type2)))
|
||||
@ -2794,48 +2780,6 @@ ix86_function_regparm (tree type, tree decl)
|
||||
return regparm;
|
||||
}
|
||||
|
||||
/* Return 1 if we can pass up to X87_REGPARM_MAX floating point
|
||||
arguments in x87 registers for a function with the indicated
|
||||
TYPE and DECL. DECL may be NULL when calling function indirectly
|
||||
or considering a libcall. For local functions, return 2.
|
||||
Otherwise return 0. */
|
||||
|
||||
static int
|
||||
ix86_function_x87regparm (tree type, tree decl)
|
||||
{
|
||||
/* Use x87 registers to pass floating point arguments if requested
|
||||
by the x87regparm attribute. */
|
||||
if (TARGET_X87REGPARM
|
||||
|| (type
|
||||
&& lookup_attribute ("x87regparm", TYPE_ATTRIBUTES (type))))
|
||||
{
|
||||
if (!TARGET_80387)
|
||||
{
|
||||
if (decl)
|
||||
error ("Calling %qD with attribute x87regparm without "
|
||||
"80387 enabled", decl);
|
||||
else
|
||||
error ("Calling %qT with attribute x87regparm without "
|
||||
"80387 enabled", type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* For local functions, pass up to X87_REGPARM_MAX floating point
|
||||
arguments in x87 registers. */
|
||||
if (!TARGET_64BIT && decl
|
||||
&& flag_unit_at_a_time && !profile_flag)
|
||||
{
|
||||
struct cgraph_local_info *i = cgraph_local_info (decl);
|
||||
if (i && i->local)
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return 1 or 2, if we can pass up to SSE_REGPARM_MAX SFmode (1) and
|
||||
DFmode (2) arguments in SSE registers for a function with the
|
||||
indicated TYPE and DECL. DECL may be NULL when calling function
|
||||
@ -2955,8 +2899,6 @@ ix86_function_arg_regno_p (int regno)
|
||||
int i;
|
||||
if (!TARGET_64BIT)
|
||||
return (regno < REGPARM_MAX
|
||||
|| (TARGET_80387 && FP_REGNO_P (regno)
|
||||
&& (regno < FIRST_FLOAT_REG + X87_REGPARM_MAX))
|
||||
|| (TARGET_MMX && MMX_REGNO_P (regno)
|
||||
&& (regno < FIRST_MMX_REG + MMX_REGPARM_MAX))
|
||||
|| (TARGET_SSE && SSE_REGNO_P (regno)
|
||||
@ -3020,8 +2962,6 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */
|
||||
|
||||
/* Set up the number of registers to use for passing arguments. */
|
||||
cum->nregs = ix86_regparm;
|
||||
if (TARGET_80387)
|
||||
cum->x87_nregs = X87_REGPARM_MAX;
|
||||
if (TARGET_SSE)
|
||||
cum->sse_nregs = SSE_REGPARM_MAX;
|
||||
if (TARGET_MMX)
|
||||
@ -3043,10 +2983,6 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */
|
||||
cum->nregs = ix86_function_regparm (fntype, fndecl);
|
||||
}
|
||||
|
||||
/* Set up the number of 80387 registers used for passing
|
||||
floating point arguments. Warn for mismatching ABI. */
|
||||
cum->float_in_x87 = ix86_function_x87regparm (fntype, fndecl);
|
||||
|
||||
/* Set up the number of SSE registers used for passing SFmode
|
||||
and DFmode arguments. Warn for mismatching ABI. */
|
||||
cum->float_in_sse = ix86_function_sseregparm (fntype, fndecl);
|
||||
@ -3056,8 +2992,7 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */
|
||||
are no variable arguments. If there are variable arguments, then
|
||||
we won't pass anything in registers in 32-bit mode. */
|
||||
|
||||
if (cum->nregs || cum->mmx_nregs
|
||||
|| cum->x87_nregs || cum->sse_nregs)
|
||||
if (cum->nregs || cum->mmx_nregs || cum->sse_nregs)
|
||||
{
|
||||
for (param = (fntype) ? TYPE_ARG_TYPES (fntype) : 0;
|
||||
param != 0; param = next_param)
|
||||
@ -3068,13 +3003,11 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */
|
||||
if (!TARGET_64BIT)
|
||||
{
|
||||
cum->nregs = 0;
|
||||
cum->x87_nregs = 0;
|
||||
cum->sse_nregs = 0;
|
||||
cum->mmx_nregs = 0;
|
||||
cum->warn_sse = 0;
|
||||
cum->warn_mmx = 0;
|
||||
cum->fastcall = 0;
|
||||
cum->float_in_x87 = 0;
|
||||
cum->float_in_sse = 0;
|
||||
}
|
||||
cum->maybe_vaarg = true;
|
||||
@ -3771,40 +3704,13 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
||||
}
|
||||
break;
|
||||
|
||||
case SFmode:
|
||||
if (cum->float_in_sse > 0)
|
||||
goto skip_80387;
|
||||
|
||||
case DFmode:
|
||||
if (cum->float_in_sse > 1)
|
||||
goto skip_80387;
|
||||
|
||||
/* Because no inherent XFmode->DFmode and XFmode->SFmode
|
||||
rounding takes place when values are passed in x87
|
||||
registers, pass DFmode and SFmode types to local functions
|
||||
only when flag_unsafe_math_optimizations is set. */
|
||||
if (!cum->float_in_x87
|
||||
|| (cum->float_in_x87 == 2
|
||||
&& !flag_unsafe_math_optimizations))
|
||||
if (cum->float_in_sse < 2)
|
||||
break;
|
||||
|
||||
case XFmode:
|
||||
if (!cum->float_in_x87)
|
||||
case SFmode:
|
||||
if (cum->float_in_sse < 1)
|
||||
break;
|
||||
|
||||
if (!type || !AGGREGATE_TYPE_P (type))
|
||||
{
|
||||
cum->x87_nregs -= 1;
|
||||
cum->x87_regno += 1;
|
||||
if (cum->x87_nregs <= 0)
|
||||
{
|
||||
cum->x87_nregs = 0;
|
||||
cum->x87_regno = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
skip_80387:
|
||||
/* FALLTHRU */
|
||||
|
||||
case TImode:
|
||||
case V16QImode:
|
||||
@ -3815,6 +3721,7 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
||||
case V2DFmode:
|
||||
if (!type || !AGGREGATE_TYPE_P (type))
|
||||
{
|
||||
cum->sse_words += words;
|
||||
cum->sse_nregs -= 1;
|
||||
cum->sse_regno += 1;
|
||||
if (cum->sse_nregs <= 0)
|
||||
@ -3831,6 +3738,7 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
||||
case V2SFmode:
|
||||
if (!type || !AGGREGATE_TYPE_P (type))
|
||||
{
|
||||
cum->mmx_words += words;
|
||||
cum->mmx_nregs -= 1;
|
||||
cum->mmx_regno += 1;
|
||||
if (cum->mmx_nregs <= 0)
|
||||
@ -3895,6 +3803,7 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode orig_mode,
|
||||
else
|
||||
switch (mode)
|
||||
{
|
||||
/* For now, pass fp/complex values on the stack. */
|
||||
default:
|
||||
break;
|
||||
|
||||
@ -3924,35 +3833,13 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode orig_mode,
|
||||
ret = gen_rtx_REG (mode, regno);
|
||||
}
|
||||
break;
|
||||
|
||||
case SFmode:
|
||||
if (cum->float_in_sse > 0)
|
||||
goto skip_80387;
|
||||
|
||||
case DFmode:
|
||||
if (cum->float_in_sse > 1)
|
||||
goto skip_80387;
|
||||
|
||||
/* Because no inherent XFmode->DFmode and XFmode->SFmode
|
||||
rounding takes place when values are passed in x87
|
||||
registers, pass DFmode and SFmode types to local functions
|
||||
only when flag_unsafe_math_optimizations is set. */
|
||||
if (!cum->float_in_x87
|
||||
|| (cum->float_in_x87 == 2
|
||||
&& !flag_unsafe_math_optimizations))
|
||||
break;
|
||||
|
||||
case XFmode:
|
||||
if (!cum->float_in_x87)
|
||||
break;
|
||||
|
||||
if (!type || !AGGREGATE_TYPE_P (type))
|
||||
if (cum->x87_nregs)
|
||||
ret = gen_rtx_REG (mode, cum->x87_regno + FIRST_FLOAT_REG);
|
||||
case DFmode:
|
||||
if (cum->float_in_sse < 2)
|
||||
break;
|
||||
|
||||
skip_80387:
|
||||
|
||||
case SFmode:
|
||||
if (cum->float_in_sse < 1)
|
||||
break;
|
||||
/* FALLTHRU */
|
||||
case TImode:
|
||||
case V16QImode:
|
||||
case V8HImode:
|
||||
|
@ -1481,21 +1481,19 @@ enum reg_class
|
||||
such as FUNCTION_ARG to determine where the next arg should go. */
|
||||
|
||||
typedef struct ix86_args {
|
||||
int words; /* # words passed so far */
|
||||
int nregs; /* # registers available for passing */
|
||||
int regno; /* next available register number */
|
||||
int words; /* # words passed so far */
|
||||
int fastcall; /* fastcall calling convention is used */
|
||||
int x87_nregs; /* # x87 registers available for passing */
|
||||
int x87_regno; /* # next available x87 register number */
|
||||
int sse_words; /* # sse words passed so far */
|
||||
int sse_nregs; /* # sse registers available for passing */
|
||||
int sse_regno; /* next available sse register number */
|
||||
int warn_sse; /* True when we want to warn about SSE ABI. */
|
||||
int warn_mmx; /* True when we want to warn about MMX ABI. */
|
||||
int sse_regno; /* next available sse register number */
|
||||
int mmx_words; /* # mmx words passed so far */
|
||||
int mmx_nregs; /* # mmx registers available for passing */
|
||||
int mmx_regno; /* next available mmx register number */
|
||||
int warn_mmx; /* True when we want to warn about MMX ABI. */
|
||||
int maybe_vaarg; /* true for calls to possibly vardic fncts. */
|
||||
int float_in_x87; /* 1 if floating point arguments should
|
||||
be passed in 80387 registers. */
|
||||
int float_in_sse; /* 1 if in 32-bit mode SFmode (2 for DFmode) should
|
||||
be passed in SSE registers. Otherwise 0. */
|
||||
} CUMULATIVE_ARGS;
|
||||
@ -1778,10 +1776,6 @@ do { \
|
||||
|
||||
#define REGPARM_MAX (TARGET_64BIT ? 6 : 3)
|
||||
|
||||
/* ??? Currently disabled, as reg-stack.c does not know how to
|
||||
rearrange input registers if some arguments are left unused. */
|
||||
#define X87_REGPARM_MAX 0
|
||||
|
||||
#define SSE_REGPARM_MAX (TARGET_64BIT ? 8 : (TARGET_SSE ? 3 : 0))
|
||||
|
||||
#define MMX_REGPARM_MAX (TARGET_64BIT ? 0 : (TARGET_MMX ? 3 : 0))
|
||||
|
@ -205,10 +205,6 @@ mssse3
|
||||
Target Report Mask(SSSE3)
|
||||
Support MMX, SSE, SSE2, SSE3 and SSSE3 built-in functions and code generation
|
||||
|
||||
mx87regparm
|
||||
Target RejectNegative Mask(X87REGPARM)
|
||||
Use x87 register passing conventions to pass floating point arguments
|
||||
|
||||
msseregparm
|
||||
Target RejectNegative Mask(SSEREGPARM)
|
||||
Use SSE register passing conventions for SF and DF mode
|
||||
|
@ -2221,14 +2221,6 @@ safe since the loaders there save all registers. (Lazy binding can be
|
||||
disabled with the linker or the loader if desired, to avoid the
|
||||
problem.)
|
||||
|
||||
@item x87regparm
|
||||
@cindex @code{x87regparm} attribute
|
||||
On the Intel x86 with 80387 @code{x87regparm} attribute causes the
|
||||
compiler to pass up to 3 floating point arguments in 80387 registers
|
||||
instead of on the stack. Functions that take a variable number of
|
||||
arguments will continue to pass all of their floating point arguments
|
||||
on the stack.
|
||||
|
||||
@item sseregparm
|
||||
@cindex @code{sseregparm} attribute
|
||||
On the Intel 386 with SSE support, the @code{sseregparm} attribute
|
||||
|
@ -536,8 +536,8 @@ Objective-C and Objective-C++ Dialects}.
|
||||
-mmmx -msse -msse2 -msse3 -mssse3 -m3dnow @gol
|
||||
-mthreads -mno-align-stringops -minline-all-stringops @gol
|
||||
-mpush-args -maccumulate-outgoing-args -m128bit-long-double @gol
|
||||
-m96bit-long-double -mregparm=@var{num} -mx87regparm @gol
|
||||
-msseregparm @gol -mstackrealign @gol
|
||||
-m96bit-long-double -mregparm=@var{num} -msseregparm @gol
|
||||
-mstackrealign @gol
|
||||
-momit-leaf-frame-pointer -mno-red-zone -mno-tls-direct-seg-refs @gol
|
||||
-mcmodel=@var{code-model} @gol
|
||||
-m32 -m64 -mlarge-data-threshold=@var{num}}
|
||||
@ -9597,17 +9597,6 @@ function by using the function attribute @samp{regparm}.
|
||||
value, including any libraries. This includes the system libraries and
|
||||
startup modules.
|
||||
|
||||
@item -mx87regparm
|
||||
@opindex mx87regparm
|
||||
Use 80387 register passing conventions for floating point arguments.
|
||||
You can control this behavior for a specific function by using the
|
||||
function attribute @samp{x87regparm}.
|
||||
@xref{Function Attributes}.
|
||||
|
||||
@strong{Warning:} if you use this switch then you must build all
|
||||
modules with the same value, including any libraries. This includes
|
||||
the system libraries and startup modules.
|
||||
|
||||
@item -msseregparm
|
||||
@opindex msseregparm
|
||||
Use SSE register passing conventions for float and double arguments
|
||||
|
@ -2558,28 +2558,11 @@ print_stack (FILE *file, stack s)
|
||||
static int
|
||||
convert_regs_entry (void)
|
||||
{
|
||||
tree params = DECL_ARGUMENTS (current_function_decl);
|
||||
tree p;
|
||||
HARD_REG_SET incoming_regs;
|
||||
rtx inc_rtx;
|
||||
|
||||
int inserted = 0;
|
||||
edge e;
|
||||
edge_iterator ei;
|
||||
|
||||
/* Find out which registers were used as argument passing registers. */
|
||||
|
||||
CLEAR_HARD_REG_SET (incoming_regs);
|
||||
for (p = params; p; p = TREE_CHAIN (p))
|
||||
{
|
||||
inc_rtx = DECL_INCOMING_RTL (p);
|
||||
|
||||
if (REG_P (inc_rtx)
|
||||
&& IN_RANGE (REGNO (inc_rtx), FIRST_STACK_REG, LAST_STACK_REG))
|
||||
SET_HARD_REG_BIT (incoming_regs, REGNO (inc_rtx));
|
||||
}
|
||||
|
||||
/* Load something into remaining stack register live at function entry.
|
||||
/* Load something into each stack register live at function entry.
|
||||
Such live registers can be caused by uninitialized variables or
|
||||
functions not returning values on all paths. In order to keep
|
||||
the push/pop code happy, and to not scrog the register stack, we
|
||||
@ -2595,17 +2578,12 @@ convert_regs_entry (void)
|
||||
int reg, top = -1;
|
||||
|
||||
for (reg = LAST_STACK_REG; reg >= FIRST_STACK_REG; --reg)
|
||||
if (TEST_HARD_REG_BIT (bi->stack_in.reg_set, reg)
|
||||
|| TEST_HARD_REG_BIT (incoming_regs, reg))
|
||||
if (TEST_HARD_REG_BIT (bi->stack_in.reg_set, reg))
|
||||
{
|
||||
rtx init;
|
||||
|
||||
bi->stack_in.reg[++top] = reg;
|
||||
|
||||
/* Skip argument passing registers. */
|
||||
if (TEST_HARD_REG_BIT (incoming_regs, reg))
|
||||
continue;
|
||||
|
||||
init = gen_rtx_SET (VOIDmode,
|
||||
FP_MODE_REG (FIRST_STACK_REG, SFmode),
|
||||
not_a_num);
|
||||
|
@ -1,3 +1,16 @@
|
||||
2006-12-11 Uros Bizjak <ubizjak@gmail.com>
|
||||
|
||||
PR target/30120
|
||||
* gcc.target/i386/pr30120.c: New test.
|
||||
|
||||
Revert:
|
||||
2006-11-15 Uros Bizjak <ubizjak@gmail.com>
|
||||
|
||||
* gcc.target/i386/x87regparm-1.c: New test.
|
||||
* gcc.target/i386/x87regparm-2.c: New test.
|
||||
* gcc.target/i386/x87regparm-3.c: New test.
|
||||
* gcc.target/i386/x87regparm-4.c: New test.
|
||||
|
||||
2006-12-10 Zdenek Dvorak <dvorakz@suse.cz>
|
||||
|
||||
* gcc.dg/tree-ssa/loop-17.c: Update outcome.
|
||||
|
27
gcc/testsuite/gcc.target/i386/pr30120.c
Normal file
27
gcc/testsuite/gcc.target/i386/pr30120.c
Normal file
@ -0,0 +1,27 @@
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2 -ffast-math" } */
|
||||
|
||||
extern void abort (void);
|
||||
|
||||
static void
|
||||
foo (double a, double weight, const double *ring, double *phase)
|
||||
{
|
||||
*phase = *ring * weight;
|
||||
}
|
||||
|
||||
void
|
||||
foo2 (void)
|
||||
{
|
||||
foo (0, 1, (double *) 0, (double *) 0);
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
double t1 = 1, c1;
|
||||
foo (0, 1, &t1, &c1);
|
||||
if (c1 < 0.5)
|
||||
abort();
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fomit-frame-pointer" } */
|
||||
/* { dg-require-effective-target ilp32 } */
|
||||
|
||||
float foo_f(float) __attribute__((x87regparm));
|
||||
double foo_d(double) __attribute__((x87regparm));
|
||||
long double foo_ld(long double) __attribute__((x87regparm));
|
||||
|
||||
volatile float f;
|
||||
volatile double d;
|
||||
volatile long double ld;
|
||||
|
||||
void test()
|
||||
{
|
||||
f = foo_f(f);
|
||||
d = foo_d(d);
|
||||
ld = foo_ld(ld);
|
||||
}
|
||||
|
||||
/* Check that no memory is used to pass arguments. */
|
||||
|
||||
/* { dg-final { scan-assembler-not "\\(%esp\\)" { xfail *-*-* } } } */
|
@ -1,22 +0,0 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fomit-frame-pointer -mx87regparm" } */
|
||||
/* { dg-require-effective-target ilp32 } */
|
||||
|
||||
float efoo_f(float);
|
||||
double efoo_d(double);
|
||||
long double efoo_ld(long double);
|
||||
|
||||
volatile float f;
|
||||
volatile double d;
|
||||
volatile long double ld;
|
||||
|
||||
void test()
|
||||
{
|
||||
f = efoo_f(f);
|
||||
d = efoo_d(d);
|
||||
ld = efoo_ld(ld);
|
||||
}
|
||||
|
||||
/* Check that no memory is used to pass arguments. */
|
||||
|
||||
/* { dg-final { scan-assembler-not "\\(%esp\\)" { xfail *-*-* } } } */
|
@ -1,22 +0,0 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fomit-frame-pointer" } */
|
||||
/* { dg-require-effective-target ilp32 } */
|
||||
|
||||
static float __attribute__((noinline)) foo_f(float f) { return f; }
|
||||
static double __attribute__((noinline)) foo_d(double d) { return d; }
|
||||
static long double __attribute__((noinline)) foo_ld(long double ld) { return ld; }
|
||||
|
||||
volatile float f;
|
||||
volatile double d;
|
||||
volatile long double ld;
|
||||
|
||||
void test()
|
||||
{
|
||||
f = foo_f(f);
|
||||
d = foo_d(d);
|
||||
ld = foo_ld(ld);
|
||||
}
|
||||
|
||||
/* Check that float and double arguments are passed through memory. */
|
||||
|
||||
/* { dg-final { scan-assembler-times "\\(%esp\\)" 4 { xfail *-*-* } } } */
|
@ -1,22 +0,0 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fomit-frame-pointer -ffast-math" } */
|
||||
/* { dg-require-effective-target ilp32 } */
|
||||
|
||||
static float __attribute__((noinline)) foo_f(float f) { return f; }
|
||||
static double __attribute__((noinline)) foo_d(double d) { return d; }
|
||||
static long double __attribute__((noinline)) foo_ld(long double ld) { return ld; }
|
||||
|
||||
volatile float f;
|
||||
volatile double d;
|
||||
volatile long double ld;
|
||||
|
||||
void test()
|
||||
{
|
||||
f = foo_f(f);
|
||||
d = foo_d(d);
|
||||
ld = foo_ld(ld);
|
||||
}
|
||||
|
||||
/* Check that no memory is used to pass arguments. */
|
||||
|
||||
/* { dg-final { scan-assembler-not "\\(%esp\\)" { xfail *-*-* } } } */
|
Loading…
Reference in New Issue
Block a user