/// <summary> /// Simplifies the CFG of the given implementation impl by merging each /// basic block with a single predecessor into that predecessor if the /// predecessor has a single successor. If a uniformity analyser is /// being used then blocks will only be merged if they are both uniform /// or both non-uniform /// </summary> public static void MergeBlocksIntoPredecessors(Program prog, Implementation impl, UniformityAnalyser uni) { var blockGraph = prog.ProcessLoops(impl); var predMap = new Dictionary<Block, Block>(); foreach (var block in blockGraph.Nodes) { try { var pred = blockGraph.Predecessors(block).Single(); if (blockGraph.Successors(pred).Single() == block && (uni == null || (uni.IsUniform(impl.Name, pred) && uni.IsUniform(impl.Name, block)) || (!uni.IsUniform(impl.Name, pred) && !uni.IsUniform(impl.Name, block)))) { Block predMapping; while (predMap.TryGetValue(pred, out predMapping)) pred = predMapping; pred.Cmds.AddRange(block.Cmds); pred.TransferCmd = block.TransferCmd; impl.Blocks.Remove(block); predMap[block] = pred; } // If Single throws an exception above (i.e. not exactly one pred/succ), skip this block. } catch (InvalidOperationException) { } } }
public static void Predicate(Program p, Func<Procedure, bool> useProcedurePredicates = null, UniformityAnalyser uni = null) { useProcedurePredicates = useProcedurePredicates ?? (proc => false); if (uni != null) { var oldUPP = useProcedurePredicates; useProcedurePredicates = proc => oldUPP(proc) && !uni.IsUniform(proc.Name); } foreach (var decl in p.TopLevelDeclarations.ToList()) { if (decl is Procedure || decl is Implementation) { var proc = decl as Procedure; Implementation impl = null; if (proc == null) { impl = (Implementation)decl; proc = impl.Proc; } bool upp = useProcedurePredicates(proc); if (upp) { var dwf = (DeclWithFormals)decl; var fpVar = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "_P", Microsoft.Boogie.Type.Bool), /*incoming=*/true); dwf.InParams = new List<Variable>( (new Variable[] {fpVar}.Concat(dwf.InParams.Cast<Variable>())) .ToArray()); if (impl == null) { var fpIdentifierExpr = new IdentifierExpr(Token.NoToken, fpVar); foreach (Requires r in proc.Requires) { new EnabledReplacementVisitor(fpIdentifierExpr).VisitExpr(r.Condition); if (!QKeyValue.FindBoolAttribute(r.Attributes, "do_not_predicate")) { r.Condition = Expr.Imp(fpIdentifierExpr, r.Condition); } } foreach (Ensures e in proc.Ensures) { new EnabledReplacementVisitor(new IdentifierExpr(Token.NoToken, fpVar)).VisitExpr(e.Condition); if (!QKeyValue.FindBoolAttribute(e.Attributes, "do_not_predicate")) { e.Condition = Expr.Imp(fpIdentifierExpr, e.Condition); } } } } if (impl != null) { try { new SmartBlockPredicator(p, impl, useProcedurePredicates, uni).PredicateImplementation(); } catch (Program.IrreducibleLoopException) { } } } } }
public static void Predicate(Program p, Func <Procedure, bool> useProcedurePredicates = null, UniformityAnalyser uni = null) { useProcedurePredicates = useProcedurePredicates ?? (proc => false); if (uni != null) { var oldUPP = useProcedurePredicates; useProcedurePredicates = proc => oldUPP(proc) && !uni.IsUniform(proc.Name); } foreach (var decl in p.TopLevelDeclarations.ToList()) { if (decl is Procedure || decl is Implementation) { var proc = decl as Procedure; Implementation impl = null; if (proc == null) { impl = (Implementation)decl; proc = impl.Proc; } bool upp = useProcedurePredicates(proc); if (upp) { var dwf = (DeclWithFormals)decl; var fpVar = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "_P", Microsoft.Boogie.Type.Bool), /*incoming=*/ true); dwf.InParams = new List <Variable>( (new Variable[] { fpVar }.Concat(dwf.InParams.Cast <Variable>())) .ToArray()); if (impl == null) { var fpIdentifierExpr = new IdentifierExpr(Token.NoToken, fpVar); foreach (Requires r in proc.Requires) { new EnabledReplacementVisitor(fpIdentifierExpr, Expr.True).VisitExpr(r.Condition); if (!QKeyValue.FindBoolAttribute(r.Attributes, "do_not_predicate")) { r.Condition = Expr.Imp(fpIdentifierExpr, r.Condition); } } foreach (Ensures e in proc.Ensures) { new EnabledReplacementVisitor(new IdentifierExpr(Token.NoToken, fpVar), Expr.True).VisitExpr(e.Condition); if (!QKeyValue.FindBoolAttribute(e.Attributes, "do_not_predicate")) { e.Condition = Expr.Imp(fpIdentifierExpr, e.Condition); } } } } else { if (impl == null) { foreach (Requires r in proc.Requires) { new EnabledReplacementVisitor(Expr.True, Expr.True).VisitExpr(r.Condition); } foreach (Ensures e in proc.Ensures) { new EnabledReplacementVisitor(Expr.True, Expr.True).VisitExpr(e.Condition); } } } if (impl != null) { try { new SmartBlockPredicator(p, impl, useProcedurePredicates, uni).PredicateImplementation(); } catch (Program.IrreducibleLoopException) { } } } } }
// hasPredicatedRegion is true iff the block or its targets are predicated // (i.e. we enter, stay within or exit a predicated region). void PredicateTransferCmd(Expr p, Block src, List <Cmd> cmdSeq, TransferCmd cmd, out bool hasPredicatedRegion) { hasPredicatedRegion = predMap.ContainsKey(src); if (cmd is GotoCmd) { var gCmd = (GotoCmd)cmd; hasPredicatedRegion = hasPredicatedRegion || gCmd.labelTargets.Cast <Block>().Any(b => predMap.ContainsKey(b)); if (gCmd.labelTargets.Count == 1) { if (defMap.ContainsKey(gCmd.labelTargets[0])) { PredicateCmd(p, Expr.True, cmdSeq, Cmd.SimpleAssign(Token.NoToken, Expr.Ident(predMap[gCmd.labelTargets[0]]), Expr.True)); } } else { Debug.Assert(gCmd.labelTargets.Count > 1); Debug.Assert(gCmd.labelTargets.Cast <Block>().All(t => uni.IsUniform(impl.Name, t) || partInfo.ContainsKey(t))); foreach (Block target in gCmd.labelTargets) { if (!partInfo.ContainsKey(target)) { continue; } // In this case we not only predicate with the current predicate p, // but also with the "part predicate"; this ensures that we do not // update a predicate twice when it occurs in both parts. var part = partInfo[target]; if (defMap.ContainsKey(part.realDest)) { PredicateCmd(p == null ? part.pred : Expr.And(p, part.pred), Expr.True, cmdSeq, Cmd.SimpleAssign(Token.NoToken, Expr.Ident(predMap[part.realDest]), part.pred)); } var predsExitingLoop = new Dictionary <Block, List <Expr> >(); foreach (Block exit in LoopsExited(src, target)) { List <Expr> predList; if (!predsExitingLoop.ContainsKey(exit)) { predList = predsExitingLoop[exit] = new List <Expr>(); } else { predList = predsExitingLoop[exit]; } predList.Add(part.pred); } foreach (var pred in predsExitingLoop) { PredicateCmd(p == null ? part.pred : Expr.And(p, part.pred), Expr.True, cmdSeq, Cmd.SimpleAssign(Token.NoToken, Expr.Ident(predMap[pred.Key]), Expr.Not(pred.Value.Aggregate(Expr.Or)))); } } } } else if (cmd is ReturnCmd) { // Blocks which end in a return will never share a predicate with a block // which appears after it. Furthermore, such a block cannot be part of a // loop. So it is safe to do nothing here. } else { Console.WriteLine("Unsupported cmd: " + cmd.GetType().ToString()); } }
public static void Predicate(Program p, Func <Procedure, bool> useProcedurePredicates = null, UniformityAnalyser uni = null) { useProcedurePredicates = useProcedurePredicates ?? (proc => false); if (uni != null) { var oldUPP = useProcedurePredicates; useProcedurePredicates = proc => oldUPP(proc) && !uni.IsUniform(proc.Name); } foreach (var decl in p.TopLevelDeclarations.ToList()) { if (decl is Procedure || decl is Implementation) { var proc = decl as Procedure; Implementation impl = null; if (proc == null) { impl = (Implementation)decl; proc = impl.Proc; } bool upp = useProcedurePredicates(proc); if (upp) { var dwf = (DeclWithFormals)decl; // Copy InParams, as the list is shared between impl and proc var inParams = new List <Variable>(dwf.InParams); var fpVar = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "_P", Microsoft.Boogie.Type.Bool), /*incoming=*/ true); inParams.Insert(0, fpVar); var fpIdentifierExpr = new IdentifierExpr(Token.NoToken, fpVar); // Add in-parameters for all out-parameters. These new in-parameters // are used to ensure we preserve the value of the variable assigned // to when the passed predicate value is false. var newEqParamExprs = new List <Expr>(); var newAssignCmds = new List <Cmd>(); foreach (Variable outV in dwf.OutParams) { var inV = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "_V" + outV.TypedIdent.Name, outV.TypedIdent.Type), /*incoming=*/ true); inParams.Add(inV); var inVExpr = new IdentifierExpr(Token.NoToken, inV); var outVExpr = new IdentifierExpr(Token.NoToken, outV); newEqParamExprs.Add(Expr.Imp(Expr.Not(fpIdentifierExpr), Expr.Eq(inVExpr, outVExpr))); newAssignCmds.Add(new AssignCmd(Token.NoToken, new List <AssignLhs> { new SimpleAssignLhs(Token.NoToken, outVExpr) }, new List <Expr> { new NAryExpr(Token.NoToken, new IfThenElse(Token.NoToken), new List <Expr> { fpIdentifierExpr, outVExpr, inVExpr }) })); } dwf.InParams = inParams; if (impl == null) { foreach (Requires r in proc.Requires) { new EnabledReplacementVisitor(fpIdentifierExpr, Expr.True).VisitExpr(r.Condition); if (!QKeyValue.FindBoolAttribute(r.Attributes, "do_not_predicate")) { r.Condition = Expr.Imp(fpIdentifierExpr, r.Condition); } } foreach (Ensures e in proc.Ensures) { new EnabledReplacementVisitor(new IdentifierExpr(Token.NoToken, fpVar), Expr.True).VisitExpr(e.Condition); if (!QKeyValue.FindBoolAttribute(e.Attributes, "do_not_predicate")) { e.Condition = Expr.Imp(fpIdentifierExpr, e.Condition); } } foreach (Expr e in newEqParamExprs) { proc.Ensures.Add(new Ensures(false, e)); } } else { try { new SmartBlockPredicator(p, impl, useProcedurePredicates, uni).PredicateImplementation(); foreach (AssignCmd c in newAssignCmds) { impl.Blocks.First().Cmds.Insert(0, c); } } catch (Program.IrreducibleLoopException) { } } } else { if (impl == null) { foreach (Requires r in proc.Requires) { new EnabledReplacementVisitor(Expr.True, Expr.True).VisitExpr(r.Condition); } foreach (Ensures e in proc.Ensures) { new EnabledReplacementVisitor(Expr.True, Expr.True).VisitExpr(e.Condition); } } else { try { new SmartBlockPredicator(p, impl, useProcedurePredicates, uni).PredicateImplementation(); } catch (Program.IrreducibleLoopException) { } } } } } }