// TODO simplify this mess - if IRTuples knew what block they were in public void RemoveStatement(IRTuple stmt) { foreach (IRBlock block in this.GetSetOfAllBlocks()) { block.RemoveStatement(stmt); } }
private static void DeadCodeElimination(IRGraph graph) { Dictionary <Ident, IRIdent> identAnalysis = SimpleVariableAnalysis(graph); Queue <Ident> worklist = new Queue <Ident>(identAnalysis.Keys); while (worklist.Count > 0) { Ident ident = worklist.Dequeue(); IRIdent identObj = identAnalysis[ident]; if (identObj.CountUsesites() == 0) { IRTuple defStatement = identObj.GetDefsite(); if (!defStatement.HasSideEffects()) { Console.WriteLine("SSA: Deleting tuple: " + defStatement.toString() + " as it is dead code"); HashSet <Ident> usedVars = defStatement.GetUsedVars(); foreach (Ident used in usedVars) { IRIdent usedObj = identAnalysis[used]; usedObj.DeleteUsesite(defStatement); worklist.Enqueue(used); } graph.RemoveStatement(defStatement); } } } }
public static void Main(string [] args) { List <IRTuple> irstream = new List <IRTuple>(); irstream.Add(new IRTuple(IrOp.LABEL, "F$1")); irstream.Add(new IRTupleOneOpIdent(IrOp.STORE, "T", "R2")); irstream.Add(new IRTupleOneOpIdent(IrOp.STORE, "A", "R0")); irstream.Add(new IRTupleOneOpIdent(IrOp.STORE, "B", "R1")); irstream.Add(new IRTupleOneOpImm <int>(IrOp.STORE, "C", 0)); irstream.Add(new IRTupleOneOpIdent(IrOp.STORE, "D", "A")); irstream.Add(new IRTuple(IrOp.LABEL, "L$1")); irstream.Add(new IRTupleTwoOp(IrOp.ADD, "C", "C", "B")); irstream.Add(new IRTupleOneOpImm <int>(IrOp.STORE, "T$1", 1)); irstream.Add(new IRTupleTwoOp(IrOp.SUB, "D", "D", "T$1")); irstream.Add(new IRTupleOneOpImm <int>(IrOp.STORE, "T$2", 0)); irstream.Add(new IRTupleTwoOp(IrOp.LTE, "T$3", "D", "T$2")); irstream.Add(new IRTupleOneOpIdent(IrOp.JMPF, "L$1", "T$3")); irstream.Add(new IRTupleOneOpIdent(IrOp.STORE, "R0", "C")); irstream.Add(new IRTupleOneOpIdent(IrOp.STORE, "R2", "T")); IRGraph graph = new IRGraph(irstream); List <string> livein; List <List <string> > liveouts; graph.ComputeLiveness(out livein, out liveouts); Dictionary <string, string> registerAllocation = Allocate.run(liveouts, livein); List <IRTuple> irstream_out = new List <IRTuple>(); foreach (IRTuple irt in irstream) { IRTuple translated = irt.TranslateNames(registerAllocation); irstream_out.Add(translated); } Console.WriteLine(); foreach (var kvp in registerAllocation) { Console.WriteLine("{0} : {1}", kvp.Key, kvp.Value); } Console.WriteLine(); foreach (IRTuple irt in irstream_out) { irt.Print(); Console.WriteLine(); } }
// Split an IR stream into this graph; firsts and lasts are maps of indices of the first and last index in the stream of each block private void SplitStream(List <IRTuple> tuples, out SortedDictionary <int, int> firsts, out SortedDictionary <int, int> lasts) { firsts = new SortedDictionary <int, int>(); lasts = new SortedDictionary <int, int>(); int currentIndex = BLOCK_INDEX_INITIAL; // The next block index in the graph firsts[currentIndex] = 0; // By definition, the very first tuple is the first tuple in the first block this.blocks[currentIndex] = new IRBlock(currentIndex); this.blocks[currentIndex].AppendStatement(tuples[0]); int j = 1; while (j < tuples.Count) { IRTuple tuple = tuples[j]; if (IsTerminator(tuple)) { this.blocks[currentIndex].AppendStatement(tuple); lasts[currentIndex] = j; // If we find a statement that closes current block and there is not one obviously opened by the following tuple, create a new block if (j != tuples.Count - 1 && !IsLeader(tuples[j + 1])) { currentIndex++; this.blocks[currentIndex] = new IRBlock(currentIndex); firsts[currentIndex] = j + 1; } } else { if (IsLeader(tuple)) { lasts[currentIndex] = j - 1; // If we find a statement that starts a block, create a new block currentIndex++; this.blocks[currentIndex] = new IRBlock(currentIndex); firsts[currentIndex] = j; } this.blocks[currentIndex].AppendStatement(tuple); } j++; if (j == tuples.Count) { lasts[currentIndex] = j - 1; } } }
// Establish pointers between each block in the graph and its successor blocks private void LinkSuccessors(SortedDictionary <int, int> firsts, SortedDictionary <int, int> lasts) { foreach (KeyValuePair <int, IRBlock> pair in this.blocks) { IRBlock block = pair.Value; IRTuple tup = block.GetLast(); // Get last statement in block if (tup.getOp() == IrOp.JMP) { foreach (KeyValuePair <int, IRBlock> pair0 in this.blocks) { IRBlock block0 = pair0.Value; IRTuple tup0 = block0.GetFirst(); if (tup0.getOp() == IrOp.LABEL && tup0.getDest() == tup.getDest()) { block.AddSuccessor(block0); } } } else if (tup.getOp() == IrOp.JMPF) { foreach (KeyValuePair <int, IRBlock> pair0 in this.blocks) { IRBlock block0 = pair0.Value; IRTuple tup0 = block0.GetFirst(); if (tup0.getOp() == IrOp.LABEL && tup0.getDest() == ((IRTupleOneOpIdent)tup).getDest()) { block.AddSuccessor(block0); } else if (firsts[block0.GetIndex()] == lasts[block.GetIndex()] + 1) { block.AddSuccessor(block0); } } } else { foreach (KeyValuePair <int, IRBlock> pair0 in this.blocks) { IRBlock block0 = pair0.Value; if (firsts[block0.GetIndex()] == lasts[block.GetIndex()] + 1) { block.AddSuccessor(block0); } } } } }
private static void RenameTupleSourcesHelper(IRTuple tuple, Ident replaceIdent, int numbering) { Console.WriteLine(); Console.Write("Before: "); tuple.Print(); Console.WriteLine(); if (tuple.GetType() == typeof(IRTupleTwoOp)) { IRTupleTwoOp twoTuple = (IRTupleTwoOp)tuple; if (twoTuple.getSrc2() == replaceIdent) { twoTuple.setSrc2(RenameVar(replaceIdent, numbering)); } if (twoTuple.getSrc1() == replaceIdent) { twoTuple.setSrc1(RenameVar(replaceIdent, numbering)); } } else if (tuple.GetType() == typeof(IRTupleOneOpIdent)) { IRTupleOneOpIdent oneTuple = (IRTupleOneOpIdent)tuple; if (oneTuple.getSrc1() == replaceIdent) { oneTuple.setSrc1(RenameVar(replaceIdent, numbering)); } } else { throw new Exception("You need to deal with more types: " + tuple.GetType()); } Console.Write("After: "); tuple.Print(); Console.WriteLine(); }
public static void Main(string [] args) { IRTuple[] tuples = { new IRTuple(IrOp.LABEL, "F$1"), new IRTupleOneOpIdent(IrOp.STORE, "T", "R$2"), new IRTupleOneOpIdent(IrOp.STORE, "A", "R$0"), new IRTupleOneOpIdent(IrOp.STORE, "B", "R$1"), new IRTupleOneOpImm <int>(IrOp.STORE, "C", 0), new IRTupleOneOpIdent(IrOp.STORE, "D", "A"), new IRTuple(IrOp.LABEL, "L$1"), new IRTupleTwoOp(IrOp.ADD, "C", "C", "B"), new IRTupleOneOpImm <int>(IrOp.STORE, "T$1", 1), new IRTupleTwoOp(IrOp.SUB, "D", "D", "T$1"), new IRTupleOneOpImm <int>(IrOp.STORE, "T$2", 0), new IRTupleTwoOp(IrOp.LTE, "T$3", "D", "T$2"), new IRTupleOneOpIdent(IrOp.JMPF, "L$1", "T$3"), new IRTupleOneOpIdent(IrOp.STORE, "R$0", "C"), new IRTupleOneOpIdent(IrOp.STORE, "R$2", "T") }; Dictionary <string, string> translations = new Dictionary <string, string>() { { "R$0", "R$0" }, { "R$1", "R$1" }, { "R$2", "R$2" }, { "D", "R$1" }, { "C", "R$2" }, { "B", "R$3" }, { "A", "R$0" }, { "T", "R$4" }, { "T$1", "R$0" }, { "T$2", "R$0" }, { "T$3", "R$0" } }; foreach (IRTuple irt in tuples) { irt.Print(); HashSet <Ident> usedvars = irt.GetUsedVars(); Console.Write("\tUses: "); foreach (Ident ident in usedvars) { Console.Write(ident + " "); } HashSet <Ident> definedvars = irt.GetDefinedVars(); Console.Write("\tDefines: "); foreach (Ident ident in definedvars) { Console.Write(ident + " "); } Console.WriteLine(); } Console.WriteLine("-------"); foreach (IRTuple irt in tuples) { IRTuple translated = irt.TranslateNames(translations); translated.Print(); Console.WriteLine(); } }
public void RemoveStatement(IRTuple stat) { this.statements.Remove(stat); }
private static void RenameTupleSourcesHelper(IRTuple tuple, Ident replaceIdent, int numbering) { Console.WriteLine(); Console.Write("Before: "); tuple.Print(); Console.WriteLine(); if (tuple.GetType() == typeof(IRTupleTwoOp)) { IRTupleTwoOp twoTuple = (IRTupleTwoOp)tuple; if (twoTuple.getSrc2() == replaceIdent) twoTuple.setSrc2(RenameVar(replaceIdent, numbering)); if (twoTuple.getSrc1() == replaceIdent) twoTuple.setSrc1(RenameVar(replaceIdent, numbering)); } else if (tuple.GetType() == typeof(IRTupleOneOpIdent)) { IRTupleOneOpIdent oneTuple = (IRTupleOneOpIdent)tuple; if (oneTuple.getSrc1() == replaceIdent) oneTuple.setSrc1(RenameVar(replaceIdent, numbering)); } else throw new Exception("You need to deal with more types: " + tuple.GetType()); Console.Write("After: "); tuple.Print(); Console.WriteLine(); }
public void DeleteUsesite(IRTuple stmt) { this.usesites.Remove(stmt); }
// Backward pass to determine liveness at each point in the block public void ComputeLiveouts() { this.liveouts.Clear(); Stack <List <string> > reversed = new Stack <List <string> >(); // Because this is a backward pass, lists will be found in reverse HashSet <Ident> lo = new HashSet <Ident>(this.liveout); // Extract liveness information for last statement in block IRTuple last = this.statements[this.statements.Count - 1]; HashSet <Ident> prevdef = last.GetDefinedVars(); string deflabel = ""; foreach (Ident ident in prevdef) { deflabel = ident; } HashSet <Ident> prevused = last.GetUsedVars(); List <string> lastliveout = new List <string>(); lastliveout.Add(deflabel); foreach (Ident ident in lo) { lastliveout.Add(ident); } reversed.Push(lastliveout); Console.WriteLine(); for (int i = this.statements.Count - 2; i >= 0; i--) // Start from second-last statement, as we already have liveout for last one { IRTuple tup = this.statements[i]; if (lo.Contains(deflabel)) { lo.Remove(deflabel); // Remove whatever is defined in the next statement } foreach (Ident ident in prevused) { if (!lo.Contains(ident)) { lo.Add(ident); // Add whatever is used in the next statement } } deflabel = ""; prevdef = tup.GetDefinedVars(); foreach (Ident ident in prevdef) { deflabel = ident; } prevused = tup.GetUsedVars(); List <string> currentliveout = new List <string>(); currentliveout.Add(deflabel); foreach (Ident ident in lo) { currentliveout.Add(ident); } reversed.Push(currentliveout); } while (reversed.Count > 0) { this.liveouts.Add(reversed.Pop()); } }
// Return whether a tuple is of the type that may terminate a block private bool IsTerminator(IRTuple tuple) { return(tuple.getOp() == IrOp.JMP || tuple.getOp() == IrOp.JMPF || tuple.getOp() == IrOp.RET); }
// Return whether a tuple is of the type that may start a block private bool IsLeader(IRTuple tuple) { return(tuple.getOp() == IrOp.FUNC || tuple.getOp() == IrOp.LABEL); }
public IRIdent(Ident name, IRTuple defsite) { this.name = name; this.defsite = defsite; this.usesites = new HashSet <IRTuple>(); }
/* Forwarding functions */ public void AppendStatement(IRTuple stat) { this.statements.Add(stat); }
public void AddUsesite(IRTuple stmt) { this.usesites.Add(stmt); }
public void InsertStatement(IRTuple stat, int index) { this.statements.Insert(index, stat); }
public static string IRToARM(IRTuple IR) { IRTupleOneOpIdent IROOI = IR as IRTupleOneOpIdent; IRTupleOneOpImm<string> IROOImm = IR as IRTupleOneOpImm<string>; IRTupleTwoOp IRTO = IR as IRTupleTwoOp; if(IR.getOp() == IrOp.NEG){ return "Neg " + IROOI.getDest(); } if(IR.getOp() == IrOp.ADD){ return "ADD " + IR.getDest() + ", " + IRTO.getSrc1() + ", " + IRTO.getSrc2(); } if(IR.getOp() == IrOp.SUB){ return "SUB " + IR.getDest() + ", " + IRTO.getSrc1() + ", " + IRTO.getSrc2(); } if(IR.getOp() == IrOp.AND){ return "AND " + IRTO.getDest() + ", " + IRTO.getSrc1() + ", " + IRTO.getSrc2(); } if(IR.getOp() == IrOp.MUL){ if(IRTO.getDest() != IRTO.getSrc1()){ return "MUL " + IRTO.getDest() + ", " + IRTO.getSrc1() + ", " + IRTO.getSrc2(); } else{ return "MUL " + IRTO.getDest() + ", " + IRTO.getSrc2() + ", " + IRTO.getSrc1(); } } if(IR.getOp() == IrOp.CALL){ string str = "STRMFD sp, {R1-R12, lr}\n"; str += "BL " + IROOI.getDest(); if(IR.getDest()[0] == 'R'){ str = "MOV " + IROOI.getSrc1() + ", R0"; } else{ str = "LDR " + IROOI.getSrc1() + ", R0"; } return str; } if(IR.getOp() == IrOp.RET){ string str = ""; if(IR.getDest()[0] == 'R'){ str = "MOV R0, " + IR.getDest(); } else{ str = "LDR R0, " + IR.getDest(); } str += "\nLDMFD sp, {R1-R12, pc}"; return str; } // DIV if(IR.getOp() == IrOp.EQU){ string str = "CMP " + IRTO.getSrc1() + ", " + IRTO.getSrc2() +'\n'; str += "MOVEQ " + IRTO.getDest() + ", #1\n"; str += "MOVNE " + IRTO.getDest() + ", #0"; return str; } if(IR.getOp() == IrOp.NEQ){ string str = "CMP " + IRTO.getSrc1() + ", " + IRTO.getSrc2() +'\n'; str += "MOVEQ " + IRTO.getDest() + ", #0\n"; str += "MOVNE " + IRTO.getDest() + ", #1"; return str; } if(IR.getOp() == IrOp.LT){ string str = "CMP " + IRTO.getSrc1() + ", " + IRTO.getSrc2() +'\n'; str += "MOVGE " + IRTO.getDest() + ", #0\n"; str += "MOVLT " + IRTO.getDest() + ", #1"; return str; } if(IR.getOp() == IrOp.GT){ string str = "CMP " + IRTO.getSrc1() + ", " + IRTO.getSrc2() +'\n'; str += "MOVLE " + IRTO.getDest() + ", #0\n"; str += "MOVGT " + IRTO.getDest() + ", #1"; return str; } if(IR.getOp() == IrOp.JMP){ return "JMP " + IR.getDest(); } if(IR.getOp() == IrOp.JMPF){ string str = "CMP " + IROOI.getSrc1() + ", #0\n"; str += "JMPEQ " + IROOI.getDest(); return str; } if(IR.getOp() == IrOp.LABEL){ return IR.getDest() + ':'; } if(IR.getOp() == IrOp.FUNC) { return IR.getDest() + ':'; } // MOD if(IR.getOp() == IrOp.NOT){ return "MVN " + IROOI.getDest() + ", " + IROOI.getSrc1(); } if(IR.getOp() == IrOp.OR){ return "ORR " + IRTO.getDest() + ", " + IRTO.getSrc1() + ", " + IRTO.getSrc2(); } if(IR.getOp() == IrOp.XOR){ return "EOR " + IRTO.getDest() + ", " + IRTO.getSrc1() + ", " + IRTO.getSrc2(); } if(IR.getOp() == IrOp.STORE){ if(IR.getDest()[0] == 'R'){ return "LDR " + IROOI.getDest() + ", " + IROOI.getSrc1(); } return "STR " + IROOI.getDest() + ", " + IROOI.getSrc1(); } IR.Print(); return ""; }
public static string IRToARM(IRTuple IR) { IRTupleOneOpIdent IROOI = IR as IRTupleOneOpIdent; IRTupleOneOpImm <string> IROOImm = IR as IRTupleOneOpImm <string>; IRTupleTwoOp IRTO = IR as IRTupleTwoOp; if (IR.getOp() == IrOp.NEG) { return("Neg " + IROOI.getDest()); } if (IR.getOp() == IrOp.ADD) { return("ADD " + IR.getDest() + ", " + IRTO.getSrc1() + ", " + IRTO.getSrc2()); } if (IR.getOp() == IrOp.SUB) { return("SUB " + IR.getDest() + ", " + IRTO.getSrc1() + ", " + IRTO.getSrc2()); } if (IR.getOp() == IrOp.AND) { return("AND " + IRTO.getDest() + ", " + IRTO.getSrc1() + ", " + IRTO.getSrc2()); } if (IR.getOp() == IrOp.MUL) { if (IRTO.getDest() != IRTO.getSrc1()) { return("MUL " + IRTO.getDest() + ", " + IRTO.getSrc1() + ", " + IRTO.getSrc2()); } else { return("MUL " + IRTO.getDest() + ", " + IRTO.getSrc2() + ", " + IRTO.getSrc1()); } } if (IR.getOp() == IrOp.CALL) { string str = "STRMFD sp, {R1-R12, lr}\n"; str += "BL " + IROOI.getDest(); if (IR.getDest()[0] == 'R') { str = "MOV " + IROOI.getSrc1() + ", R0"; } else { str = "LDR " + IROOI.getSrc1() + ", R0"; } return(str); } if (IR.getOp() == IrOp.RET) { string str = ""; if (IR.getDest()[0] == 'R') { str = "MOV R0, " + IR.getDest(); } else { str = "LDR R0, " + IR.getDest(); } str += "\nLDMFD sp, {R1-R12, pc}"; return(str); } // DIV if (IR.getOp() == IrOp.EQU) { string str = "CMP " + IRTO.getSrc1() + ", " + IRTO.getSrc2() + '\n'; str += "MOVEQ " + IRTO.getDest() + ", #1\n"; str += "MOVNE " + IRTO.getDest() + ", #0"; return(str); } if (IR.getOp() == IrOp.NEQ) { string str = "CMP " + IRTO.getSrc1() + ", " + IRTO.getSrc2() + '\n'; str += "MOVEQ " + IRTO.getDest() + ", #0\n"; str += "MOVNE " + IRTO.getDest() + ", #1"; return(str); } if (IR.getOp() == IrOp.LT) { string str = "CMP " + IRTO.getSrc1() + ", " + IRTO.getSrc2() + '\n'; str += "MOVGE " + IRTO.getDest() + ", #0\n"; str += "MOVLT " + IRTO.getDest() + ", #1"; return(str); } if (IR.getOp() == IrOp.GT) { string str = "CMP " + IRTO.getSrc1() + ", " + IRTO.getSrc2() + '\n'; str += "MOVLE " + IRTO.getDest() + ", #0\n"; str += "MOVGT " + IRTO.getDest() + ", #1"; return(str); } if (IR.getOp() == IrOp.JMP) { return("JMP " + IR.getDest()); } if (IR.getOp() == IrOp.JMPF) { string str = "CMP " + IROOI.getSrc1() + ", #0\n"; str += "JMPEQ " + IROOI.getDest(); return(str); } if (IR.getOp() == IrOp.LABEL) { return(IR.getDest() + ':'); } if (IR.getOp() == IrOp.FUNC) { return(IR.getDest() + ':'); } // MOD if (IR.getOp() == IrOp.NOT) { return("MVN " + IROOI.getDest() + ", " + IROOI.getSrc1()); } if (IR.getOp() == IrOp.OR) { return("ORR " + IRTO.getDest() + ", " + IRTO.getSrc1() + ", " + IRTO.getSrc2()); } if (IR.getOp() == IrOp.XOR) { return("EOR " + IRTO.getDest() + ", " + IRTO.getSrc1() + ", " + IRTO.getSrc2()); } if (IR.getOp() == IrOp.STORE) { if (IR.getDest()[0] == 'R') { return("LDR " + IROOI.getDest() + ", " + IROOI.getSrc1()); } return("STR " + IROOI.getDest() + ", " + IROOI.getSrc1()); } IR.Print(); return(""); }