void PredicateImplementation()
        {
            blockGraph   = prog.ProcessLoops(impl);
            sortedBlocks = blockGraph.LoopyTopSort();

            AssignPredicates();
            partInfo = BuildPartitionInfo();

            if (myUseProcedurePredicates)
            {
                fp = Expr.Ident(impl.InParams[0]);
            }

            var   newBlocks = new List <Block>();
            Block prevBlock = null;

            foreach (var n in sortedBlocks)
            {
                if (predMap.ContainsKey(n.Item1))
                {
                    var p     = predMap[n.Item1];
                    var pExpr = Expr.Ident(p);

                    if (n.Item2)
                    {
                        var dominator = FindImmediateDominator(n.Item1);
                        if (dominator != null && predMap.ContainsKey(dominator))
                        {
                            AssumeCmd aCmd = new AssumeCmd(Token.NoToken, Expr.True);
                            aCmd.Attributes = new QKeyValue(Token.NoToken, "dominator_predicate", new List <object>()
                            {
                                predMap[dominator].ToString()
                            }, aCmd.Attributes);
                            aCmd.Attributes = new QKeyValue(Token.NoToken, "predicate", new List <object>()
                            {
                                predMap[n.Item1].ToString()
                            }, aCmd.Attributes);
                            n.Item1.Cmds.Insert(0, aCmd);
                        }

                        var backedgeBlock = new Block();
                        newBlocks.Add(backedgeBlock);

                        backedgeBlock.Label = n.Item1.Label + ".backedge";
                        backedgeBlock.Cmds  = new List <Cmd> {
                            new AssumeCmd(Token.NoToken, pExpr,
                                          new QKeyValue(Token.NoToken, "backedge", new List <object>(), null))
                        };
                        backedgeBlock.TransferCmd = new GotoCmd(Token.NoToken,
                                                                new List <Block> {
                            n.Item1
                        });

                        var tailBlock = new Block();
                        newBlocks.Add(tailBlock);

                        tailBlock.Label = n.Item1.Label + ".tail";
                        tailBlock.Cmds  = new List <Cmd> {
                            new AssumeCmd(Token.NoToken,
                                          Expr.Not(pExpr))
                        };

                        if (uni != null && !uni.IsUniform(impl.Name, n.Item1))
                        {
                            uni.AddNonUniform(impl.Name, backedgeBlock);
                            uni.AddNonUniform(impl.Name, tailBlock);
                        }

                        if (prevBlock != null)
                        {
                            prevBlock.TransferCmd = new GotoCmd(Token.NoToken,
                                                                new List <Block> {
                                backedgeBlock, tailBlock
                            });
                        }
                        prevBlock = tailBlock;
                    }
                    else
                    {
                        PredicateBlock(pExpr, n.Item1, newBlocks, ref prevBlock);
                    }
                }
                else
                {
                    if (!n.Item2)
                    {
                        PredicateBlock(null, n.Item1, newBlocks, ref prevBlock);
                    }
                }
            }

            if (prevBlock != null)
            {
                prevBlock.TransferCmd = new ReturnCmd(Token.NoToken);
            }

            impl.Blocks = newBlocks;
        }