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.
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).
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.