You've already forked linux-packaging-mono
							
							
		
			
	
	
		
			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. |