i386-local.c: New.

* gcc.dg/i386-local.c: New.

	* toplev.c (rest_of_compilation):  Deffer RTL compilation only when
	RTL inlining is done.

	* cgraphunit.c (cgraph_mark_local_functions): New local function.
	(cgraph_optimize): Mark local functions.
	* i386-protos.h (init_cumulative_args): Update prototype.
	* i386.c (init_cumulative_args): Use register passing convention for
	local functions.

	* cgraph.c (cgraph_global_info_ready): New global variable
	(cgraph_local_info, cgraph_global_info): New functions.
	* cgraph.h (struct cgraph_local_info, cgraph_global_info): New
	structures.
	(cgraph_local_info, cgraph_global_info, cgraph_global_info_ready):
	Declare.
	* cgraphunit.c (cgraph_finalize_function): Set inline_many.
	(cgraph_mark_functions_to_output): Use inline_many.
	(cgraph_expand_function): Free DECL_SAVED_TREE uncondtionally.
	(cgraph_expand_functions): Expand inline functions last.
	(cgraph_optimize): Do not emit uneeded functions.

From-SVN: r63822
This commit is contained in:
Jan Hubicka 2003-03-05 02:33:27 +01:00 committed by Jan Hubicka
parent 75d8f260df
commit dafc5b82d5
11 changed files with 199 additions and 30 deletions

View file

@ -1,3 +1,26 @@
Wed Mar 5 02:04:04 CET 2003 Jan Hubicka <jh@suse.cz>
* toplev.c (rest_of_compilation): Deffer RTL compilation only when
RTL inlining is done.
* cgraphunit.c (cgraph_mark_local_functions): New local function.
(cgraph_optimize): Mark local functions.
* i386-protos.h (init_cumulative_args): Update prototype.
* i386.c (init_cumulative_args): Use register passing convention for
local functions.
* cgraph.c (cgraph_global_info_ready): New global variable
(cgraph_local_info, cgraph_global_info): New functions.
* cgraph.h (struct cgraph_local_info, cgraph_global_info): New
structures.
(cgraph_local_info, cgraph_global_info, cgraph_global_info_ready):
Declare.
* cgraphunit.c (cgraph_finalize_function): Set inline_many.
(cgraph_mark_functions_to_output): Use inline_many.
(cgraph_expand_function): Free DECL_SAVED_TREE uncondtionally.
(cgraph_expand_functions): Expand inline functions last.
(cgraph_optimize): Do not emit uneeded functions.
2003-03-04 Steve Ellcey <sje@cup.hp.com>
* expr.c (convert_modes): Check for legal hard register.

View file

@ -43,6 +43,9 @@ struct cgraph_node *cgraph_nodes;
/* Number of nodes in existence. */
int cgraph_n_nodes;
/* Set when whole unit has been analyzed so we can access global info. */
bool cgraph_global_info_ready = false;
static struct cgraph_edge *create_edge PARAMS ((struct cgraph_node *,
struct cgraph_node *));
static void remove_edge PARAMS ((struct cgraph_node *, struct cgraph_node *));
@ -175,6 +178,33 @@ cgraph_calls_p (caller_decl, callee_decl)
return edge != NULL;
}
/* Return local info for the compiled function. */
struct cgraph_local_info *
cgraph_local_info (decl)
tree decl;
{
struct cgraph_node *node;
if (TREE_CODE (decl) != FUNCTION_DECL)
abort ();
node = cgraph_node (decl);
return &node->local;
}
/* Return local info for the compiled function. */
struct cgraph_global_info *
cgraph_global_info (decl)
tree decl;
{
struct cgraph_node *node;
if (TREE_CODE (decl) != FUNCTION_DECL || !cgraph_global_info_ready)
abort ();
node = cgraph_node (decl);
return &node->global;
}
/* Dump the callgraph. */
void

View file

@ -22,6 +22,27 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#ifndef GCC_CGRAPH_H
#define GCC_CGRAPH_H
/* Information about the function collected locally.
Available after function is lowered */
struct cgraph_local_info
{
/* Set when function function is visiable in current compilation unit only
and it's address is never taken. */
bool local;
bool inline_many;
};
/* Information about the function that needs to be computed globally
once compilation is finished. Available only with -funit-at-time. */
struct cgraph_global_info
{
/* Empty for the moment. */
int dummy;
};
/* The cgraph data strutcture.
Each function decl has assigned cgraph_node listing calees and callers. */
@ -51,6 +72,8 @@ struct cgraph_node
bool lowered;
/* Set when function is scheduled to be assembled. */
bool output;
struct cgraph_local_info local;
struct cgraph_global_info global;
};
struct cgraph_edge
@ -62,6 +85,7 @@ struct cgraph_edge
extern struct cgraph_node *cgraph_nodes;
extern int cgraph_n_nodes;
extern bool cgraph_global_info_ready;
/* In cgraph.c */
void dump_cgraph PARAMS ((FILE *));
@ -69,6 +93,8 @@ void cgraph_remove_call PARAMS ((tree, tree));
struct cgraph_edge *cgraph_record_call PARAMS ((tree, tree));
struct cgraph_node *cgraph_node PARAMS ((tree decl));
bool cgraph_calls_p PARAMS ((tree, tree));
struct cgraph_local_info *cgraph_local_info PARAMS ((tree));
struct cgraph_global_info *cgraph_global_info PARAMS ((tree));
/* In cgraphunit.c */
void cgraph_finalize_function PARAMS ((tree, tree));

View file

@ -33,11 +33,13 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "debug.h"
#include "target.h"
#include "cgraph.h"
#include "diagnostic.h"
static void cgraph_expand_functions PARAMS ((void));
static void cgraph_mark_functions_to_output PARAMS ((void));
static void cgraph_expand_function PARAMS ((struct cgraph_node *));
static tree record_call_1 PARAMS ((tree *, int *, void *));
static void cgraph_mark_local_functions PARAMS ((void));
/* Analyze function once it is parsed. Set up the local information
available - create cgraph edges for function calles via BODY. */
@ -51,8 +53,10 @@ cgraph_finalize_function (decl, body)
node->decl = decl;
/* Set TREE_UNINLINABLE flag. */
tree_inlinable_function_p (decl);
if (flag_inline_trees)
node->local.inline_many = tree_inlinable_function_p (decl);
else
node->local.inline_many = 0;
(*debug_hooks->deferred_inline_function) (decl);
}
@ -217,7 +221,7 @@ cgraph_mark_functions_to_output ()
if (DECL_SAVED_TREE (decl)
&& (node->needed
|| (DECL_UNINLINABLE (decl) && node->reachable)
|| (!node->local.inline_many && node->reachable)
|| TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
&& !TREE_ASM_WRITTEN (decl) && !node->origin
&& !DECL_EXTERNAL (decl))
@ -235,6 +239,8 @@ cgraph_expand_function (node)
announce_function (decl);
if (flag_inline_trees)
optimize_inline_calls (decl);
/* Avoid RTL inlining from taking place. */
(*lang_hooks.callgraph.expand_function) (decl);
if (DECL_UNINLINABLE (decl))
DECL_SAVED_TREE (decl) = NULL;
@ -325,6 +331,30 @@ cgraph_expand_functions ()
free (order);
}
/* Mark all local functions.
We can not use node->needed directly as it is modified during
execution of cgraph_optimize. */
static void
cgraph_mark_local_functions ()
{
struct cgraph_node *node;
if (!quiet_flag)
fprintf (stderr, "\n\nMarking local functions:");
/* Figure out functions we want to assemble. */
for (node = cgraph_nodes; node; node = node->next)
{
node->local.local = (!node->needed
&& DECL_SAVED_TREE (node->decl)
&& !TREE_PUBLIC (node->decl));
if (node->local.local)
announce_function (node->decl);
}
}
/* Perform simple optimizations based on callgraph. */
void
@ -332,8 +362,10 @@ cgraph_optimize ()
{
struct cgraph_node *node;
bool changed = true;
struct cgraph_edge *edge;
cgraph_mark_local_functions ();
cgraph_global_info_ready = true;
if (!quiet_flag)
fprintf (stderr, "\n\nAssembling functions:");
@ -343,18 +375,29 @@ cgraph_optimize ()
Later we should move all inlining decisions to callgraph code to make
this impossible. */
cgraph_expand_functions ();
while (changed)
if (!quiet_flag)
fprintf (stderr, "\n\nAssembling functions that failed to inline:");
while (changed && !errorcount && !sorrycount)
{
changed = false;
for (node = cgraph_nodes; node; node = node->next)
{
if (!node->needed)
continue;
tree decl = node->decl;
if (!node->origin
&& !TREE_ASM_WRITTEN (decl)
&& DECL_SAVED_TREE (decl)
&& !DECL_EXTERNAL (decl))
{
struct cgraph_edge *edge;
for (edge = node->callees; edge; edge = edge->next_callee)
if (!edge->callee->needed)
changed = edge->callee->needed = true;
for (edge = node->callers; edge; edge = edge->next_caller)
if (TREE_ASM_WRITTEN (edge->caller->decl))
{
changed = true;
cgraph_expand_function (node);
break;
}
}
}
}
cgraph_expand_functions ();
}

View file

@ -194,7 +194,7 @@ extern void x86_emit_floatuns PARAMS ((rtx [2]));
#ifdef TREE_CODE
extern void init_cumulative_args PARAMS ((CUMULATIVE_ARGS *, tree, rtx));
extern void init_cumulative_args PARAMS ((CUMULATIVE_ARGS *, tree, rtx, tree));
extern rtx function_arg PARAMS ((CUMULATIVE_ARGS *, enum machine_mode, tree, int));
extern int function_arg_pass_by_reference PARAMS ((CUMULATIVE_ARGS *,
enum machine_mode,
@ -226,6 +226,7 @@ extern int x86_field_alignment PARAMS ((tree, int));
extern rtx ix86_tls_get_addr PARAMS ((void));
extern void x86_machine_dependent_reorg PARAMS ((rtx));
extern bool ix86_must_pass_in_stack PARAMS ((enum machine_mode mode, tree));
/* In winnt.c */
extern int i386_pe_dllexport_name_p PARAMS ((const char *));

View file

@ -45,6 +45,7 @@ Boston, MA 02111-1307, USA. */
#include "target.h"
#include "target-def.h"
#include "langhooks.h"
#include "cgraph.h"
#ifndef CHECK_STACK_LIMIT
#define CHECK_STACK_LIMIT (-1)
@ -1765,13 +1766,15 @@ ix86_function_arg_regno_p (regno)
For a library call, FNTYPE is 0. */
void
init_cumulative_args (cum, fntype, libname)
init_cumulative_args (cum, fntype, libname, fndecl)
CUMULATIVE_ARGS *cum; /* Argument info to initialize */
tree fntype; /* tree ptr for function decl */
rtx libname; /* SYMBOL_REF of library name or 0 */
tree fndecl;
{
static CUMULATIVE_ARGS zero_cum;
tree param, next_param;
bool user_convention = false;
if (TARGET_DEBUG_ARG)
{
@ -1797,7 +1800,10 @@ init_cumulative_args (cum, fntype, libname)
tree attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (fntype));
if (attr)
cum->nregs = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));
{
cum->nregs = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));
user_convention = true;
}
}
cum->maybe_vaarg = false;
@ -1808,6 +1814,23 @@ init_cumulative_args (cum, fntype, libname)
{
cum->nregs = 2;
cum->fastcall = 1;
user_convention = true;
}
}
/* Use register calling convention for local functions when possible. */
if (!TARGET_64BIT && !user_convention && fndecl
&& flag_unit_at_a_time)
{
struct cgraph_local_info *i = cgraph_local_info (fndecl);
if (i && i->local)
{
/* We can't use regparm(3) for nested functions as these use
static chain pointer in third argument. */
if (DECL_CONTEXT (fndecl) && !DECL_NO_STATIC_CHAIN (fndecl))
cum->nregs = 2;
else
cum->nregs = 3;
}
}
@ -1914,6 +1937,10 @@ classify_argument (mode, type, classes, bit_offset)
if (bytes < 0)
return 0;
if (mode != VOIDmode
&& MUST_PASS_IN_STACK (mode, type))
return 0;
if (type && AGGREGATE_TYPE_P (type))
{
int i;
@ -15639,4 +15666,15 @@ x86_emit_floatuns (operands)
emit_label (donelab);
}
/* Return if we do not know how to pass TYPE solely in registers. */
bool
ix86_must_pass_in_stack (mode, type)
enum machine_mode mode;
tree type;
{
if (default_must_pass_in_stack (mode, type))
return true;
return (!TARGET_64BIT && type && mode == TImode);
}
#include "gt-i386.h"

View file

@ -1664,18 +1664,7 @@ enum reg_class
definition that is usually appropriate, refer to expr.h for additional
documentation. If `REG_PARM_STACK_SPACE' is defined, the argument will be
computed in the stack and then loaded into a register. */
#define MUST_PASS_IN_STACK(MODE, TYPE) \
((TYPE) != 0 \
&& (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \
|| TREE_ADDRESSABLE (TYPE) \
|| ((MODE) == TImode) \
|| ((MODE) == BLKmode \
&& ! ((TYPE) != 0 \
&& TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \
&& 0 == (int_size_in_bytes (TYPE) \
% (PARM_BOUNDARY / BITS_PER_UNIT))) \
&& (FUNCTION_ARG_PADDING (MODE, TYPE) \
== (BYTES_BIG_ENDIAN ? upward : downward)))))
#define MUST_PASS_IN_STACK(MODE, TYPE) ix86_must_pass_in_stack ((MODE), (TYPE))
/* Value is the number of bytes of arguments automatically
popped when returning from a subroutine call.
@ -1743,8 +1732,8 @@ typedef struct ix86_args {
for a call to a function whose data type is FNTYPE.
For a library call, FNTYPE is 0. */
#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \
init_cumulative_args (&(CUM), (FNTYPE), (LIBNAME))
#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL) \
init_cumulative_args (&(CUM), (FNTYPE), (LIBNAME), (FNDECL))
/* Update the data in CUM to advance over an argument
of mode MODE and data type TYPE.

View file

@ -3521,8 +3521,8 @@ invoking @option{-O2} on programs that use computed gotos.
@item -O3
@opindex O3
Optimize yet more. @option{-O3} turns on all optimizations specified by
@option{-O2} and also turns on the @option{-finline-functions} and
@option{-frename-registers} options.
@option{-O2} and also turns on the @option{-finline-functions},
@option{-funit-at-a-time} and @option{-frename-registers} options.
@item -O0
@opindex O0

View file

@ -1,3 +1,7 @@
Wed Mar 5 02:05:19 CET 2003 Jan Hubicka <jh@suse.cz>
* gcc.dg/i386-local.c: New.
Tue Mar 4 19:39:18 2003 J"orn Rennecke <joern.rennecke@superh.com>
* gcc.dg/sh-relax.c: Disable for sh64-*-*.

View file

@ -0,0 +1,14 @@
/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
/* { dg-options "-O2 -funit-at-a-time" } */
/* { dg-final { scan-assembler "magic.*eax" } } */
/* Verify that local calling convention is used. */
static t(int) __attribute__ ((noinline));
m()
{
t(1);
}
static t(int a)
{
asm("magic %1"::"g"(a));
}

View file

@ -2518,6 +2518,7 @@ rest_of_compilation (decl)
if (inlinable
|| (DECL_INLINE (decl)
&& flag_inline_functions
&& ((! TREE_PUBLIC (decl) && ! TREE_ADDRESSABLE (decl)
&& ! TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
&& ! flag_keep_inline_functions)