111 lines
3.9 KiB
Plaintext
111 lines
3.9 KiB
Plaintext
|
Thu Jun 26 14:43:04 CDT 2003
|
||
|
|
||
|
Information about BinInterface
|
||
|
------------------------------
|
||
|
|
||
|
Take in a set of instructions with some particular register
|
||
|
allocation. It allows you to add, modify, or delete some instructions,
|
||
|
in SSA form (kind of like LLVM's MachineInstrs.) Then re-allocate
|
||
|
registers. It assumes that the transformations you are doing are safe.
|
||
|
It does not update the mapping information or the LLVM representation
|
||
|
for the modified trace (so it would not, for instance, support
|
||
|
multiple optimization passes; passes have to be aware of and update
|
||
|
manually the mapping information.)
|
||
|
|
||
|
The way you use it is you take the original code and provide it to
|
||
|
BinInterface; then you do optimizations to it, then you put it in the
|
||
|
trace cache.
|
||
|
|
||
|
The BinInterface tries to find live-outs for traces so that it can do
|
||
|
register allocation on just the trace, and stitch the trace back into
|
||
|
the original code. It has to preserve the live-ins and live-outs when
|
||
|
it does its register allocation. (On exits from the trace we have
|
||
|
epilogues that copy live-outs back into the right registers, but
|
||
|
live-ins have to be in the right registers.)
|
||
|
|
||
|
|
||
|
Limitations of BinInterface
|
||
|
---------------------------
|
||
|
|
||
|
It does copy insertions for PHIs, which it infers from the machine
|
||
|
code. The mapping info inserted by LLC is not sufficient to determine
|
||
|
the PHIs.
|
||
|
|
||
|
It does not handle integer or floating-point condition codes and it
|
||
|
does not handle floating-point register allocation.
|
||
|
|
||
|
It is not aggressively able to use lots of registers.
|
||
|
|
||
|
There is a problem with alloca: we cannot find our spill space for
|
||
|
spilling registers, normally allocated on the stack, if the trace
|
||
|
follows an alloca(). What might be an acceptable solution would be to
|
||
|
disable trace generation on functions that have variable-sized
|
||
|
alloca()s. Variable-sized allocas in the trace would also probably
|
||
|
screw things up.
|
||
|
|
||
|
Because of the FP and alloca limitations, the BinInterface is
|
||
|
completely disabled right now.
|
||
|
|
||
|
|
||
|
Demo
|
||
|
----
|
||
|
|
||
|
This is a demo of the Ball & Larus version that does NOT use 2-level
|
||
|
profiling.
|
||
|
|
||
|
1. Compile program with llvm-gcc.
|
||
|
2. Run opt -lowerswitch -paths -emitfuncs on the bytecode.
|
||
|
-lowerswitch change switch statements to branches
|
||
|
-paths Ball & Larus path-profiling algorithm
|
||
|
-emitfuncs emit the table of functions
|
||
|
3. Run llc to generate SPARC assembly code for the result of step 2.
|
||
|
4. Use g++ to link the (instrumented) assembly code.
|
||
|
|
||
|
We use a script to do all this:
|
||
|
------------------------------------------------------------------------------
|
||
|
#!/bin/sh
|
||
|
llvm-gcc $1.c -o $1
|
||
|
opt -lowerswitch -paths -emitfuncs $1.bc > $1.run.bc
|
||
|
llc -f $1.run.bc
|
||
|
LIBS=$HOME/llvm_sparc/lib/Debug
|
||
|
GXX=/usr/dcs/software/evaluation/bin/g++
|
||
|
$GXX -g -L $LIBS $1.run.s -o $1.run.llc \
|
||
|
$LIBS/tracecache.o \
|
||
|
$LIBS/mapinfo.o \
|
||
|
$LIBS/trigger.o \
|
||
|
$LIBS/profpaths.o \
|
||
|
$LIBS/bininterface.o \
|
||
|
$LIBS/support.o \
|
||
|
$LIBS/vmcore.o \
|
||
|
$LIBS/transformutils.o \
|
||
|
$LIBS/bcreader.o \
|
||
|
-lscalaropts -lscalaropts -lanalysis \
|
||
|
-lmalloc -lcpc -lm -ldl
|
||
|
------------------------------------------------------------------------------
|
||
|
|
||
|
5. Run the resulting binary. You will see output from BinInterface
|
||
|
(described below) intermixed with the output from the program.
|
||
|
|
||
|
|
||
|
Output from BinInterface
|
||
|
------------------------
|
||
|
|
||
|
BinInterface's debugging code prints out the following stuff in order:
|
||
|
|
||
|
1. Initial code provided to BinInterface with original register
|
||
|
allocation.
|
||
|
|
||
|
2. Section 0 is the trace prolog, consisting mainly of live-ins and
|
||
|
register saves which will be restored in epilogs.
|
||
|
|
||
|
3. Section 1 is the trace itself, in SSA form used by BinInterface,
|
||
|
along with the PHIs that are inserted.
|
||
|
PHIs are followed by the copies that implement them.
|
||
|
Each branch (i.e., out of the trace) is annotated with the
|
||
|
section number that represents the epilog it branches to.
|
||
|
|
||
|
4. All the other sections starting with Section 2 are trace epilogs.
|
||
|
Every branch from the trace has to go to some epilog.
|
||
|
|
||
|
5. After the last section is the register allocation output.
|