// 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()); } }
void PredicateTransferCmd(List<Cmd> cmdSeq, TransferCmd cmd) { if (cmd is GotoCmd) { var gCmd = (GotoCmd)cmd; var targets = new List<Expr>( gCmd.labelTargets.Cast<Block>().Select(b => blockIds[b])); if (targets.Count == 1) { PredicateCmd(cmdSeq, Cmd.SimpleAssign(Token.NoToken, cur, targets[0])); } else { PredicateCmd(cmdSeq, new HavocCmd(Token.NoToken, new List<IdentifierExpr> { cur })); PredicateCmd(cmdSeq, new AssumeCmd(Token.NoToken, targets.Select(t => (Expr)Expr.Eq(cur, t)).Aggregate(Expr.Or))); } foreach (Block b in gCmd.labelTargets) { if (blockGraph.Predecessors(b).Count() == 1) { if (!doneBlocks.Contains(b)) { var assumes = b.Cmds.Cast<Cmd>().TakeWhile(c => c is AssumeCmd); if (assumes.Count() > 0) { foreach (AssumeCmd aCmd in assumes) { cmdSeq.Add(new AssumeCmd(Token.NoToken, Expr.Imp(Expr.Eq(cur, blockIds[b]), aCmd.Expr))); } b.Cmds = new List<Cmd>(b.Cmds.Cast<Cmd>().Skip(assumes.Count()).ToArray()); } } } } } else if (cmd is ReturnCmd) { PredicateCmd(cmdSeq, Cmd.SimpleAssign(Token.NoToken, cur, returnBlockId)); } else { Console.WriteLine("Unsupported cmd: " + cmd.GetType().ToString()); } }