Firm Logo

Statistics

Introduction

Collecting compilation statistics like the number of instructions, basic blocks, load or store instruction, the time spent in each phase, etc. are important information for development and analysis of the compiler. Gathering fine grained statistics, can result in a huge amount of data. libFirm features a sophisticated statistics system which simplifies storage, retrieval and analysis of such data. (Actually firm has several statistic systems, the recommended approach, which is described here, is using ir/stat/statev.*)

Events & Contexts

The basis of the statistics are statistic-events. A statistic-event is a pair of an event name and a double value. A compiler can throw a statistic event at any time in the compilation process. Typical examples for an event are the number of instructions modified during a phase, or a time measurement of some algorithmic step.

Events have to be put into some context to be useful. You want to know which file and which function was compiled, or which compiler flags were used. Contexts can often be thought of in an hierarchical manner: On the upper level you have data like compiler flags or the file that is compiled. Going down the hierarchy you find things like the function currently being compiled or the register class getting assigned some registers. Because of this hierarchic nature contexts in this system are organized as a stack.

To keep track of the context, a series of context-push and context-pop events is generated by the compiler. A typical context is bemain_irg which represents the currently processed graph in the backend, or the refinement bechordal_cls which specifies the current register class during register allocation.

A sequence of normal events, context-push and context-pop events form a statistic trace.

Change your code to produce events

Events can be generated by calling stat_ev_dbl():

stat_ev_dbl("mymodule_event", event_value);

Contexts can be pushed and popped like this:

stat_ev_ctx_push_str("mymodule_context", context_value);

/* put normal events here */

stat_ev_ctx_pop("mymodule_context");

It is good style to add a prefix to the event and context names which describes the module which contains the calls. This makes it easier to filter out events from modules, we’re not interested in.

Activating events in the firm library/compiler

Events can be activated with the --statev cparser switch. The compiler will then generate a file ending in .ev which contains the event trace.

For bigger programs like the SPEC it is recommended (and necessary because of the huge amount of data) to restrict the event trace to events from some modules only. This is done with the --filtev switch which accept a string. Only events (which includes context-pushs and -pops) contain the filtev string will be written to the log. A simple invocation looks like this:

$ cparser --statev somefile.c

Generating Events Manually

We also successfully used the statev system from scripts in which case you have to produce the event stream manually. Anyway this is quite easy. You have to generate an asciss file with the following conventions:

 # Push context named CTX with value VAL
 P;CTX;VAL
 # Pop named CTX
 O;CTX
 # Record event named EV with value VAL
E;EV;VAL

Analysing event traces

You can generate summaries and statistics by processing the event traces. libFirm comes with a script which preprocesses the events and puts them into a sqlite (or mysql) database. Example usage:

$ statev_sql.py -v -D results.db somefile.ev someotherfile.ev ...

This creates a file results.db containing an sqlite database with a table for contexts and events. You can then write SQL-queries to gather data. Example sqlite invocation

$ sqlite3 results.db

Some example queries:

# Display the number of blocks and instructions for each function:
SELECT c.bemain_irg, sum(e.bemain_blocks_start), sum(e.bemain_insns_start)
FROM ctx as c, ev as e
WHERE e.id = c.id
GROUP BY c.bemain_irg
# Display the maximal and average register pressure of the ia32_gp register class grouped by filename
SELECT c.bemain_compilation_unit, max(e.bechordal_maximum_register_pressure), avg(e.bechordal_average_register_pressure)
FROM ctx as c, ev as e
WHERE e.id = c.id AND c.bechordal_cls = 'ia32_gp'
GROUP BY c.bemain_compilation_unit

Producing nice looking latex Graphics

You can use the data in scripts to produce tables and tikz pictures for your LaTeX documents.

images/Tableexample.png
images/Plotexample.png

I have added some of my scripts into the firm svn repository as examples: 1