private static BasicBlock InlineIR(this CALLInstruction call, IList<BasicBlockInstruction> preamble, BasicBlock backend, Dictionary<Subprogram, Dictionary<VirtualRegister, VirtualRegister>> inlineRegMaps) { Dictionary<VirtualRegister, VirtualRegister> inlineRegMap; if (!inlineRegMaps.TryGetValue(call.Target, out inlineRegMap)) { inlineRegMap = call.Target.LocalVariables.Select(lv => new KeyValuePair<VirtualRegister, VirtualRegister>(lv, new VirtualRegister(lv.UnderlyingType, lv.StateSpace))). ToDictionary(kvp => kvp.Key, kvp => kvp.Value); inlineRegMaps.Add(call.Target, inlineRegMap); } inlineRegMap = inlineRegMap.Concat(call.Target.FormalParameters.Zip(call.Arguments, (formal, actual) => new KeyValuePair<VirtualRegister, VirtualRegister>(formal, (actual is VirtualRegister) ? (actual as VirtualRegister) : (formal.StateSpace != StateSpaces.REG) ? new VirtualRegister(formal.UnderlyingType, formal.StateSpace) : new VirtualRegister(formal.DataType)))). ToDictionary(kvp => kvp.Key, kvp => kvp.Value); Dictionary<BasicBlock, BasicBlock> cfgmap = call.Target.GetBasicBlocks().Select(bb => { VirtualRegister flag = (bb.Trailer is JumpIfInstruction) ? (bb.Trailer as JumpIfInstruction).Flag.MapOperand(inlineRegMap) : null; ControlFlowInstruction trailer; switch (bb.Trailer.OpCode) { case IROpCodes.RET: trailer = new JMPInstruction() { Target = backend }; break; case IROpCodes.JMP: trailer = new JMPInstruction(); break; case IROpCodes.JT: trailer = new JTInstruction(flag); break; case IROpCodes.JF: trailer = new JFInstruction(flag); break; default: throw new NotSupportedException(); } return new KeyValuePair<BasicBlock, BasicBlock>(bb, new BasicBlock(bb.Code.Select(bbi => bbi.MapInstruction(inlineRegMap)).ToList(), trailer)); }).ToDictionary(kvp => kvp.Key, kvp => kvp.Value); foreach (KeyValuePair<BasicBlock, BasicBlock> bbmap in cfgmap) { if (bbmap.Key.Successor != null) bbmap.Value.Successor = cfgmap[bbmap.Key.Successor]; if (bbmap.Key.Target != null) bbmap.Value.Target = cfgmap[bbmap.Key.Target]; } BasicBlock root = cfgmap[call.Target.CFGRoot]; return new BasicBlock(preamble.Concat(root.Code).ToList(), root.Trailer); }
private void Enumerate(BasicBlock bb, Action<BasicBlock> handler, IList<BasicBlock> visited) { if (bb != null && !visited.Contains(bb)) { handler(bb); visited.Add(bb); Enumerate(bb.Successor, handler, visited); Enumerate(bb.Target, handler, visited); } }
private static string ToPTX(this ControlFlowInstruction cfi, BasicBlock following) { JumpInstruction jump = cfi as JumpInstruction; JumpIfInstruction jumpif = cfi as JumpIfInstruction; switch (cfi.OpCode) { case IROpCodes.JMP: return jump.Target == following ? "" : "bra.uni " + jump.Target.Label + ";\n"; case IROpCodes.JT: return "setp.ne." + jumpif.Flag.DataType.ToPTX() + " %p, 0, " + jumpif.Flag + ";\n" + "@%p bra.uni " + jump.Target.Label + ";\n" + (jumpif.Next == following ? "" : "bra.uni " + jumpif.Next.Label + ";\n"); case IROpCodes.JF: return "setp.eq." + jumpif.Flag.DataType.ToPTX() + " %p, 0, " + jumpif.Flag + ";\n" + "@%p bra.uni " + jump.Target.Label + ";\n" + (jumpif.Next == following ? "" : "bra.uni " + jumpif.Next.Label + ";\n"); case IROpCodes.RET: return "ret;\n"; default: throw new NotSupportedException(cfi.OpCode.ToString()); } }
private static string ToPTX(this BasicBlock bb, BasicBlock following) { string bbcode = string.Join("\n", bb.Code.Select(bbi => bbi.ToPTX() + ";")); return bb.Label + ":\n" + (bbcode != "" ? bbcode + "\n" : "") + bb.Trailer.ToPTX(following); }
private static BasicBlock InlineIR(this IList<BasicBlockInstruction> code, ControlFlowInstruction trailer, Func<Subprogram, bool> permitInline, Dictionary<VirtualRegister, VirtualRegister> copyRegMap, Dictionary<Subprogram, Dictionary<VirtualRegister, VirtualRegister>> inlineRegMaps, IList<Subprogram> subprograms, out BasicBlock backend) { List<BasicBlockInstruction> preamble = new List<BasicBlockInstruction>(); int i = 0; while (i < code.Count && !(code[i].OpCode == IROpCodes.CALL && permitInline(subprograms.Single(sp => sp.Name == (code[i] as CALLInstruction).Target.Name)))) preamble.Add(code[i++].MapInstruction(copyRegMap)); if (i < code.Count) { CALLInstruction call = code[i++] as CALLInstruction; call = new CALLInstruction(subprograms.Single(sp => sp.Name == call.Target.Name), call.Arguments.Select(op => op.MapOperand(copyRegMap)).ToList()); List<BasicBlockInstruction> tail = new List<BasicBlockInstruction>(); while (i < code.Count) tail.Add(code[i++]); return call.InlineIR(preamble, tail.InlineIR(trailer, permitInline, copyRegMap, inlineRegMaps, subprograms, out backend), inlineRegMaps); } else { backend = new BasicBlock(preamble, trailer); return backend; } }
public int GetPathLength(BasicBlock s, BasicBlock t) { return GetPathLength(bblist.IndexOf(s), bblist.IndexOf(t)); }
public Stack<BasicBlock> GetPath(BasicBlock s, BasicBlock t) { return new Stack<BasicBlock>(GetPath(bblist.IndexOf(s), bblist.IndexOf(t)).Select( i => bblist[i]).Reverse()); }
private static BasicBlock HandleBranch( ControlFlowInstruction cfi, BasicBlock enclosing_loop_frontier, IList<BasicBlock> bblist, Dictionary<BasicBlock, IEnumerable<BasicBlock>> pred, Dictionary<BasicBlock, List<BasicBlock>> dom, GraphPathFinder path_finder, List<TreeStatement> code) { JumpInstruction jump = cfi as JumpInstruction; JumpIfInstruction jumpif = cfi as JumpIfInstruction; switch (cfi.OpCode) { case IROpCodes.RET: return null; case IROpCodes.JMP: return jump.Target; case IROpCodes.JT: case IROpCodes.JF: { // loop condition check if (jumpif.Target == enclosing_loop_frontier) { // while-do break condition check code.Add(new BranchStatement( jumpif.Flag, cfi.OpCode == IROpCodes.JT ? new TreeStatement[] { new BreakStatement() } : null, cfi.OpCode == IROpCodes.JF ? new TreeStatement[] { new BreakStatement() } : null)); return jumpif.Next; } if (jumpif.Next == enclosing_loop_frontier) { // do-while continue condition check code.Add(new BranchStatement( jumpif.Flag, cfi.OpCode == IROpCodes.JF ? new TreeStatement[] { new BreakStatement() } : null, cfi.OpCode == IROpCodes.JT ? new TreeStatement[] { new BreakStatement() } : null)); return jumpif.Target; } // initialize IF statement frontier with enclosing loop frontier or the last block in CFG BasicBlock frontier = (enclosing_loop_frontier != null) ? enclosing_loop_frontier : bblist.Single(bb => bb.Trailer.OpCode == IROpCodes.RET); // precise IF statement frontier with last common block in reversed paths going // from initial frontier value to both successors of basic block ending with this branch IEnumerator<BasicBlock> targetPathRev = path_finder.GetPath(jumpif.Target, frontier).Reverse().GetEnumerator(); IEnumerator<BasicBlock> nextPathRev = path_finder.GetPath(jumpif.Next, frontier).Reverse().GetEnumerator(); while (targetPathRev.MoveNext() && nextPathRev.MoveNext() && targetPathRev.Current == nextPathRev.Current) frontier = targetPathRev.Current; List<TreeStatement> trueBranchCode = new List<TreeStatement>(); List<TreeStatement> falseBranchCode = new List<TreeStatement>(); BasicBlock cursor; cursor = cfi.OpCode == IROpCodes.JT ? jumpif.Target : jumpif.Next; while (cursor != frontier) cursor = HandleStatement(cursor, null, bblist, pred, dom, path_finder, trueBranchCode); cursor = cfi.OpCode == IROpCodes.JF ? jumpif.Target : jumpif.Next; while (cursor != frontier) cursor = HandleStatement(cursor, null, bblist, pred, dom, path_finder, falseBranchCode); code.Add(new BranchStatement(jumpif.Flag, trueBranchCode, falseBranchCode)); return frontier; } default: throw new NotSupportedException(cfi.OpCode.ToString()); } }
private static void NumDepth(BasicBlock n, Dictionary<BasicBlock, int> dfn, ref int c, IList<BasicBlock> visited) { visited.Add(n); foreach (BasicBlock s in new [] { n.Successor, n.Target }) { if (s != null && !visited.Contains(s)) NumDepth(s, dfn, ref c, visited); } dfn[n] = c--; }
private static BasicBlock HandleStatement( BasicBlock start, BasicBlock enclosing_loop_frontier, IList<BasicBlock> bblist, Dictionary<BasicBlock, IEnumerable<BasicBlock>> pred, Dictionary<BasicBlock, List<BasicBlock>> dom, GraphPathFinder path_finder, List<TreeStatement> code) { BasicBlock loop_tail; try { loop_tail = pred[start].Where(bb => dom[bb].Contains(start)).SingleOrDefault(); } catch (InvalidOperationException e) { throw new IrreducibleCFGException("Loop must have only one route to its header from its body"); } if (loop_tail != null) { IEnumerable<BasicBlock> loop_insiders = bblist.Where( bb => path_finder.GetPathLength(bb, loop_tail) < (int)short.MaxValue && !path_finder.GetPath(bb, loop_tail).Contains(start) && dom[bb].Contains(start)).Add(start); BasicBlock loop_frontier; try { loop_frontier = (from insider in loop_insiders from adj in new [] { insider.Target, insider.Successor } where adj != null && !loop_insiders.Contains(adj) select adj).Single(); } catch (InvalidOperationException e) { throw new IrreducibleCFGException("Loop must have only one exit route from its body"); } List<TreeStatement> loop_body = start.Code.Select(bbi => new InstructionStatement(bbi) as TreeStatement).ToList(); BasicBlock statement_cursor = HandleBranch(start.Trailer, loop_frontier, bblist, pred, dom, path_finder, loop_body); while (statement_cursor != start) statement_cursor = HandleStatement(statement_cursor, loop_frontier, bblist, pred, dom, path_finder, loop_body); code.Add(new InfiniteLoopStatement(loop_body)); return loop_frontier; } code.AddRange(start.Code.Select(bbi => new InstructionStatement(bbi))); return HandleBranch(start.Trailer, enclosing_loop_frontier, bblist, pred, dom, path_finder, code); }
public static IList <TreeStatement> BuildAST(this Subprogram src) { IList <BasicBlock> bblist = src.GetBasicBlocks(); Dictionary <BasicBlock, IEnumerable <BasicBlock> > pred = bblist.Select(bb => new KeyValuePair <BasicBlock, IEnumerable <BasicBlock> >(bb, bblist.Where(bbel => bbel.Successor == bb || bbel.Target == bb))). ToDictionary(kvp => kvp.Key, kvp => kvp.Value); // Determine dominators. Dictionary <BasicBlock, List <BasicBlock> > dom = bblist.Select(bb => new KeyValuePair <BasicBlock, List <BasicBlock> >(bb, bb == src.CFGRoot ? new List <BasicBlock> { src.CFGRoot } : bblist.ToList())). ToDictionary(kvp => kvp.Key, kvp => kvp.Value); bool changes = true; while (changes) { changes = false; foreach (BasicBlock n in bblist) { if (n != src.CFGRoot) { IEnumerable <BasicBlock> doms = null; foreach (BasicBlock p in pred[n]) { doms = (doms == null) ? dom[p] : doms.Intersect(dom[p]); } doms = doms.Union(new [] { n }); if (!doms.SequenceEqual(dom[n])) { changes = true; dom[n] = new List <BasicBlock>(doms); } } } } // Perform depth-first enumeration. Dictionary <BasicBlock, int> dfn = bblist.Select(bb => new KeyValuePair <BasicBlock, int>(bb, 0)). ToDictionary(kvp => kvp.Key, kvp => kvp.Value); int c = bblist.Count; NumDepth(src.CFGRoot, dfn, ref c, new List <BasicBlock>()); // Test CFG reducibility: each retreating edge must be back edge. foreach (BasicBlock sbb in bblist) { foreach (BasicBlock tbb in new [] { sbb.Successor, sbb.Target }) { if (tbb != null && dfn[tbb] < dfn[sbb] && !dom[sbb].Contains(tbb)) { throw new IrreducibleCFGException("There is non-back retreating edge"); } } } if (bblist.Where(bb => bb.Trailer.OpCode == IROpCodes.RET).Count() != 1) { throw new IrreducibleCFGException("Control flow graph must have single node with RET ending"); } List <TreeStatement> code = new List <TreeStatement>(); BasicBlock cur = src.CFGRoot; GraphPathFinder path_finder = new GraphPathFinder(bblist); while (cur != null) { cur = HandleStatement(cur, null, bblist, pred, dom, path_finder, code); } return(code.AsReadOnly()); }
public Stack <BasicBlock> GetPath(BasicBlock s, BasicBlock t) { return(new Stack <BasicBlock>(GetPath(bblist.IndexOf(s), bblist.IndexOf(t)).Select( i => bblist[i]).Reverse())); }
public int GetPathLength(BasicBlock s, BasicBlock t) { return(GetPathLength(bblist.IndexOf(s), bblist.IndexOf(t))); }
private static BasicBlock HandleBranch( ControlFlowInstruction cfi, BasicBlock enclosing_loop_frontier, IList <BasicBlock> bblist, Dictionary <BasicBlock, IEnumerable <BasicBlock> > pred, Dictionary <BasicBlock, List <BasicBlock> > dom, GraphPathFinder path_finder, List <TreeStatement> code) { JumpInstruction jump = cfi as JumpInstruction; JumpIfInstruction jumpif = cfi as JumpIfInstruction; switch (cfi.OpCode) { case IROpCodes.RET: return(null); case IROpCodes.JMP: return(jump.Target); case IROpCodes.JT: case IROpCodes.JF: { // loop condition check if (jumpif.Target == enclosing_loop_frontier) { // while-do break condition check code.Add(new BranchStatement( jumpif.Flag, cfi.OpCode == IROpCodes.JT ? new TreeStatement[] { new BreakStatement() } : null, cfi.OpCode == IROpCodes.JF ? new TreeStatement[] { new BreakStatement() } : null)); return(jumpif.Next); } if (jumpif.Next == enclosing_loop_frontier) { // do-while continue condition check code.Add(new BranchStatement( jumpif.Flag, cfi.OpCode == IROpCodes.JF ? new TreeStatement[] { new BreakStatement() } : null, cfi.OpCode == IROpCodes.JT ? new TreeStatement[] { new BreakStatement() } : null)); return(jumpif.Target); } // initialize IF statement frontier with enclosing loop frontier or the last block in CFG BasicBlock frontier = (enclosing_loop_frontier != null) ? enclosing_loop_frontier : bblist.Single(bb => bb.Trailer.OpCode == IROpCodes.RET); // precise IF statement frontier with last common block in reversed paths going // from initial frontier value to both successors of basic block ending with this branch IEnumerator <BasicBlock> targetPathRev = path_finder.GetPath(jumpif.Target, frontier).Reverse().GetEnumerator(); IEnumerator <BasicBlock> nextPathRev = path_finder.GetPath(jumpif.Next, frontier).Reverse().GetEnumerator(); while (targetPathRev.MoveNext() && nextPathRev.MoveNext() && targetPathRev.Current == nextPathRev.Current) { frontier = targetPathRev.Current; } List <TreeStatement> trueBranchCode = new List <TreeStatement>(); List <TreeStatement> falseBranchCode = new List <TreeStatement>(); BasicBlock cursor; cursor = cfi.OpCode == IROpCodes.JT ? jumpif.Target : jumpif.Next; while (cursor != frontier) { cursor = HandleStatement(cursor, null, bblist, pred, dom, path_finder, trueBranchCode); } cursor = cfi.OpCode == IROpCodes.JF ? jumpif.Target : jumpif.Next; while (cursor != frontier) { cursor = HandleStatement(cursor, null, bblist, pred, dom, path_finder, falseBranchCode); } code.Add(new BranchStatement(jumpif.Flag, trueBranchCode, falseBranchCode)); return(frontier); } default: throw new NotSupportedException(cfi.OpCode.ToString()); } }