void AnalyseAssignment(Variable variable, List <Tuple <IRegion, Expr> > defs, Graph <Block> cfg, HashSet <Variable> modSet) { // Ensure defs[0] refers to the definition from the outermost region // This also checks that the definitions are in different regions if (!OrderDefs(defs, cfg)) { return; } var regionId = defs[1].Item1.Identifier(); var varDefAnalysis = verifier.varDefAnalysesRegion[impl]; var varDef = varDefAnalysis.GetPossibleInductionVariableDefintion(variable.Name, regionId); if (varDef == null) { return; } HashSet <string> loopFreeVars; var defInd = varDefAnalysis.SubstDefinitions(varDef, impl.Name, out loopFreeVars); if (loopFreeVars.Any(i => i != variable.Name)) { return; } var modSetLoop = LoopInvariantGenerator.GetModifiedVariables(defs[1].Item1); var v = new VariablesOccurringInExpressionVisitor(); v.Visit(defs[0].Item2); if (v.GetVariables().Intersect(modSetLoop).Any()) { return; } AddDefinitionPair(variable, defInd, defs[0].Item2, regionId, modSet); }
private void DiscoverVariableAssignments(Variable variable) { Absy assignment = null; foreach (Block block in cfg.Nodes) { foreach (Cmd cmd in block.Cmds) { if (cmd is AssignCmd) { AssignCmd assignCmd = cmd as AssignCmd; var lhss = assignCmd.Lhss.OfType <SimpleAssignLhs>(); foreach (var LhsRhs in lhss.Zip(assignCmd.Rhss)) { if (LhsRhs.Item1.DeepAssignedVariable.Name == variable.Name) { assignment = LhsRhs.Item2; if (variable.Name == this.initialVariable.Name) { unexpandedExpr = LhsRhs.Item2; } goto AnalyseAssignment; } } } else if (cmd is CallCmd) { CallCmd call = cmd as CallCmd; foreach (IdentifierExpr outParam in call.Outs) { if (outParam.Name == variable.Name) { assignment = cmd; goto AnalyseAssignment; } } } } } // Label used to allow exit from multiple levels in the previous loop nest AnalyseAssignment: if (assignment != null) { var visitor = new VariablesOccurringInExpressionVisitor(); visitor.Visit(assignment); foreach (Variable discovered in visitor.GetVariables()) { if (TEMP_VARIABLE.IsMatch(discovered.Name) && discovered.Name != variable.Name) { DiscoverVariableAssignments(discovered); } else if (GPU_VARIABLE.IsMatch(discovered.Name)) { GPUVariables.Add(discovered); } } } }
public ExprTree(Expr expr) { this.expr = expr; root = Node.CreateFromExpr(expr); levels[0] = new HashSet <Node>(); levels[0].Add(root); SetLevels(root, 0); // Set node IDs and see if any scalar node is a race offset variable int nodeID = 0; foreach (Node node in nodes) { node.ID = nodeID++; if (node is ScalarSymbolNode) { ScalarSymbolNode scalarNode = node as ScalarSymbolNode; if (BoogieInterpreter.RegularExpressions.OffsetVariable.IsMatch(scalarNode.Symbol)) { OffsetVariables.Add(scalarNode.Symbol); } if (BoogieInterpreter.RegularExpressions.WatchdoVariable.IsMatch(scalarNode.Symbol)) { var visitor = new VariablesOccurringInExpressionVisitor(); visitor.Visit(this.expr); string offsetVariable = string.Empty; foreach (Variable variable in visitor.GetVariables()) { if (BoogieInterpreter.RegularExpressions.TrackingVariable.IsMatch(variable.Name)) { int index = variable.Name.IndexOf('$'); string arrayName = variable.Name.Substring(index); string accessType = variable.Name.Substring(0, index); if (accessType == "_WRITE_HAS_OCCURRED_") { offsetVariable = "_WRITE_OFFSET_" + arrayName; } else if (accessType == "_READ_HAS_OCCURRED_") { offsetVariable = "_READ_OFFSET_" + arrayName; } else { offsetVariable = "_ATOMIC_OFFSET_" + arrayName; } break; } } OffsetVariables.Add(offsetVariable); } } } }
public HashSet <Variable> PartitionVariablesOfHeader() { if (header == null) { return(new HashSet <Variable>()); } HashSet <Variable> partitionVars = new HashSet <Variable>(); var visitor = new VariablesOccurringInExpressionVisitor(); var dualBlockGraph = blockGraph.Dual(new Block()); Block loopConditionDominator = header; // The dominator might have multiple successors, traverse these while (blockGraph.Successors(loopConditionDominator).Count(item => loopNodes[header].Contains(item)) > 1) { foreach (Block b in blockGraph.Successors(loopConditionDominator)) { foreach (var assume in b.Cmds.OfType <AssumeCmd>().Where(x => QKeyValue.FindBoolAttribute(x.Attributes, "partition"))) { visitor.Visit(assume.Expr); partitionVars.UnionWith(visitor.GetVariables()); } } // Find the immediate post-dominator of the successors Block block = null; foreach (var succ in blockGraph.Successors(loopConditionDominator).Where(item => loopNodes[header].Contains(item))) { if (block == null) { block = succ; } else { block = dualBlockGraph.DominatorMap.LeastCommonAncestor(block, succ); } } // Use the immediate post-dominator loopConditionDominator = block; } foreach (Block b in blockGraph.Successors(loopConditionDominator)) { foreach (var assume in b.Cmds.OfType <AssumeCmd>().Where(x => QKeyValue.FindBoolAttribute(x.Attributes, "partition"))) { visitor.Visit(assume.Expr); partitionVars.UnionWith(visitor.GetVariables()); } } return(partitionVars); }
private static void GenerateCandidateForLoopBounds(GPUVerifier verifier, Implementation impl, IRegion region) { HashSet <Variable> loopCounters = new HashSet <Variable>(); HashSet <Variable> modifiedVariables = region.GetModifiedVariables(); // Get the partition variables associated with the header HashSet <Variable> partitionVars = region.PartitionVariablesOfRegion(); foreach (Variable v in partitionVars) { // Find the expression which defines a particular partition variable. // Visit the expression and select any variable in the mod set of the loop. // We assume that any variable satisfying these conditions is a loop counter Expr partitionDefExpr = verifier.VarDefAnalysesRegion[impl].DefOfVariableName(v.Name); if (partitionDefExpr == null) // multiple definitions or no definition { continue; } var visitor = new VariablesOccurringInExpressionVisitor(); visitor.Visit(partitionDefExpr); foreach (Variable variable in visitor.GetVariables()) { if (modifiedVariables.Contains(variable)) { loopCounters.Add(variable); } } } foreach (Variable loopCounter in loopCounters) { foreach (Block preheader in region.PreHeaders()) { foreach (AssignCmd cmd in preheader.Cmds.Where(x => x is AssignCmd).Reverse <Cmd>()) { var lhss = cmd.Lhss.Where(x => x is SimpleAssignLhs); foreach (var lhsRhs in lhss.Zip(cmd.Rhss)) { if (lhsRhs.Item1.DeepAssignedVariable.Name == loopCounter.Name) { verifier.AddCandidateInvariant(region, verifier.IntRep.MakeSle(new IdentifierExpr(loopCounter.tok, loopCounter), lhsRhs.Item2), "loopBound"); verifier.AddCandidateInvariant(region, verifier.IntRep.MakeSge(new IdentifierExpr(loopCounter.tok, loopCounter), lhsRhs.Item2), "loopBound"); verifier.AddCandidateInvariant(region, verifier.IntRep.MakeUle(new IdentifierExpr(loopCounter.tok, loopCounter), lhsRhs.Item2), "loopBound"); verifier.AddCandidateInvariant(region, verifier.IntRep.MakeUge(new IdentifierExpr(loopCounter.tok, loopCounter), lhsRhs.Item2), "loopBound"); } } } } } }
private static void GenerateCandidateForNonNegativeGuardVariables(GPUVerifier verifier, Implementation impl, IRegion region) { HashSet <Variable> partitionVars = region.PartitionVariablesOfHeader(); HashSet <Variable> nonnegVars = new HashSet <Variable>(); var formals = impl.InParams.Select(x => x.Name); var modset = GetModifiedVariables(region).Select(x => x.Name); Regex pattern = new Regex(@"\bBV\d*_((SLE)|(SLT)|(SGE)|(SGT))\b"); foreach (var v in partitionVars) { var expr = verifier.varDefAnalysesRegion[impl].DefOfVariableName(v.Name); if (!(expr is NAryExpr)) { continue; } var nary = expr as NAryExpr; if (!pattern.Match(nary.Fun.FunctionName).Success) { continue; } var visitor = new VariablesOccurringInExpressionVisitor(); visitor.Visit(nary); nonnegVars.UnionWith( visitor.GetVariables().Where( x => x.Name.StartsWith("$") && !formals.Contains(x.Name) && modset.Contains(x.Name) && x.TypedIdent.Type.IsBv ) ); } foreach (var v in nonnegVars) { int BVWidth = v.TypedIdent.Type.BvBits; // REVISIT: really we only want to guess for /integer/ variables. if (BVWidth >= 8) { var inv = verifier.IntRep.MakeSle(verifier.Zero(BVWidth), new IdentifierExpr(v.tok, v)); verifier.AddCandidateInvariant(region, inv, "guardNonNeg"); } } }
private void ExprMayAffectControlFlow(string proc, Expr e) { var visitor = new VariablesOccurringInExpressionVisitor(); visitor.VisitExpr(e); foreach (Variable v in visitor.GetVariables()) { if (!mayBeDerivedFrom[proc].ContainsKey(v.Name)) { continue; } foreach (string s in mayBeDerivedFrom[proc][v.Name]) { if (!arraysWhichMayAffectControlFlow.Contains(s)) { SetArrayMayAffectControlFlow(s); } } } }
public IEnumerable <Tuple <Variable, Expr> > FindSelfReferentialVariables(Dictionary <Block, VarDefs> blockVarDefs) { var predVarDefs = MergePredecessors(blockVarDefs, predecessors); foreach (var p in predVarDefs) { if (p.Value == null || p.Value is IdentifierExpr) { continue; } var v = new VariablesOccurringInExpressionVisitor(); v.Visit(p.Value); var modVars = v.GetVariables() .Where(i => i is Variable && modSet.Contains(i as Variable)); if (modVars.Count() == 1 && modVars.Single() as Variable == p.Key) { yield return(new Tuple <Variable, Expr>(p.Key, p.Value)); } } }
public HashSet <Variable> PartitionVariablesOfRegion() { if (header == null) { return(new HashSet <Variable>()); } HashSet <Variable> partitionVars = new HashSet <Variable>(); foreach (Block loopNode in loopNodes[header]) { var visitor = new VariablesOccurringInExpressionVisitor(); foreach (Block succ in blockGraph.Successors(loopNode)) { foreach (var assume in succ.Cmds.OfType <AssumeCmd>().Where(x => QKeyValue.FindBoolAttribute(x.Attributes, "partition"))) { visitor.Visit(assume.Expr); partitionVars.UnionWith(visitor.GetVariables()); } } } return(partitionVars); }
private static void GetReadAndWrittenVariables(IRegion region, out IEnumerable <Variable> ReadVariables, out IEnumerable <Variable> WrittenVariables) { var readVisitor = new VariablesOccurringInExpressionVisitor(); var writeVisitor = new VariablesOccurringInExpressionVisitor(); foreach (AssignCmd assignment in region.Cmds().OfType <AssignCmd>()) { var mapLhss = assignment.Lhss.OfType <MapAssignLhs>(); foreach (var LhsRhs in mapLhss.Zip(assignment.Rhss)) { writeVisitor.Visit(LhsRhs.Item1); readVisitor.Visit(LhsRhs.Item2); } var simpleLhss = assignment.Lhss.OfType <SimpleAssignLhs>(); foreach (var LhsRhs in simpleLhss.Zip(assignment.Rhss)) { readVisitor.Visit(LhsRhs.Item2); } } ReadVariables = readVisitor.GetVariables(); WrittenVariables = writeVisitor.GetVariables(); }
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"); } } } } }
private void Analyse(Implementation impl, List <Cmd> cs) { foreach (var c in cs) { if (c is AssignCmd) { AssignCmd assignCmd = c as AssignCmd; for (int i = 0; i != assignCmd.Lhss.Count; i++) { if (assignCmd.Lhss[i] is SimpleAssignLhs) { SimpleAssignLhs lhs = assignCmd.Lhss[i] as SimpleAssignLhs; Expr rhs = assignCmd.Rhss[i]; VariablesOccurringInExpressionVisitor visitor = new VariablesOccurringInExpressionVisitor(); visitor.VisitExpr(rhs); foreach (Variable v in visitor.GetVariables()) { if (!mayBeDerivedFrom[impl.Name].ContainsKey(v.Name)) { continue; } foreach (string s in mayBeDerivedFrom[impl.Name][v.Name]) { if (mayBeDerivedFrom[impl.Name].ContainsKey(lhs.AssignedVariable.Name) && !mayBeDerivedFrom[impl.Name][lhs.AssignedVariable.Name].Contains(s)) { SetMayBeDerivedFrom(impl.Name, lhs.AssignedVariable.Name, s); } } } } } } else if (c is CallCmd) { CallCmd callCmd = c as CallCmd; if (QKeyValue.FindBoolAttribute(callCmd.Proc.Attributes, "barrier_invariant") || QKeyValue.FindBoolAttribute(callCmd.Proc.Attributes, "binary_barrier_invariant")) { foreach (Expr param in callCmd.Ins) { ExprMayAffectControlFlow(impl.Name, param); } } else if (!GPUVerifier.IsBarrier(callCmd.Proc)) { Implementation CalleeImplementation = verifier.GetImplementation(callCmd.callee); if (CalleeImplementation != null) { for (int i = 0; i < CalleeImplementation.InParams.Count(); i++) { VariablesOccurringInExpressionVisitor visitor = new VariablesOccurringInExpressionVisitor(); visitor.VisitExpr(callCmd.Ins[i]); foreach (Variable v in visitor.GetVariables()) { if (!mayBeDerivedFrom[impl.Name].ContainsKey(v.Name)) { continue; } foreach (string s in mayBeDerivedFrom[impl.Name][v.Name]) { if (!mayBeDerivedFrom[callCmd.callee][CalleeImplementation.InParams[i].Name].Contains(s)) { SetMayBeDerivedFrom(callCmd.callee, CalleeImplementation.InParams[i].Name, s); } } } } for (int i = 0; i < CalleeImplementation.OutParams.Count(); i++) { foreach (string s in mayBeDerivedFrom[callCmd.callee][CalleeImplementation.OutParams[i].Name]) { if (!mayBeDerivedFrom[impl.Name][callCmd.Outs[i].Name].Contains(s)) { SetMayBeDerivedFrom(impl.Name, callCmd.Outs[i].Name, s); } } } } } } else if (c is AssumeCmd) { var assumeCmd = c as AssumeCmd; ExprMayAffectControlFlow(impl.Name, assumeCmd.Expr); } else if (c is AssertCmd) { var assertCmd = c as AssertCmd; ExprMayAffectControlFlow(impl.Name, assertCmd.Expr); } } }