private void AddBarrierDivergenceCandidates(HashSet <Variable> localVars, Implementation impl, IRegion region)
        {
            if (!verifier.ContainsBarrierCall(region) && !GPUVerifyVCGenCommandLineOptions.WarpSync)
            {
                return;
            }

            Expr guard = region.Guard();

            if (guard != null && verifier.UniformityAnalyser.IsUniform(impl.Name, guard))
            {
                return;
            }

            if (IsDisjunctionOfPredicates(guard))
            {
                string loopPredicate = ((guard as NAryExpr).Args[0] as IdentifierExpr).Name;
                loopPredicate = loopPredicate.Substring(0, loopPredicate.IndexOf('$'));

                // Int type used here, but it doesn't matter as we will print and then re-parse the program
                var uniformEnabledPredicate = Expr.Eq(
                    new IdentifierExpr(Token.NoToken, new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, loopPredicate + "$1", Type.Int))),
                    new IdentifierExpr(Token.NoToken, new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, loopPredicate + "$2", Type.Int))));

                verifier.AddCandidateInvariant(region, uniformEnabledPredicate, "loopPredicateEquality");

                verifier.AddCandidateInvariant(region, Expr.Imp(verifier.ThreadsInSameGroup(), uniformEnabledPredicate), "loopPredicateEquality");

                Dictionary <string, int> assignmentCounts = GetAssignmentCounts(impl);

                HashSet <string> alreadyConsidered = new HashSet <string>();

                foreach (var v in localVars)
                {
                    string lv = Utilities.StripThreadIdentifier(v.Name);
                    if (alreadyConsidered.Contains(lv))
                    {
                        continue;
                    }

                    alreadyConsidered.Add(lv);

                    if (verifier.UniformityAnalyser.IsUniform(impl.Name, v.Name))
                    {
                        continue;
                    }

                    if (GPUVerifier.IsPredicate(lv))
                    {
                        continue;
                    }

                    if (!assignmentCounts.ContainsKey(lv) || assignmentCounts[lv] <= 1)
                    {
                        continue;
                    }

                    if (!verifier.ContainsNamedVariable(region.GetModifiedVariables(), lv))
                    {
                        continue;
                    }

                    AddPredicatedEqualityCandidateInvariant(region, loopPredicate, new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, lv, Type.Int)));
                }
            }
        }
        private static void GenerateCandidateForNonUniformGuardVariables(GPUVerifier verifier, Implementation impl, IRegion region)
        {
            if (!verifier.ContainsBarrierCall(region) && !GPUVerifyVCGenCommandLineOptions.WarpSync)
            {
                return;
            }

            HashSet <Variable> partitionVars = region.PartitionVariablesOfHeader();
            HashSet <Variable> guardVars     = new HashSet <Variable>();

            var formals = impl.InParams.Select(x => x.Name);
            var modset  = region.GetModifiedVariables().Select(x => x.Name);

            foreach (var v in partitionVars)
            {
                Expr expr = verifier.VarDefAnalysesRegion[impl].DefOfVariableName(v.Name);
                if (expr == null)
                {
                    continue;
                }
                var visitor = new VariablesOccurringInExpressionVisitor();
                visitor.Visit(expr);
                guardVars.UnionWith(
                    visitor.GetVariables().Where(x => x.Name.StartsWith("$") &&
                                                 !formals.Contains(x.Name) && modset.Contains(x.Name) &&
                                                 !verifier.UniformityAnalyser.IsUniform(impl.Name, x.Name) &&
                                                 x.TypedIdent.Type.IsBv && (x.TypedIdent.Type.BvBits % 8 == 0)));
            }

            List <AssignCmd> assignments = new List <AssignCmd>();

            foreach (Block b in region.PreHeaders())
            {
                foreach (AssignCmd c in b.Cmds.Where(x => x is AssignCmd))
                {
                    assignments.Add(c);
                }
            }

            foreach (var v in guardVars)
            {
                foreach (AssignCmd c in assignments)
                {
                    foreach (var a in c.Lhss.Zip(c.Rhss))
                    {
                        var lhs = a.Item1;
                        var rhs = a.Item2;
                        if (!(lhs is SimpleAssignLhs))
                        {
                            continue;
                        }
                        var sLhs   = (SimpleAssignLhs)lhs;
                        var theVar = sLhs.DeepAssignedVariable;
                        if (theVar.Name == v.Name)
                        {
                            var         sub  = verifier.IntRep.MakeSub(new IdentifierExpr(Token.NoToken, v), rhs as Expr);
                            List <Expr> args = new List <Expr>();
                            args.Add(sub);
                            Function otherbv = verifier.FindOrCreateOther(sub.Type);
                            var      inv     = Expr.Eq(sub, new NAryExpr(Token.NoToken, new FunctionCall(otherbv), args));
                            verifier.AddCandidateInvariant(region, inv, "guardMinusInitialIsUniform");
                            var groupInv = Expr.Imp(verifier.ThreadsInSameGroup(), inv);
                            verifier.AddCandidateInvariant(region, groupInv, "guardMinusInitialIsUniform");
                        }
                    }
                }
            }
        }