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);
        }
Пример #3
0
        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);
        }
Пример #4
0
        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();
 }