Example #1
1
		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);
		}
Example #2
0
		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);
			}
		}
Example #3
0
		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());
			}
		}
Example #4
0
		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);
		}
Example #5
0
		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;
			}
		}
Example #6
0
			public int GetPathLength(BasicBlock s, BasicBlock t)
			{
				return GetPathLength(bblist.IndexOf(s), bblist.IndexOf(t));
			}
Example #7
0
			public Stack<BasicBlock> GetPath(BasicBlock s, BasicBlock t)
			{
				return new Stack<BasicBlock>(GetPath(bblist.IndexOf(s), bblist.IndexOf(t)).Select(
					i => bblist[i]).Reverse());
			}
Example #8
0
		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());

			}
		}
Example #9
0
		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--;
		}
Example #10
0
		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);
		}
Example #11
0
        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());
        }
Example #12
0
 public Stack <BasicBlock> GetPath(BasicBlock s, BasicBlock t)
 {
     return(new Stack <BasicBlock>(GetPath(bblist.IndexOf(s), bblist.IndexOf(t)).Select(
                                       i => bblist[i]).Reverse()));
 }
Example #13
0
 public int GetPathLength(BasicBlock s, BasicBlock t)
 {
     return(GetPathLength(bblist.IndexOf(s), bblist.IndexOf(t)));
 }
Example #14
0
        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());
            }
        }