public static bool Any(ICode ast) { var v = new VisitorFindContinuationsRecursive(); v.Visit(ast); return(v.Continuations.Any()); }
public static IEnumerable <StmtContinuation> Get(ICode ast) { var v = new VisitorFindContinuationsRecursive(); v.Visit(ast); return(v.Continuations); }
public static ICode V(ICode ast) { var ctx = ast.Ctx; var blockInfo = VisitorSubstituteIrreducable.FindSuitableBlocks.GetInfo(ast); var bInfo = blockInfo.Select(x => new { toCount = VisitorContToCounter.GetCount(x.Key, ast), ast = x.Key, codeCount = x.Value.numICodes, }).ToArray(); var block = bInfo.Where(x => x.toCount >= 2).OrderBy(x => x.toCount * x.codeCount).FirstOrDefault(); if (block == null) { return(ast); } var phis = new Dictionary <Expr, Expr>(); var blockCopies = Enumerable.Range(0, block.toCount - 1) .Select(x => { var v = new VisitorDuplicateCode(); var ret = v.Visit(block.ast); phis = phis.Merge(v.phiMap, (a, b) => new ExprVarPhi(ctx) { Exprs = new[] { a, b } }); return(ret); }) .Concat(block.ast) .ToArray(); var contTos = VisitorFindContinuationsRecursive.Get(ast).Where(x => x.To == block.ast).ToArray(); for (int i = 0; i < contTos.Length; i++) { var contTo = contTos[i]; var blockCopy = blockCopies[i]; ast = VisitorReplace.V(ast, contTo, blockCopy); } ast = VisitorReplaceExprUse.V(ast, phis); return(ast); }
public static ICode V(ICode ast) { var ctx = ast.Ctx; var blockInfo = FindSuitableBlocks.GetInfo(ast); var bestBlock = blockInfo .Where(x => !x.Value.containsLeaveProtectedRegion && x.Value.numConts <= 1) .OrderBy(x => x.Value.numConts == 0 ? 1000 : x.Value.numConts) .ThenBy(x => x.Value.numICodes) .FirstOrDefault(); if (bestBlock.Key == null) { return(ast); } if (bestBlock.Value.numConts > 1) { // Best block must have just one continuation return(ast); } Stmt addContTo = null; if (bestBlock.Value.numConts == 0) { addContTo = (Stmt)blockInfo.FirstOrDefault(x => x.Value.numConts == 0 && x.Key != bestBlock.Key).Key; if (addContTo == null) { return(ast); } } var blockAst = (Stmt)bestBlock.Key; if (blockAst.StmtType != Stmt.NodeType.Block) { // Best block must be StmtBlock return(ast); } var stmtBlock = (StmtBlock)blockAst; var stmts = stmtBlock.Statements.ToArray(); var cont = bestBlock.Value.numConts == 0 ? new StmtContinuation(ctx, addContTo, false) : (StmtContinuation)stmts.Last(); var ifSkipContentPhi = new ExprVarPhi(ctx); var ifSkipInitialVar = ctx.Local(ctx.Boolean); var ifSkipContentVar = ctx.Local(ctx.Boolean); var ifSkipContentPhiExprs = new List <Expr> { ifSkipInitialVar, ifSkipContentVar }; var ifSkipReset = new StmtAssignment(ctx, ifSkipContentVar, ctx.Literal(false)); var inIfBlock = new StmtBlock(ctx, stmts.Take(stmts.Length - (bestBlock.Value.numConts == 0 ? 0 : 1))); var ifBlock = new StmtIf(ctx, ctx.ExprGen.Not(ifSkipContentPhi), inIfBlock, null); var newBlock = new StmtBlock(ctx, ifBlock, ifSkipReset, cont); ast = VisitorReplace.V(ast, blockAst, newBlock); var allConts = VisitorFindContinuationsRecursive.Get(ast); var contsNeedChanging = allConts.Where(x => x != cont && x.To == cont.To).ToArray(); var contsReplaceInfo = contsNeedChanging .Select(x => { var ifVar = ctx.Local(ctx.Boolean); var newCont = new StmtBlock(ctx, new StmtAssignment(ctx, ifVar, ctx.Literal(true)), new StmtContinuation(ctx, newBlock, x.LeaveProtectedRegion)); return(new { oldCont = x, ifVar, newCont }); }) .ToArray(); foreach (var contReplace in contsReplaceInfo) { ifSkipContentPhiExprs.Add(contReplace.ifVar); ast = VisitorReplace.V(ast, contReplace.oldCont, contReplace.newCont); } ifSkipContentPhi.Exprs = ifSkipContentPhiExprs; // TODO: Shouldn't be required, but definite-assignment doesn't quite work properly, so is required var initalSkipVarAssignment = new StmtAssignment(ctx, ifSkipInitialVar, ctx.Literal(false)); var newAst = new StmtBlock(ctx, initalSkipVarAssignment, (Stmt)ast); return(newAst); }
public static IEnumerable<StmtContinuation> Get(ICode ast) { var v = new VisitorFindContinuationsRecursive(); v.Visit(ast); return v.Continuations; }
public static bool Any(ICode ast) { var v = new VisitorFindContinuationsRecursive(); v.Visit(ast); return v.Continuations.Any(); }