private List <Cmd> AddConstantWriteAsserts(List <Cmd> cs) { var result = new List <Cmd>(); foreach (Cmd c in cs) { result.Add(c); if (c is AssertCmd) { AssertCmd assertion = c as AssertCmd; if (QKeyValue.FindBoolAttribute(assertion.Attributes, "sourceloc")) { sourceLocationAttributes = assertion.Attributes; // Do not remove source location assertions // This is done by the race instrumenter } } if (c is AssignCmd) { AssignCmd assign = c as AssignCmd; foreach (var lhsRhs in assign.Lhss.Zip(assign.Rhss)) { ConstantWriteCollector cwc = new ConstantWriteCollector(stateToCheck); cwc.Visit(lhsRhs.Item1); if (cwc.FoundWrite()) { AssertCmd constantAssert = new AssertCmd(Token.NoToken, Expr.False); constantAssert.Attributes = new QKeyValue(Token.NoToken, "constant_write", new List <object>(), null); for (QKeyValue attr = sourceLocationAttributes; attr != null; attr = attr.Next) { if (attr.Key != "sourceloc") { constantAssert.Attributes = new QKeyValue(attr.tok, attr.Key, attr.Params, constantAssert.Attributes); } } result.Add(constantAssert); } } } } return(result); }
private static bool AccessesGlobalArrayOrUnsafeBarrier(Cmd c, GPUVerifier verifier) { var stateToCheck = verifier.KernelArrayInfo; if (c is CallCmd) { // Speculate invariants if we see atomics, async_work_group_copy, and // wait_group_events, which relate to race checking CallCmd call = c as CallCmd; if (QKeyValue.FindBoolAttribute(call.Attributes, "atomic")) { return(true); } if (QKeyValue.FindBoolAttribute(call.Attributes, "async_work_group_copy")) { return(true); } if (QKeyValue.FindBoolAttribute(call.Attributes, "wait_group_events")) { return(true); } // Speculate invariants if we see an unsafe barrier, // which we need to check for barrier divergence if (GPUVerifier.IsBarrier(call.Proc) && !QKeyValue.FindBoolAttribute(call.Proc.Attributes, "safe_barrier")) { return(true); } // Speculate invariants if we see a call to a procedure that has a non-local array // or constant array in its modset List <Variable> vars = new List <Variable>(); call.AddAssignedVariables(vars); foreach (Variable v in vars) { if (stateToCheck.GetGlobalAndGroupSharedArrays(false).Contains(v)) { return(true); } if (stateToCheck.GetConstantArrays().Contains(v)) { return(true); } } } // Speculate invariants if race instrumentation or a constant write // instrumentation will occur if (c is AssignCmd) { AssignCmd assign = c as AssignCmd; ReadCollector rc = new ReadCollector(stateToCheck); foreach (var rhs in assign.Rhss) { rc.Visit(rhs); } foreach (var access in rc.NonPrivateAccesses) { // Ignore disabled arrays if (stateToCheck.GetGlobalAndGroupSharedArrays(false).Contains(access.V)) { // Ignore read-only arrays (whether or not they are disabled) if (!stateToCheck.GetReadOnlyGlobalAndGroupSharedArrays(true).Contains(access.V)) { return(true); } } } foreach (var lhsRhs in assign.Lhss.Zip(assign.Rhss)) { WriteCollector wc = new WriteCollector(stateToCheck); wc.Visit(lhsRhs.Item1); if (wc.FoundNonPrivateWrite()) { // Ignore disabled arrays if (stateToCheck.GetGlobalAndGroupSharedArrays(false).Contains(wc.GetAccess().V)) { return(true); } } } foreach (var lhsRhs in assign.Lhss.Zip(assign.Rhss)) { ConstantWriteCollector cwc = new ConstantWriteCollector(stateToCheck); cwc.Visit(lhsRhs.Item1); if (cwc.FoundWrite()) { // Ignore disabled arrays if (stateToCheck.GetGlobalAndGroupSharedArrays(false).Contains(cwc.GetAccess().V)) { return(true); } } } } // Speculate invariants if we see an assert that is not a sourceloc or // block_sourceloc assert; such asserts is likely user supplied. if (c is AssertCmd) { AssertCmd assertion = c as AssertCmd; if (!QKeyValue.FindBoolAttribute(assertion.Attributes, "sourceloc") && !QKeyValue.FindBoolAttribute(assertion.Attributes, "block_sourceloc") && !assertion.Expr.Equals(Expr.True)) { return(true); } } // Speculate invariants if we see an assume that is not a partition; such // an assume is likely user supplied. if (c is AssumeCmd) { AssumeCmd assumption = c as AssumeCmd; if (!QKeyValue.FindBoolAttribute(assumption.Attributes, "partition")) { return(true); } } return(false); }