diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 34598e15b18d9526e03e28a70d5d1dc00f07a9f7..83019f916986e18d574f4f5c60314d246d852b5c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2015-02-08 Jan Hubicka <hubicka@ucw.cz> + + PR ipa/63566 + * i386.c (ix86_function_regparm): Look through aliases to see if callee + is local and optimized. + (ix86_function_sseregparm): Likewise; also use target's SSE math + settings; error out instead of silently generating wrong code + on mismatches. + (init_cumulative_args): Look through aliases. + 2015-02-08 Jan Hubicka <hubicka@ucw.cz> PR ipa/63566 diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 7f5796ab52e7644651e2c8227c3da232bbba9b90..b39e5077ae15122a3166b8e4c918eae0a56f1ed7 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -5767,49 +5767,55 @@ ix86_function_regparm (const_tree type, const_tree decl) /* Use register calling convention for local functions when possible. */ if (decl - && TREE_CODE (decl) == FUNCTION_DECL + && TREE_CODE (decl) == FUNCTION_DECL) + { + cgraph_node *target = cgraph_node::get (decl); + if (target) + target = target->function_symbol (); + /* Caller and callee must agree on the calling convention, so checking here just optimize means that with __attribute__((optimize (...))) caller could use regparm convention and callee not, or vice versa. Instead look at whether the callee is optimized or not. */ - && opt_for_fn (decl, optimize) - && !(profile_flag && !flag_fentry)) - { - /* FIXME: remove this CONST_CAST when cgraph.[ch] is constified. */ - cgraph_local_info *i = cgraph_node::local_info (CONST_CAST_TREE (decl)); - if (i && i->local && i->can_change_signature) + if (target && opt_for_fn (target->decl, optimize) + && !(profile_flag && !flag_fentry)) { - int local_regparm, globals = 0, regno; + cgraph_local_info *i = &target->local; + if (i && i->local && i->can_change_signature) + { + int local_regparm, globals = 0, regno; - /* Make sure no regparm register is taken by a - fixed register variable. */ - for (local_regparm = 0; local_regparm < REGPARM_MAX; local_regparm++) - if (fixed_regs[local_regparm]) - break; + /* Make sure no regparm register is taken by a + fixed register variable. */ + for (local_regparm = 0; local_regparm < REGPARM_MAX; + local_regparm++) + if (fixed_regs[local_regparm]) + break; - /* We don't want to use regparm(3) for nested functions as - these use a static chain pointer in the third argument. */ - if (local_regparm == 3 && DECL_STATIC_CHAIN (decl)) - local_regparm = 2; + /* We don't want to use regparm(3) for nested functions as + these use a static chain pointer in the third argument. */ + if (local_regparm == 3 && DECL_STATIC_CHAIN (target->decl)) + local_regparm = 2; - /* In 32-bit mode save a register for the split stack. */ - if (!TARGET_64BIT && local_regparm == 3 && flag_split_stack) - local_regparm = 2; + /* Save a register for the split stack. */ + if (local_regparm == 3 && flag_split_stack) + local_regparm = 2; - /* Each fixed register usage increases register pressure, - so less registers should be used for argument passing. - This functionality can be overriden by an explicit - regparm value. */ - for (regno = AX_REG; regno <= DI_REG; regno++) - if (fixed_regs[regno]) - globals++; + /* Each fixed register usage increases register pressure, + so less registers should be used for argument passing. + This functionality can be overriden by an explicit + regparm value. */ + for (regno = AX_REG; regno <= DI_REG; regno++) + if (fixed_regs[regno]) + globals++; - local_regparm - = globals < local_regparm ? local_regparm - globals : 0; + local_regparm + = globals < local_regparm ? local_regparm - globals : 0; - if (local_regparm > regparm) - regparm = local_regparm; + if (local_regparm > regparm) + regparm = local_regparm; + } } } @@ -5848,15 +5854,37 @@ ix86_function_sseregparm (const_tree type, const_tree decl, bool warn) return 2; } + if (!decl) + return 0; + + cgraph_node *target = cgraph_node::get (decl); + if (target) + target = target->function_symbol (); + /* For local functions, pass up to SSE_REGPARM_MAX SFmode (and DFmode for SSE2) arguments in SSE registers. */ - if (decl && TARGET_SSE_MATH && optimize + if (target + /* TARGET_SSE_MATH */ + && (target_opts_for_fn (target->decl)->x_ix86_fpmath & FPMATH_SSE) + && opt_for_fn (target->decl, optimize) && !(profile_flag && !flag_fentry)) { - /* FIXME: remove this CONST_CAST when cgraph.[ch] is constified. */ - cgraph_local_info *i = cgraph_node::local_info (CONST_CAST_TREE(decl)); + cgraph_local_info *i = &target->local; if (i && i->local && i->can_change_signature) - return TARGET_SSE2 ? 2 : 1; + { + /* Refuse to produce wrong code when local function with SSE enabled + is called from SSE disabled function. + We may work hard to work out these scenarios but hopefully + it doesnot matter in practice. */ + if (!TARGET_SSE && warn) + { + error ("calling %qD with SSE caling convention without " + "SSE/SSE2 enabled", decl); + return 0; + } + return TARGET_SSE2_P (target_opts_for_fn (target->decl) + ->x_ix86_isa_flags) ? 2 : 1; + } } return 0; @@ -6343,20 +6371,25 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */ tree fndecl, int caller) { - struct cgraph_local_info *i; + struct cgraph_local_info *i = NULL; + struct cgraph_node *target = NULL; memset (cum, 0, sizeof (*cum)); if (fndecl) { - i = cgraph_node::local_info (fndecl); - cum->call_abi = ix86_function_abi (fndecl); + target = cgraph_node::get (fndecl); + if (target) + { + target = target->function_symbol (); + i = cgraph_node::local_info (target->decl); + cum->call_abi = ix86_function_abi (target->decl); + } + else + cum->call_abi = ix86_function_abi (fndecl); } else - { - i = NULL; - cum->call_abi = ix86_function_type_abi (fntype); - } + cum->call_abi = ix86_function_type_abi (fntype); cum->caller = caller; @@ -6392,7 +6425,7 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */ helping K&R code. FIXME: once typesytem is fixed, we won't need this code anymore. */ if (i && i->local && i->can_change_signature) - fntype = TREE_TYPE (fndecl); + fntype = TREE_TYPE (target->decl); cum->stdarg = stdarg_p (fntype); cum->maybe_vaarg = (fntype ? (!prototype_p (fntype) || stdarg_p (fntype))