5.13.5.3.2.
Optimization based on cgraph
Back finish_file
from cgraph_finalize_compilation_unit
,
at that time global variables and reachable static variables have assembler
code output, and functions needed are also built into cgraph map, in which
relationship of caller and callee is clear. Following, in cgraph_optimize
, it will do
optimization according to this cgraph map and output assembler code for the
function.
1579
void
1580
cgraph_optimize
(void)
in cgraphunit.c
1581
{
1582
if (!flag_unit_at_a_time
)
1583
return
;
1584
timevar_push (TV_CGRAPHOPT);
1585
if (!quiet_flag
)
1586
fprintf (stderr
, "Performing
intraprocedural optimizations/n");
1587
1588
cgraph_mark_local_functions
();
1589
if (cgraph_dump_file
)
1590
{
1591
fprintf (cgraph_dump_file
, "Marked
");
1592
dump_cgraph (cgraph_dump_file
);
1593
}
1594
1595
cgraph_decide_inlining
();
1596
cgraph_global_info_ready
= true;
1597
if (cgraph_dump_file
)
1598
{
1599
fprintf (cgraph_dump_file
, "Optimized
");
1600
dump_cgraph (cgraph_dump_file
);
1601
}
1602
timevar_pop (TV_CGRAPHOPT);
1603
1604
/* Output
everything.
*/
1605
if (!quiet_flag
)
1606
fprintf (stderr
, "Assembling
functions:/n");
1607
cgraph_expand_all_functions
();
1608
if (cgraph_dump_file
)
1609
{
1610
fprintf (cgraph_dump_file
, "/nFinal
");
1611
dump_cgraph (cgraph_dump_file
);
1612
}
1613
}
See that it is a heavy optimization, which is done only the switch
is on.
5.13.5.3.2.1.
Mark local function
First mark local function. A local function is one whose calls can
occur only in the current compilation unit and all it's calls are explicit, so
we can change its calling convention.
1556
static
void
1557
cgraph_mark_local_functions
(void)
in cgraphunit.c
1558
{
1559
struct
cgraph_node *node;
1560
1561
if (cgraph_dump_file
)
1562
fprintf (cgraph_dump_file
, "/nMarking
local functions:");
1563
1564
/* Figure out
functions we want to assemble.
*
/
1565
for
(node = cgraph_nodes
;
node; node = node->next)
1566
{
1567
node->local.local = (!node->needed
1568
&& DECL_SAVED_TREE
(node->decl)
1569
&& !TREE_PUBLIC
(node->decl));
1570
if (cgraph_dump_file &&
node->local.local)
1571
fprintf (cgraph_dump_file
, " %s",
cgraph_node_name (node));
1572
}
1573
if (cgraph_dump_file
)
1574
fprintf (cgraph_dump_file
,
"/n/n");
1575
}
The function makes the right hand side of the assignment expression
at line 1567 is static function (TREE_PUBLIC is 0) that having address referred
(thus node->needed is 0).
5.13.5.3.2.2.
Determine inlinability
Before we have analyzed functions declared as inline, now we need
further decide if function inlinable in theory can be inlined really.
1233
static
void
1234
cgraph_decide_inlining
(void)
in cgraphunit.c
1235
{
1236
struct
cgraph_node
*node;
1237
int nnodes;
1238
struct
cgraph_node **order =
1239
xcalloc (cgraph_n_nodes
, sizeof
(struct
cgraph_node *));
1240
struct
cgraph_node **inlined =
1241
xcalloc (cgraph_n_nodes
, sizeof
(struct
cgraph_node *));
1242
struct
cgraph_node **inlined_callees =
1243
xcalloc (cgraph_n_nodes
, sizeof
(struct
cgraph_node *));
1244
int ninlined;
1245
int ninlined_callees;
1246
int old_insns = 0;
1247
int i, y;
1248
1249
for
(node = cgraph_nodes
;
node; node = node->next)
1250
initial_insns
+= node->local.self_insns;
1251
overall_insns
= initial_insns
;
1252
1253
nnodes = cgraph_postorder
(order);
1254
1255
if (cgraph_dump_file
)
1256
fprintf (cgraph_dump_file
,
1257
"/nDeciding on inlining.
Starting with %i insns./n",
1258
initial_insns);
1259
1260
for
(node = cgraph_nodes
;
node; node = node->next)
1261
node->aux = 0;
1262
1263
if (cgraph_dump_file
)
1264
fprintf (cgraph_dump_file
, "/nInlining
always_inline functions:/n");
1265
#ifdef
ENABLE_CHECKING
1266
for
(node = cgraph_nodes
;
node; node = node->next)
1267
if (node->aux || node->output)
1268
abort ();
1269
#endif
In previous, in cgraph_node, local.self_insns saves the estimated
instruction number of the function (not confined to inlined function), so at
line 1251, overall_insns
and initial_insns
get the total instruction number of this translation-unit.