package de.fuberlin.optimierung;
import java.io.*;
import java.util.LinkedList;
public class LLVM_Optimization implements ILLVM_Optimization {
private String code = "";
private String beforeFunc = "";
private LinkedList<LLVM_Function> functions;
public static final boolean DEBUG = false;
public static final boolean STATISTIC = false;
public LLVM_Optimization(){
functions = new LinkedList<LLVM_Function>();
}
private void parseCode() throws LLVM_OptimizationException{
// Splitte in Funktionen
String[] functions = this.code.split("define ");
this.beforeFunc = functions[0];
for (int i = 1; i < functions.length; i++) {
this.functions.add(new LLVM_Function(functions[i]));
}
}
private String optimizeCode() throws LLVM_OptimizationException{
// Code steht als String in this.code
// Starte Optimierung
this.parseCode();
String outputLLVM = this.beforeFunc;
if(STATISTIC) {
System.out.println("Before optimization\n"+getStatistic());
}
int i = 0;
// Gehe Funktionen durch
for(LLVM_Function tmp : this.functions) {
// Erstelle Flussgraph
tmp.createFlowGraph();
//createGraph("func"+i, tmp);
// Optimierungsfunktionen
tmp.createRegisterMaps();
//Constant Folding
tmp.constantFolding();
// Reaching vor Lebendigkeitsanalyse
// Koennen tote Stores entstehen, also vor live variable analysis
tmp.reachingAnalysis();
// Dead register elimination
// Reaching ruft folding/propagtion auf
// Dadurch kann neuer unerreichbarer Block entstehen
// Also tote Register/Blöcke nach reaching
tmp.eliminateDeadRegisters();
tmp.eliminateDeadBlocks();
tmp.reachingAnalysis();
// CommonExpressions
// Store/Load-Paare muessen vorher eliminiert werden, also nach reaching analysis
// Wenn getelementptr zusammengefasst wird, so kann ein neues store/load-paar
// entstehen. Dieses arbeitet aber auf Arrays/Structs und wird daher nicht
// zusammengefasst.
tmp.removeCommonExpressions();
// Globale Lebendigkeitsanalyse fuer Store, Load
tmp.globalLiveVariableAnalysis();
// Entferne Bloecke, die nur unbedingten Sprungbefehl enthalten
tmp.deleteEmptyBlocks();
tmp.strengthReduction();
// Optimierte Ausgabe
tmp.updateUnnamedLabelNames();
outputLLVM += tmp.toString();
//createGraph("opt_func"+i++, tmp);
}
if(STATISTIC) {
System.out.println("After optimization\n"+getStatistic());
}
return outputLLVM;
}
private void createGraph(String filename, LLVM_Function func) {
try{
FileWriter fstream = new FileWriter(System.getProperty("user.home")+"/"+filename+".dot");
BufferedWriter out = new BufferedWriter(fstream);
out.write(func.toGraph());
out.close();
Runtime r = Runtime.getRuntime();
String[] cmds = {"/bin/sh", "-c", "/opt/local/bin/dot -Tjpg "+System.getProperty("user.home")+"/"+filename+".dot -o "+System.getProperty("user.home")+"/"+filename+".jpg"};
Process proc = r.exec(cmds);
InputStream stderr = proc.getErrorStream();
InputStreamReader isr = new InputStreamReader(stderr);
BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line = null;
while((line = br.readLine()) != null) {
System.out.println(line);
}
BufferedReader brerr = new BufferedReader(isr);
while((line = brerr.readLine()) != null) {
System.err.println(line);
}
}catch(Exception e){
System.err.println(e.getMessage());
}
}
private void readCodeFromFile(String fileName){
try {
BufferedReader fileReader = new BufferedReader(new FileReader(fileName));
String line = "";
while((line = fileReader.readLine()) != null) {
this.code = this.code + line;
this.code = this.code + "\n";
}
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public String optimizeCodeFromString(String code) throws LLVM_OptimizationException{
this.code = code;
return this.optimizeCode();
}
public String optimizeCodeFromFile(String fileName) throws LLVM_OptimizationException{
this.readCodeFromFile(fileName);
return this.optimizeCode();
}
public String getCode(){
return this.code;
}
private int getBlockCount(){
int count = 0;
for (LLVM_Function f : functions) {
count += f.getBlocks().size();
}
return count;
}
private int getCommandsCount(){
int count = 0;
for (LLVM_Function f : functions) {
for(LLVM_Block c : f.getBlocks()) {
count += c.countCommands();
}
}
return count;
}
public String getStatistic(){
String out = "";
out += "############################\n";
out += "Count Functions: "+functions.size()+"\n";
out += "Count Blocks: "+getBlockCount()+"\n";
out += "Count Commands: "+getCommandsCount()+"\n";
out += "############################\n";
return out;
}
public static void main(String args[]) {
ILLVM_Optimization optimization = new LLVM_Optimization();
try{
if(args.length>0) {
String optimizedCode = optimization.optimizeCodeFromFile(args[0]);
System.out.println(optimizedCode);
}
else {
optimization = new LLVM_Optimization();
//String optimizedCode = optimization.optimizeCodeFromFile("input/de/fuberlin/optimierung/llvm_test.llvm");
//String optimizedCode = optimization.optimizeCodeFromFile("input/de/fuberlin/optimierung/llvm_constant_folding1");
//String optimizedCode = optimization.optimizeCodeFromFile("input/de/fuberlin/optimierung/llvm_cf_prop_deadb");
//String optimizedCode = optimization.optimizeCodeFromFile("input/de/fuberlin/optimierung/llvm_lebendigkeit_global1");
//String optimizedCode = optimization.optimizeCodeFromFile("input/de/fuberlin/optimierung/llvm_dag");
//String optimizedCode = optimization.optimizeCodeFromFile("input/de/fuberlin/optimierung/llvm_dead_block");
//String optimizedCode = optimization.optimizeCodeFromFile("input/de/fuberlin/optimierung/llvm_localsub_registerprop");
//String optimizedCode = optimization.optimizeCodeFromFile("input/de/fuberlin/optimierung/llvm_clangdemo");
//String optimizedCode = optimization.optimizeCodeFromFile("input/de/fuberlin/optimierung/strength_reduction_argv.s");//test_new.ll");
//String optimizedCode = optimization.optimizeCodeFromFile("input/de/fuberlin/optimierung/llvm_maschco");//test_new.ll");
//String optimizedCode = optimization.optimizeCodeFromFile("input/de/fuberlin/optimierung/srem_test.ll");
//String optimizedCode = optimization.optimizeCodeFromFile("input/de/fuberlin/optimierung/emptyBlocksTest.s");
String optimizedCode = optimization.optimizeCodeFromFile("input/de/fuberlin/optimierung/test.s");
//String optimizedCode = optimization.optimizeCodeFromFile("input/de/fuberlin/optimierung/doubleTest1.s");
System.out.println("###########################################################");
System.out.println("################## Optimization Input #####################");
System.out.println("###########################################################");
System.out.println(optimization.getCode());
System.out.println("###########################################################");
System.out.println("################## Optimization Output ####################");
System.out.println("###########################################################");
System.out.println(optimizedCode);
}
}
catch (LLVM_OptimizationException e){
// Unoptimierten Code weiterleiten
System.out.println("; OPTIMIZATION-ERROR: " + e.getMessage());
System.out.println(optimization.getCode());
} catch (Exception e) {
e.printStackTrace();
}
}
}