diff options
author | Unknown <afd@afd-THINK.home> | 2012-09-18 23:03:30 +0100 |
---|---|---|
committer | Unknown <afd@afd-THINK.home> | 2012-09-18 23:03:30 +0100 |
commit | ff3465d251f498b778dd00f6d97784f3cc8c6408 (patch) | |
tree | eb5f3f1fc8a71885e9ca00765d43a19266c3a5d9 | |
parent | 024f5aa8a58340d4073c2921aba2ed7b07d41451 (diff) |
Uniformity analysis. Patch by Peter Collingbourne.
-rw-r--r-- | Source/GPUVerify/CommandLineOptions.cs | 8 | ||||
-rw-r--r-- | Source/GPUVerify/GPUVerifier.cs | 4409 | ||||
-rw-r--r-- | Source/GPUVerify/GPUVerify.csproj | 356 | ||||
-rw-r--r-- | Source/GPUVerify/IRaceInstrumenter.cs | 61 | ||||
-rw-r--r-- | Source/GPUVerify/InvariantGenerationRules/LoopVariableBoundsInvariantGenerator.cs | 109 | ||||
-rw-r--r-- | Source/GPUVerify/InvariantGenerationRules/PowerOfTwoInvariantGenerator.cs | 122 | ||||
-rw-r--r-- | Source/GPUVerify/KernelDualiser.cs | 43 | ||||
-rw-r--r-- | Source/GPUVerify/LoopInvariantGenerator.cs | 516 | ||||
-rw-r--r-- | Source/GPUVerify/NullRaceInstrumenter.cs | 129 | ||||
-rw-r--r-- | Source/GPUVerify/RaceInstrumenter.cs | 2277 | ||||
-rw-r--r-- | Source/GPUVerify/UniformExpressionAnalysisVisitor.cs | 39 | ||||
-rw-r--r-- | Source/Graph/Graph.cs | 1913 | ||||
-rw-r--r-- | Source/VCGeneration/GraphAlgorithms.cs | 28 | ||||
-rw-r--r-- | Source/VCGeneration/SmartBlockPredicator.cs | 992 | ||||
-rw-r--r-- | Source/VCGeneration/UniformityAnalyser.cs (renamed from Source/GPUVerify/UniformityAnalyser.cs) | 938 | ||||
-rw-r--r-- | Source/VCGeneration/VCGeneration.csproj | 455 |
16 files changed, 6292 insertions, 6103 deletions
diff --git a/Source/GPUVerify/CommandLineOptions.cs b/Source/GPUVerify/CommandLineOptions.cs index 2f9ed792..5f6f0066 100644 --- a/Source/GPUVerify/CommandLineOptions.cs +++ b/Source/GPUVerify/CommandLineOptions.cs @@ -25,7 +25,7 @@ namespace GPUVerify public static bool ShowStages = false;
public static bool ShowUniformityAnalysis = false;
- public static bool DoUniformityAnalysis = true;
+ public static bool DoUniformityAnalysis = false;
public static bool ShowMayBePowerOfTwoAnalysis = false;
public static bool ShowArrayControlFlowAnalysis = false;
@@ -116,9 +116,9 @@ namespace GPUVerify ShowUniformityAnalysis = true;
break;
- case "-noUniformityAnalysis":
- case "/noUniformityAnalysis":
- DoUniformityAnalysis = false;
+ case "-uniformityAnalysis":
+ case "/uniformityAnalysis":
+ DoUniformityAnalysis = true;
break;
case "-showMayBePowerOfTwoAnalysis":
diff --git a/Source/GPUVerify/GPUVerifier.cs b/Source/GPUVerify/GPUVerifier.cs index 26dffc0f..5afabe80 100644 --- a/Source/GPUVerify/GPUVerifier.cs +++ b/Source/GPUVerify/GPUVerifier.cs @@ -1,2201 +1,2212 @@ -using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.IO;
-using System.Diagnostics;
-using System.Diagnostics.Contracts;
-using Microsoft.Boogie;
-using Microsoft.Basetypes;
-
-namespace GPUVerify
-{
- class GPUVerifier : CheckingContext
- {
- public string outputFilename;
- public Program Program;
- public ResolutionContext ResContext;
-
- public Procedure KernelProcedure;
- public Implementation KernelImplementation;
- public Procedure BarrierProcedure;
-
- public IKernelArrayInfo KernelArrayInfo = new KernelArrayInfoLists();
-
- private HashSet<string> ReservedNames = new HashSet<string>();
-
- internal HashSet<string> OnlyThread1 = new HashSet<string>();
- internal HashSet<string> OnlyThread2 = new HashSet<string>();
-
- private int TempCounter = 0;
-
- internal const string LOCAL_ID_X_STRING = "local_id_x";
- internal const string LOCAL_ID_Y_STRING = "local_id_y";
- internal const string LOCAL_ID_Z_STRING = "local_id_z";
-
- internal static Constant _X = null;
- internal static Constant _Y = null;
- internal static Constant _Z = null;
-
- internal const string GROUP_SIZE_X_STRING = "group_size_x";
- internal const string GROUP_SIZE_Y_STRING = "group_size_y";
- internal const string GROUP_SIZE_Z_STRING = "group_size_z";
-
- internal static Constant _GROUP_SIZE_X = null;
- internal static Constant _GROUP_SIZE_Y = null;
- internal static Constant _GROUP_SIZE_Z = null;
-
- internal const string GROUP_ID_X_STRING = "group_id_x";
- internal const string GROUP_ID_Y_STRING = "group_id_y";
- internal const string GROUP_ID_Z_STRING = "group_id_z";
-
- internal static Constant _GROUP_X = null;
- internal static Constant _GROUP_Y = null;
- internal static Constant _GROUP_Z = null;
-
- internal const string NUM_GROUPS_X_STRING = "num_groups_x";
- internal const string NUM_GROUPS_Y_STRING = "num_groups_y";
- internal const string NUM_GROUPS_Z_STRING = "num_groups_z";
-
- internal static Constant _NUM_GROUPS_X = null;
- internal static Constant _NUM_GROUPS_Y = null;
- internal static Constant _NUM_GROUPS_Z = null;
-
- public IRaceInstrumenter RaceInstrumenter;
-
- public UniformityAnalyser uniformityAnalyser;
- public MayBePowerOfTwoAnalyser mayBePowerOfTwoAnalyser;
- public LiveVariableAnalyser liveVariableAnalyser;
- public ArrayControlFlowAnalyser arrayControlFlowAnalyser;
- public Dictionary<Implementation, VariableDefinitionAnalysis> varDefAnalyses;
- public Dictionary<Implementation, ReducedStrengthAnalysis> reducedStrengthAnalyses;
-
- public GPUVerifier(string filename, Program program, ResolutionContext rc, IRaceInstrumenter raceInstrumenter) : this(filename, program, rc, raceInstrumenter, false)
- {
- }
-
- public GPUVerifier(string filename, Program program, ResolutionContext rc, IRaceInstrumenter raceInstrumenter, bool skipCheck)
- : base((IErrorSink)null)
- {
- this.outputFilename = filename;
- this.Program = program;
- this.ResContext = rc;
- this.RaceInstrumenter = raceInstrumenter;
- if(!skipCheck)
- CheckWellFormedness();
- }
-
- public void setRaceInstrumenter(IRaceInstrumenter ri)
- {
- this.RaceInstrumenter = ri;
- }
-
- private void CheckWellFormedness()
- {
- int errorCount = Check();
- if (errorCount != 0)
- {
- Console.WriteLine("{0} GPUVerify format errors detected in {1}", errorCount, CommandLineOptions.inputFiles[CommandLineOptions.inputFiles.Count - 1]);
- Environment.Exit(1);
- }
- }
-
- private Procedure CheckExactlyOneKernelProcedure()
- {
- var p = CheckSingleInstanceOfAttributedProcedure("kernel");
- if (p == null)
- {
- Error(Program, "\"kernel\" attribute has not been specified for any procedure. You must mark exactly one procedure with this attribute");
- }
-
- return p;
- }
-
- private Procedure FindOrCreateBarrierProcedure()
- {
- var p = CheckSingleInstanceOfAttributedProcedure("barrier");
- if (p == null)
- {
- p = new Procedure(Token.NoToken, "barrier", new TypeVariableSeq(),
- new VariableSeq(new Variable[] {
- new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "__local_fence", new BvType(1)), true),
- new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "__global_fence", new BvType(1)), true) }),
- new VariableSeq(),
- new RequiresSeq(), new IdentifierExprSeq(),
- new EnsuresSeq(),
- new QKeyValue(Token.NoToken, "barrier", new List<object>(), null));
- Program.TopLevelDeclarations.Add(p);
- ResContext.AddProcedure(p);
- }
- return p;
- }
-
- private Procedure CheckSingleInstanceOfAttributedProcedure(string attribute)
- {
- Procedure attributedProcedure = null;
-
- foreach (Declaration decl in Program.TopLevelDeclarations)
- {
- if (!QKeyValue.FindBoolAttribute(decl.Attributes, attribute))
- {
- continue;
- }
-
- if (decl is Implementation)
- {
- continue;
- }
-
- if (decl is Procedure)
- {
- if (attributedProcedure == null)
- {
- attributedProcedure = decl as Procedure;
- }
- else
- {
- Error(decl, "\"{0}\" attribute specified for procedure {1}, but it has already been specified for procedure {2}", attribute, (decl as Procedure).Name, attributedProcedure.Name);
- }
-
- }
- else
- {
- Error(decl, "\"{0}\" attribute can only be applied to a procedure", attribute);
- }
- }
-
- return attributedProcedure;
- }
-
- private void CheckLocalVariables()
- {
- foreach (LocalVariable LV in KernelImplementation.LocVars)
- {
- if (QKeyValue.FindBoolAttribute(LV.Attributes, "group_shared"))
- {
- Error(LV.tok, "Local variable must not be marked 'group_shared' -- promote the variable to global scope");
- }
- }
- }
-
-
- private void ReportMultipleAttributeError(string attribute, IToken first, IToken second)
- {
- Error(
- second,
- "Can only have one {0} attribute, but previously saw this attribute at ({1}, {2})",
- attribute,
- first.filename,
- first.line, first.col - 1);
- }
-
- private bool setConstAttributeField(Constant constInProgram, string attr, ref Constant constFieldRef)
- {
- if (QKeyValue.FindBoolAttribute(constInProgram.Attributes, attr))
- {
- if (constFieldRef != null)
- {
- ReportMultipleAttributeError(attr, constFieldRef.tok, constInProgram.tok);
- return false;
- }
- CheckSpecialConstantType(constInProgram);
- constFieldRef = constInProgram;
- }
- return true;
- }
-
- private void MaybeCreateAttributedConst(string attr, ref Constant constFieldRef)
- {
- if (constFieldRef == null)
- {
- constFieldRef = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, attr, Microsoft.Boogie.Type.GetBvType(32)), /*unique=*/false);
- constFieldRef.AddAttribute(attr);
- Program.TopLevelDeclarations.Add(constFieldRef);
- }
- }
-
- private bool FindNonLocalVariables()
- {
- bool success = true;
- foreach (Declaration D in Program.TopLevelDeclarations)
- {
- if (D is Variable &&
- (D as Variable).IsMutable &&
- (D as Variable).TypedIdent.Type is MapType &&
- !ReservedNames.Contains((D as Variable).Name))
- {
- if (QKeyValue.FindBoolAttribute(D.Attributes, "group_shared"))
- {
- KernelArrayInfo.getGroupSharedArrays().Add(D as Variable);
- }
- else if (QKeyValue.FindBoolAttribute(D.Attributes, "global"))
- {
- KernelArrayInfo.getGlobalArrays().Add(D as Variable);
- }
- else
- {
- KernelArrayInfo.getPrivateArrays().Add(D as Variable);
- }
- }
- else if (D is Constant)
- {
- Constant C = D as Constant;
-
- success &= setConstAttributeField(C, LOCAL_ID_X_STRING, ref _X);
- success &= setConstAttributeField(C, LOCAL_ID_Y_STRING, ref _Y);
- success &= setConstAttributeField(C, LOCAL_ID_Z_STRING, ref _Z);
-
- success &= setConstAttributeField(C, GROUP_SIZE_X_STRING, ref _GROUP_SIZE_X);
- success &= setConstAttributeField(C, GROUP_SIZE_Y_STRING, ref _GROUP_SIZE_Y);
- success &= setConstAttributeField(C, GROUP_SIZE_Z_STRING, ref _GROUP_SIZE_Z);
-
- success &= setConstAttributeField(C, GROUP_ID_X_STRING, ref _GROUP_X);
- success &= setConstAttributeField(C, GROUP_ID_Y_STRING, ref _GROUP_Y);
- success &= setConstAttributeField(C, GROUP_ID_Z_STRING, ref _GROUP_Z);
-
- success &= setConstAttributeField(C, NUM_GROUPS_X_STRING, ref _NUM_GROUPS_X);
- success &= setConstAttributeField(C, NUM_GROUPS_Y_STRING, ref _NUM_GROUPS_Y);
- success &= setConstAttributeField(C, NUM_GROUPS_Z_STRING, ref _NUM_GROUPS_Z);
-
-
- }
- }
-
- MaybeCreateAttributedConst(LOCAL_ID_X_STRING, ref _X);
- MaybeCreateAttributedConst(LOCAL_ID_Y_STRING, ref _Y);
- MaybeCreateAttributedConst(LOCAL_ID_Z_STRING, ref _Z);
-
- MaybeCreateAttributedConst(GROUP_SIZE_X_STRING, ref _GROUP_SIZE_X);
- MaybeCreateAttributedConst(GROUP_SIZE_Y_STRING, ref _GROUP_SIZE_Y);
- MaybeCreateAttributedConst(GROUP_SIZE_Z_STRING, ref _GROUP_SIZE_Z);
-
- MaybeCreateAttributedConst(GROUP_ID_X_STRING, ref _GROUP_X);
- MaybeCreateAttributedConst(GROUP_ID_Y_STRING, ref _GROUP_Y);
- MaybeCreateAttributedConst(GROUP_ID_Z_STRING, ref _GROUP_Z);
-
- MaybeCreateAttributedConst(NUM_GROUPS_X_STRING, ref _NUM_GROUPS_X);
- MaybeCreateAttributedConst(NUM_GROUPS_Y_STRING, ref _NUM_GROUPS_Y);
- MaybeCreateAttributedConst(NUM_GROUPS_Z_STRING, ref _NUM_GROUPS_Z);
-
- return success;
- }
-
- private void CheckSpecialConstantType(Constant C)
- {
- if (!(C.TypedIdent.Type.Equals(Microsoft.Boogie.Type.Int) || C.TypedIdent.Type.Equals(Microsoft.Boogie.Type.GetBvType(32))))
- {
- Error(C.tok, "Special constant '" + C.Name + "' must have type 'int' or 'bv32'");
- }
- }
-
- private void GetKernelImplementation()
- {
- foreach (Declaration decl in Program.TopLevelDeclarations)
- {
- if (!(decl is Implementation))
- {
- continue;
- }
-
- Implementation Impl = decl as Implementation;
-
- if (Impl.Proc == KernelProcedure)
- {
- KernelImplementation = Impl;
- break;
- }
-
- }
-
- if (KernelImplementation == null)
- {
- Error(Token.NoToken, "*** Error: no implementation of kernel procedure");
- }
- }
-
-
-
-
- protected virtual void CheckKernelImplementation()
- {
- CheckKernelParameters();
- GetKernelImplementation();
-
- if (KernelImplementation == null)
- {
- return;
- }
-
- CheckLocalVariables();
- CheckNoReturns();
- }
-
- private void CheckNoReturns()
- {
- // TODO!
- }
-
- internal void preProcess()
- {
- RemoveRedundantReturns();
-
- RemoveElseIfs();
-
- PullOutNonLocalAccesses();
- }
-
- private void MergeBlocksIntoPredecessors()
- {
- foreach (var impl in Program.TopLevelDeclarations.OfType<Implementation>())
- VC.VCGen.MergeBlocksIntoPredecessors(Program, impl);
- }
-
- internal void doit()
- {
- File.Delete(Path.GetFileNameWithoutExtension(CommandLineOptions.inputFiles[0]) + ".loc");
- if (CommandLineOptions.Unstructured)
- {
- Microsoft.Boogie.CommandLineOptions.Clo.PrintUnstructured = 2;
- }
-
- if (CommandLineOptions.ShowStages)
- {
- emitProgram(outputFilename + "_original");
- }
-
- preProcess();
-
- if (CommandLineOptions.ShowStages) {
- emitProgram(outputFilename + "_preprocessed");
- }
-
- DoLiveVariableAnalysis();
-
+using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using System.Diagnostics; +using System.Diagnostics.Contracts; +using Microsoft.Boogie; +using Microsoft.Basetypes; + +namespace GPUVerify +{ + class GPUVerifier : CheckingContext + { + public string outputFilename; + public Program Program; + public ResolutionContext ResContext; + + public Procedure KernelProcedure; + public Implementation KernelImplementation; + public Procedure BarrierProcedure; + + public IKernelArrayInfo KernelArrayInfo = new KernelArrayInfoLists(); + + private HashSet<string> ReservedNames = new HashSet<string>(); + + internal HashSet<string> OnlyThread1 = new HashSet<string>(); + internal HashSet<string> OnlyThread2 = new HashSet<string>(); + + private int TempCounter = 0; + + internal const string LOCAL_ID_X_STRING = "local_id_x"; + internal const string LOCAL_ID_Y_STRING = "local_id_y"; + internal const string LOCAL_ID_Z_STRING = "local_id_z"; + + internal static Constant _X = null; + internal static Constant _Y = null; + internal static Constant _Z = null; + + internal const string GROUP_SIZE_X_STRING = "group_size_x"; + internal const string GROUP_SIZE_Y_STRING = "group_size_y"; + internal const string GROUP_SIZE_Z_STRING = "group_size_z"; + + internal static Constant _GROUP_SIZE_X = null; + internal static Constant _GROUP_SIZE_Y = null; + internal static Constant _GROUP_SIZE_Z = null; + + internal const string GROUP_ID_X_STRING = "group_id_x"; + internal const string GROUP_ID_Y_STRING = "group_id_y"; + internal const string GROUP_ID_Z_STRING = "group_id_z"; + + internal static Constant _GROUP_X = null; + internal static Constant _GROUP_Y = null; + internal static Constant _GROUP_Z = null; + + internal const string NUM_GROUPS_X_STRING = "num_groups_x"; + internal const string NUM_GROUPS_Y_STRING = "num_groups_y"; + internal const string NUM_GROUPS_Z_STRING = "num_groups_z"; + + internal static Constant _NUM_GROUPS_X = null; + internal static Constant _NUM_GROUPS_Y = null; + internal static Constant _NUM_GROUPS_Z = null; + + public IRaceInstrumenter RaceInstrumenter; + + public UniformityAnalyser uniformityAnalyser; + public MayBePowerOfTwoAnalyser mayBePowerOfTwoAnalyser; + public LiveVariableAnalyser liveVariableAnalyser; + public ArrayControlFlowAnalyser arrayControlFlowAnalyser; + public Dictionary<Implementation, VariableDefinitionAnalysis> varDefAnalyses; + public Dictionary<Implementation, ReducedStrengthAnalysis> reducedStrengthAnalyses; + + public GPUVerifier(string filename, Program program, ResolutionContext rc, IRaceInstrumenter raceInstrumenter) : this(filename, program, rc, raceInstrumenter, false) + { + } + + public GPUVerifier(string filename, Program program, ResolutionContext rc, IRaceInstrumenter raceInstrumenter, bool skipCheck) + : base((IErrorSink)null) + { + this.outputFilename = filename; + this.Program = program; + this.ResContext = rc; + this.RaceInstrumenter = raceInstrumenter; + if(!skipCheck) + CheckWellFormedness(); + } + + public void setRaceInstrumenter(IRaceInstrumenter ri) + { + this.RaceInstrumenter = ri; + } + + private void CheckWellFormedness() + { + int errorCount = Check(); + if (errorCount != 0) + { + Console.WriteLine("{0} GPUVerify format errors detected in {1}", errorCount, CommandLineOptions.inputFiles[CommandLineOptions.inputFiles.Count - 1]); + Environment.Exit(1); + } + } + + private Procedure CheckExactlyOneKernelProcedure() + { + var p = CheckSingleInstanceOfAttributedProcedure("kernel"); + if (p == null) + { + Error(Program, "\"kernel\" attribute has not been specified for any procedure. You must mark exactly one procedure with this attribute"); + } + + return p; + } + + private Procedure FindOrCreateBarrierProcedure() + { + var p = CheckSingleInstanceOfAttributedProcedure("barrier"); + if (p == null) + { + p = new Procedure(Token.NoToken, "barrier", new TypeVariableSeq(), + new VariableSeq(new Variable[] { + new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "__local_fence", new BvType(1)), true), + new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "__global_fence", new BvType(1)), true) }), + new VariableSeq(), + new RequiresSeq(), new IdentifierExprSeq(), + new EnsuresSeq(), + new QKeyValue(Token.NoToken, "barrier", new List<object>(), null)); + Program.TopLevelDeclarations.Add(p); + ResContext.AddProcedure(p); + } + return p; + } + + private Procedure CheckSingleInstanceOfAttributedProcedure(string attribute) + { + Procedure attributedProcedure = null; + + foreach (Declaration decl in Program.TopLevelDeclarations) + { + if (!QKeyValue.FindBoolAttribute(decl.Attributes, attribute)) + { + continue; + } + + if (decl is Implementation) + { + continue; + } + + if (decl is Procedure) + { + if (attributedProcedure == null) + { + attributedProcedure = decl as Procedure; + } + else + { + Error(decl, "\"{0}\" attribute specified for procedure {1}, but it has already been specified for procedure {2}", attribute, (decl as Procedure).Name, attributedProcedure.Name); + } + + } + else + { + Error(decl, "\"{0}\" attribute can only be applied to a procedure", attribute); + } + } + + return attributedProcedure; + } + + private void CheckLocalVariables() + { + foreach (LocalVariable LV in KernelImplementation.LocVars) + { + if (QKeyValue.FindBoolAttribute(LV.Attributes, "group_shared")) + { + Error(LV.tok, "Local variable must not be marked 'group_shared' -- promote the variable to global scope"); + } + } + } + + + private void ReportMultipleAttributeError(string attribute, IToken first, IToken second) + { + Error( + second, + "Can only have one {0} attribute, but previously saw this attribute at ({1}, {2})", + attribute, + first.filename, + first.line, first.col - 1); + } + + private bool setConstAttributeField(Constant constInProgram, string attr, ref Constant constFieldRef) + { + if (QKeyValue.FindBoolAttribute(constInProgram.Attributes, attr)) + { + if (constFieldRef != null) + { + ReportMultipleAttributeError(attr, constFieldRef.tok, constInProgram.tok); + return false; + } + CheckSpecialConstantType(constInProgram); + constFieldRef = constInProgram; + } + return true; + } + + private void MaybeCreateAttributedConst(string attr, ref Constant constFieldRef) + { + if (constFieldRef == null) + { + constFieldRef = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, attr, Microsoft.Boogie.Type.GetBvType(32)), /*unique=*/false); + constFieldRef.AddAttribute(attr); + Program.TopLevelDeclarations.Add(constFieldRef); + } + } + + private bool FindNonLocalVariables() + { + bool success = true; + foreach (Declaration D in Program.TopLevelDeclarations) + { + if (D is Variable && + (D as Variable).IsMutable && + (D as Variable).TypedIdent.Type is MapType && + !ReservedNames.Contains((D as Variable).Name)) + { + if (QKeyValue.FindBoolAttribute(D.Attributes, "group_shared")) + { + KernelArrayInfo.getGroupSharedArrays().Add(D as Variable); + } + else if (QKeyValue.FindBoolAttribute(D.Attributes, "global")) + { + KernelArrayInfo.getGlobalArrays().Add(D as Variable); + } + else + { + KernelArrayInfo.getPrivateArrays().Add(D as Variable); + } + } + else if (D is Constant) + { + Constant C = D as Constant; + + success &= setConstAttributeField(C, LOCAL_ID_X_STRING, ref _X); + success &= setConstAttributeField(C, LOCAL_ID_Y_STRING, ref _Y); + success &= setConstAttributeField(C, LOCAL_ID_Z_STRING, ref _Z); + + success &= setConstAttributeField(C, GROUP_SIZE_X_STRING, ref _GROUP_SIZE_X); + success &= setConstAttributeField(C, GROUP_SIZE_Y_STRING, ref _GROUP_SIZE_Y); + success &= setConstAttributeField(C, GROUP_SIZE_Z_STRING, ref _GROUP_SIZE_Z); + + success &= setConstAttributeField(C, GROUP_ID_X_STRING, ref _GROUP_X); + success &= setConstAttributeField(C, GROUP_ID_Y_STRING, ref _GROUP_Y); + success &= setConstAttributeField(C, GROUP_ID_Z_STRING, ref _GROUP_Z); + + success &= setConstAttributeField(C, NUM_GROUPS_X_STRING, ref _NUM_GROUPS_X); + success &= setConstAttributeField(C, NUM_GROUPS_Y_STRING, ref _NUM_GROUPS_Y); + success &= setConstAttributeField(C, NUM_GROUPS_Z_STRING, ref _NUM_GROUPS_Z); + + + } + } + + MaybeCreateAttributedConst(LOCAL_ID_X_STRING, ref _X); + MaybeCreateAttributedConst(LOCAL_ID_Y_STRING, ref _Y); + MaybeCreateAttributedConst(LOCAL_ID_Z_STRING, ref _Z); + + MaybeCreateAttributedConst(GROUP_SIZE_X_STRING, ref _GROUP_SIZE_X); + MaybeCreateAttributedConst(GROUP_SIZE_Y_STRING, ref _GROUP_SIZE_Y); + MaybeCreateAttributedConst(GROUP_SIZE_Z_STRING, ref _GROUP_SIZE_Z); + + MaybeCreateAttributedConst(GROUP_ID_X_STRING, ref _GROUP_X); + MaybeCreateAttributedConst(GROUP_ID_Y_STRING, ref _GROUP_Y); + MaybeCreateAttributedConst(GROUP_ID_Z_STRING, ref _GROUP_Z); + + MaybeCreateAttributedConst(NUM_GROUPS_X_STRING, ref _NUM_GROUPS_X); + MaybeCreateAttributedConst(NUM_GROUPS_Y_STRING, ref _NUM_GROUPS_Y); + MaybeCreateAttributedConst(NUM_GROUPS_Z_STRING, ref _NUM_GROUPS_Z); + + return success; + } + + private void CheckSpecialConstantType(Constant C) + { + if (!(C.TypedIdent.Type.Equals(Microsoft.Boogie.Type.Int) || C.TypedIdent.Type.Equals(Microsoft.Boogie.Type.GetBvType(32)))) + { + Error(C.tok, "Special constant '" + C.Name + "' must have type 'int' or 'bv32'"); + } + } + + private void GetKernelImplementation() + { + foreach (Declaration decl in Program.TopLevelDeclarations) + { + if (!(decl is Implementation)) + { + continue; + } + + Implementation Impl = decl as Implementation; + + if (Impl.Proc == KernelProcedure) + { + KernelImplementation = Impl; + break; + } + + } + + if (KernelImplementation == null) + { + Error(Token.NoToken, "*** Error: no implementation of kernel procedure"); + } + } + + + + + protected virtual void CheckKernelImplementation() + { + CheckKernelParameters(); + GetKernelImplementation(); + + if (KernelImplementation == null) + { + return; + } + + CheckLocalVariables(); + CheckNoReturns(); + } + + private void CheckNoReturns() + { + // TODO! + } + + internal void preProcess() + { + RemoveRedundantReturns(); + + RemoveElseIfs(); + + PullOutNonLocalAccesses(); + } + + private void MergeBlocksIntoPredecessors() + { + foreach (var impl in Program.TopLevelDeclarations.OfType<Implementation>()) + VC.VCGen.MergeBlocksIntoPredecessors(Program, impl); + } + + internal void doit() + { + File.Delete(Path.GetFileNameWithoutExtension(CommandLineOptions.inputFiles[0]) + ".loc"); + if (CommandLineOptions.Unstructured) + { + Microsoft.Boogie.CommandLineOptions.Clo.PrintUnstructured = 2; + } + + if (CommandLineOptions.ShowStages) + { + emitProgram(outputFilename + "_original"); + } + + preProcess(); + + if (CommandLineOptions.ShowStages) { + emitProgram(outputFilename + "_preprocessed"); + } + + DoLiveVariableAnalysis(); + DoUniformityAnalysis();
- DoVariableDefinitionAnalysis();
-
- DoReducedStrengthAnalysis();
-
- DoMayBePowerOfTwoAnalysis();
-
- DoArrayControlFlowAnalysis();
-
- if (CommandLineOptions.Inference)
- {
- foreach (var impl in Program.TopLevelDeclarations.OfType<Implementation>().ToList())
- {
- LoopInvariantGenerator.PreInstrument(this, impl);
- }
-
- if (CommandLineOptions.ShowStages) {
- emitProgram(outputFilename + "_pre_inference");
- }
-
- }
-
- RaceInstrumenter.AddRaceCheckingInstrumentation();
-
- if (CommandLineOptions.ShowStages)
- {
- emitProgram(outputFilename + "_instrumented");
- }
-
- AbstractSharedState();
-
- if (CommandLineOptions.ShowStages)
- {
- emitProgram(outputFilename + "_abstracted");
- }
-
- MergeBlocksIntoPredecessors();
-
- if (CommandLineOptions.ShowStages)
- {
- emitProgram(outputFilename + "_merged_pre_predication");
- }
-
- MakeKernelPredicated();
-
- if (CommandLineOptions.ShowStages)
- {
- emitProgram(outputFilename + "_predicated");
- }
-
- MergeBlocksIntoPredecessors();
-
- if (CommandLineOptions.ShowStages)
- {
- emitProgram(outputFilename + "_merged_post_predication");
- }
-
- MakeKernelDualised();
-
- if (CommandLineOptions.ShowStages)
- {
- emitProgram(outputFilename + "_dualised");
- }
-
- RaceInstrumenter.AddRaceCheckingDeclarations();
-
- GenerateBarrierImplementation();
-
- GenerateStandardKernelContract();
-
- if (CommandLineOptions.ShowStages)
- {
- emitProgram(outputFilename + "_ready_to_verify");
- }
-
- if (CommandLineOptions.Inference)
- {
- ComputeInvariant();
- }
-
- emitProgram(outputFilename);
-
- }
-
- private void DoMayBePowerOfTwoAnalysis()
- {
- mayBePowerOfTwoAnalyser = new MayBePowerOfTwoAnalyser(this);
- mayBePowerOfTwoAnalyser.Analyse();
- }
-
- private void DoArrayControlFlowAnalysis()
- {
- arrayControlFlowAnalyser = new ArrayControlFlowAnalyser(this);
- arrayControlFlowAnalyser.Analyse();
- }
-
- private void DoUniformityAnalysis()
- {
- uniformityAnalyser = new UniformityAnalyser(this);
- uniformityAnalyser.Analyse();
- }
-
- private void DoLiveVariableAnalysis()
- {
- liveVariableAnalyser = new LiveVariableAnalyser(this);
- liveVariableAnalyser.Analyse();
- }
-
- private void DoVariableDefinitionAnalysis()
- {
- varDefAnalyses = Program.TopLevelDeclarations
- .OfType<Implementation>()
- .ToDictionary(i => i, i => VariableDefinitionAnalysis.Analyse(this, i));
- }
-
- private void DoReducedStrengthAnalysis()
- {
- reducedStrengthAnalyses = Program.TopLevelDeclarations
- .OfType<Implementation>()
- .ToDictionary(i => i, i => ReducedStrengthAnalysis.Analyse(this, i));
- }
-
- private void emitProgram(string filename)
- {
- using (TokenTextWriter writer = new TokenTextWriter(filename + ".bpl"))
- {
- Program.Emit(writer);
- }
- }
-
- private void ComputeInvariant()
- {
- for (int i = 0; i < Program.TopLevelDeclarations.Count; i++)
- {
- if (Program.TopLevelDeclarations[i] is Implementation)
- {
-
- Implementation Impl = Program.TopLevelDeclarations[i] as Implementation;
-
- List<Expr> UserSuppliedInvariants = GetUserSuppliedInvariants(Impl.Name);
-
- LoopInvariantGenerator.PostInstrument(this, Impl, UserSuppliedInvariants);
-
- Procedure Proc = Impl.Proc;
-
- if (QKeyValue.FindIntAttribute(Proc.Attributes, "inline", -1) == 1)
- {
- continue;
- }
-
- if (Proc == KernelProcedure)
- {
- continue;
- }
-
- AddCandidateRequires(Proc);
- RaceInstrumenter.AddRaceCheckingCandidateRequires(Proc);
- AddUserSuppliedCandidateRequires(Proc, UserSuppliedInvariants);
-
- AddCandidateEnsures(Proc);
- RaceInstrumenter.AddRaceCheckingCandidateEnsures(Proc);
- AddUserSuppliedCandidateEnsures(Proc, UserSuppliedInvariants);
-
- }
-
-
- }
-
- }
-
- private void AddCandidateEnsures(Procedure Proc)
- {
- HashSet<string> names = new HashSet<String>();
- foreach (Variable v in Proc.OutParams)
- {
- names.Add(StripThreadIdentifier(v.Name));
- }
-
- foreach (string name in names)
- {
- if (!uniformityAnalyser.IsUniform(Proc.Name, name))
- {
- AddEqualityCandidateEnsures(Proc, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, name, Microsoft.Boogie.Type.Int)));
- }
- }
-
- }
-
- private void AddCandidateRequires(Procedure Proc)
- {
- HashSet<string> names = new HashSet<String>();
- foreach (Variable v in Proc.InParams)
- {
- names.Add(StripThreadIdentifier(v.Name));
- }
-
- foreach (string name in names)
- {
-
- if (IsPredicateOrTemp(name))
- {
- Debug.Assert(name.Equals("_P"));
- Debug.Assert(!uniformityAnalyser.IsUniform(Proc.Name));
- AddCandidateRequires(Proc, Expr.Eq(
- new IdentifierExpr(Proc.tok, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, name + "$1", Microsoft.Boogie.Type.Bool))),
- new IdentifierExpr(Proc.tok, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, name + "$2", Microsoft.Boogie.Type.Bool)))
- ));
- }
- else
- {
- if (!uniformityAnalyser.IsUniform(Proc.Name, name))
- {
- if (!uniformityAnalyser.IsUniform(Proc.Name))
- {
- AddPredicatedEqualityCandidateRequires(Proc, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, name, Microsoft.Boogie.Type.Int)));
- }
- AddEqualityCandidateRequires(Proc, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, name, Microsoft.Boogie.Type.Int)));
- }
- }
- }
-
- }
-
- private void AddPredicatedEqualityCandidateRequires(Procedure Proc, Variable v)
- {
- AddCandidateRequires(Proc, Expr.Imp(
- Expr.And(
- new IdentifierExpr(Proc.tok, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, "_P$1", Microsoft.Boogie.Type.Bool))),
- new IdentifierExpr(Proc.tok, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, "_P$2", Microsoft.Boogie.Type.Bool)))
- ),
- Expr.Eq(
- new IdentifierExpr(Proc.tok, new VariableDualiser(1, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable)),
- new IdentifierExpr(Proc.tok, new VariableDualiser(2, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable))
- )
- ));
- }
-
- private void AddEqualityCandidateRequires(Procedure Proc, Variable v)
- {
- AddCandidateRequires(Proc,
- Expr.Eq(
- new IdentifierExpr(Proc.tok, new VariableDualiser(1, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable)),
- new IdentifierExpr(Proc.tok, new VariableDualiser(2, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable))
- )
- );
- }
-
- private void AddEqualityCandidateEnsures(Procedure Proc, Variable v)
- {
- AddCandidateEnsures(Proc,
- Expr.Eq(
- new IdentifierExpr(Proc.tok, new VariableDualiser(1, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable)),
- new IdentifierExpr(Proc.tok, new VariableDualiser(2, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable))
- ));
- }
-
-
- private void AddUserSuppliedCandidateRequires(Procedure Proc, List<Expr> UserSuppliedInvariants)
- {
- foreach (Expr e in UserSuppliedInvariants)
- {
- Requires r = new Requires(false, e);
- Proc.Requires.Add(r);
- bool OK = ProgramIsOK(Proc);
- Proc.Requires.Remove(r);
- if (OK)
- {
- AddCandidateRequires(Proc, e);
- }
- }
- }
-
- private void AddUserSuppliedCandidateEnsures(Procedure Proc, List<Expr> UserSuppliedInvariants)
- {
- foreach (Expr e in UserSuppliedInvariants)
- {
- Ensures ens = new Ensures(false, e);
- Proc.Ensures.Add(ens);
- bool OK = ProgramIsOK(Proc);
- Proc.Ensures.Remove(ens);
- if (OK)
- {
- AddCandidateEnsures(Proc, e);
- }
- }
- }
-
-
-
- internal void AddCandidateRequires(Procedure Proc, Expr e)
- {
- Constant ExistentialBooleanConstant = Program.MakeExistentialBoolean();
- IdentifierExpr ExistentialBoolean = new IdentifierExpr(Proc.tok, ExistentialBooleanConstant);
- Proc.Requires.Add(new Requires(false, Expr.Imp(ExistentialBoolean, e)));
- }
-
- internal void AddCandidateEnsures(Procedure Proc, Expr e)
- {
- Constant ExistentialBooleanConstant = Program.MakeExistentialBoolean();
- IdentifierExpr ExistentialBoolean = new IdentifierExpr(Proc.tok, ExistentialBooleanConstant);
- Proc.Ensures.Add(new Ensures(false, Expr.Imp(ExistentialBoolean, e)));
- }
-
- private List<Expr> GetUserSuppliedInvariants(string ProcedureName)
- {
- List<Expr> result = new List<Expr>();
-
- if (CommandLineOptions.invariantsFile == null)
- {
- return result;
- }
-
- StreamReader sr = new StreamReader(new FileStream(CommandLineOptions.invariantsFile, FileMode.Open, FileAccess.Read));
- string line;
- int lineNumber = 1;
- while ((line = sr.ReadLine()) != null)
- {
- string[] components = line.Split(':');
-
- if (components.Length != 1 && components.Length != 2)
- {
- Console.WriteLine("Ignoring badly formed candidate invariant '" + line + "' at '" + CommandLineOptions.invariantsFile + "' line " + lineNumber);
- continue;
- }
-
- if (components.Length == 2)
- {
- if (!components[0].Trim().Equals(ProcedureName))
- {
- continue;
- }
-
- line = components[1];
- }
-
- string temp_program_text = "axiom (" + line + ");";
- TokenTextWriter writer = new TokenTextWriter("temp_out.bpl");
- writer.WriteLine(temp_program_text);
- writer.Close();
-
- Program temp_program = GPUVerify.ParseBoogieProgram(new List<string>(new string[] { "temp_out.bpl" }), false);
-
- if (null == temp_program)
- {
- Console.WriteLine("Ignoring badly formed candidate invariant '" + line + "' at '" + CommandLineOptions.invariantsFile + "' line " + lineNumber);
- }
- else
- {
- Debug.Assert(temp_program.TopLevelDeclarations[0] is Axiom);
- result.Add((temp_program.TopLevelDeclarations[0] as Axiom).Expr);
- }
-
- lineNumber++;
- }
-
- return result;
- }
-
- internal bool ContainsNamedVariable(HashSet<Variable> variables, string name)
- {
- foreach(Variable v in variables)
- {
- if(StripThreadIdentifier(v.Name) == name)
- {
- return true;
- }
- }
- return false;
- }
-
- internal static bool IsPredicate(string v) {
- if (v.Length < 2) {
- return false;
- }
- if (!v.Substring(0, 1).Equals("p")) {
- return false;
- }
- for (int i = 1; i < v.Length; i++) {
- if (!Char.IsDigit(v.ToCharArray()[i])) {
- return false;
- }
- }
- return true;
- }
-
- internal static bool IsPredicateOrTemp(string lv) {
-
- // We should improve this by having a general convention
- // for names of temporary or predicate variables
-
- if (lv.Length >= 2) {
- if (lv.Substring(0, 1).Equals("p") || lv.Substring(0, 1).Equals("v")) {
- for (int i = 1; i < lv.Length; i++) {
- if (!Char.IsDigit(lv.ToCharArray()[i])) {
- return false;
- }
- }
- return true;
- }
-
- }
-
- if (lv.Contains("_HAVOC_")) {
- return true;
- }
-
- return (lv.Length >= 2 && lv.Substring(0,2).Equals("_P")) ||
- (lv.Length > 3 && lv.Substring(0,3).Equals("_LC")) ||
- (lv.Length > 5 && lv.Substring(0,5).Equals("_temp"));
- }
-
-
-
-
- internal bool ProgramIsOK(Declaration d)
- {
- Debug.Assert(d is Procedure || d is Implementation);
- TokenTextWriter writer = new TokenTextWriter("temp_out.bpl");
- List<Declaration> RealDecls = Program.TopLevelDeclarations;
- List<Declaration> TempDecls = new List<Declaration>();
- foreach (Declaration d2 in RealDecls)
- {
- if (d is Procedure)
- {
- if ((d == d2) || !(d2 is Implementation || d2 is Procedure))
- {
- TempDecls.Add(d2);
- }
- }
- else if (d is Implementation)
- {
- if ((d == d2) || !(d2 is Implementation))
- {
- TempDecls.Add(d2);
- }
- }
- }
- Program.TopLevelDeclarations = TempDecls;
- Program.Emit(writer);
- writer.Close();
- Program.TopLevelDeclarations = RealDecls;
- Program temp_program = GPUVerify.ParseBoogieProgram(new List<string>(new string[] { "temp_out.bpl" }), false);
-
- if (temp_program == null)
- {
- return false;
- }
-
- if (temp_program.Resolve() != 0)
- {
- return false;
- }
-
- if (temp_program.Typecheck() != 0)
- {
- return false;
- }
- return true;
- }
-
-
-
- public static Microsoft.Boogie.Type GetTypeOfIdX()
- {
- Contract.Requires(_X != null);
- return _X.TypedIdent.Type;
- }
-
- public static Microsoft.Boogie.Type GetTypeOfIdY()
- {
- Contract.Requires(_Y != null);
- return _Y.TypedIdent.Type;
- }
-
- public static Microsoft.Boogie.Type GetTypeOfIdZ()
- {
- Contract.Requires(_Z != null);
- return _Z.TypedIdent.Type;
- }
-
- public static Microsoft.Boogie.Type GetTypeOfId(string dimension)
- {
- Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z"));
- if (dimension.Equals("X")) return GetTypeOfIdX();
- if (dimension.Equals("Y")) return GetTypeOfIdY();
- if (dimension.Equals("Z")) return GetTypeOfIdZ();
- Debug.Assert(false);
- return null;
- }
-
- public bool KernelHasIdX()
- {
- return _X != null;
- }
-
- public bool KernelHasIdY()
- {
- return _Y != null;
- }
-
- public bool KernelHasIdZ()
- {
- return _Z != null;
- }
-
- public bool KernelHasGroupIdX()
- {
- return _GROUP_X != null;
- }
-
- public bool KernelHasGroupIdY()
- {
- return _GROUP_Y != null;
- }
-
- public bool KernelHasGroupIdZ()
- {
- return _GROUP_Z != null;
- }
-
- public bool KernelHasNumGroupsX()
- {
- return _NUM_GROUPS_X != null;
- }
-
- public bool KernelHasNumGroupsY()
- {
- return _NUM_GROUPS_Y != null;
- }
-
- public bool KernelHasNumGroupsZ()
- {
- return _NUM_GROUPS_Z != null;
- }
-
- public bool KernelHasGroupSizeX()
- {
- return _GROUP_SIZE_X != null;
- }
-
- public bool KernelHasGroupSizeY()
- {
- return _GROUP_SIZE_Y != null;
- }
-
- public bool KernelHasGroupSizeZ()
- {
- return _GROUP_SIZE_Z != null;
- }
-
- internal static string StripThreadIdentifier(string p, out int id)
- {
- if (p.EndsWith("$1"))
- {
- id = 1;
- return p.Substring(0, p.Length - 2);
- }
- if (p.EndsWith("$2"))
- {
- id = 2;
- return p.Substring(0, p.Length - 2);
- }
-
- id = 0;
- return p;
- }
-
- internal static string StripThreadIdentifier(string p)
- {
- int id;
- return StripThreadIdentifier(p, out id);
- }
-
- private void GenerateStandardKernelContract()
- {
- RaceInstrumenter.AddKernelPrecondition();
-
- IToken tok = KernelImplementation.tok;
-
- GeneratePreconditionsForDimension(tok, "X");
- GeneratePreconditionsForDimension(tok, "Y");
- GeneratePreconditionsForDimension(tok, "Z");
-
- RaceInstrumenter.AddStandardSourceVariablePreconditions();
- RaceInstrumenter.AddStandardSourceVariablePostconditions();
-
- foreach (Declaration D in Program.TopLevelDeclarations)
- {
- if (!(D is Procedure))
- {
- continue;
- }
- Procedure Proc = D as Procedure;
- if (QKeyValue.FindIntAttribute(Proc.Attributes, "inline", -1) == 1)
- {
- continue;
- }
-
- Expr DistinctLocalIds =
- Expr.Or(
- Expr.Or(
- Expr.Neq(
- new IdentifierExpr(tok, MakeThreadId(tok, "X", 1)),
- new IdentifierExpr(tok, MakeThreadId(tok, "X", 2))
- ),
- Expr.Neq(
- new IdentifierExpr(tok, MakeThreadId(tok, "Y", 1)),
- new IdentifierExpr(tok, MakeThreadId(tok, "Y", 2))
- )
- ),
- Expr.Neq(
- new IdentifierExpr(tok, MakeThreadId(tok, "Z", 1)),
- new IdentifierExpr(tok, MakeThreadId(tok, "Z", 2))
- )
- );
-
- Proc.Requires.Add(new Requires(false, Expr.Imp(ThreadsInSameGroup(), DistinctLocalIds)));
-
- if (CommandLineOptions.OnlyIntraGroupRaceChecking)
- {
- Proc.Requires.Add(new Requires(false, ThreadsInSameGroup()));
- }
-
- if (Proc == KernelProcedure)
- {
- bool foundNonUniform = false;
- int indexOfFirstNonUniformParameter;
- for (indexOfFirstNonUniformParameter = 0; indexOfFirstNonUniformParameter < Proc.InParams.Length; indexOfFirstNonUniformParameter++)
- {
- if (!uniformityAnalyser.IsUniform(Proc.Name, StripThreadIdentifier(Proc.InParams[indexOfFirstNonUniformParameter].Name)))
- {
- foundNonUniform = true;
- break;
- }
- }
-
- if (foundNonUniform)
- {
- // I have a feeling this will never be reachable!!!
- int numberOfNonUniformParameters = (Proc.InParams.Length - indexOfFirstNonUniformParameter) / 2;
- for (int i = indexOfFirstNonUniformParameter; i < numberOfNonUniformParameters; i++)
- {
- Proc.Requires.Add(new Requires(false,
- Expr.Eq(new IdentifierExpr(Proc.InParams[i].tok, Proc.InParams[i]),
- new IdentifierExpr(Proc.InParams[i + numberOfNonUniformParameters].tok, Proc.InParams[i + numberOfNonUniformParameters]))));
- }
- }
- }
-
- }
-
- foreach (Declaration D in Program.TopLevelDeclarations)
- {
- if (!(D is Implementation))
- {
- continue;
- }
- Implementation Impl = D as Implementation;
-
- foreach (IRegion subregion in RootRegion(Impl).SubRegions())
- {
- RaceInstrumenter.AddSourceLocationLoopInvariants(Impl, subregion);
- }
- }
-
- foreach (Declaration D in Program.TopLevelDeclarations)
- {
- if (!(D is Implementation))
- {
- continue;
- }
- Implementation Impl = D as Implementation;
-
- if (QKeyValue.FindIntAttribute(Impl.Proc.Attributes, "inline", -1) == 1)
- {
- continue;
- }
- if (Impl.Proc == KernelProcedure)
- {
- continue;
- }
-
- new EnsureDisabledThreadHasNoEffectInstrumenter(this, Impl).instrument();
-
- }
-
- }
-
- internal static Expr ThreadsInSameGroup()
- {
- return Expr.And(
- Expr.And(
- Expr.Eq(
- new IdentifierExpr(Token.NoToken, MakeGroupId("X", 1)),
- new IdentifierExpr(Token.NoToken, MakeGroupId("X", 2))
- ),
- Expr.Eq(
- new IdentifierExpr(Token.NoToken, MakeGroupId("Y", 1)),
- new IdentifierExpr(Token.NoToken, MakeGroupId("Y", 2))
- )
- ),
- Expr.Eq(
- new IdentifierExpr(Token.NoToken, MakeGroupId("Z", 1)),
- new IdentifierExpr(Token.NoToken, MakeGroupId("Z", 2))
- )
- );
- }
-
- internal static void AddInvariantToAllLoops(Expr Invariant, StmtList stmtList)
- {
- foreach (BigBlock bb in stmtList.BigBlocks)
- {
- AddInvariantToAllLoops(Invariant, bb);
- }
- }
-
- internal static void AddInvariantToAllLoops(Expr Invariant, BigBlock bb)
- {
- if (bb.ec is WhileCmd)
- {
- WhileCmd wc = bb.ec as WhileCmd;
- wc.Invariants.Add(new AssertCmd(wc.tok, Invariant));
- AddInvariantToAllLoops(Invariant, wc.Body);
- }
- Debug.Assert(!(bb.ec is IfCmd));
- }
-
- internal static int GetThreadSuffix(string p)
- {
- return Int32.Parse(p.Substring(p.IndexOf("$") + 1, p.Length - (p.IndexOf("$") + 1)));
- }
-
- private void GeneratePreconditionsForDimension(IToken tok, String dimension)
- {
- foreach (Declaration D in Program.TopLevelDeclarations.ToList())
- {
- if (!(D is Procedure))
- {
- continue;
- }
- Procedure Proc = D as Procedure;
- if (QKeyValue.FindIntAttribute(Proc.Attributes, "inline", -1) == 1)
- {
- continue;
- }
-
- Expr GroupSizePositive;
- Expr NumGroupsPositive;
- Expr GroupIdNonNegative;
- Expr GroupIdLessThanNumGroups;
-
- if (GetTypeOfId(dimension).Equals(Microsoft.Boogie.Type.GetBvType(32)))
- {
- GroupSizePositive = MakeBVSgt(new IdentifierExpr(tok, GetGroupSize(dimension)), ZeroBV());
- NumGroupsPositive = MakeBVSgt(new IdentifierExpr(tok, GetNumGroups(dimension)), ZeroBV());
- GroupIdNonNegative = MakeBVSge(new IdentifierExpr(tok, GetGroupId(dimension)), ZeroBV());
- GroupIdLessThanNumGroups = MakeBVSlt(new IdentifierExpr(tok, GetGroupId(dimension)), new IdentifierExpr(tok, GetNumGroups(dimension)));
- }
- else
- {
- GroupSizePositive = Expr.Gt(new IdentifierExpr(tok, GetGroupSize(dimension)), Zero());
- NumGroupsPositive = Expr.Gt(new IdentifierExpr(tok, GetNumGroups(dimension)), Zero());
- GroupIdNonNegative = Expr.Ge(new IdentifierExpr(tok, GetGroupId(dimension)), Zero());
- GroupIdLessThanNumGroups = Expr.Lt(new IdentifierExpr(tok, GetGroupId(dimension)), new IdentifierExpr(tok, GetNumGroups(dimension)));
- }
-
- Proc.Requires.Add(new Requires(false, GroupSizePositive));
- Proc.Requires.Add(new Requires(false, NumGroupsPositive));
- Proc.Requires.Add(new Requires(false, new VariableDualiser(1, null, null).VisitExpr(GroupIdNonNegative)));
- Proc.Requires.Add(new Requires(false, new VariableDualiser(2, null, null).VisitExpr(GroupIdNonNegative)));
- Proc.Requires.Add(new Requires(false, new VariableDualiser(1, null, null).VisitExpr(GroupIdLessThanNumGroups)));
- Proc.Requires.Add(new Requires(false, new VariableDualiser(2, null, null).VisitExpr(GroupIdLessThanNumGroups)));
-
- Expr ThreadIdNonNegative =
- GetTypeOfId(dimension).Equals(Microsoft.Boogie.Type.GetBvType(32)) ?
- MakeBVSge(new IdentifierExpr(tok, MakeThreadId(tok, dimension)), ZeroBV())
- :
- Expr.Ge(new IdentifierExpr(tok, MakeThreadId(tok, dimension)), Zero());
- Expr ThreadIdLessThanGroupSize =
- GetTypeOfId(dimension).Equals(Microsoft.Boogie.Type.GetBvType(32)) ?
- MakeBVSlt(new IdentifierExpr(tok, MakeThreadId(tok, dimension)), new IdentifierExpr(tok, GetGroupSize(dimension)))
- :
- Expr.Lt(new IdentifierExpr(tok, MakeThreadId(tok, dimension)), new IdentifierExpr(tok, GetGroupSize(dimension)));
-
- Proc.Requires.Add(new Requires(false, new VariableDualiser(1, null, null).VisitExpr(ThreadIdNonNegative)));
- Proc.Requires.Add(new Requires(false, new VariableDualiser(2, null, null).VisitExpr(ThreadIdNonNegative)));
- Proc.Requires.Add(new Requires(false, new VariableDualiser(1, null, null).VisitExpr(ThreadIdLessThanGroupSize)));
- Proc.Requires.Add(new Requires(false, new VariableDualiser(2, null, null).VisitExpr(ThreadIdLessThanGroupSize)));
-
- }
-
- }
-
- private Function GetOrCreateBVFunction(string functionName, string smtName, Microsoft.Boogie.Type resultType, params Microsoft.Boogie.Type[] argTypes)
- {
- Function f = (Function)ResContext.LookUpProcedure(functionName);
- if (f != null)
- return f;
-
- f = new Function(Token.NoToken, functionName,
- new VariableSeq(argTypes.Select(t => new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "", t))).ToArray()),
- new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "", resultType)));
- f.AddAttribute("bvbuiltin", smtName);
- Program.TopLevelDeclarations.Add(f);
- ResContext.AddProcedure(f);
- return f;
- }
-
- private Expr MakeBVFunctionCall(string functionName, string smtName, Microsoft.Boogie.Type resultType, params Expr[] args)
- {
- Function f = GetOrCreateBVFunction(functionName, smtName, resultType, args.Select(a => a.Type).ToArray());
- var e = new NAryExpr(Token.NoToken, new FunctionCall(f), new ExprSeq(args));
- e.Type = resultType;
- return e;
- }
-
- private Expr MakeBitVectorBinaryBoolean(string suffix, string smtName, Expr lhs, Expr rhs)
- {
- return MakeBVFunctionCall("BV" + lhs.Type.BvBits + "_" + suffix, smtName, Microsoft.Boogie.Type.Bool, lhs, rhs);
- }
-
- private Expr MakeBitVectorBinaryBitVector(string suffix, string smtName, Expr lhs, Expr rhs)
- {
- return MakeBVFunctionCall("BV" + lhs.Type.BvBits + "_" + suffix, smtName, lhs.Type, lhs, rhs);
- }
-
- internal Expr MakeBVSlt(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBoolean("SLT", "bvslt", lhs, rhs); }
- internal Expr MakeBVSgt(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBoolean("SGT", "bvsgt", lhs, rhs); }
- internal Expr MakeBVSge(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBoolean("SGE", "bvsge", lhs, rhs); }
-
- internal Expr MakeBVAnd(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBitVector("AND", "bvand", lhs, rhs); }
- internal Expr MakeBVAdd(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBitVector("ADD", "bvadd", lhs, rhs); }
- internal Expr MakeBVSub(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBitVector("SUB", "bvsub", lhs, rhs); }
- internal Expr MakeBVMul(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBitVector("MUL", "bvmul", lhs, rhs); }
- internal Expr MakeBVURem(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBitVector("UREM", "bvurem", lhs, rhs); }
-
- internal static Expr MakeBitVectorBinaryBoolean(string functionName, Expr lhs, Expr rhs)
- {
- return new NAryExpr(lhs.tok, new FunctionCall(new Function(lhs.tok, functionName, new VariableSeq(new Variable[] {
- new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "arg1", Microsoft.Boogie.Type.GetBvType(32))),
- new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "arg2", Microsoft.Boogie.Type.GetBvType(32)))
- }), new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "result", Microsoft.Boogie.Type.Bool)))), new ExprSeq(new Expr[] { lhs, rhs }));
- }
-
- internal static Expr MakeBitVectorBinaryBitVector(string functionName, Expr lhs, Expr rhs)
- {
- return new NAryExpr(lhs.tok, new FunctionCall(new Function(lhs.tok, functionName, new VariableSeq(new Variable[] {
- new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "arg1", Microsoft.Boogie.Type.GetBvType(32))),
- new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "arg2", Microsoft.Boogie.Type.GetBvType(32)))
- }), new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "result", Microsoft.Boogie.Type.GetBvType(32))))), new ExprSeq(new Expr[] { lhs, rhs }));
- }
-
- private static bool IsBVFunctionCall(Expr e, string smtName, out ExprSeq args)
- {
- args = null;
- var ne = e as NAryExpr;
- if (ne == null)
- return false;
-
- var fc = ne.Fun as FunctionCall;
- if (fc == null)
- return false;
-
- string bvBuiltin = QKeyValue.FindStringAttribute(fc.Func.Attributes, "bvbuiltin");
- if (bvBuiltin == smtName)
- {
- args = ne.Args;
- return true;
- }
-
- return false;
- }
-
- private static bool IsBVFunctionCall(Expr e, string smtName, out Expr lhs, out Expr rhs)
- {
- ExprSeq es;
- if (IsBVFunctionCall(e, smtName, out es))
- {
- lhs = es[0]; rhs = es[1];
- return true;
- }
- lhs = null; rhs = null;
- return false;
- }
-
- internal static bool IsBVAdd(Expr e, out Expr lhs, out Expr rhs) { return IsBVFunctionCall(e, "bvadd", out lhs, out rhs); }
- internal static bool IsBVMul(Expr e, out Expr lhs, out Expr rhs) { return IsBVFunctionCall(e, "bvmul", out lhs, out rhs); }
-
- internal Constant GetGroupSize(string dimension)
- {
- Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z"));
- if (dimension.Equals("X")) return _GROUP_SIZE_X;
- if (dimension.Equals("Y")) return _GROUP_SIZE_Y;
- if (dimension.Equals("Z")) return _GROUP_SIZE_Z;
- Debug.Assert(false);
- return null;
- }
-
- internal Constant GetNumGroups(string dimension)
- {
- Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z"));
- if (dimension.Equals("X")) return _NUM_GROUPS_X;
- if (dimension.Equals("Y")) return _NUM_GROUPS_Y;
- if (dimension.Equals("Z")) return _NUM_GROUPS_Z;
- Debug.Assert(false);
- return null;
- }
-
- internal Constant MakeThreadId(IToken tok, string dimension)
- {
- Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z"));
- string name = null;
- if (dimension.Equals("X")) name = _X.Name;
- if (dimension.Equals("Y")) name = _Y.Name;
- if (dimension.Equals("Z")) name = _Z.Name;
- Debug.Assert(name != null);
- return new Constant(tok, new TypedIdent(tok, name, GetTypeOfId(dimension)));
- }
-
- internal Constant MakeThreadId(IToken tok, string dimension, int number)
- {
- Constant resultWithoutThreadId = MakeThreadId(tok, dimension);
- return new Constant(tok, new TypedIdent(tok, resultWithoutThreadId.Name + "$" + number, GetTypeOfId(dimension)));
- }
-
- internal static Constant GetGroupId(string dimension)
- {
- Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z"));
- if (dimension.Equals("X")) return _GROUP_X;
- if (dimension.Equals("Y")) return _GROUP_Y;
- if (dimension.Equals("Z")) return _GROUP_Z;
- Debug.Assert(false);
- return null;
- }
-
- internal static Constant MakeGroupId(string dimension, int number)
- {
- Constant resultWithoutThreadId = GetGroupId(dimension);
- return new Constant(Token.NoToken, new TypedIdent(Token.NoToken, resultWithoutThreadId.Name + "$" + number, GetTypeOfId(dimension)));
- }
-
- private static LiteralExpr Zero()
- {
- return new LiteralExpr(Token.NoToken, BigNum.FromInt(0));
- }
-
- internal static LiteralExpr ZeroBV()
- {
- return new LiteralExpr(Token.NoToken, BigNum.FromInt(0), 32);
- }
-
-
-
- private void GenerateBarrierImplementation()
- {
- IToken tok = BarrierProcedure.tok;
-
- List<BigBlock> bigblocks = new List<BigBlock>();
- BigBlock barrierEntryBlock = new BigBlock(tok, "__BarrierImpl", new CmdSeq(), null, null);
- bigblocks.Add(barrierEntryBlock);
-
- Debug.Assert((BarrierProcedure.InParams.Length % 2) == 0);
- int paramsPerThread = BarrierProcedure.InParams.Length / 2;
- IdentifierExpr P1 = new IdentifierExpr(tok, new LocalVariable(tok, BarrierProcedure.InParams[0].TypedIdent));
- IdentifierExpr P2 = new IdentifierExpr(tok, new LocalVariable(tok, BarrierProcedure.InParams[paramsPerThread].TypedIdent));
-
- Expr LocalFence1 = MakeFenceExpr(BarrierProcedure.InParams[1]);
- Expr LocalFence2 = MakeFenceExpr(BarrierProcedure.InParams[paramsPerThread + 1]);
-
- Expr GlobalFence1 = MakeFenceExpr(BarrierProcedure.InParams[2]);
- Expr GlobalFence2 = MakeFenceExpr(BarrierProcedure.InParams[paramsPerThread + 2]);
-
- Expr DivergenceCondition = Expr.Imp(ThreadsInSameGroup(), Expr.Eq(P1, P2));
-
- Requires nonDivergenceRequires = new Requires(false, DivergenceCondition);
- nonDivergenceRequires.Attributes = new QKeyValue(Token.NoToken, "barrier_divergence",
- new List<object>(new object[] { }), null);
- BarrierProcedure.Requires.Add(nonDivergenceRequires);
-
- if (!CommandLineOptions.OnlyDivergence)
- {
- List<BigBlock> returnbigblocks = new List<BigBlock>();
- returnbigblocks.Add(new BigBlock(tok, "__Disabled", new CmdSeq(), null, new ReturnCmd(tok)));
- StmtList returnstatement = new StmtList(returnbigblocks, BarrierProcedure.tok);
-
- Expr IfGuard = Expr.Or(Expr.And(Expr.Not(P1), Expr.Not(P2)), Expr.And(ThreadsInSameGroup(), Expr.Or(Expr.Not(P1), Expr.Not(P2))));
- barrierEntryBlock.ec = new IfCmd(tok, IfGuard, returnstatement, null, null);
- }
-
- if(KernelArrayInfo.getGroupSharedArrays().Count > 0) {
-
- Expr IfGuard1 = Expr.And(P1, LocalFence1);
- Expr IfGuard2 = Expr.And(P2, LocalFence2);
-
- bigblocks.Add(new BigBlock(Token.NoToken, null, new CmdSeq(),
- new IfCmd(Token.NoToken, IfGuard1, new StmtList(MakeResetBlocks(1, KernelArrayInfo.getGroupSharedArrays()), Token.NoToken), null, null),
- null));
- bigblocks.Add(new BigBlock(Token.NoToken, null, new CmdSeq(),
- new IfCmd(Token.NoToken, IfGuard2, new StmtList(MakeResetBlocks(2, KernelArrayInfo.getGroupSharedArrays()), Token.NoToken), null, null),
- null));
-
- bigblocks.AddRange(MakeHavocBlocks(KernelArrayInfo.getGroupSharedArrays()));
- }
-
- if (KernelArrayInfo.getGlobalArrays().Count > 0)
- {
- Expr IfGuard1 = Expr.And(P1, GlobalFence1);
- Expr IfGuard2 = Expr.And(P2, GlobalFence2);
-
- bigblocks.Add(new BigBlock(Token.NoToken, null, new CmdSeq(),
- new IfCmd(Token.NoToken, IfGuard1, new StmtList(MakeResetBlocks(1, KernelArrayInfo.getGlobalArrays()), Token.NoToken), null, null),
- null));
- bigblocks.Add(new BigBlock(Token.NoToken, null, new CmdSeq(),
- new IfCmd(Token.NoToken, IfGuard2, new StmtList(MakeResetBlocks(2, KernelArrayInfo.getGlobalArrays()), Token.NoToken), null, null),
- null));
-
- bigblocks.AddRange(MakeHavocBlocks(KernelArrayInfo.getGlobalArrays()));
- }
-
- StmtList statements = new StmtList(bigblocks, BarrierProcedure.tok);
- Implementation BarrierImplementation =
- new Implementation(BarrierProcedure.tok, BarrierProcedure.Name, new TypeVariableSeq(),
- BarrierProcedure.InParams, BarrierProcedure.OutParams, new VariableSeq(), statements);
-
- if (CommandLineOptions.Unstructured)
- BarrierImplementation.Resolve(ResContext);
-
- BarrierImplementation.AddAttribute("inline", new object[] { new LiteralExpr(tok, BigNum.FromInt(1)) });
- BarrierProcedure.AddAttribute("inline", new object[] { new LiteralExpr(tok, BigNum.FromInt(1)) });
-
- BarrierImplementation.Proc = BarrierProcedure;
-
- Program.TopLevelDeclarations.Add(BarrierImplementation);
- }
-
- private static NAryExpr MakeFenceExpr(Variable v) {
- return Expr.Eq(new IdentifierExpr(Token.NoToken, new LocalVariable(Token.NoToken, v.TypedIdent)),
- new LiteralExpr(Token.NoToken, BigNum.FromInt(1), 1));
- }
-
- private static Expr flagIsSet(Expr Flags, int flag)
- {
- return Expr.Eq(new BvExtractExpr(
- Token.NoToken, Flags, flag, flag - 1),
- new LiteralExpr(Token.NoToken, BigNum.FromInt(1), 1));
- }
-
- private List<BigBlock> MakeResetBlocks(int Thread, ICollection<Variable> variables)
- {
- Debug.Assert(variables.Count > 0);
- List<BigBlock> ResetAndHavocBlocks = new List<BigBlock>();
- foreach (Variable v in variables)
- {
- ResetAndHavocBlocks.Add(RaceInstrumenter.MakeResetReadWriteSetStatements(v, Thread));
- }
- Debug.Assert(ResetAndHavocBlocks.Count > 0);
- return ResetAndHavocBlocks;
- }
-
- private List<BigBlock> MakeHavocBlocks(ICollection<Variable> variables) {
- Debug.Assert(variables.Count > 0);
- List<BigBlock> result = new List<BigBlock>();
- foreach (Variable v in variables) {
- if (!ArrayModelledAdversarially(v)) {
- result.Add(HavocSharedArray(v));
- }
- }
- return result;
- }
-
- public static bool HasZDimension(Variable v)
- {
- if (v.TypedIdent.Type is MapType)
- {
- MapType mt = v.TypedIdent.Type as MapType;
-
- if (mt.Result is MapType)
- {
- MapType mt2 = mt.Result as MapType;
- if (mt2.Result is MapType)
- {
- Debug.Assert(!((mt2.Result as MapType).Result is MapType));
- return true;
- }
- }
- }
- return false;
- }
-
- private BigBlock HavocSharedArray(Variable v)
- {
- return new BigBlock(Token.NoToken, null,
- new CmdSeq(new Cmd[] { new HavocCmd(Token.NoToken,
- new IdentifierExprSeq(new IdentifierExpr[] { new IdentifierExpr(Token.NoToken, v) })) }), null, null);
- }
-
- internal static bool ModifiesSetContains(IdentifierExprSeq Modifies, IdentifierExpr v)
- {
- foreach (IdentifierExpr ie in Modifies)
- {
- if (ie.Name.Equals(v.Name))
- {
- return true;
- }
- }
- return false;
- }
-
- private void AbstractSharedState()
- {
- new AdversarialAbstraction(this).Abstract();
- }
-
- internal static string MakeOffsetVariableName(string Name, string AccessType)
- {
- return "_" + AccessType + "_OFFSET_" + Name;
- }
-
- internal static GlobalVariable MakeOffsetVariable(string Name, string ReadOrWrite)
- {
- return new GlobalVariable(Token.NoToken, new TypedIdent(Token.NoToken, MakeOffsetVariableName(Name, ReadOrWrite),
- Microsoft.Boogie.Type.GetBvType(32)));
- }
-
- internal static string MakeSourceVariableName(string Name, string AccessType)
- {
- return "_" + AccessType + "_SOURCE_" + Name;
- }
-
- internal static GlobalVariable MakeSourceVariable(string name, string ReadOrWrite)
- {
- return new GlobalVariable(Token.NoToken, new TypedIdent(Token.NoToken, MakeSourceVariableName(name, ReadOrWrite),
- Microsoft.Boogie.Type.GetBvType(32)));
- }
-
- internal GlobalVariable FindOrCreateAccessHasOccurredVariable(string varName, string accessType)
- {
- string name = MakeAccessHasOccurredVariableName(varName, accessType) + "$1";
- foreach(Declaration D in Program.TopLevelDeclarations)
- {
- if(D is GlobalVariable && ((GlobalVariable)D).Name.Equals(name))
- {
- return D as GlobalVariable;
- }
- }
-
- GlobalVariable result = new VariableDualiser(1, null, null).VisitVariable(
- MakeAccessHasOccurredVariable(varName, accessType)) as GlobalVariable;
-
- Program.TopLevelDeclarations.Add(result);
- return result;
-
- }
-
- internal GlobalVariable FindOrCreateOffsetVariable(string varName, string accessType)
- {
- string name = MakeOffsetVariableName(varName, accessType) + "$1";
- foreach (Declaration D in Program.TopLevelDeclarations)
- {
- if (D is GlobalVariable && ((GlobalVariable)D).Name.Equals(name))
- {
- return D as GlobalVariable;
- }
- }
-
- GlobalVariable result = new VariableDualiser(1, null, null).VisitVariable(
- MakeOffsetVariable(varName, accessType)) as GlobalVariable;
-
- Program.TopLevelDeclarations.Add(result);
- return result;
-
- }
-
- internal GlobalVariable FindOrCreateSourceVariable(string varName, string accessType) {
- string name = MakeSourceVariableName(varName, accessType) + "$1";
- foreach (Declaration D in Program.TopLevelDeclarations) {
- if (D is GlobalVariable && ((GlobalVariable)D).Name.Equals(name)) {
- return D as GlobalVariable;
- }
- }
-
- GlobalVariable result = new VariableDualiser(1, null, null).VisitVariable(
- MakeSourceVariable(varName, accessType)) as GlobalVariable;
-
- Program.TopLevelDeclarations.Add(result);
- return result;
-
- }
-
- internal static GlobalVariable MakeAccessHasOccurredVariable(string varName, string accessType)
- {
- return new GlobalVariable(Token.NoToken, new TypedIdent(Token.NoToken, MakeAccessHasOccurredVariableName(varName, accessType), Microsoft.Boogie.Type.Bool));
- }
-
- internal static string MakeAccessHasOccurredVariableName(string varName, string accessType)
- {
- return "_" + accessType + "_HAS_OCCURRED_" + varName;
- }
-
- internal static IdentifierExpr MakeAccessHasOccurredExpr(string varName, string accessType)
- {
- return new IdentifierExpr(Token.NoToken, MakeAccessHasOccurredVariable(varName, accessType));
- }
-
- internal static bool IsIntOrBv32(Microsoft.Boogie.Type type)
- {
- return type.Equals(Microsoft.Boogie.Type.Int) || type.Equals(Microsoft.Boogie.Type.GetBvType(32));
- }
-
- private void PullOutNonLocalAccesses()
- {
- foreach (Declaration d in Program.TopLevelDeclarations)
- {
- if (d is Implementation)
- {
- (d as Implementation).StructuredStmts = PullOutNonLocalAccesses((d as Implementation).StructuredStmts, (d as Implementation));
- }
- }
- }
-
- private void RemoveElseIfs()
- {
- foreach (Declaration d in Program.TopLevelDeclarations)
- {
- if (d is Implementation)
- {
- (d as Implementation).StructuredStmts = RemoveElseIfs((d as Implementation).StructuredStmts);
- }
- }
- }
-
- private void RemoveRedundantReturns()
- {
- foreach (Declaration d in Program.TopLevelDeclarations)
- {
- if (d is Implementation)
- {
- RemoveRedundantReturns((d as Implementation).StructuredStmts);
- }
- }
- }
-
- private StmtList RemoveElseIfs(StmtList stmtList)
- {
- Contract.Requires(stmtList != null);
-
- StmtList result = new StmtList(new List<BigBlock>(), stmtList.EndCurly);
-
- foreach (BigBlock bodyBlock in stmtList.BigBlocks)
- {
- result.BigBlocks.Add(RemoveElseIfs(bodyBlock));
- }
-
- return result;
- }
-
- private void RemoveRedundantReturns(StmtList stmtList)
- {
- Contract.Requires(stmtList != null);
-
- BigBlock bb = stmtList.BigBlocks[stmtList.BigBlocks.Count - 1];
-
- if (bb.tc is ReturnCmd)
- {
- bb.tc = null;
- }
- }
-
- private BigBlock RemoveElseIfs(BigBlock bb)
- {
- BigBlock result = bb;
- if (bb.ec is IfCmd)
- {
- IfCmd IfCommand = bb.ec as IfCmd;
-
- Debug.Assert(IfCommand.elseIf == null || IfCommand.elseBlock == null);
-
- if (IfCommand.elseIf != null)
- {
- IfCommand.elseBlock = new StmtList(new List<BigBlock>(new BigBlock[] {
- new BigBlock(bb.tok, null, new CmdSeq(), IfCommand.elseIf, null)
- }), bb.tok);
- IfCommand.elseIf = null;
- }
-
- IfCommand.thn = RemoveElseIfs(IfCommand.thn);
- if (IfCommand.elseBlock != null)
- {
- IfCommand.elseBlock = RemoveElseIfs(IfCommand.elseBlock);
- }
-
- }
- else if (bb.ec is WhileCmd)
- {
- (bb.ec as WhileCmd).Body = RemoveElseIfs((bb.ec as WhileCmd).Body);
- }
-
- return result;
- }
-
- private StmtList PullOutNonLocalAccesses(StmtList stmtList, Implementation impl)
- {
- Contract.Requires(stmtList != null);
-
- StmtList result = new StmtList(new List<BigBlock>(), stmtList.EndCurly);
-
- foreach (BigBlock bodyBlock in stmtList.BigBlocks)
- {
- result.BigBlocks.Add(PullOutNonLocalAccesses(bodyBlock, impl));
- }
-
- return result;
- }
-
- private BigBlock PullOutNonLocalAccesses(BigBlock bb, Implementation impl)
- {
-
- BigBlock result = new BigBlock(bb.tok, bb.LabelName, new CmdSeq(), null, bb.tc);
-
- foreach (Cmd c in bb.simpleCmds)
- {
-
- if (c is CallCmd)
- {
- CallCmd call = c as CallCmd;
-
- List<Expr> newIns = new List<Expr>();
-
- for (int i = 0; i < call.Ins.Count; i++)
- {
- Expr e = call.Ins[i];
-
- while (NonLocalAccessCollector.ContainsNonLocalAccess(e, KernelArrayInfo))
- {
- AssignCmd assignToTemp;
- LocalVariable tempDecl;
- e = ExtractLocalAccessToTemp(e, out assignToTemp, out tempDecl);
- result.simpleCmds.Add(assignToTemp);
- impl.LocVars.Add(tempDecl);
- }
-
- newIns.Add(e);
-
- }
-
- CallCmd newCall = new CallCmd(call.tok, call.callee, newIns, call.Outs);
- newCall.Proc = call.Proc;
- result.simpleCmds.Add(newCall);
- }
- else if (c is AssignCmd)
- {
- AssignCmd assign = c as AssignCmd;
-
- if (assign.Lhss.Zip(assign.Rhss, (lhs, rhs) =>
- !NonLocalAccessCollector.ContainsNonLocalAccess(rhs, KernelArrayInfo) ||
- (!NonLocalAccessCollector.ContainsNonLocalAccess(lhs, KernelArrayInfo) &&
- NonLocalAccessCollector.IsNonLocalAccess(rhs, KernelArrayInfo))).All(b => b))
- {
- result.simpleCmds.Add(c);
- }
- else
- {
- Debug.Assert(assign.Lhss.Count == 1 && assign.Rhss.Count == 1);
- AssignLhs lhs = assign.Lhss.ElementAt(0);
- Expr rhs = assign.Rhss.ElementAt(0);
- rhs = PullOutNonLocalAccessesIntoTemps(result, rhs, impl);
- List<AssignLhs> newLhss = new List<AssignLhs>();
- newLhss.Add(lhs);
- List<Expr> newRhss = new List<Expr>();
- newRhss.Add(rhs);
- result.simpleCmds.Add(new AssignCmd(assign.tok, newLhss, newRhss));
- }
-
- }
- else if (c is HavocCmd)
- {
- result.simpleCmds.Add(c);
- }
- else if (c is AssertCmd)
- {
- result.simpleCmds.Add(new AssertCmd(c.tok, PullOutNonLocalAccessesIntoTemps(result, (c as AssertCmd).Expr, impl)));
- }
- else if (c is AssumeCmd)
- {
- result.simpleCmds.Add(new AssumeCmd(c.tok, PullOutNonLocalAccessesIntoTemps(result, (c as AssumeCmd).Expr, impl)));
- }
- else
- {
- Console.WriteLine(c);
- Debug.Assert(false);
- }
- }
-
- if (bb.ec is WhileCmd)
- {
- WhileCmd WhileCommand = bb.ec as WhileCmd;
- while (NonLocalAccessCollector.ContainsNonLocalAccess(WhileCommand.Guard, KernelArrayInfo))
- {
- AssignCmd assignToTemp;
- LocalVariable tempDecl;
- WhileCommand.Guard = ExtractLocalAccessToTemp(WhileCommand.Guard, out assignToTemp, out tempDecl);
- result.simpleCmds.Add(assignToTemp);
- impl.LocVars.Add(tempDecl);
- }
- result.ec = new WhileCmd(WhileCommand.tok, WhileCommand.Guard, WhileCommand.Invariants, PullOutNonLocalAccesses(WhileCommand.Body, impl));
- }
- else if (bb.ec is IfCmd)
- {
- IfCmd IfCommand = bb.ec as IfCmd;
- Debug.Assert(IfCommand.elseIf == null); // "else if" must have been eliminated by this phase
- while (NonLocalAccessCollector.ContainsNonLocalAccess(IfCommand.Guard, KernelArrayInfo))
- {
- AssignCmd assignToTemp;
- LocalVariable tempDecl;
- IfCommand.Guard = ExtractLocalAccessToTemp(IfCommand.Guard, out assignToTemp, out tempDecl);
- result.simpleCmds.Add(assignToTemp);
- impl.LocVars.Add(tempDecl);
- }
- result.ec = new IfCmd(IfCommand.tok, IfCommand.Guard, PullOutNonLocalAccesses(IfCommand.thn, impl), IfCommand.elseIf, IfCommand.elseBlock != null ? PullOutNonLocalAccesses(IfCommand.elseBlock, impl) : null);
- }
- else if (bb.ec is BreakCmd)
- {
- result.ec = bb.ec;
- }
- else
- {
- Debug.Assert(bb.ec == null);
- }
-
- return result;
-
- }
-
- private Expr PullOutNonLocalAccessesIntoTemps(BigBlock result, Expr e, Implementation impl)
- {
- while (NonLocalAccessCollector.ContainsNonLocalAccess(e, KernelArrayInfo))
- {
- AssignCmd assignToTemp;
- LocalVariable tempDecl;
- e = ExtractLocalAccessToTemp(e, out assignToTemp, out tempDecl);
- result.simpleCmds.Add(assignToTemp);
- impl.LocVars.Add(tempDecl);
- }
- return e;
- }
-
- private Expr ExtractLocalAccessToTemp(Expr rhs, out AssignCmd tempAssignment, out LocalVariable tempDeclaration)
- {
- NonLocalAccessExtractor extractor = new NonLocalAccessExtractor(TempCounter, KernelArrayInfo);
- TempCounter++;
- rhs = extractor.VisitExpr(rhs);
- tempAssignment = extractor.Assignment;
- tempDeclaration = extractor.Declaration;
- return rhs;
- }
-
- private void MakeKernelDualised()
- {
-
- List<Declaration> NewTopLevelDeclarations = new List<Declaration>();
-
- foreach (Declaration d in Program.TopLevelDeclarations)
- {
- if (d is Procedure)
- {
-
- new KernelDualiser(this).DualiseProcedure(d as Procedure);
-
- NewTopLevelDeclarations.Add(d as Procedure);
-
- continue;
-
- }
-
- if (d is Implementation)
- {
-
- new KernelDualiser(this).DualiseImplementation(d as Implementation, CommandLineOptions.Unstructured);
-
- NewTopLevelDeclarations.Add(d as Implementation);
-
- continue;
-
- }
-
- if (d is Variable && ((d as Variable).IsMutable ||
- IsThreadLocalIdConstant(d as Variable) ||
- IsGroupIdConstant(d as Variable))) {
- var v = d as Variable;
-
- if (KernelArrayInfo.getGlobalArrays().Contains(v)) {
- NewTopLevelDeclarations.Add(v);
- continue;
- }
-
- if (KernelArrayInfo.getGroupSharedArrays().Contains(v)) {
- Variable newV = new GlobalVariable(Token.NoToken, new TypedIdent(Token.NoToken,
- v.Name, new MapType(Token.NoToken, new TypeVariableSeq(),
- new TypeSeq(new Microsoft.Boogie.Type[] { Microsoft.Boogie.Type.Bool }),
- v.TypedIdent.Type)));
- newV.Attributes = v.Attributes;
- NewTopLevelDeclarations.Add(newV);
- continue;
- }
-
- NewTopLevelDeclarations.Add(new VariableDualiser(1, null, null).VisitVariable((Variable)v.Clone()));
- if (!QKeyValue.FindBoolAttribute(v.Attributes, "race_checking")) {
- NewTopLevelDeclarations.Add(new VariableDualiser(2, null, null).VisitVariable((Variable)v.Clone()));
- }
-
- continue;
- }
-
- NewTopLevelDeclarations.Add(d);
-
- }
-
- Program.TopLevelDeclarations = NewTopLevelDeclarations;
-
- }
-
- private void MakeKernelPredicated()
- {
- if (CommandLineOptions.Unstructured)
- {
- if (CommandLineOptions.SmartPredication)
- {
- SmartBlockPredicator.Predicate(Program);
- }
- else
- {
- BlockPredicator.Predicate(Program, /*createCandidateInvariants=*/CommandLineOptions.Inference);
- }
- return;
- }
-
- foreach (Declaration d in Program.TopLevelDeclarations)
- {
- if (d is Procedure)
- {
- Procedure proc = d as Procedure;
- IdentifierExpr enabled = new IdentifierExpr(proc.tok,
- new LocalVariable(proc.tok, new TypedIdent(proc.tok, "_P", Microsoft.Boogie.Type.Bool)));
- Expr predicateExpr;
- if (!uniformityAnalyser.IsUniform(proc.Name))
- {
- // Add predicate to start of parameter list
- VariableSeq NewIns = new VariableSeq();
- NewIns.Add(enabled.Decl);
- foreach (Variable v in proc.InParams)
- {
- NewIns.Add(v);
- }
- proc.InParams = NewIns;
- predicateExpr = enabled;
- }
- else
- {
- predicateExpr = Expr.True;
- }
-
- RequiresSeq newRequires = new RequiresSeq();
- foreach (Requires r in proc.Requires)
- {
- newRequires.Add(new Requires(r.Free, Predicator.ProcessEnabledIntrinsics(r.Condition, predicateExpr)));
- }
- proc.Requires = newRequires;
-
- EnsuresSeq newEnsures = new EnsuresSeq();
- foreach (Ensures e in proc.Ensures)
- {
- newEnsures.Add(new Ensures(e.Free, Predicator.ProcessEnabledIntrinsics(e.Condition, predicateExpr)));
- }
- proc.Ensures = newEnsures;
-
- }
- else if (d is Implementation)
- {
- Implementation impl = d as Implementation;
- new Predicator(this, !uniformityAnalyser.IsUniform(impl.Name)).transform
- (impl);
- }
- }
-
- }
-
- private void CheckKernelParameters()
- {
- if (KernelProcedure.OutParams.Length != 0)
- {
- Error(KernelProcedure.tok, "Kernel should not take return anything");
- }
- }
-
-
- private int Check()
- {
- BarrierProcedure = FindOrCreateBarrierProcedure();
- KernelProcedure = CheckExactlyOneKernelProcedure();
-
- if (ErrorCount > 0)
- {
- return ErrorCount;
- }
-
- if (BarrierProcedure.InParams.Length != 2)
- {
- Error(BarrierProcedure, "Barrier procedure must take exactly two arguments");
- }
- else if (!BarrierProcedure.InParams[0].TypedIdent.Type.Equals(new BvType(1)))
- {
- Error(BarrierProcedure, "First argument to barrier procedure must have type bv1");
- }
- else if (!BarrierProcedure.InParams[1].TypedIdent.Type.Equals(new BvType(1))) {
- Error(BarrierProcedure, "Second argument to barrier procedure must have type bv1");
- }
-
- if (BarrierProcedure.OutParams.Length != 0)
- {
- Error(BarrierProcedure, "Barrier procedure must not return any results");
- }
-
- if (!FindNonLocalVariables())
- {
- return ErrorCount;
- }
-
- CheckKernelImplementation();
- return ErrorCount;
- }
-
- public static bool IsThreadLocalIdConstant(Variable variable)
- {
- return variable.Name.Equals(_X.Name) || variable.Name.Equals(_Y.Name) || variable.Name.Equals(_Z.Name);
- }
-
- public static bool IsGroupIdConstant(Variable variable)
- {
- return variable.Name.Equals(_GROUP_X.Name) || variable.Name.Equals(_GROUP_Y.Name) || variable.Name.Equals(_GROUP_Z.Name);
- }
-
- internal void AddCandidateInvariant(IRegion region, Expr e, string tag)
- {
- region.AddInvariant(Program.CreateCandidateInvariant(e, tag));
- }
-
- internal Implementation GetImplementation(string procedureName)
- {
- foreach (Declaration D in Program.TopLevelDeclarations)
- {
- if (D is Implementation && ((D as Implementation).Name == procedureName))
- {
- return D as Implementation;
- }
- }
- Debug.Assert(false);
- return null;
- }
-
-
- internal bool ContainsBarrierCall(IRegion loop)
- {
- foreach (Cmd c in loop.Cmds())
- {
- if (c is CallCmd && ((c as CallCmd).Proc == BarrierProcedure))
- {
- return true;
- }
- }
-
- return false;
- }
-
-
-
- internal bool ArrayModelledAdversarially(Variable v)
- {
- if (CommandLineOptions.AdversarialAbstraction)
- {
- return true;
- }
- if (CommandLineOptions.EqualityAbstraction)
- {
- return false;
- }
- return !arrayControlFlowAnalyser.MayAffectControlFlow(v.Name);
- }
-
- internal Expr GlobalIdExpr(string dimension)
- {
- return MakeBVAdd(MakeBVMul(
- new IdentifierExpr(Token.NoToken, GetGroupId(dimension)), new IdentifierExpr(Token.NoToken, GetGroupSize(dimension))),
- new IdentifierExpr(Token.NoToken, MakeThreadId(Token.NoToken, dimension)));
- }
-
- internal IRegion RootRegion(Implementation Impl)
- {
- if (CommandLineOptions.Unstructured)
- return new UnstructuredRegion(Program, Impl);
- else
- return new StructuredRegion(Impl);
- }
-
-
- public static bool IsGivenConstant(Expr e, Constant c)
- {
- if (!(e is IdentifierExpr))
- return false;
-
- var varName = ((IdentifierExpr)e).Decl.Name;
- return (StripThreadIdentifier(varName) == StripThreadIdentifier(c.Name));
- }
-
- public bool SubstIsGivenConstant(Implementation impl, Expr e, Constant c)
- {
- if (!(e is IdentifierExpr))
- return false;
- e = varDefAnalyses[impl].SubstDefinitions(e, impl.Name);
- return IsGivenConstant(e, c);
- }
-
- public Constant GetLocalIdConst(int dim)
- {
- switch (dim)
- {
- case 0: return _X;
- case 1: return _Y;
- case 2: return _Z;
- default: Debug.Assert(false);
- return null;
- }
- }
-
- public Constant GetGroupIdConst(int dim)
- {
- switch (dim)
- {
- case 0: return _GROUP_X;
- case 1: return _GROUP_Y;
- case 2: return _GROUP_Z;
- default: Debug.Assert(false);
- return null;
- }
- }
-
- public Constant GetGroupSizeConst(int dim)
- {
- switch (dim)
- {
- case 0: return _GROUP_SIZE_X;
- case 1: return _GROUP_SIZE_Y;
- case 2: return _GROUP_SIZE_Z;
- default: Debug.Assert(false);
- return null;
- }
- }
-
- public bool IsLocalId(Expr e, int dim, Implementation impl)
- {
- return SubstIsGivenConstant(impl, e, GetLocalIdConst(dim));
- }
-
- public bool IsGlobalId(Expr e, int dim, Implementation impl)
- {
- e = varDefAnalyses[impl].SubstDefinitions(e, impl.Name);
-
- if (e is NAryExpr && (e as NAryExpr).Fun.FunctionName.Equals("BV32_ADD"))
- {
- NAryExpr nary = e as NAryExpr;
- Constant localId = GetLocalIdConst(dim);
-
- if (IsGivenConstant(nary.Args[1], localId))
- {
- return IsGroupIdTimesGroupSize(nary.Args[0], dim);
- }
-
- if (IsGivenConstant(nary.Args[0], localId))
- {
- return IsGroupIdTimesGroupSize(nary.Args[1], dim);
- }
- }
-
- return false;
- }
-
- private bool IsGroupIdTimesGroupSize(Expr expr, int dim)
- {
- if (expr is NAryExpr && (expr as NAryExpr).Fun.FunctionName.Equals("BV32_MUL"))
- {
- NAryExpr innerNary = expr as NAryExpr;
-
- if (IsGroupIdAndSize(dim, innerNary.Args[0], innerNary.Args[1]))
- {
- return true;
- }
-
- if (IsGroupIdAndSize(dim, innerNary.Args[1], innerNary.Args[0]))
- {
- return true;
- }
- }
- return false;
- }
-
- private bool IsGroupIdAndSize(int dim, Expr maybeGroupId, Expr maybeGroupSize)
- {
- return IsGivenConstant(maybeGroupId, GetGroupIdConst(dim)) &&
- IsGivenConstant(maybeGroupSize, GetGroupSizeConst(dim));
- }
-
- internal Expr MaybeDualise(Expr e, int id, string procName)
- {
- if (id == 0)
- return e;
- else
- return (Expr)new VariableDualiser(id, uniformityAnalyser, procName).Visit(e.Clone());
- }
-
- internal static bool IsConstantInCurrentRegion(IdentifierExpr expr) {
- return (expr.Decl is Constant) ||
- (expr.Decl is Formal && ((Formal)expr.Decl).InComing);
- }
-
- }
-
-
-}
+ DoVariableDefinitionAnalysis(); + + DoReducedStrengthAnalysis(); + + DoMayBePowerOfTwoAnalysis(); + + DoArrayControlFlowAnalysis(); + + if (CommandLineOptions.Inference) + { + foreach (var proc in Program.TopLevelDeclarations.OfType<Procedure>().ToList()) + { + RaceInstrumenter.DoHoudiniPointerAnalysis(proc); + } + + foreach (var impl in Program.TopLevelDeclarations.OfType<Implementation>().ToList()) + { + LoopInvariantGenerator.PreInstrument(this, impl); + } + + if (CommandLineOptions.ShowStages) { + emitProgram(outputFilename + "_pre_inference"); + } + + } + + RaceInstrumenter.AddRaceCheckingInstrumentation(); + + if (CommandLineOptions.ShowStages) + { + emitProgram(outputFilename + "_instrumented"); + } + + AbstractSharedState(); + + if (CommandLineOptions.ShowStages) + { + emitProgram(outputFilename + "_abstracted"); + } + + MergeBlocksIntoPredecessors(); + + if (CommandLineOptions.ShowStages) + { + emitProgram(outputFilename + "_merged_pre_predication"); + } + + MakeKernelPredicated(); + + if (CommandLineOptions.ShowStages) + { + emitProgram(outputFilename + "_predicated"); + } + + MergeBlocksIntoPredecessors(); + + if (CommandLineOptions.ShowStages) + { + emitProgram(outputFilename + "_merged_post_predication"); + } + + MakeKernelDualised(); + + if (CommandLineOptions.ShowStages) + { + emitProgram(outputFilename + "_dualised"); + } + + RaceInstrumenter.AddRaceCheckingDeclarations(); + + GenerateBarrierImplementation(); + + GenerateStandardKernelContract(); + + if (CommandLineOptions.ShowStages) + { + emitProgram(outputFilename + "_ready_to_verify"); + } + + if (CommandLineOptions.Inference) + { + ComputeInvariant(); + } + + emitProgram(outputFilename); + + } + + private void DoMayBePowerOfTwoAnalysis() + { + mayBePowerOfTwoAnalyser = new MayBePowerOfTwoAnalyser(this); + mayBePowerOfTwoAnalyser.Analyse(); + } + + private void DoArrayControlFlowAnalysis() + { + arrayControlFlowAnalyser = new ArrayControlFlowAnalyser(this); + arrayControlFlowAnalyser.Analyse(); + } + + private void DoUniformityAnalysis() + { + var entryPoints = new HashSet<Implementation>(); + entryPoints.Add(KernelImplementation); + + var nonUniformVars = new Variable[] { _X, _Y, _Z, _GROUP_X, _GROUP_Y, _GROUP_Z }; + + uniformityAnalyser = new UniformityAnalyser(Program, CommandLineOptions.DoUniformityAnalysis, CommandLineOptions.Unstructured, + entryPoints, nonUniformVars); + uniformityAnalyser.Analyse(); + } + + private void DoLiveVariableAnalysis() + { + liveVariableAnalyser = new LiveVariableAnalyser(this); + liveVariableAnalyser.Analyse(); + } + + private void DoVariableDefinitionAnalysis() + { + varDefAnalyses = Program.TopLevelDeclarations + .OfType<Implementation>() + .ToDictionary(i => i, i => VariableDefinitionAnalysis.Analyse(this, i)); + } + + private void DoReducedStrengthAnalysis() + { + reducedStrengthAnalyses = Program.TopLevelDeclarations + .OfType<Implementation>() + .ToDictionary(i => i, i => ReducedStrengthAnalysis.Analyse(this, i)); + } + + private void emitProgram(string filename) + { + using (TokenTextWriter writer = new TokenTextWriter(filename + ".bpl")) + { + Program.Emit(writer); + } + } + + private void ComputeInvariant() + { + for (int i = 0; i < Program.TopLevelDeclarations.Count; i++) + { + if (Program.TopLevelDeclarations[i] is Implementation) + { + + Implementation Impl = Program.TopLevelDeclarations[i] as Implementation; + + List<Expr> UserSuppliedInvariants = GetUserSuppliedInvariants(Impl.Name); + + LoopInvariantGenerator.PostInstrument(this, Impl, UserSuppliedInvariants); + + Procedure Proc = Impl.Proc; + + if (QKeyValue.FindIntAttribute(Proc.Attributes, "inline", -1) == 1) + { + continue; + } + + if (Proc == KernelProcedure) + { + continue; + } + + AddCandidateRequires(Proc); + RaceInstrumenter.AddRaceCheckingCandidateRequires(Proc); + AddUserSuppliedCandidateRequires(Proc, UserSuppliedInvariants); + + AddCandidateEnsures(Proc); + RaceInstrumenter.AddRaceCheckingCandidateEnsures(Proc); + AddUserSuppliedCandidateEnsures(Proc, UserSuppliedInvariants); + + } + + + } + + } + + private void AddCandidateEnsures(Procedure Proc) + { + HashSet<string> names = new HashSet<String>(); + foreach (Variable v in Proc.OutParams) + { + names.Add(StripThreadIdentifier(v.Name)); + } + + foreach (string name in names) + { + if (!uniformityAnalyser.IsUniform(Proc.Name, name)) + { + AddEqualityCandidateEnsures(Proc, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, name, Microsoft.Boogie.Type.Int))); + } + } + + } + + private void AddCandidateRequires(Procedure Proc) + { + HashSet<string> names = new HashSet<String>(); + foreach (Variable v in Proc.InParams) + { + names.Add(StripThreadIdentifier(v.Name)); + } + + foreach (string name in names) + { + + if (IsPredicateOrTemp(name)) + { + Debug.Assert(name.Equals("_P")); + Debug.Assert(!uniformityAnalyser.IsUniform(Proc.Name)); + AddCandidateRequires(Proc, Expr.Eq( + new IdentifierExpr(Proc.tok, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, name + "$1", Microsoft.Boogie.Type.Bool))), + new IdentifierExpr(Proc.tok, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, name + "$2", Microsoft.Boogie.Type.Bool))) + )); + } + else + { + if (!uniformityAnalyser.IsUniform(Proc.Name, name)) + { + if (!uniformityAnalyser.IsUniform(Proc.Name)) + { + AddPredicatedEqualityCandidateRequires(Proc, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, name, Microsoft.Boogie.Type.Int))); + } + AddEqualityCandidateRequires(Proc, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, name, Microsoft.Boogie.Type.Int))); + } + } + } + + } + + private void AddPredicatedEqualityCandidateRequires(Procedure Proc, Variable v) + { + AddCandidateRequires(Proc, Expr.Imp( + Expr.And( + new IdentifierExpr(Proc.tok, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, "_P$1", Microsoft.Boogie.Type.Bool))), + new IdentifierExpr(Proc.tok, new LocalVariable(Proc.tok, new TypedIdent(Proc.tok, "_P$2", Microsoft.Boogie.Type.Bool))) + ), + Expr.Eq( + new IdentifierExpr(Proc.tok, new VariableDualiser(1, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable)), + new IdentifierExpr(Proc.tok, new VariableDualiser(2, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable)) + ) + )); + } + + private void AddEqualityCandidateRequires(Procedure Proc, Variable v) + { + AddCandidateRequires(Proc, + Expr.Eq( + new IdentifierExpr(Proc.tok, new VariableDualiser(1, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable)), + new IdentifierExpr(Proc.tok, new VariableDualiser(2, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable)) + ) + ); + } + + private void AddEqualityCandidateEnsures(Procedure Proc, Variable v) + { + AddCandidateEnsures(Proc, + Expr.Eq( + new IdentifierExpr(Proc.tok, new VariableDualiser(1, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable)), + new IdentifierExpr(Proc.tok, new VariableDualiser(2, uniformityAnalyser, Proc.Name).VisitVariable(v.Clone() as Variable)) + )); + } + + + private void AddUserSuppliedCandidateRequires(Procedure Proc, List<Expr> UserSuppliedInvariants) + { + foreach (Expr e in UserSuppliedInvariants) + { + Requires r = new Requires(false, e); + Proc.Requires.Add(r); + bool OK = ProgramIsOK(Proc); + Proc.Requires.Remove(r); + if (OK) + { + AddCandidateRequires(Proc, e); + } + } + } + + private void AddUserSuppliedCandidateEnsures(Procedure Proc, List<Expr> UserSuppliedInvariants) + { + foreach (Expr e in UserSuppliedInvariants) + { + Ensures ens = new Ensures(false, e); + Proc.Ensures.Add(ens); + bool OK = ProgramIsOK(Proc); + Proc.Ensures.Remove(ens); + if (OK) + { + AddCandidateEnsures(Proc, e); + } + } + } + + + + internal void AddCandidateRequires(Procedure Proc, Expr e) + { + Constant ExistentialBooleanConstant = Program.MakeExistentialBoolean(); + IdentifierExpr ExistentialBoolean = new IdentifierExpr(Proc.tok, ExistentialBooleanConstant); + Proc.Requires.Add(new Requires(false, Expr.Imp(ExistentialBoolean, e))); + } + + internal void AddCandidateEnsures(Procedure Proc, Expr e) + { + Constant ExistentialBooleanConstant = Program.MakeExistentialBoolean(); + IdentifierExpr ExistentialBoolean = new IdentifierExpr(Proc.tok, ExistentialBooleanConstant); + Proc.Ensures.Add(new Ensures(false, Expr.Imp(ExistentialBoolean, e))); + } + + private List<Expr> GetUserSuppliedInvariants(string ProcedureName) + { + List<Expr> result = new List<Expr>(); + + if (CommandLineOptions.invariantsFile == null) + { + return result; + } + + StreamReader sr = new StreamReader(new FileStream(CommandLineOptions.invariantsFile, FileMode.Open, FileAccess.Read)); + string line; + int lineNumber = 1; + while ((line = sr.ReadLine()) != null) + { + string[] components = line.Split(':'); + + if (components.Length != 1 && components.Length != 2) + { + Console.WriteLine("Ignoring badly formed candidate invariant '" + line + "' at '" + CommandLineOptions.invariantsFile + "' line " + lineNumber); + continue; + } + + if (components.Length == 2) + { + if (!components[0].Trim().Equals(ProcedureName)) + { + continue; + } + + line = components[1]; + } + + string temp_program_text = "axiom (" + line + ");"; + TokenTextWriter writer = new TokenTextWriter("temp_out.bpl"); + writer.WriteLine(temp_program_text); + writer.Close(); + + Program temp_program = GPUVerify.ParseBoogieProgram(new List<string>(new string[] { "temp_out.bpl" }), false); + + if (null == temp_program) + { + Console.WriteLine("Ignoring badly formed candidate invariant '" + line + "' at '" + CommandLineOptions.invariantsFile + "' line " + lineNumber); + } + else + { + Debug.Assert(temp_program.TopLevelDeclarations[0] is Axiom); + result.Add((temp_program.TopLevelDeclarations[0] as Axiom).Expr); + } + + lineNumber++; + } + + return result; + } + + internal bool ContainsNamedVariable(HashSet<Variable> variables, string name) + { + foreach(Variable v in variables) + { + if(StripThreadIdentifier(v.Name) == name) + { + return true; + } + } + return false; + } + + internal static bool IsPredicate(string v) { + if (v.Length < 2) { + return false; + } + if (!v.Substring(0, 1).Equals("p")) { + return false; + } + for (int i = 1; i < v.Length; i++) { + if (!Char.IsDigit(v.ToCharArray()[i])) { + return false; + } + } + return true; + } + + internal static bool IsPredicateOrTemp(string lv) { + + // We should improve this by having a general convention + // for names of temporary or predicate variables + + if (lv.Length >= 2) { + if (lv.Substring(0, 1).Equals("p") || lv.Substring(0, 1).Equals("v")) { + for (int i = 1; i < lv.Length; i++) { + if (!Char.IsDigit(lv.ToCharArray()[i])) { + return false; + } + } + return true; + } + + } + + if (lv.Contains("_HAVOC_")) { + return true; + } + + return (lv.Length >= 2 && lv.Substring(0,2).Equals("_P")) || + (lv.Length > 3 && lv.Substring(0,3).Equals("_LC")) || + (lv.Length > 5 && lv.Substring(0,5).Equals("_temp")); + } + + + + + internal bool ProgramIsOK(Declaration d) + { + Debug.Assert(d is Procedure || d is Implementation); + TokenTextWriter writer = new TokenTextWriter("temp_out.bpl"); + List<Declaration> RealDecls = Program.TopLevelDeclarations; + List<Declaration> TempDecls = new List<Declaration>(); + foreach (Declaration d2 in RealDecls) + { + if (d is Procedure) + { + if ((d == d2) || !(d2 is Implementation || d2 is Procedure)) + { + TempDecls.Add(d2); + } + } + else if (d is Implementation) + { + if ((d == d2) || !(d2 is Implementation)) + { + TempDecls.Add(d2); + } + } + } + Program.TopLevelDeclarations = TempDecls; + Program.Emit(writer); + writer.Close(); + Program.TopLevelDeclarations = RealDecls; + Program temp_program = GPUVerify.ParseBoogieProgram(new List<string>(new string[] { "temp_out.bpl" }), false); + + if (temp_program == null) + { + return false; + } + + if (temp_program.Resolve() != 0) + { + return false; + } + + if (temp_program.Typecheck() != 0) + { + return false; + } + return true; + } + + + + public static Microsoft.Boogie.Type GetTypeOfIdX() + { + Contract.Requires(_X != null); + return _X.TypedIdent.Type; + } + + public static Microsoft.Boogie.Type GetTypeOfIdY() + { + Contract.Requires(_Y != null); + return _Y.TypedIdent.Type; + } + + public static Microsoft.Boogie.Type GetTypeOfIdZ() + { + Contract.Requires(_Z != null); + return _Z.TypedIdent.Type; + } + + public static Microsoft.Boogie.Type GetTypeOfId(string dimension) + { + Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z")); + if (dimension.Equals("X")) return GetTypeOfIdX(); + if (dimension.Equals("Y")) return GetTypeOfIdY(); + if (dimension.Equals("Z")) return GetTypeOfIdZ(); + Debug.Assert(false); + return null; + } + + public bool KernelHasIdX() + { + return _X != null; + } + + public bool KernelHasIdY() + { + return _Y != null; + } + + public bool KernelHasIdZ() + { + return _Z != null; + } + + public bool KernelHasGroupIdX() + { + return _GROUP_X != null; + } + + public bool KernelHasGroupIdY() + { + return _GROUP_Y != null; + } + + public bool KernelHasGroupIdZ() + { + return _GROUP_Z != null; + } + + public bool KernelHasNumGroupsX() + { + return _NUM_GROUPS_X != null; + } + + public bool KernelHasNumGroupsY() + { + return _NUM_GROUPS_Y != null; + } + + public bool KernelHasNumGroupsZ() + { + return _NUM_GROUPS_Z != null; + } + + public bool KernelHasGroupSizeX() + { + return _GROUP_SIZE_X != null; + } + + public bool KernelHasGroupSizeY() + { + return _GROUP_SIZE_Y != null; + } + + public bool KernelHasGroupSizeZ() + { + return _GROUP_SIZE_Z != null; + } + + internal static string StripThreadIdentifier(string p, out int id) + { + if (p.EndsWith("$1")) + { + id = 1; + return p.Substring(0, p.Length - 2); + } + if (p.EndsWith("$2")) + { + id = 2; + return p.Substring(0, p.Length - 2); + } + + id = 0; + return p; + } + + internal static string StripThreadIdentifier(string p) + { + int id; + return StripThreadIdentifier(p, out id); + } + + private void GenerateStandardKernelContract() + { + RaceInstrumenter.AddKernelPrecondition(); + + IToken tok = KernelImplementation.tok; + + GeneratePreconditionsForDimension(tok, "X"); + GeneratePreconditionsForDimension(tok, "Y"); + GeneratePreconditionsForDimension(tok, "Z"); + + RaceInstrumenter.AddStandardSourceVariablePreconditions(); + RaceInstrumenter.AddStandardSourceVariablePostconditions(); + + foreach (Declaration D in Program.TopLevelDeclarations) + { + if (!(D is Procedure)) + { + continue; + } + Procedure Proc = D as Procedure; + if (QKeyValue.FindIntAttribute(Proc.Attributes, "inline", -1) == 1) + { + continue; + } + + Expr DistinctLocalIds = + Expr.Or( + Expr.Or( + Expr.Neq( + new IdentifierExpr(tok, MakeThreadId(tok, "X", 1)), + new IdentifierExpr(tok, MakeThreadId(tok, "X", 2)) + ), + Expr.Neq( + new IdentifierExpr(tok, MakeThreadId(tok, "Y", 1)), + new IdentifierExpr(tok, MakeThreadId(tok, "Y", 2)) + ) + ), + Expr.Neq( + new IdentifierExpr(tok, MakeThreadId(tok, "Z", 1)), + new IdentifierExpr(tok, MakeThreadId(tok, "Z", 2)) + ) + ); + + Proc.Requires.Add(new Requires(false, Expr.Imp(ThreadsInSameGroup(), DistinctLocalIds))); + + if (CommandLineOptions.OnlyIntraGroupRaceChecking) + { + Proc.Requires.Add(new Requires(false, ThreadsInSameGroup())); + } + + if (Proc == KernelProcedure) + { + bool foundNonUniform = false; + int indexOfFirstNonUniformParameter; + for (indexOfFirstNonUniformParameter = 0; indexOfFirstNonUniformParameter < Proc.InParams.Length; indexOfFirstNonUniformParameter++) + { + if (!uniformityAnalyser.IsUniform(Proc.Name, StripThreadIdentifier(Proc.InParams[indexOfFirstNonUniformParameter].Name))) + { + foundNonUniform = true; + break; + } + } + + if (foundNonUniform) + { + // I have a feeling this will never be reachable!!! + int numberOfNonUniformParameters = (Proc.InParams.Length - indexOfFirstNonUniformParameter) / 2; + for (int i = indexOfFirstNonUniformParameter; i < numberOfNonUniformParameters; i++) + { + Proc.Requires.Add(new Requires(false, + Expr.Eq(new IdentifierExpr(Proc.InParams[i].tok, Proc.InParams[i]), + new IdentifierExpr(Proc.InParams[i + numberOfNonUniformParameters].tok, Proc.InParams[i + numberOfNonUniformParameters])))); + } + } + } + + } + + foreach (Declaration D in Program.TopLevelDeclarations) + { + if (!(D is Implementation)) + { + continue; + } + Implementation Impl = D as Implementation; + + foreach (IRegion subregion in RootRegion(Impl).SubRegions()) + { + RaceInstrumenter.AddSourceLocationLoopInvariants(Impl, subregion); + } + } + + foreach (Declaration D in Program.TopLevelDeclarations) + { + if (!(D is Implementation)) + { + continue; + } + Implementation Impl = D as Implementation; + + if (QKeyValue.FindIntAttribute(Impl.Proc.Attributes, "inline", -1) == 1) + { + continue; + } + if (Impl.Proc == KernelProcedure) + { + continue; + } + + new EnsureDisabledThreadHasNoEffectInstrumenter(this, Impl).instrument(); + + } + + } + + internal static Expr ThreadsInSameGroup() + { + return Expr.And( + Expr.And( + Expr.Eq( + new IdentifierExpr(Token.NoToken, MakeGroupId("X", 1)), + new IdentifierExpr(Token.NoToken, MakeGroupId("X", 2)) + ), + Expr.Eq( + new IdentifierExpr(Token.NoToken, MakeGroupId("Y", 1)), + new IdentifierExpr(Token.NoToken, MakeGroupId("Y", 2)) + ) + ), + Expr.Eq( + new IdentifierExpr(Token.NoToken, MakeGroupId("Z", 1)), + new IdentifierExpr(Token.NoToken, MakeGroupId("Z", 2)) + ) + ); + } + + internal static void AddInvariantToAllLoops(Expr Invariant, StmtList stmtList) + { + foreach (BigBlock bb in stmtList.BigBlocks) + { + AddInvariantToAllLoops(Invariant, bb); + } + } + + internal static void AddInvariantToAllLoops(Expr Invariant, BigBlock bb) + { + if (bb.ec is WhileCmd) + { + WhileCmd wc = bb.ec as WhileCmd; + wc.Invariants.Add(new AssertCmd(wc.tok, Invariant)); + AddInvariantToAllLoops(Invariant, wc.Body); + } + Debug.Assert(!(bb.ec is IfCmd)); + } + + internal static int GetThreadSuffix(string p) + { + return Int32.Parse(p.Substring(p.IndexOf("$") + 1, p.Length - (p.IndexOf("$") + 1))); + } + + private void GeneratePreconditionsForDimension(IToken tok, String dimension) + { + foreach (Declaration D in Program.TopLevelDeclarations.ToList()) + { + if (!(D is Procedure)) + { + continue; + } + Procedure Proc = D as Procedure; + if (QKeyValue.FindIntAttribute(Proc.Attributes, "inline", -1) == 1) + { + continue; + } + + Expr GroupSizePositive; + Expr NumGroupsPositive; + Expr GroupIdNonNegative; + Expr GroupIdLessThanNumGroups; + + if (GetTypeOfId(dimension).Equals(Microsoft.Boogie.Type.GetBvType(32))) + { + GroupSizePositive = MakeBVSgt(new IdentifierExpr(tok, GetGroupSize(dimension)), ZeroBV()); + NumGroupsPositive = MakeBVSgt(new IdentifierExpr(tok, GetNumGroups(dimension)), ZeroBV()); + GroupIdNonNegative = MakeBVSge(new IdentifierExpr(tok, GetGroupId(dimension)), ZeroBV()); + GroupIdLessThanNumGroups = MakeBVSlt(new IdentifierExpr(tok, GetGroupId(dimension)), new IdentifierExpr(tok, GetNumGroups(dimension))); + } + else + { + GroupSizePositive = Expr.Gt(new IdentifierExpr(tok, GetGroupSize(dimension)), Zero()); + NumGroupsPositive = Expr.Gt(new IdentifierExpr(tok, GetNumGroups(dimension)), Zero()); + GroupIdNonNegative = Expr.Ge(new IdentifierExpr(tok, GetGroupId(dimension)), Zero()); + GroupIdLessThanNumGroups = Expr.Lt(new IdentifierExpr(tok, GetGroupId(dimension)), new IdentifierExpr(tok, GetNumGroups(dimension))); + } + + Proc.Requires.Add(new Requires(false, GroupSizePositive)); + Proc.Requires.Add(new Requires(false, NumGroupsPositive)); + Proc.Requires.Add(new Requires(false, new VariableDualiser(1, null, null).VisitExpr(GroupIdNonNegative))); + Proc.Requires.Add(new Requires(false, new VariableDualiser(2, null, null).VisitExpr(GroupIdNonNegative))); + Proc.Requires.Add(new Requires(false, new VariableDualiser(1, null, null).VisitExpr(GroupIdLessThanNumGroups))); + Proc.Requires.Add(new Requires(false, new VariableDualiser(2, null, null).VisitExpr(GroupIdLessThanNumGroups))); + + Expr ThreadIdNonNegative = + GetTypeOfId(dimension).Equals(Microsoft.Boogie.Type.GetBvType(32)) ? + MakeBVSge(new IdentifierExpr(tok, MakeThreadId(tok, dimension)), ZeroBV()) + : + Expr.Ge(new IdentifierExpr(tok, MakeThreadId(tok, dimension)), Zero()); + Expr ThreadIdLessThanGroupSize = + GetTypeOfId(dimension).Equals(Microsoft.Boogie.Type.GetBvType(32)) ? + MakeBVSlt(new IdentifierExpr(tok, MakeThreadId(tok, dimension)), new IdentifierExpr(tok, GetGroupSize(dimension))) + : + Expr.Lt(new IdentifierExpr(tok, MakeThreadId(tok, dimension)), new IdentifierExpr(tok, GetGroupSize(dimension))); + + Proc.Requires.Add(new Requires(false, new VariableDualiser(1, null, null).VisitExpr(ThreadIdNonNegative))); + Proc.Requires.Add(new Requires(false, new VariableDualiser(2, null, null).VisitExpr(ThreadIdNonNegative))); + Proc.Requires.Add(new Requires(false, new VariableDualiser(1, null, null).VisitExpr(ThreadIdLessThanGroupSize))); + Proc.Requires.Add(new Requires(false, new VariableDualiser(2, null, null).VisitExpr(ThreadIdLessThanGroupSize))); + + } + + } + + private Function GetOrCreateBVFunction(string functionName, string smtName, Microsoft.Boogie.Type resultType, params Microsoft.Boogie.Type[] argTypes) + { + Function f = (Function)ResContext.LookUpProcedure(functionName); + if (f != null) + return f; + + f = new Function(Token.NoToken, functionName, + new VariableSeq(argTypes.Select(t => new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "", t))).ToArray()), + new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "", resultType))); + f.AddAttribute("bvbuiltin", smtName); + Program.TopLevelDeclarations.Add(f); + ResContext.AddProcedure(f); + return f; + } + + private Expr MakeBVFunctionCall(string functionName, string smtName, Microsoft.Boogie.Type resultType, params Expr[] args) + { + Function f = GetOrCreateBVFunction(functionName, smtName, resultType, args.Select(a => a.Type).ToArray()); + var e = new NAryExpr(Token.NoToken, new FunctionCall(f), new ExprSeq(args)); + e.Type = resultType; + return e; + } + + private Expr MakeBitVectorBinaryBoolean(string suffix, string smtName, Expr lhs, Expr rhs) + { + return MakeBVFunctionCall("BV" + lhs.Type.BvBits + "_" + suffix, smtName, Microsoft.Boogie.Type.Bool, lhs, rhs); + } + + private Expr MakeBitVectorBinaryBitVector(string suffix, string smtName, Expr lhs, Expr rhs) + { + return MakeBVFunctionCall("BV" + lhs.Type.BvBits + "_" + suffix, smtName, lhs.Type, lhs, rhs); + } + + internal Expr MakeBVSlt(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBoolean("SLT", "bvslt", lhs, rhs); } + internal Expr MakeBVSgt(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBoolean("SGT", "bvsgt", lhs, rhs); } + internal Expr MakeBVSge(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBoolean("SGE", "bvsge", lhs, rhs); } + + internal Expr MakeBVAnd(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBitVector("AND", "bvand", lhs, rhs); } + internal Expr MakeBVAdd(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBitVector("ADD", "bvadd", lhs, rhs); } + internal Expr MakeBVSub(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBitVector("SUB", "bvsub", lhs, rhs); } + internal Expr MakeBVMul(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBitVector("MUL", "bvmul", lhs, rhs); } + internal Expr MakeBVURem(Expr lhs, Expr rhs) { return MakeBitVectorBinaryBitVector("UREM", "bvurem", lhs, rhs); } + + internal static Expr MakeBitVectorBinaryBoolean(string functionName, Expr lhs, Expr rhs) + { + return new NAryExpr(lhs.tok, new FunctionCall(new Function(lhs.tok, functionName, new VariableSeq(new Variable[] { + new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "arg1", Microsoft.Boogie.Type.GetBvType(32))), + new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "arg2", Microsoft.Boogie.Type.GetBvType(32))) + }), new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "result", Microsoft.Boogie.Type.Bool)))), new ExprSeq(new Expr[] { lhs, rhs })); + } + + internal static Expr MakeBitVectorBinaryBitVector(string functionName, Expr lhs, Expr rhs) + { + return new NAryExpr(lhs.tok, new FunctionCall(new Function(lhs.tok, functionName, new VariableSeq(new Variable[] { + new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "arg1", Microsoft.Boogie.Type.GetBvType(32))), + new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "arg2", Microsoft.Boogie.Type.GetBvType(32))) + }), new LocalVariable(lhs.tok, new TypedIdent(lhs.tok, "result", Microsoft.Boogie.Type.GetBvType(32))))), new ExprSeq(new Expr[] { lhs, rhs })); + } + + private static bool IsBVFunctionCall(Expr e, string smtName, out ExprSeq args) + { + args = null; + var ne = e as NAryExpr; + if (ne == null) + return false; + + var fc = ne.Fun as FunctionCall; + if (fc == null) + return false; + + string bvBuiltin = QKeyValue.FindStringAttribute(fc.Func.Attributes, "bvbuiltin"); + if (bvBuiltin == smtName) + { + args = ne.Args; + return true; + } + + return false; + } + + private static bool IsBVFunctionCall(Expr e, string smtName, out Expr lhs, out Expr rhs) + { + ExprSeq es; + if (IsBVFunctionCall(e, smtName, out es)) + { + lhs = es[0]; rhs = es[1]; + return true; + } + lhs = null; rhs = null; + return false; + } + + internal static bool IsBVAdd(Expr e, out Expr lhs, out Expr rhs) { return IsBVFunctionCall(e, "bvadd", out lhs, out rhs); } + internal static bool IsBVMul(Expr e, out Expr lhs, out Expr rhs) { return IsBVFunctionCall(e, "bvmul", out lhs, out rhs); } + + internal Constant GetGroupSize(string dimension) + { + Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z")); + if (dimension.Equals("X")) return _GROUP_SIZE_X; + if (dimension.Equals("Y")) return _GROUP_SIZE_Y; + if (dimension.Equals("Z")) return _GROUP_SIZE_Z; + Debug.Assert(false); + return null; + } + + internal Constant GetNumGroups(string dimension) + { + Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z")); + if (dimension.Equals("X")) return _NUM_GROUPS_X; + if (dimension.Equals("Y")) return _NUM_GROUPS_Y; + if (dimension.Equals("Z")) return _NUM_GROUPS_Z; + Debug.Assert(false); + return null; + } + + internal Constant MakeThreadId(IToken tok, string dimension) + { + Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z")); + string name = null; + if (dimension.Equals("X")) name = _X.Name; + if (dimension.Equals("Y")) name = _Y.Name; + if (dimension.Equals("Z")) name = _Z.Name; + Debug.Assert(name != null); + return new Constant(tok, new TypedIdent(tok, name, GetTypeOfId(dimension))); + } + + internal Constant MakeThreadId(IToken tok, string dimension, int number) + { + Constant resultWithoutThreadId = MakeThreadId(tok, dimension); + return new Constant(tok, new TypedIdent(tok, resultWithoutThreadId.Name + "$" + number, GetTypeOfId(dimension))); + } + + internal static Constant GetGroupId(string dimension) + { + Contract.Requires(dimension.Equals("X") || dimension.Equals("Y") || dimension.Equals("Z")); + if (dimension.Equals("X")) return _GROUP_X; + if (dimension.Equals("Y")) return _GROUP_Y; + if (dimension.Equals("Z")) return _GROUP_Z; + Debug.Assert(false); + return null; + } + + internal static Constant MakeGroupId(string dimension, int number) + { + Constant resultWithoutThreadId = GetGroupId(dimension); + return new Constant(Token.NoToken, new TypedIdent(Token.NoToken, resultWithoutThreadId.Name + "$" + number, GetTypeOfId(dimension))); + } + + private static LiteralExpr Zero() + { + return new LiteralExpr(Token.NoToken, BigNum.FromInt(0)); + } + + internal static LiteralExpr ZeroBV() + { + return new LiteralExpr(Token.NoToken, BigNum.FromInt(0), 32); + } + + + + private void GenerateBarrierImplementation() + { + IToken tok = BarrierProcedure.tok; + + List<BigBlock> bigblocks = new List<BigBlock>(); + BigBlock barrierEntryBlock = new BigBlock(tok, "__BarrierImpl", new CmdSeq(), null, null); + bigblocks.Add(barrierEntryBlock); + + Debug.Assert((BarrierProcedure.InParams.Length % 2) == 0); + int paramsPerThread = BarrierProcedure.InParams.Length / 2; + IdentifierExpr P1 = new IdentifierExpr(tok, new LocalVariable(tok, BarrierProcedure.InParams[0].TypedIdent)); + IdentifierExpr P2 = new IdentifierExpr(tok, new LocalVariable(tok, BarrierProcedure.InParams[paramsPerThread].TypedIdent)); + + Expr LocalFence1 = MakeFenceExpr(BarrierProcedure.InParams[1]); + Expr LocalFence2 = MakeFenceExpr(BarrierProcedure.InParams[paramsPerThread + 1]); + + Expr GlobalFence1 = MakeFenceExpr(BarrierProcedure.InParams[2]); + Expr GlobalFence2 = MakeFenceExpr(BarrierProcedure.InParams[paramsPerThread + 2]); + + Expr DivergenceCondition = Expr.Imp(ThreadsInSameGroup(), Expr.Eq(P1, P2)); + + Requires nonDivergenceRequires = new Requires(false, DivergenceCondition); + nonDivergenceRequires.Attributes = new QKeyValue(Token.NoToken, "barrier_divergence", + new List<object>(new object[] { }), null); + BarrierProcedure.Requires.Add(nonDivergenceRequires); + + if (!CommandLineOptions.OnlyDivergence) + { + List<BigBlock> returnbigblocks = new List<BigBlock>(); + returnbigblocks.Add(new BigBlock(tok, "__Disabled", new CmdSeq(), null, new ReturnCmd(tok))); + StmtList returnstatement = new StmtList(returnbigblocks, BarrierProcedure.tok); + + Expr IfGuard = Expr.Or(Expr.And(Expr.Not(P1), Expr.Not(P2)), Expr.And(ThreadsInSameGroup(), Expr.Or(Expr.Not(P1), Expr.Not(P2)))); + barrierEntryBlock.ec = new IfCmd(tok, IfGuard, returnstatement, null, null); + } + + if(KernelArrayInfo.getGroupSharedArrays().Count > 0) { + + Expr IfGuard1 = Expr.And(P1, LocalFence1); + Expr IfGuard2 = Expr.And(P2, LocalFence2); + + bigblocks.Add(new BigBlock(Token.NoToken, null, new CmdSeq(), + new IfCmd(Token.NoToken, IfGuard1, new StmtList(MakeResetBlocks(1, KernelArrayInfo.getGroupSharedArrays()), Token.NoToken), null, null), + null)); + bigblocks.Add(new BigBlock(Token.NoToken, null, new CmdSeq(), + new IfCmd(Token.NoToken, IfGuard2, new StmtList(MakeResetBlocks(2, KernelArrayInfo.getGroupSharedArrays()), Token.NoToken), null, null), + null)); + + bigblocks.AddRange(MakeHavocBlocks(KernelArrayInfo.getGroupSharedArrays())); + } + + if (KernelArrayInfo.getGlobalArrays().Count > 0) + { + Expr IfGuard1 = Expr.And(P1, GlobalFence1); + Expr IfGuard2 = Expr.And(P2, GlobalFence2); + + bigblocks.Add(new BigBlock(Token.NoToken, null, new CmdSeq(), + new IfCmd(Token.NoToken, IfGuard1, new StmtList(MakeResetBlocks(1, KernelArrayInfo.getGlobalArrays()), Token.NoToken), null, null), + null)); + bigblocks.Add(new BigBlock(Token.NoToken, null, new CmdSeq(), + new IfCmd(Token.NoToken, IfGuard2, new StmtList(MakeResetBlocks(2, KernelArrayInfo.getGlobalArrays()), Token.NoToken), null, null), + null)); + + bigblocks.AddRange(MakeHavocBlocks(KernelArrayInfo.getGlobalArrays())); + } + + StmtList statements = new StmtList(bigblocks, BarrierProcedure.tok); + Implementation BarrierImplementation = + new Implementation(BarrierProcedure.tok, BarrierProcedure.Name, new TypeVariableSeq(), + BarrierProcedure.InParams, BarrierProcedure.OutParams, new VariableSeq(), statements); + + if (CommandLineOptions.Unstructured) + BarrierImplementation.Resolve(ResContext); + + BarrierImplementation.AddAttribute("inline", new object[] { new LiteralExpr(tok, BigNum.FromInt(1)) }); + BarrierProcedure.AddAttribute("inline", new object[] { new LiteralExpr(tok, BigNum.FromInt(1)) }); + + BarrierImplementation.Proc = BarrierProcedure; + + Program.TopLevelDeclarations.Add(BarrierImplementation); + } + + private static NAryExpr MakeFenceExpr(Variable v) { + return Expr.Eq(new IdentifierExpr(Token.NoToken, new LocalVariable(Token.NoToken, v.TypedIdent)), + new LiteralExpr(Token.NoToken, BigNum.FromInt(1), 1)); + } + + private static Expr flagIsSet(Expr Flags, int flag) + { + return Expr.Eq(new BvExtractExpr( + Token.NoToken, Flags, flag, flag - 1), + new LiteralExpr(Token.NoToken, BigNum.FromInt(1), 1)); + } + + private List<BigBlock> MakeResetBlocks(int Thread, ICollection<Variable> variables) + { + Debug.Assert(variables.Count > 0); + List<BigBlock> ResetAndHavocBlocks = new List<BigBlock>(); + foreach (Variable v in variables) + { + ResetAndHavocBlocks.Add(RaceInstrumenter.MakeResetReadWriteSetStatements(v, Thread)); + } + Debug.Assert(ResetAndHavocBlocks.Count > 0); + return ResetAndHavocBlocks; + } + + private List<BigBlock> MakeHavocBlocks(ICollection<Variable> variables) { + Debug.Assert(variables.Count > 0); + List<BigBlock> result = new List<BigBlock>(); + foreach (Variable v in variables) { + if (!ArrayModelledAdversarially(v)) { + result.Add(HavocSharedArray(v)); + } + } + return result; + } + + public static bool HasZDimension(Variable v) + { + if (v.TypedIdent.Type is MapType) + { + MapType mt = v.TypedIdent.Type as MapType; + + if (mt.Result is MapType) + { + MapType mt2 = mt.Result as MapType; + if (mt2.Result is MapType) + { + Debug.Assert(!((mt2.Result as MapType).Result is MapType)); + return true; + } + } + } + return false; + } + + private BigBlock HavocSharedArray(Variable v) + { + return new BigBlock(Token.NoToken, null, + new CmdSeq(new Cmd[] { new HavocCmd(Token.NoToken, + new IdentifierExprSeq(new IdentifierExpr[] { new IdentifierExpr(Token.NoToken, v) })) }), null, null); + } + + internal static bool ModifiesSetContains(IdentifierExprSeq Modifies, IdentifierExpr v) + { + foreach (IdentifierExpr ie in Modifies) + { + if (ie.Name.Equals(v.Name)) + { + return true; + } + } + return false; + } + + private void AbstractSharedState() + { + new AdversarialAbstraction(this).Abstract(); + } + + internal static string MakeOffsetVariableName(string Name, string AccessType) + { + return "_" + AccessType + "_OFFSET_" + Name; + } + + internal static GlobalVariable MakeOffsetVariable(string Name, string ReadOrWrite) + { + return new GlobalVariable(Token.NoToken, new TypedIdent(Token.NoToken, MakeOffsetVariableName(Name, ReadOrWrite), + Microsoft.Boogie.Type.GetBvType(32))); + } + + internal static string MakeSourceVariableName(string Name, string AccessType) + { + return "_" + AccessType + "_SOURCE_" + Name; + } + + internal static GlobalVariable MakeSourceVariable(string name, string ReadOrWrite) + { + return new GlobalVariable(Token.NoToken, new TypedIdent(Token.NoToken, MakeSourceVariableName(name, ReadOrWrite), + Microsoft.Boogie.Type.GetBvType(32))); + } + + internal GlobalVariable FindOrCreateAccessHasOccurredVariable(string varName, string accessType) + { + string name = MakeAccessHasOccurredVariableName(varName, accessType) + "$1"; + foreach(Declaration D in Program.TopLevelDeclarations) + { + if(D is GlobalVariable && ((GlobalVariable)D).Name.Equals(name)) + { + return D as GlobalVariable; + } + } + + GlobalVariable result = new VariableDualiser(1, null, null).VisitVariable( + MakeAccessHasOccurredVariable(varName, accessType)) as GlobalVariable; + + Program.TopLevelDeclarations.Add(result); + return result; + + } + + internal GlobalVariable FindOrCreateOffsetVariable(string varName, string accessType) + { + string name = MakeOffsetVariableName(varName, accessType) + "$1"; + foreach (Declaration D in Program.TopLevelDeclarations) + { + if (D is GlobalVariable && ((GlobalVariable)D).Name.Equals(name)) + { + return D as GlobalVariable; + } + } + + GlobalVariable result = new VariableDualiser(1, null, null).VisitVariable( + MakeOffsetVariable(varName, accessType)) as GlobalVariable; + + Program.TopLevelDeclarations.Add(result); + return result; + + } + + internal GlobalVariable FindOrCreateSourceVariable(string varName, string accessType) { + string name = MakeSourceVariableName(varName, accessType) + "$1"; + foreach (Declaration D in Program.TopLevelDeclarations) { + if (D is GlobalVariable && ((GlobalVariable)D).Name.Equals(name)) { + return D as GlobalVariable; + } + } + + GlobalVariable result = new VariableDualiser(1, null, null).VisitVariable( + MakeSourceVariable(varName, accessType)) as GlobalVariable; + + Program.TopLevelDeclarations.Add(result); + return result; + + } + + internal static GlobalVariable MakeAccessHasOccurredVariable(string varName, string accessType) + { + return new GlobalVariable(Token.NoToken, new TypedIdent(Token.NoToken, MakeAccessHasOccurredVariableName(varName, accessType), Microsoft.Boogie.Type.Bool)); + } + + internal static string MakeAccessHasOccurredVariableName(string varName, string accessType) + { + return "_" + accessType + "_HAS_OCCURRED_" + varName; + } + + internal static IdentifierExpr MakeAccessHasOccurredExpr(string varName, string accessType) + { + return new IdentifierExpr(Token.NoToken, MakeAccessHasOccurredVariable(varName, accessType)); + } + + internal static bool IsIntOrBv32(Microsoft.Boogie.Type type) + { + return type.Equals(Microsoft.Boogie.Type.Int) || type.Equals(Microsoft.Boogie.Type.GetBvType(32)); + } + + private void PullOutNonLocalAccesses() + { + foreach (Declaration d in Program.TopLevelDeclarations) + { + if (d is Implementation) + { + (d as Implementation).StructuredStmts = PullOutNonLocalAccesses((d as Implementation).StructuredStmts, (d as Implementation)); + } + } + } + + private void RemoveElseIfs() + { + foreach (Declaration d in Program.TopLevelDeclarations) + { + if (d is Implementation) + { + (d as Implementation).StructuredStmts = RemoveElseIfs((d as Implementation).StructuredStmts); + } + } + } + + private void RemoveRedundantReturns() + { + foreach (Declaration d in Program.TopLevelDeclarations) + { + if (d is Implementation) + { + RemoveRedundantReturns((d as Implementation).StructuredStmts); + } + } + } + + private StmtList RemoveElseIfs(StmtList stmtList) + { + Contract.Requires(stmtList != null); + + StmtList result = new StmtList(new List<BigBlock>(), stmtList.EndCurly); + + foreach (BigBlock bodyBlock in stmtList.BigBlocks) + { + result.BigBlocks.Add(RemoveElseIfs(bodyBlock)); + } + + return result; + } + + private void RemoveRedundantReturns(StmtList stmtList) + { + Contract.Requires(stmtList != null); + + BigBlock bb = stmtList.BigBlocks[stmtList.BigBlocks.Count - 1]; + + if (bb.tc is ReturnCmd) + { + bb.tc = null; + } + } + + private BigBlock RemoveElseIfs(BigBlock bb) + { + BigBlock result = bb; + if (bb.ec is IfCmd) + { + IfCmd IfCommand = bb.ec as IfCmd; + + Debug.Assert(IfCommand.elseIf == null || IfCommand.elseBlock == null); + + if (IfCommand.elseIf != null) + { + IfCommand.elseBlock = new StmtList(new List<BigBlock>(new BigBlock[] { + new BigBlock(bb.tok, null, new CmdSeq(), IfCommand.elseIf, null) + }), bb.tok); + IfCommand.elseIf = null; + } + + IfCommand.thn = RemoveElseIfs(IfCommand.thn); + if (IfCommand.elseBlock != null) + { + IfCommand.elseBlock = RemoveElseIfs(IfCommand.elseBlock); + } + + } + else if (bb.ec is WhileCmd) + { + (bb.ec as WhileCmd).Body = RemoveElseIfs((bb.ec as WhileCmd).Body); + } + + return result; + } + + private StmtList PullOutNonLocalAccesses(StmtList stmtList, Implementation impl) + { + Contract.Requires(stmtList != null); + + StmtList result = new StmtList(new List<BigBlock>(), stmtList.EndCurly); + + foreach (BigBlock bodyBlock in stmtList.BigBlocks) + { + result.BigBlocks.Add(PullOutNonLocalAccesses(bodyBlock, impl)); + } + + return result; + } + + private BigBlock PullOutNonLocalAccesses(BigBlock bb, Implementation impl) + { + + BigBlock result = new BigBlock(bb.tok, bb.LabelName, new CmdSeq(), null, bb.tc); + + foreach (Cmd c in bb.simpleCmds) + { + + if (c is CallCmd) + { + CallCmd call = c as CallCmd; + + List<Expr> newIns = new List<Expr>(); + + for (int i = 0; i < call.Ins.Count; i++) + { + Expr e = call.Ins[i]; + + while (NonLocalAccessCollector.ContainsNonLocalAccess(e, KernelArrayInfo)) + { + AssignCmd assignToTemp; + LocalVariable tempDecl; + e = ExtractLocalAccessToTemp(e, out assignToTemp, out tempDecl); + result.simpleCmds.Add(assignToTemp); + impl.LocVars.Add(tempDecl); + } + + newIns.Add(e); + + } + + CallCmd newCall = new CallCmd(call.tok, call.callee, newIns, call.Outs); + newCall.Proc = call.Proc; + result.simpleCmds.Add(newCall); + } + else if (c is AssignCmd) + { + AssignCmd assign = c as AssignCmd; + + if (assign.Lhss.Zip(assign.Rhss, (lhs, rhs) => + !NonLocalAccessCollector.ContainsNonLocalAccess(rhs, KernelArrayInfo) || + (!NonLocalAccessCollector.ContainsNonLocalAccess(lhs, KernelArrayInfo) && + NonLocalAccessCollector.IsNonLocalAccess(rhs, KernelArrayInfo))).All(b => b)) + { + result.simpleCmds.Add(c); + } + else + { + Debug.Assert(assign.Lhss.Count == 1 && assign.Rhss.Count == 1); + AssignLhs lhs = assign.Lhss.ElementAt(0); + Expr rhs = assign.Rhss.ElementAt(0); + rhs = PullOutNonLocalAccessesIntoTemps(result, rhs, impl); + List<AssignLhs> newLhss = new List<AssignLhs>(); + newLhss.Add(lhs); + List<Expr> newRhss = new List<Expr>(); + newRhss.Add(rhs); + result.simpleCmds.Add(new AssignCmd(assign.tok, newLhss, newRhss)); + } + + } + else if (c is HavocCmd) + { + result.simpleCmds.Add(c); + } + else if (c is AssertCmd) + { + result.simpleCmds.Add(new AssertCmd(c.tok, PullOutNonLocalAccessesIntoTemps(result, (c as AssertCmd).Expr, impl))); + } + else if (c is AssumeCmd) + { + result.simpleCmds.Add(new AssumeCmd(c.tok, PullOutNonLocalAccessesIntoTemps(result, (c as AssumeCmd).Expr, impl))); + } + else + { + Console.WriteLine(c); + Debug.Assert(false); + } + } + + if (bb.ec is WhileCmd) + { + WhileCmd WhileCommand = bb.ec as WhileCmd; + while (NonLocalAccessCollector.ContainsNonLocalAccess(WhileCommand.Guard, KernelArrayInfo)) + { + AssignCmd assignToTemp; + LocalVariable tempDecl; + WhileCommand.Guard = ExtractLocalAccessToTemp(WhileCommand.Guard, out assignToTemp, out tempDecl); + result.simpleCmds.Add(assignToTemp); + impl.LocVars.Add(tempDecl); + } + result.ec = new WhileCmd(WhileCommand.tok, WhileCommand.Guard, WhileCommand.Invariants, PullOutNonLocalAccesses(WhileCommand.Body, impl)); + } + else if (bb.ec is IfCmd) + { + IfCmd IfCommand = bb.ec as IfCmd; + Debug.Assert(IfCommand.elseIf == null); // "else if" must have been eliminated by this phase + while (NonLocalAccessCollector.ContainsNonLocalAccess(IfCommand.Guard, KernelArrayInfo)) + { + AssignCmd assignToTemp; + LocalVariable tempDecl; + IfCommand.Guard = ExtractLocalAccessToTemp(IfCommand.Guard, out assignToTemp, out tempDecl); + result.simpleCmds.Add(assignToTemp); + impl.LocVars.Add(tempDecl); + } + result.ec = new IfCmd(IfCommand.tok, IfCommand.Guard, PullOutNonLocalAccesses(IfCommand.thn, impl), IfCommand.elseIf, IfCommand.elseBlock != null ? PullOutNonLocalAccesses(IfCommand.elseBlock, impl) : null); + } + else if (bb.ec is BreakCmd) + { + result.ec = bb.ec; + } + else + { + Debug.Assert(bb.ec == null); + } + + return result; + + } + + private Expr PullOutNonLocalAccessesIntoTemps(BigBlock result, Expr e, Implementation impl) + { + while (NonLocalAccessCollector.ContainsNonLocalAccess(e, KernelArrayInfo)) + { + AssignCmd assignToTemp; + LocalVariable tempDecl; + e = ExtractLocalAccessToTemp(e, out assignToTemp, out tempDecl); + result.simpleCmds.Add(assignToTemp); + impl.LocVars.Add(tempDecl); + } + return e; + } + + private Expr ExtractLocalAccessToTemp(Expr rhs, out AssignCmd tempAssignment, out LocalVariable tempDeclaration) + { + NonLocalAccessExtractor extractor = new NonLocalAccessExtractor(TempCounter, KernelArrayInfo); + TempCounter++; + rhs = extractor.VisitExpr(rhs); + tempAssignment = extractor.Assignment; + tempDeclaration = extractor.Declaration; + return rhs; + } + + private void MakeKernelDualised() + { + + List<Declaration> NewTopLevelDeclarations = new List<Declaration>(); + + foreach (Declaration d in Program.TopLevelDeclarations) + { + if (d is Procedure) + { + + new KernelDualiser(this).DualiseProcedure(d as Procedure); + + NewTopLevelDeclarations.Add(d as Procedure); + + continue; + + } + + if (d is Implementation) + { + + new KernelDualiser(this).DualiseImplementation(d as Implementation, CommandLineOptions.Unstructured); + + NewTopLevelDeclarations.Add(d as Implementation); + + continue; + + } + + if (d is Variable && ((d as Variable).IsMutable || + IsThreadLocalIdConstant(d as Variable) || + IsGroupIdConstant(d as Variable))) { + var v = d as Variable; + + if (KernelArrayInfo.getGlobalArrays().Contains(v)) { + NewTopLevelDeclarations.Add(v); + continue; + } + + if (KernelArrayInfo.getGroupSharedArrays().Contains(v)) { + Variable newV = new GlobalVariable(Token.NoToken, new TypedIdent(Token.NoToken, + v.Name, new MapType(Token.NoToken, new TypeVariableSeq(), + new TypeSeq(new Microsoft.Boogie.Type[] { Microsoft.Boogie.Type.Bool }), + v.TypedIdent.Type))); + newV.Attributes = v.Attributes; + NewTopLevelDeclarations.Add(newV); + continue; + } + + NewTopLevelDeclarations.Add(new VariableDualiser(1, null, null).VisitVariable((Variable)v.Clone())); + if (!QKeyValue.FindBoolAttribute(v.Attributes, "race_checking")) { + NewTopLevelDeclarations.Add(new VariableDualiser(2, null, null).VisitVariable((Variable)v.Clone())); + } + + continue; + } + + NewTopLevelDeclarations.Add(d); + + } + + Program.TopLevelDeclarations = NewTopLevelDeclarations; + + } + + private void MakeKernelPredicated() + { + if (CommandLineOptions.Unstructured) + { + if (CommandLineOptions.SmartPredication) + { + SmartBlockPredicator.Predicate(Program, proc => proc != KernelProcedure, uniformityAnalyser); + } + else + { + BlockPredicator.Predicate(Program, /*createCandidateInvariants=*/CommandLineOptions.Inference); + } + return; + } + + foreach (Declaration d in Program.TopLevelDeclarations) + { + if (d is Procedure) + { + Procedure proc = d as Procedure; + IdentifierExpr enabled = new IdentifierExpr(proc.tok, + new LocalVariable(proc.tok, new TypedIdent(proc.tok, "_P", Microsoft.Boogie.Type.Bool))); + Expr predicateExpr; + if (!uniformityAnalyser.IsUniform(proc.Name)) + { + // Add predicate to start of parameter list + VariableSeq NewIns = new VariableSeq(); + NewIns.Add(enabled.Decl); + foreach (Variable v in proc.InParams) + { + NewIns.Add(v); + } + proc.InParams = NewIns; + predicateExpr = enabled; + } + else + { + predicateExpr = Expr.True; + } + + RequiresSeq newRequires = new RequiresSeq(); + foreach (Requires r in proc.Requires) + { + newRequires.Add(new Requires(r.Free, Predicator.ProcessEnabledIntrinsics(r.Condition, predicateExpr))); + } + proc.Requires = newRequires; + + EnsuresSeq newEnsures = new EnsuresSeq(); + foreach (Ensures e in proc.Ensures) + { + newEnsures.Add(new Ensures(e.Free, Predicator.ProcessEnabledIntrinsics(e.Condition, predicateExpr))); + } + proc.Ensures = newEnsures; + + } + else if (d is Implementation) + { + Implementation impl = d as Implementation; + new Predicator(this, !uniformityAnalyser.IsUniform(impl.Name)).transform + (impl); + } + } + + } + + private void CheckKernelParameters() + { + if (KernelProcedure.OutParams.Length != 0) + { + Error(KernelProcedure.tok, "Kernel should not take return anything"); + } + } + + + private int Check() + { + BarrierProcedure = FindOrCreateBarrierProcedure(); + KernelProcedure = CheckExactlyOneKernelProcedure(); + + if (ErrorCount > 0) + { + return ErrorCount; + } + + if (BarrierProcedure.InParams.Length != 2) + { + Error(BarrierProcedure, "Barrier procedure must take exactly two arguments"); + } + else if (!BarrierProcedure.InParams[0].TypedIdent.Type.Equals(new BvType(1))) + { + Error(BarrierProcedure, "First argument to barrier procedure must have type bv1"); + } + else if (!BarrierProcedure.InParams[1].TypedIdent.Type.Equals(new BvType(1))) { + Error(BarrierProcedure, "Second argument to barrier procedure must have type bv1"); + } + + if (BarrierProcedure.OutParams.Length != 0) + { + Error(BarrierProcedure, "Barrier procedure must not return any results"); + } + + if (!FindNonLocalVariables()) + { + return ErrorCount; + } + + CheckKernelImplementation(); + return ErrorCount; + } + + public static bool IsThreadLocalIdConstant(Variable variable) + { + return variable.Name.Equals(_X.Name) || variable.Name.Equals(_Y.Name) || variable.Name.Equals(_Z.Name); + } + + public static bool IsGroupIdConstant(Variable variable) + { + return variable.Name.Equals(_GROUP_X.Name) || variable.Name.Equals(_GROUP_Y.Name) || variable.Name.Equals(_GROUP_Z.Name); + } + + internal void AddCandidateInvariant(IRegion region, Expr e, string tag) + { + region.AddInvariant(Program.CreateCandidateInvariant(e, tag)); + } + + internal Implementation GetImplementation(string procedureName) + { + foreach (Declaration D in Program.TopLevelDeclarations) + { + if (D is Implementation && ((D as Implementation).Name == procedureName)) + { + return D as Implementation; + } + } + Debug.Assert(false); + return null; + } + + + internal bool ContainsBarrierCall(IRegion loop) + { + foreach (Cmd c in loop.Cmds()) + { + if (c is CallCmd && ((c as CallCmd).Proc == BarrierProcedure)) + { + return true; + } + } + + return false; + } + + + + internal bool ArrayModelledAdversarially(Variable v) + { + if (CommandLineOptions.AdversarialAbstraction) + { + return true; + } + if (CommandLineOptions.EqualityAbstraction) + { + return false; + } + return !arrayControlFlowAnalyser.MayAffectControlFlow(v.Name); + } + + internal Expr GlobalIdExpr(string dimension) + { + return MakeBVAdd(MakeBVMul( + new IdentifierExpr(Token.NoToken, GetGroupId(dimension)), new IdentifierExpr(Token.NoToken, GetGroupSize(dimension))), + new IdentifierExpr(Token.NoToken, MakeThreadId(Token.NoToken, dimension))); + } + + internal IRegion RootRegion(Implementation Impl) + { + if (CommandLineOptions.Unstructured) + return new UnstructuredRegion(Program, Impl); + else + return new StructuredRegion(Impl); + } + + + public static bool IsGivenConstant(Expr e, Constant c) + { + if (!(e is IdentifierExpr)) + return false; + + var varName = ((IdentifierExpr)e).Decl.Name; + return (StripThreadIdentifier(varName) == StripThreadIdentifier(c.Name)); + } + + public bool SubstIsGivenConstant(Implementation impl, Expr e, Constant c) + { + if (!(e is IdentifierExpr)) + return false; + e = varDefAnalyses[impl].SubstDefinitions(e, impl.Name); + return IsGivenConstant(e, c); + } + + public Constant GetLocalIdConst(int dim) + { + switch (dim) + { + case 0: return _X; + case 1: return _Y; + case 2: return _Z; + default: Debug.Assert(false); + return null; + } + } + + public Constant GetGroupIdConst(int dim) + { + switch (dim) + { + case 0: return _GROUP_X; + case 1: return _GROUP_Y; + case 2: return _GROUP_Z; + default: Debug.Assert(false); + return null; + } + } + + public Constant GetGroupSizeConst(int dim) + { + switch (dim) + { + case 0: return _GROUP_SIZE_X; + case 1: return _GROUP_SIZE_Y; + case 2: return _GROUP_SIZE_Z; + default: Debug.Assert(false); + return null; + } + } + + public bool IsLocalId(Expr e, int dim, Implementation impl) + { + return SubstIsGivenConstant(impl, e, GetLocalIdConst(dim)); + } + + public bool IsGlobalId(Expr e, int dim, Implementation impl) + { + e = varDefAnalyses[impl].SubstDefinitions(e, impl.Name); + + if (e is NAryExpr && (e as NAryExpr).Fun.FunctionName.Equals("BV32_ADD")) + { + NAryExpr nary = e as NAryExpr; + Constant localId = GetLocalIdConst(dim); + + if (IsGivenConstant(nary.Args[1], localId)) + { + return IsGroupIdTimesGroupSize(nary.Args[0], dim); + } + + if (IsGivenConstant(nary.Args[0], localId)) + { + return IsGroupIdTimesGroupSize(nary.Args[1], dim); + } + } + + return false; + } + + private bool IsGroupIdTimesGroupSize(Expr expr, int dim) + { + if (expr is NAryExpr && (expr as NAryExpr).Fun.FunctionName.Equals("BV32_MUL")) + { + NAryExpr innerNary = expr as NAryExpr; + + if (IsGroupIdAndSize(dim, innerNary.Args[0], innerNary.Args[1])) + { + return true; + } + + if (IsGroupIdAndSize(dim, innerNary.Args[1], innerNary.Args[0])) + { + return true; + } + } + return false; + } + + private bool IsGroupIdAndSize(int dim, Expr maybeGroupId, Expr maybeGroupSize) + { + return IsGivenConstant(maybeGroupId, GetGroupIdConst(dim)) && + IsGivenConstant(maybeGroupSize, GetGroupSizeConst(dim)); + } + + internal Expr MaybeDualise(Expr e, int id, string procName) + { + if (id == 0) + return e; + else + return (Expr)new VariableDualiser(id, uniformityAnalyser, procName).Visit(e.Clone()); + } + + internal static bool IsConstantInCurrentRegion(IdentifierExpr expr) { + return (expr.Decl is Constant) || + (expr.Decl is Formal && ((Formal)expr.Decl).InComing); + } + + } + + +} diff --git a/Source/GPUVerify/GPUVerify.csproj b/Source/GPUVerify/GPUVerify.csproj index 08913944..e7122edf 100644 --- a/Source/GPUVerify/GPUVerify.csproj +++ b/Source/GPUVerify/GPUVerify.csproj @@ -1,180 +1,178 @@ -<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
- <ProductVersion>8.0.30703</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{E5D16606-06D0-434F-A9D7-7D079BC80229}</ProjectGuid>
- <OutputType>Exe</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>GPUVerify</RootNamespace>
- <AssemblyName>GPUVerifyVCGen</AssemblyName>
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <TargetFrameworkProfile>Client</TargetFrameworkProfile>
- <FileAlignment>512</FileAlignment>
- <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
- <PlatformTarget>x86</PlatformTarget>
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>bin\Debug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>True</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>True</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>True</CodeContractsArithmeticObligations>
- <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>True</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly />
- <CodeContractsCustomRewriterClass />
- <CodeContractsLibPaths />
- <CodeContractsExtraRewriteOptions />
- <CodeContractsExtraAnalysisOptions />
- <CodeContractsBaseLineFile />
- <CodeContractsCacheAnalysisResults>True</CodeContractsCacheAnalysisResults>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
- <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
- <CodeContractsAnalysisPrecisionLevel>0</CodeContractsAnalysisPrecisionLevel>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
- <PlatformTarget>x86</PlatformTarget>
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>bin\Release\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\Debug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisLogFile>bin\Debug\GPUVerify.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
- <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
- <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
- <CodeAnalysisFailOnMissingRules>false</CodeAnalysisFailOnMissingRules>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
- <OutputPath>bin\Release\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <Optimize>true</Optimize>
- <DebugType>pdbonly</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisLogFile>bin\Release\GPUVerify.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- <Reference Include="System.Core" />
- <Reference Include="System.Windows.Forms" />
- <Reference Include="System.Xml.Linq" />
- <Reference Include="System.Data.DataSetExtensions" />
- <Reference Include="Microsoft.CSharp" />
- <Reference Include="System.Data" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="AccessCollector.cs" />
- <Compile Include="AccessRecord.cs" />
- <Compile Include="AdversarialAbstraction.cs" />
- <Compile Include="ArrayControlFlowAnalyser.cs" />
- <Compile Include="AsymmetricExpressionFinder.cs" />
- <Compile Include="StrideConstraint.cs" />
- <Compile Include="ReducedStrengthAnalysis.cs" />
- <Compile Include="UnstructuredRegion.cs" />
- <Compile Include="IRegion.cs" />
- <Compile Include="InvariantGenerationRules\LoopVariableBoundsInvariantGenerator.cs" />
- <Compile Include="InvariantGenerationRules\InvariantGenerationRule.cs" />
- <Compile Include="InvariantGenerationRules\PowerOfTwoInvariantGenerator.cs" />
- <Compile Include="EnsureDisabledThreadHasNoEffectInstrumenter.cs" />
- <Compile Include="KernelDualiser.cs" />
- <Compile Include="LiveVariableAnalyser.cs" />
- <Compile Include="LoopInvariantGenerator.cs" />
- <Compile Include="MayBePowerOfTwoAnalyser.cs" />
- <Compile Include="StructuredProgramVisitor.cs" />
- <Compile Include="EnabledToPredicateVisitor.cs" />
- <Compile Include="CommandLineOptions.cs" />
- <Compile Include="GPUVerifier.cs" />
- <Compile Include="IKernelArrayInfo.cs" />
- <Compile Include="IRaceInstrumenter.cs" />
- <Compile Include="Main.cs" />
- <Compile Include="NonLocalAccessCollector.cs" />
- <Compile Include="NonLocalAccessExtractor.cs" />
- <Compile Include="KernelArrayInfoLists.cs" />
- <Compile Include="NullRaceInstrumenter.cs" />
- <Compile Include="Predicator.cs" />
- <Compile Include="Properties\AssemblyInfo.cs" />
- <Compile Include="RaceInstrumenter.cs" />
- <Compile Include="ReadCollector.cs" />
- <Compile Include="UniformExpressionAnalysisVisitor.cs" />
- <Compile Include="UniformityAnalyser.cs" />
- <Compile Include="VariableDualiser.cs" />
- <Compile Include="VariablesOccurringInExpressionVisitor.cs" />
- <Compile Include="VariableDefinitionAnalysis.cs" />
- <Compile Include="StructuredRegion.cs" />
- <Compile Include="WriteCollector.cs" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\AIFramework\AIFramework.csproj">
- <Project>{39B0658D-C955-41C5-9A43-48C97A1EF5FD}</Project>
- <Name>AIFramework</Name>
- </ProjectReference>
- <ProjectReference Include="..\Basetypes\Basetypes.csproj">
- <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
- <Name>Basetypes</Name>
- </ProjectReference>
- <ProjectReference Include="..\Core\Core.csproj">
- <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
- <Name>Core</Name>
- </ProjectReference>
- <ProjectReference Include="..\Graph\Graph.csproj">
- <Project>{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}</Project>
- <Name>Graph</Name>
- </ProjectReference>
- <ProjectReference Include="..\ParserHelper\ParserHelper.csproj">
- <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
- <Name>ParserHelper</Name>
- </ProjectReference>
- <ProjectReference Include="..\VCGeneration\VCGeneration.csproj">
- <Project>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</Project>
- <Name>VCGeneration</Name>
- </ProjectReference>
- </ItemGroup>
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
- Other similar extension points exist, see Microsoft.Common.targets.
- <Target Name="BeforeBuild">
- </Target>
- <Target Name="AfterBuild">
- </Target>
- -->
+<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">x86</Platform> + <ProductVersion>8.0.30703</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{E5D16606-06D0-434F-A9D7-7D079BC80229}</ProjectGuid> + <OutputType>Exe</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>GPUVerify</RootNamespace> + <AssemblyName>GPUVerifyVCGen</AssemblyName> + <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> + <TargetFrameworkProfile>Client</TargetFrameworkProfile> + <FileAlignment>512</FileAlignment> + <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' "> + <PlatformTarget>x86</PlatformTarget> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking> + <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface> + <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure> + <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires> + <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers> + <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis> + <CodeContractsNonNullObligations>True</CodeContractsNonNullObligations> + <CodeContractsBoundsObligations>True</CodeContractsBoundsObligations> + <CodeContractsArithmeticObligations>True</CodeContractsArithmeticObligations> + <CodeContractsEnumObligations>False</CodeContractsEnumObligations> + <CodeContractsPointerObligations>False</CodeContractsPointerObligations> + <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions> + <CodeContractsRunInBackground>True</CodeContractsRunInBackground> + <CodeContractsShowSquigglies>True</CodeContractsShowSquigglies> + <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine> + <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs> + <CodeContractsCustomRewriterAssembly /> + <CodeContractsCustomRewriterClass /> + <CodeContractsLibPaths /> + <CodeContractsExtraRewriteOptions /> + <CodeContractsExtraAnalysisOptions /> + <CodeContractsBaseLineFile /> + <CodeContractsCacheAnalysisResults>True</CodeContractsCacheAnalysisResults> + <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel> + <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly> + <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel> + <CodeContractsAnalysisPrecisionLevel>0</CodeContractsAnalysisPrecisionLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' "> + <PlatformTarget>x86</PlatformTarget> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'"> + <DebugSymbols>true</DebugSymbols> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <DebugType>full</DebugType> + <PlatformTarget>AnyCPU</PlatformTarget> + <CodeAnalysisLogFile>bin\Debug\GPUVerify.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile> + <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression> + <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile> + <ErrorReport>prompt</ErrorReport> + <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> + <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories> + <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets> + <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories> + <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules> + <CodeAnalysisFailOnMissingRules>false</CodeAnalysisFailOnMissingRules> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'"> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <Optimize>true</Optimize> + <DebugType>pdbonly</DebugType> + <PlatformTarget>AnyCPU</PlatformTarget> + <CodeAnalysisLogFile>bin\Release\GPUVerify.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile> + <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression> + <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile> + <ErrorReport>prompt</ErrorReport> + <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> + <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories> + <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Windows.Forms" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="AccessCollector.cs" /> + <Compile Include="AccessRecord.cs" /> + <Compile Include="AdversarialAbstraction.cs" /> + <Compile Include="ArrayControlFlowAnalyser.cs" /> + <Compile Include="AsymmetricExpressionFinder.cs" /> + <Compile Include="StrideConstraint.cs" /> + <Compile Include="ReducedStrengthAnalysis.cs" /> + <Compile Include="UnstructuredRegion.cs" /> + <Compile Include="IRegion.cs" /> + <Compile Include="InvariantGenerationRules\LoopVariableBoundsInvariantGenerator.cs" /> + <Compile Include="InvariantGenerationRules\InvariantGenerationRule.cs" /> + <Compile Include="InvariantGenerationRules\PowerOfTwoInvariantGenerator.cs" /> + <Compile Include="EnsureDisabledThreadHasNoEffectInstrumenter.cs" /> + <Compile Include="KernelDualiser.cs" /> + <Compile Include="LiveVariableAnalyser.cs" /> + <Compile Include="LoopInvariantGenerator.cs" /> + <Compile Include="MayBePowerOfTwoAnalyser.cs" /> + <Compile Include="StructuredProgramVisitor.cs" /> + <Compile Include="EnabledToPredicateVisitor.cs" /> + <Compile Include="CommandLineOptions.cs" /> + <Compile Include="GPUVerifier.cs" /> + <Compile Include="IKernelArrayInfo.cs" /> + <Compile Include="IRaceInstrumenter.cs" /> + <Compile Include="Main.cs" /> + <Compile Include="NonLocalAccessCollector.cs" /> + <Compile Include="NonLocalAccessExtractor.cs" /> + <Compile Include="KernelArrayInfoLists.cs" /> + <Compile Include="NullRaceInstrumenter.cs" /> + <Compile Include="Predicator.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="RaceInstrumenter.cs" /> + <Compile Include="ReadCollector.cs" /> + <Compile Include="VariableDualiser.cs" /> + <Compile Include="VariablesOccurringInExpressionVisitor.cs" /> + <Compile Include="VariableDefinitionAnalysis.cs" /> + <Compile Include="StructuredRegion.cs" /> + <Compile Include="WriteCollector.cs" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\AIFramework\AIFramework.csproj"> + <Project>{39B0658D-C955-41C5-9A43-48C97A1EF5FD}</Project> + <Name>AIFramework</Name> + </ProjectReference> + <ProjectReference Include="..\Basetypes\Basetypes.csproj"> + <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project> + <Name>Basetypes</Name> + </ProjectReference> + <ProjectReference Include="..\Core\Core.csproj"> + <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project> + <Name>Core</Name> + </ProjectReference> + <ProjectReference Include="..\Graph\Graph.csproj"> + <Project>{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}</Project> + <Name>Graph</Name> + </ProjectReference> + <ProjectReference Include="..\ParserHelper\ParserHelper.csproj"> + <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project> + <Name>ParserHelper</Name> + </ProjectReference> + <ProjectReference Include="..\VCGeneration\VCGeneration.csproj"> + <Project>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</Project> + <Name>VCGeneration</Name> + </ProjectReference> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> </Project>
\ No newline at end of file diff --git a/Source/GPUVerify/IRaceInstrumenter.cs b/Source/GPUVerify/IRaceInstrumenter.cs index 2e997fe0..c85989c9 100644 --- a/Source/GPUVerify/IRaceInstrumenter.cs +++ b/Source/GPUVerify/IRaceInstrumenter.cs @@ -1,30 +1,31 @@ -using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Microsoft.Boogie;
-
-namespace GPUVerify
-{
- interface IRaceInstrumenter
- {
- void AddRaceCheckingCandidateInvariants(Implementation impl, IRegion region);
- void AddKernelPrecondition();
-
- void AddRaceCheckingInstrumentation();
-
- void AddRaceCheckingDeclarations();
-
- BigBlock MakeResetReadWriteSetStatements(Variable v, int thread);
-
- void AddRaceCheckingCandidateRequires(Procedure Proc);
-
- void AddRaceCheckingCandidateEnsures(Procedure Proc);
-
- void AddSourceLocationLoopInvariants(Implementation impl, IRegion region);
-
- void AddStandardSourceVariablePreconditions();
-
- void AddStandardSourceVariablePostconditions();
- }
-}
+using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Boogie; + +namespace GPUVerify +{ + interface IRaceInstrumenter + { + void AddRaceCheckingCandidateInvariants(Implementation impl, IRegion region); + void AddKernelPrecondition(); + + void AddRaceCheckingInstrumentation(); + + void AddRaceCheckingDeclarations(); + + BigBlock MakeResetReadWriteSetStatements(Variable v, int thread); + + void AddRaceCheckingCandidateRequires(Procedure Proc); + + void AddRaceCheckingCandidateEnsures(Procedure Proc); + + void AddSourceLocationLoopInvariants(Implementation impl, IRegion region); + + void DoHoudiniPointerAnalysis(Procedure Proc); + void AddStandardSourceVariablePreconditions(); + + void AddStandardSourceVariablePostconditions(); + } +} diff --git a/Source/GPUVerify/InvariantGenerationRules/LoopVariableBoundsInvariantGenerator.cs b/Source/GPUVerify/InvariantGenerationRules/LoopVariableBoundsInvariantGenerator.cs index f73bddb6..c21261b0 100644 --- a/Source/GPUVerify/InvariantGenerationRules/LoopVariableBoundsInvariantGenerator.cs +++ b/Source/GPUVerify/InvariantGenerationRules/LoopVariableBoundsInvariantGenerator.cs @@ -1,54 +1,55 @@ -using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Diagnostics;
-using Microsoft.Boogie;
-using Microsoft.Basetypes;
-
-namespace GPUVerify.InvariantGenerationRules
-{
- class LoopVariableBoundsInvariantGenerator : InvariantGenerationRule
- {
-
- public LoopVariableBoundsInvariantGenerator(GPUVerifier verifier)
- : base(verifier)
- {
-
- }
-
- public override void GenerateCandidates(Implementation Impl, IRegion region)
- {
- if (verifier.uniformityAnalyser.IsUniform(Impl.Name, region.Guard()))
- {
- VariablesOccurringInExpressionVisitor visitor = new VariablesOccurringInExpressionVisitor();
- visitor.VisitExpr(region.Guard());
- foreach (Variable v in visitor.GetVariables())
- {
- if (!verifier.ContainsNamedVariable(LoopInvariantGenerator.GetModifiedVariables(region), v.Name))
- {
- continue;
- }
-
- if (IsBVType (v.TypedIdent.Type))
- {
- int BVWidth = (v.TypedIdent.Type as BvType).Bits;
-
- verifier.AddCandidateInvariant(region,
- verifier.MakeBVSge(
- new IdentifierExpr(v.tok, v),
- new LiteralExpr(v.tok, BigNum.FromInt(0), BVWidth)), "loop guard variable non-negative");
- }
- }
- }
- }
-
- private bool IsBVType(Microsoft.Boogie.Type type)
- {
- return type.Equals(Microsoft.Boogie.Type.GetBvType(32))
- || type.Equals(Microsoft.Boogie.Type.GetBvType(16))
- || type.Equals(Microsoft.Boogie.Type.GetBvType(8));
- }
-
- }
-}
+using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Diagnostics; +using Microsoft.Boogie; +using Microsoft.Basetypes; + +namespace GPUVerify.InvariantGenerationRules +{ + class LoopVariableBoundsInvariantGenerator : InvariantGenerationRule + { + + public LoopVariableBoundsInvariantGenerator(GPUVerifier verifier) + : base(verifier) + { + + } + + public override void GenerateCandidates(Implementation Impl, IRegion region) + { + var guard = region.Guard(); + if (guard != null && verifier.uniformityAnalyser.IsUniform(Impl.Name, guard)) + { + var visitor = new VariablesOccurringInExpressionVisitor(); + visitor.VisitExpr(guard); + foreach (Variable v in visitor.GetVariables()) + { + if (!verifier.ContainsNamedVariable(LoopInvariantGenerator.GetModifiedVariables(region), v.Name)) + { + continue; + } + + if (IsBVType (v.TypedIdent.Type)) + { + int BVWidth = (v.TypedIdent.Type as BvType).Bits; + + verifier.AddCandidateInvariant(region, + verifier.MakeBVSge( + new IdentifierExpr(v.tok, v), + new LiteralExpr(v.tok, BigNum.FromInt(0), BVWidth)), "loop guard variable non-negative"); + } + } + } + } + + private bool IsBVType(Microsoft.Boogie.Type type) + { + return type.Equals(Microsoft.Boogie.Type.GetBvType(32)) + || type.Equals(Microsoft.Boogie.Type.GetBvType(16)) + || type.Equals(Microsoft.Boogie.Type.GetBvType(8)); + } + + } +} diff --git a/Source/GPUVerify/InvariantGenerationRules/PowerOfTwoInvariantGenerator.cs b/Source/GPUVerify/InvariantGenerationRules/PowerOfTwoInvariantGenerator.cs index 8b24bb0a..8dab8474 100644 --- a/Source/GPUVerify/InvariantGenerationRules/PowerOfTwoInvariantGenerator.cs +++ b/Source/GPUVerify/InvariantGenerationRules/PowerOfTwoInvariantGenerator.cs @@ -1,61 +1,61 @@ -using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Diagnostics;
-using Microsoft.Boogie;
-using Microsoft.Basetypes;
-
-namespace GPUVerify.InvariantGenerationRules
-{
- class PowerOfTwoInvariantGenerator : InvariantGenerationRule
- {
-
- public PowerOfTwoInvariantGenerator(GPUVerifier verifier)
- : base(verifier)
- {
-
- }
-
- public override void GenerateCandidates(Implementation Impl, IRegion region)
- {
- foreach (Variable v in Impl.LocVars)
- {
- string basicName = GPUVerifier.StripThreadIdentifier(v.Name);
- if (verifier.uniformityAnalyser.IsUniform(Impl.Name, basicName))
- {
- if (verifier.mayBePowerOfTwoAnalyser.MayBePowerOfTwo(Impl.Name, basicName))
- {
- if (verifier.ContainsNamedVariable(LoopInvariantGenerator.GetModifiedVariables(region), basicName))
- {
- verifier.AddCandidateInvariant(region, MakePowerOfTwoExpr(v), "pow2 disjunction");
- for (int i = (1 << 15); i > 0; i >>= 1)
- {
- verifier.AddCandidateInvariant(region,
- GPUVerifier.MakeBitVectorBinaryBoolean("BV32_LT",
- new IdentifierExpr(v.tok, v),
- new LiteralExpr(v.tok, BigNum.FromInt(i), 32)), "pow2 less than " + i);
- }
- verifier.AddCandidateInvariant(region,
- Expr.Neq(new IdentifierExpr(v.tok, v),
- new LiteralExpr(v.tok, BigNum.FromInt(0), 32)), "pow2 not zero");
- }
- }
- }
- }
- }
-
- private Expr MakePowerOfTwoExpr(Variable v)
- {
- Expr result = null;
- for (int i = 1 << 15; i > 0; i >>= 1)
- {
- Expr eq = Expr.Eq(new IdentifierExpr(v.tok, v), new LiteralExpr(v.tok, BigNum.FromInt(i), 32));
- result = (result == null ? eq : Expr.Or(eq, result));
- }
-
- return Expr.Or(Expr.Eq(new IdentifierExpr(v.tok, v), new LiteralExpr(v.tok, BigNum.FromInt(0), 32)), result);
- }
-
- }
-}
+using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Diagnostics; +using Microsoft.Boogie; +using Microsoft.Basetypes; + +namespace GPUVerify.InvariantGenerationRules +{ + class PowerOfTwoInvariantGenerator : InvariantGenerationRule + { + + public PowerOfTwoInvariantGenerator(GPUVerifier verifier) + : base(verifier) + { + + } + + public override void GenerateCandidates(Implementation Impl, IRegion region) + { + foreach (Variable v in Impl.LocVars) + { + string basicName = GPUVerifier.StripThreadIdentifier(v.Name); + if (verifier.uniformityAnalyser.IsUniform(Impl.Name, basicName)) + { + if (verifier.mayBePowerOfTwoAnalyser.MayBePowerOfTwo(Impl.Name, basicName)) + { + if (verifier.ContainsNamedVariable(LoopInvariantGenerator.GetModifiedVariables(region), basicName)) + { + verifier.AddCandidateInvariant(region, MakePowerOfTwoExpr(v), "pow2 disjunction"); + for (int i = (1 << 15); i > 0; i >>= 1) + { + verifier.AddCandidateInvariant(region, + verifier.MakeBVSlt( + new IdentifierExpr(v.tok, v), + new LiteralExpr(v.tok, BigNum.FromInt(i), 32)), "pow2 less than " + i); + } + verifier.AddCandidateInvariant(region, + Expr.Neq(new IdentifierExpr(v.tok, v), + new LiteralExpr(v.tok, BigNum.FromInt(0), 32)), "pow2 not zero"); + } + } + } + } + } + + private Expr MakePowerOfTwoExpr(Variable v) + { + Expr result = null; + for (int i = 1 << 15; i > 0; i >>= 1) + { + Expr eq = Expr.Eq(new IdentifierExpr(v.tok, v), new LiteralExpr(v.tok, BigNum.FromInt(i), 32)); + result = (result == null ? eq : Expr.Or(eq, result)); + } + + return Expr.Or(Expr.Eq(new IdentifierExpr(v.tok, v), new LiteralExpr(v.tok, BigNum.FromInt(0), 32)), result); + } + + } +} diff --git a/Source/GPUVerify/KernelDualiser.cs b/Source/GPUVerify/KernelDualiser.cs index 53bee54e..201018bb 100644 --- a/Source/GPUVerify/KernelDualiser.cs +++ b/Source/GPUVerify/KernelDualiser.cs @@ -152,23 +152,36 @@ namespace GPUVerify { else if (c is AssignCmd) {
AssignCmd assign = c as AssignCmd;
- if (assign.Lhss.All(lhs =>
- lhs is SimpleAssignLhs &&
- verifier.uniformityAnalyser.IsUniform(procName, (lhs as SimpleAssignLhs).AssignedVariable.Name))) {
- cs.Add(assign);
- }
- else {
- foreach(var i in new int[] { 1, 2 }) {
- List<AssignLhs> newLhss = assign.Lhss.Select(lhs =>
- new VariableDualiser(i, verifier.uniformityAnalyser, procName).
- Visit(lhs.Clone() as AssignLhs) as AssignLhs).ToList();
- List<Expr> newRhss = assign.Rhss.Select(rhs =>
- new VariableDualiser(i, verifier.uniformityAnalyser, procName).
- VisitExpr(rhs.Clone() as Expr)).ToList();
- AssignCmd newAssign = new AssignCmd(assign.tok, newLhss, newRhss);
- cs.Add(newAssign);
+ var vd1 = new VariableDualiser(1, verifier.uniformityAnalyser, procName);
+ var vd2 = new VariableDualiser(2, verifier.uniformityAnalyser, procName);
+
+ List<AssignLhs> lhss1 = new List<AssignLhs>();
+ List<AssignLhs> lhss2 = new List<AssignLhs>();
+
+ List<Expr> rhss1 = new List<Expr>();
+ List<Expr> rhss2 = new List<Expr>();
+
+ foreach(var pair in assign.Lhss.Zip(assign.Rhss)) {
+ if(pair.Item1 is SimpleAssignLhs &&
+ verifier.uniformityAnalyser.IsUniform(procName,
+ (pair.Item1 as SimpleAssignLhs).AssignedVariable.Name)) {
+ lhss1.Add(pair.Item1);
+ rhss1.Add(pair.Item2);
+ } else {
+ lhss1.Add(vd1.Visit(pair.Item1.Clone() as AssignLhs) as AssignLhs);
+ lhss2.Add(vd2.Visit(pair.Item1.Clone() as AssignLhs) as AssignLhs);
+ rhss1.Add(vd1.VisitExpr(pair.Item2.Clone() as Expr));
+ rhss2.Add(vd2.VisitExpr(pair.Item2.Clone() as Expr));
}
}
+
+ Debug.Assert(lhss1.Count > 0);
+ cs.Add(new AssignCmd(Token.NoToken, lhss1, rhss1));
+
+ if(lhss2.Count > 0) {
+ cs.Add(new AssignCmd(Token.NoToken, lhss2, rhss2));
+ }
+
}
else if (c is HavocCmd) {
HavocCmd havoc = c as HavocCmd;
diff --git a/Source/GPUVerify/LoopInvariantGenerator.cs b/Source/GPUVerify/LoopInvariantGenerator.cs index 1c15f5e6..a465a98a 100644 --- a/Source/GPUVerify/LoopInvariantGenerator.cs +++ b/Source/GPUVerify/LoopInvariantGenerator.cs @@ -1,258 +1,258 @@ -using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Microsoft.Boogie;
-using Microsoft.Basetypes;
-using System.Diagnostics;
-
-using GPUVerify.InvariantGenerationRules;
-
-namespace GPUVerify {
- class LoopInvariantGenerator {
- private GPUVerifier verifier;
- private Implementation Impl;
-
- private List<InvariantGenerationRule> invariantGenerationRules;
-
- LoopInvariantGenerator(GPUVerifier verifier, Implementation Impl) {
- this.verifier = verifier;
- this.Impl = Impl;
-
- invariantGenerationRules = new List<InvariantGenerationRule>();
- invariantGenerationRules.Add(new PowerOfTwoInvariantGenerator(verifier));
- invariantGenerationRules.Add(new LoopVariableBoundsInvariantGenerator(verifier));
- }
-
- public static void PreInstrument(GPUVerifier verifier, Implementation impl) {
- foreach (var region in verifier.RootRegion(impl).SubRegions()) {
- GenerateCandidateForReducedStrengthStrideVariables(verifier, impl, region);
- }
- }
-
- private static void GenerateCandidateForReducedStrengthStrideVariables(GPUVerifier verifier, Implementation impl, IRegion region) {
- var rsa = verifier.reducedStrengthAnalyses[impl];
- foreach (string lc in rsa.StridedLoopCounters(region.Identifier())) {
- var sc = rsa.GetStrideConstraint(lc);
- Variable lcVariable = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, lc,
- Microsoft.Boogie.Type.GetBvType(32)));
- var lcExpr = new IdentifierExpr(Token.NoToken, lcVariable);
- var lcPred = sc.MaybeBuildPredicate(verifier, lcExpr);
-
- if (lcPred != null) {
- verifier.AddCandidateInvariant(region, lcPred, "variable " + lc + " is strided");
- }
- }
- }
-
- public static void PostInstrument(GPUVerifier verifier, Implementation Impl, List<Expr> UserSuppliedInvariants) {
- new LoopInvariantGenerator(verifier, Impl).PostInstrument(UserSuppliedInvariants);
- }
-
- internal void PostInstrument(List<Expr> UserSuppliedInvariants) {
- HashSet<Variable> LocalVars = new HashSet<Variable>();
- foreach (Variable v in Impl.LocVars) {
- LocalVars.Add(v);
- }
- foreach (Variable v in Impl.InParams) {
- LocalVars.Add(v);
- }
- foreach (Variable v in Impl.OutParams) {
- LocalVars.Add(v);
- }
-
- AddCandidateInvariants(verifier.RootRegion(Impl), LocalVars, UserSuppliedInvariants, Impl);
-
- }
-
- private void AddEqualityCandidateInvariant(IRegion region, string LoopPredicate, Variable v) {
- verifier.AddCandidateInvariant(region,
- Expr.Eq(
- new IdentifierExpr(Token.NoToken, new VariableDualiser(1, verifier.uniformityAnalyser, Impl.Name).VisitVariable(v.Clone() as Variable)),
- new IdentifierExpr(Token.NoToken, new VariableDualiser(2, verifier.uniformityAnalyser, Impl.Name).VisitVariable(v.Clone() as Variable))
- ), "equality");
- }
-
- private void AddPredicatedEqualityCandidateInvariant(IRegion region, string LoopPredicate, Variable v) {
- verifier.AddCandidateInvariant(region, Expr.Imp(
- Expr.And(
- new IdentifierExpr(Token.NoToken, new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, LoopPredicate + "$1", Microsoft.Boogie.Type.Int))),
- new IdentifierExpr(Token.NoToken, new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, LoopPredicate + "$2", Microsoft.Boogie.Type.Int)))
- ),
- Expr.Eq(
- new IdentifierExpr(Token.NoToken, new VariableDualiser(1, verifier.uniformityAnalyser, Impl.Name).VisitVariable(v.Clone() as Variable)),
- new IdentifierExpr(Token.NoToken, new VariableDualiser(2, verifier.uniformityAnalyser, Impl.Name).VisitVariable(v.Clone() as Variable))
- )), "predicated equality");
- }
-
- private Dictionary<string, int> GetAssignmentCounts(Implementation impl) {
-
- Dictionary<string, int> result = new Dictionary<string, int>();
-
- foreach (var c in verifier.RootRegion(impl).Cmds()) {
- if (c is AssignCmd) {
- var aCmd = (AssignCmd)c;
- HashSet<string> alreadySeenInThisAssignment = new HashSet<string>();
- foreach (var a in aCmd.Lhss) {
- if (a is SimpleAssignLhs) {
- var v = GPUVerifier.StripThreadIdentifier(
- ((SimpleAssignLhs)a).AssignedVariable.Name);
- if (!alreadySeenInThisAssignment.Contains(v)) {
- if (result.ContainsKey(v)) {
- result[v]++;
- }
- else {
- result[v] = 1;
- }
- alreadySeenInThisAssignment.Add(v);
- }
- }
- }
- }
- }
- return result;
- }
-
-
- private void AddBarrierDivergenceCandidates(HashSet<Variable> LocalVars, Implementation Impl, IRegion region)
- {
-
- if (!verifier.ContainsBarrierCall(region))
- {
- return;
- }
-
- Expr guard = region.Guard();
- if (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('$'));
-
- verifier.AddCandidateInvariant(region, Expr.Eq(
- // Int type used here, but it doesn't matter as we will print and then re-parse the program
- new IdentifierExpr(Token.NoToken, new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, LoopPredicate + "$1", Microsoft.Boogie.Type.Int))),
- new IdentifierExpr(Token.NoToken, new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, LoopPredicate + "$2", Microsoft.Boogie.Type.Int)))
- ), "loop predicate equality");
-
- Dictionary<string, int> assignmentCounts = GetAssignmentCounts(Impl);
-
- HashSet<string> alreadyConsidered = new HashSet<String>();
-
- foreach (var v in LocalVars)
- {
- string lv = GPUVerifier.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(
- GetModifiedVariables(region), lv))
- {
- continue;
- }
-
- AddPredicatedEqualityCandidateInvariant(region, LoopPredicate, new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, lv, Microsoft.Boogie.Type.Int)));
- }
-
- if (CommandLineOptions.ArrayEqualities)
- {
- foreach (Variable v in verifier.KernelArrayInfo.getAllNonLocalArrays())
- {
- if (!verifier.ArrayModelledAdversarially(v))
- {
- AddEqualityCandidateInvariant(region, LoopPredicate, v);
- }
- }
- }
- }
- }
-
- private static bool IsDisjunctionOfPredicates(Expr guard) {
- if (!(guard is NAryExpr)) {
- return false;
- }
- NAryExpr nary = (NAryExpr)guard;
- if(nary.Args.Length != 2) {
- return false;
- }
- if(!(nary.Fun is BinaryOperator)) {
- return false;
- }
- BinaryOperator binOp = (BinaryOperator)nary.Fun;
- if(binOp.Op != BinaryOperator.Opcode.Or) {
- return false;
- }
- if(!(nary.Args[0] is IdentifierExpr && nary.Args[1] is IdentifierExpr)) {
- return false;
- }
- return GPUVerifier.IsPredicate(GPUVerifier.StripThreadIdentifier(
- ((IdentifierExpr)nary.Args[0]).Name)) &&
- GPUVerifier.IsPredicate(GPUVerifier.StripThreadIdentifier(
- ((IdentifierExpr)nary.Args[1]).Name));
- }
-
- private void AddCandidateInvariants(IRegion region, HashSet<Variable> LocalVars, List<Expr> UserSuppliedInvariants, Implementation Impl) {
- foreach (IRegion subregion in region.SubRegions()) {
- foreach (InvariantGenerationRule r in invariantGenerationRules) {
- r.GenerateCandidates(Impl, subregion);
- }
-
- AddBarrierDivergenceCandidates(LocalVars, Impl, subregion);
-
- verifier.RaceInstrumenter.AddRaceCheckingCandidateInvariants(Impl, subregion);
-
- AddUserSuppliedInvariants(subregion, UserSuppliedInvariants, Impl);
- }
- }
-
- private void AddUserSuppliedInvariants(IRegion region, List<Expr> UserSuppliedInvariants, Implementation Impl) {
- foreach (Expr e in UserSuppliedInvariants) {
- /*
- wc.Invariants.Add(new AssertCmd(wc.tok, e));
- bool OK = verifier.ProgramIsOK(Impl);
- wc.Invariants.RemoveAt(wc.Invariants.Count - 1);
- if (OK)
- {
- verifier.AddCandidateInvariant(wc, e, "user supplied");
- }
- */
- verifier.AddCandidateInvariant(region, e, "user supplied");
- }
- }
-
- internal static HashSet<Variable> GetModifiedVariables(IRegion region) {
- HashSet<Variable> result = new HashSet<Variable>();
-
- foreach (Cmd c in region.Cmds()) {
- VariableSeq vars = new VariableSeq();
- c.AddAssignedVariables(vars);
- foreach (Variable v in vars) {
- result.Add(v);
- }
- }
-
- return result;
- }
-
- }
-}
+using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Boogie; +using Microsoft.Basetypes; +using System.Diagnostics; + +using GPUVerify.InvariantGenerationRules; + +namespace GPUVerify { + class LoopInvariantGenerator { + private GPUVerifier verifier; + private Implementation Impl; + + private List<InvariantGenerationRule> invariantGenerationRules; + + LoopInvariantGenerator(GPUVerifier verifier, Implementation Impl) { + this.verifier = verifier; + this.Impl = Impl; + + invariantGenerationRules = new List<InvariantGenerationRule>(); + invariantGenerationRules.Add(new PowerOfTwoInvariantGenerator(verifier)); + invariantGenerationRules.Add(new LoopVariableBoundsInvariantGenerator(verifier)); + } + + public static void PreInstrument(GPUVerifier verifier, Implementation impl) { + foreach (var region in verifier.RootRegion(impl).SubRegions()) { + GenerateCandidateForReducedStrengthStrideVariables(verifier, impl, region); + } + } + + private static void GenerateCandidateForReducedStrengthStrideVariables(GPUVerifier verifier, Implementation impl, IRegion region) { + var rsa = verifier.reducedStrengthAnalyses[impl]; + foreach (string lc in rsa.StridedLoopCounters(region.Identifier())) { + var sc = rsa.GetStrideConstraint(lc); + Variable lcVariable = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, lc, + Microsoft.Boogie.Type.GetBvType(32))); + var lcExpr = new IdentifierExpr(Token.NoToken, lcVariable); + var lcPred = sc.MaybeBuildPredicate(verifier, lcExpr); + + if (lcPred != null) { + verifier.AddCandidateInvariant(region, lcPred, "variable " + lc + " is strided"); + } + } + } + + public static void PostInstrument(GPUVerifier verifier, Implementation Impl, List<Expr> UserSuppliedInvariants) { + new LoopInvariantGenerator(verifier, Impl).PostInstrument(UserSuppliedInvariants); + } + + internal void PostInstrument(List<Expr> UserSuppliedInvariants) { + HashSet<Variable> LocalVars = new HashSet<Variable>(); + foreach (Variable v in Impl.LocVars) { + LocalVars.Add(v); + } + foreach (Variable v in Impl.InParams) { + LocalVars.Add(v); + } + foreach (Variable v in Impl.OutParams) { + LocalVars.Add(v); + } + + AddCandidateInvariants(verifier.RootRegion(Impl), LocalVars, UserSuppliedInvariants, Impl); + + } + + private void AddEqualityCandidateInvariant(IRegion region, string LoopPredicate, Variable v) { + verifier.AddCandidateInvariant(region, + Expr.Eq( + new IdentifierExpr(Token.NoToken, new VariableDualiser(1, verifier.uniformityAnalyser, Impl.Name).VisitVariable(v.Clone() as Variable)), + new IdentifierExpr(Token.NoToken, new VariableDualiser(2, verifier.uniformityAnalyser, Impl.Name).VisitVariable(v.Clone() as Variable)) + ), "equality"); + } + + private void AddPredicatedEqualityCandidateInvariant(IRegion region, string LoopPredicate, Variable v) { + verifier.AddCandidateInvariant(region, Expr.Imp( + Expr.And( + new IdentifierExpr(Token.NoToken, new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, LoopPredicate + "$1", Microsoft.Boogie.Type.Int))), + new IdentifierExpr(Token.NoToken, new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, LoopPredicate + "$2", Microsoft.Boogie.Type.Int))) + ), + Expr.Eq( + new IdentifierExpr(Token.NoToken, new VariableDualiser(1, verifier.uniformityAnalyser, Impl.Name).VisitVariable(v.Clone() as Variable)), + new IdentifierExpr(Token.NoToken, new VariableDualiser(2, verifier.uniformityAnalyser, Impl.Name).VisitVariable(v.Clone() as Variable)) + )), "predicated equality"); + } + + private Dictionary<string, int> GetAssignmentCounts(Implementation impl) { + + Dictionary<string, int> result = new Dictionary<string, int>(); + + foreach (var c in verifier.RootRegion(impl).Cmds()) { + if (c is AssignCmd) { + var aCmd = (AssignCmd)c; + HashSet<string> alreadySeenInThisAssignment = new HashSet<string>(); + foreach (var a in aCmd.Lhss) { + if (a is SimpleAssignLhs) { + var v = GPUVerifier.StripThreadIdentifier( + ((SimpleAssignLhs)a).AssignedVariable.Name); + if (!alreadySeenInThisAssignment.Contains(v)) { + if (result.ContainsKey(v)) { + result[v]++; + } + else { + result[v] = 1; + } + alreadySeenInThisAssignment.Add(v); + } + } + } + } + } + return result; + } + + + private void AddBarrierDivergenceCandidates(HashSet<Variable> LocalVars, Implementation Impl, IRegion region) + { + + if (!verifier.ContainsBarrierCall(region)) + { + 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('$')); + + verifier.AddCandidateInvariant(region, Expr.Eq( + // Int type used here, but it doesn't matter as we will print and then re-parse the program + new IdentifierExpr(Token.NoToken, new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, LoopPredicate + "$1", Microsoft.Boogie.Type.Int))), + new IdentifierExpr(Token.NoToken, new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, LoopPredicate + "$2", Microsoft.Boogie.Type.Int))) + ), "loop predicate equality"); + + Dictionary<string, int> assignmentCounts = GetAssignmentCounts(Impl); + + HashSet<string> alreadyConsidered = new HashSet<String>(); + + foreach (var v in LocalVars) + { + string lv = GPUVerifier.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( + GetModifiedVariables(region), lv)) + { + continue; + } + + AddPredicatedEqualityCandidateInvariant(region, LoopPredicate, new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, lv, Microsoft.Boogie.Type.Int))); + } + + if (CommandLineOptions.ArrayEqualities) + { + foreach (Variable v in verifier.KernelArrayInfo.getAllNonLocalArrays()) + { + if (!verifier.ArrayModelledAdversarially(v)) + { + AddEqualityCandidateInvariant(region, LoopPredicate, v); + } + } + } + } + } + + private static bool IsDisjunctionOfPredicates(Expr guard) { + if (!(guard is NAryExpr)) { + return false; + } + NAryExpr nary = (NAryExpr)guard; + if(nary.Args.Length != 2) { + return false; + } + if(!(nary.Fun is BinaryOperator)) { + return false; + } + BinaryOperator binOp = (BinaryOperator)nary.Fun; + if(binOp.Op != BinaryOperator.Opcode.Or) { + return false; + } + if(!(nary.Args[0] is IdentifierExpr && nary.Args[1] is IdentifierExpr)) { + return false; + } + return GPUVerifier.IsPredicate(GPUVerifier.StripThreadIdentifier( + ((IdentifierExpr)nary.Args[0]).Name)) && + GPUVerifier.IsPredicate(GPUVerifier.StripThreadIdentifier( + ((IdentifierExpr)nary.Args[1]).Name)); + } + + private void AddCandidateInvariants(IRegion region, HashSet<Variable> LocalVars, List<Expr> UserSuppliedInvariants, Implementation Impl) { + foreach (IRegion subregion in region.SubRegions()) { + foreach (InvariantGenerationRule r in invariantGenerationRules) { + r.GenerateCandidates(Impl, subregion); + } + + AddBarrierDivergenceCandidates(LocalVars, Impl, subregion); + + verifier.RaceInstrumenter.AddRaceCheckingCandidateInvariants(Impl, subregion); + + AddUserSuppliedInvariants(subregion, UserSuppliedInvariants, Impl); + } + } + + private void AddUserSuppliedInvariants(IRegion region, List<Expr> UserSuppliedInvariants, Implementation Impl) { + foreach (Expr e in UserSuppliedInvariants) { + /* + wc.Invariants.Add(new AssertCmd(wc.tok, e)); + bool OK = verifier.ProgramIsOK(Impl); + wc.Invariants.RemoveAt(wc.Invariants.Count - 1); + if (OK) + { + verifier.AddCandidateInvariant(wc, e, "user supplied"); + } + */ + verifier.AddCandidateInvariant(region, e, "user supplied"); + } + } + + internal static HashSet<Variable> GetModifiedVariables(IRegion region) { + HashSet<Variable> result = new HashSet<Variable>(); + + foreach (Cmd c in region.Cmds()) { + VariableSeq vars = new VariableSeq(); + c.AddAssignedVariables(vars); + foreach (Variable v in vars) { + result.Add(v); + } + } + + return result; + } + + } +} diff --git a/Source/GPUVerify/NullRaceInstrumenter.cs b/Source/GPUVerify/NullRaceInstrumenter.cs index 60c28b5b..fae08aa3 100644 --- a/Source/GPUVerify/NullRaceInstrumenter.cs +++ b/Source/GPUVerify/NullRaceInstrumenter.cs @@ -1,62 +1,67 @@ -using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Microsoft.Boogie;
-
-namespace GPUVerify
-{
- class NullRaceInstrumenter : IRaceInstrumenter
- {
-
- public void AddRaceCheckingCandidateInvariants(Implementation impl, IRegion region)
- {
-
- }
-
- public void AddKernelPrecondition()
- {
-
- }
-
- public void AddRaceCheckingInstrumentation()
- {
-
- }
-
- public Microsoft.Boogie.BigBlock MakeResetReadWriteSetStatements(Variable v, int Thread)
- {
- return new BigBlock(Token.NoToken, null, new CmdSeq(), null, null);
- }
-
- public void AddRaceCheckingCandidateRequires(Procedure Proc)
- {
-
- }
-
- public void AddRaceCheckingCandidateEnsures(Procedure Proc)
- {
-
- }
-
- public void AddRaceCheckingDeclarations()
- {
-
- }
-
- public void AddSourceLocationLoopInvariants(Implementation impl, IRegion region)
- {
-
- }
-
- public void AddStandardSourceVariablePreconditions()
- {
-
- }
-
- public void AddStandardSourceVariablePostconditions()
- {
-
- }
- }
-}
+using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Boogie; + +namespace GPUVerify +{ + class NullRaceInstrumenter : IRaceInstrumenter + { + + public void AddRaceCheckingCandidateInvariants(Implementation impl, IRegion region) + { + + } + + public void AddKernelPrecondition() + { + + } + + public void AddRaceCheckingInstrumentation() + { + + } + + public Microsoft.Boogie.BigBlock MakeResetReadWriteSetStatements(Variable v, int Thread) + { + return new BigBlock(Token.NoToken, null, new CmdSeq(), null, null); + } + + public void AddRaceCheckingCandidateRequires(Procedure Proc) + { + + } + + public void AddRaceCheckingCandidateEnsures(Procedure Proc) + { + + } + + public void AddRaceCheckingDeclarations() + { + + } + + public void AddSourceLocationLoopInvariants(Implementation impl, IRegion region) + { + + } + + public void DoHoudiniPointerAnalysis(Procedure Proc) + { + + } + + public void AddStandardSourceVariablePreconditions() + { + + } + + public void AddStandardSourceVariablePostconditions() + { + + } + } +} diff --git a/Source/GPUVerify/RaceInstrumenter.cs b/Source/GPUVerify/RaceInstrumenter.cs index 1e462635..c73b9b13 100644 --- a/Source/GPUVerify/RaceInstrumenter.cs +++ b/Source/GPUVerify/RaceInstrumenter.cs @@ -1,1146 +1,1131 @@ -using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Diagnostics;
-using System.Diagnostics.Contracts;
-using Microsoft.Boogie;
-using Microsoft.Basetypes;
-
-namespace GPUVerify {
- class RaceInstrumenter : IRaceInstrumenter {
- protected GPUVerifier verifier;
-
- private QKeyValue SourceLocationAttributes = null;
-
- private int CurrStmtNo = 1;
-
- private Dictionary<string, List<int>> ReadAccessSourceLocations = new Dictionary<string, List<int>>();
-
- private Dictionary<string, List<int>> WriteAccessSourceLocations = new Dictionary<string, List<int>>();
-
- public IKernelArrayInfo NonLocalStateToCheck;
-
- private Dictionary<string, Procedure> RaceCheckingProcedures = new Dictionary<string, Procedure>();
-
- public void setVerifier(GPUVerifier verifier) {
- this.verifier = verifier;
- NonLocalStateToCheck = new KernelArrayInfoLists();
- foreach (Variable v in verifier.KernelArrayInfo.getGlobalArrays()) {
- NonLocalStateToCheck.getGlobalArrays().Add(v);
- }
- foreach (Variable v in verifier.KernelArrayInfo.getGroupSharedArrays()) {
- NonLocalStateToCheck.getGroupSharedArrays().Add(v);
- }
- }
-
- private void AddNoReadOrWriteCandidateInvariants(IRegion region, Variable v) {
- // Reasoning: if READ_HAS_OCCURRED_v is not in the modifies set for the
- // loop then there is no point adding an invariant
- //
- // If READ_HAS_OCCURRED_v is in the modifies set, but the loop does not
- // contain a barrier, then it is almost certain that a read CAN be
- // pending at the loop head, so the invariant will not hold
- //
- // If there is a barrier in the loop body then READ_HAS_OCCURRED_v will
- // be in the modifies set, but there may not be a live read at the loop
- // head, so it is worth adding the loop invariant candidate.
- //
- // The same reasoning applies for WRITE
-
- if (verifier.ContainsBarrierCall(region)) {
- if (verifier.ContainsNamedVariable(
- LoopInvariantGenerator.GetModifiedVariables(region), GPUVerifier.MakeAccessHasOccurredVariableName(v.Name, "READ"))) {
- AddNoReadOrWriteCandidateInvariant(region, v, "READ");
- }
-
- if (verifier.ContainsNamedVariable(
- LoopInvariantGenerator.GetModifiedVariables(region), GPUVerifier.MakeAccessHasOccurredVariableName(v.Name, "WRITE"))) {
- AddNoReadOrWriteCandidateInvariant(region, v, "WRITE");
- }
- }
- }
-
- private void AddNoReadOrWriteCandidateRequires(Procedure Proc, Variable v) {
- AddNoReadOrWriteCandidateRequires(Proc, v, "READ", "1");
- AddNoReadOrWriteCandidateRequires(Proc, v, "WRITE", "1");
- }
-
- private void AddNoReadOrWriteCandidateEnsures(Procedure Proc, Variable v) {
- AddNoReadOrWriteCandidateEnsures(Proc, v, "READ", "1");
- AddNoReadOrWriteCandidateEnsures(Proc, v, "WRITE", "1");
- }
-
- private void AddNoReadOrWriteCandidateInvariant(IRegion region, Variable v, string ReadOrWrite) {
- Expr candidate = NoReadOrWriteExpr(v, ReadOrWrite, "1");
- verifier.AddCandidateInvariant(region, candidate, "no " + ReadOrWrite.ToLower());
- }
-
- public void AddRaceCheckingCandidateInvariants(Implementation impl, IRegion region) {
- List<Expr> offsetPredicatesRead = new List<Expr>();
- List<Expr> offsetPredicatesWrite = new List<Expr>();
- foreach (Variable v in NonLocalStateToCheck.getAllNonLocalArrays()) {
- AddNoReadOrWriteCandidateInvariants(region, v);
- AddReadOrWrittenOffsetIsThreadIdCandidateInvariants(impl, region, v, "READ");
- AddReadOrWrittenOffsetIsThreadIdCandidateInvariants(impl, region, v, "WRITE");
- offsetPredicatesRead = CollectOffsetPredicates(impl, region, v, "READ");
- offsetPredicatesWrite = CollectOffsetPredicates(impl, region, v, "WRITE");
- AddOffsetsSatisfyPredicatesCandidateInvariant(region, v, "READ", offsetPredicatesRead);
- AddOffsetsSatisfyPredicatesCandidateInvariant(region, v, "WRITE", offsetPredicatesWrite);
- AddOffsetsSatisfyPredicatesCandidateInvariant(region, v, "READ", new List<Expr>(offsetPredicatesRead.Zip(CollectSourceLocPredicates(region, v, "READ"), Expr.And)));
- AddOffsetsSatisfyPredicatesCandidateInvariant(region, v, "WRITE", new List<Expr>(offsetPredicatesWrite.Zip(CollectSourceLocPredicates(region, v, "WRITE"), Expr.And)));
- }
- }
-
- private void AddAccessRelatedCandidateInvariant(IRegion region, string accessKind, Expr candidateInvariantExpr, string procName, string tag) {
- Expr candidate = new VariableDualiser(1, verifier.uniformityAnalyser, procName).VisitExpr(candidateInvariantExpr.Clone() as Expr);
- verifier.AddCandidateInvariant(region, candidate, tag);
- }
-
- private bool DoesNotReferTo(Expr expr, string v) {
- FindReferencesToNamedVariableVisitor visitor = new FindReferencesToNamedVariableVisitor(v);
- visitor.VisitExpr(expr);
- return !visitor.found;
- }
-
- private List<Expr> CollectSourceLocPredicates(IRegion region, Variable v, string accessType) {
- var sourceVar = verifier.FindOrCreateSourceVariable(v.Name, accessType);
- var sourceExpr = new IdentifierExpr(Token.NoToken, sourceVar);
- var sourcePreds = new List<Expr>();
-
- foreach (Cmd c in region.Cmds()) {
- if (c is CallCmd) {
- CallCmd call = c as CallCmd;
- if (call.callee == "_LOG_" + accessType + "_" + v.Name) {
- sourcePreds.Add(Expr.Eq(sourceExpr, call.Ins[2]));
- }
- }
- }
-
- return sourcePreds;
- }
- private List<Expr> CollectOffsetPredicates(Implementation impl, IRegion region, Variable v, string accessType) {
- var offsetVar = new VariableDualiser(1, null, null).VisitVariable(GPUVerifier.MakeOffsetVariable(v.Name, accessType));
- var offsetExpr = new IdentifierExpr(Token.NoToken, offsetVar);
- var offsetPreds = new List<Expr>();
-
- foreach (var offset in GetOffsetsAccessed(region, v, accessType)) {
- bool isConstant;
- var def = verifier.varDefAnalyses[impl].SubstDefinitions(offset, impl.Name, out isConstant);
- if (def == null)
- continue;
-
- if (isConstant) {
- offsetPreds.Add(Expr.Eq(offsetExpr, def));
- }
- else {
- var sc = StrideConstraint.FromExpr(verifier, impl, def);
- var pred = sc.MaybeBuildPredicate(verifier, offsetExpr);
- if (pred != null)
- offsetPreds.Add(pred);
- }
- }
-
- return offsetPreds;
- }
-
- private void AddReadOrWrittenOffsetIsThreadIdCandidateInvariants(Implementation impl, IRegion region, Variable v, string accessType) {
- KeyValuePair<IdentifierExpr, Expr> iLessThanC = GetILessThanC(region.Guard());
- if (iLessThanC.Key != null) {
- foreach (Expr e in GetOffsetsAccessed(region, v, accessType)) {
- if (HasFormIPlusLocalIdTimesC(e, iLessThanC, impl)) {
- AddAccessedOffsetInRangeCTimesLocalIdToCTimesLocalIdPlusC(region, v, iLessThanC.Value, accessType);
- break;
- }
- }
-
- foreach (Expr e in GetOffsetsAccessed(region, v, accessType)) {
- if (HasFormIPlusGlobalIdTimesC(e, iLessThanC, impl)) {
- AddAccessedOffsetInRangeCTimesGlobalIdToCTimesGlobalIdPlusC(region, v, iLessThanC.Value, accessType);
- break;
- }
- }
-
- }
-
-
- }
-
- private bool HasFormIPlusLocalIdTimesC(Expr e, KeyValuePair<IdentifierExpr, Expr> iLessThanC, Implementation impl) {
- if (!(e is NAryExpr)) {
- return false;
- }
-
- NAryExpr nary = e as NAryExpr;
-
- if (!nary.Fun.FunctionName.Equals("BV32_ADD")) {
- return false;
- }
-
- return (SameIdentifierExpression(nary.Args[0], iLessThanC.Key) &&
- IsLocalIdTimesConstant(nary.Args[1], iLessThanC.Value, impl)) ||
- (SameIdentifierExpression(nary.Args[1], iLessThanC.Key) &&
- IsLocalIdTimesConstant(nary.Args[0], iLessThanC.Value, impl));
- }
-
- private bool IsLocalIdTimesConstant(Expr maybeLocalIdTimesConstant, Expr constant, Implementation impl) {
- if (!(maybeLocalIdTimesConstant is NAryExpr)) {
- return false;
- }
- NAryExpr nary = maybeLocalIdTimesConstant as NAryExpr;
- if (!nary.Fun.FunctionName.Equals("BV32_MUL")) {
- return false;
- }
-
- return
- (SameConstant(nary.Args[0], constant) && verifier.IsLocalId(nary.Args[1], 0, impl)) ||
- (SameConstant(nary.Args[1], constant) && verifier.IsLocalId(nary.Args[0], 0, impl));
- }
-
-
- private bool HasFormIPlusGlobalIdTimesC(Expr e, KeyValuePair<IdentifierExpr, Expr> iLessThanC, Implementation impl) {
- if (!(e is NAryExpr)) {
- return false;
- }
-
- NAryExpr nary = e as NAryExpr;
-
- if (!nary.Fun.FunctionName.Equals("BV32_ADD")) {
- return false;
- }
-
- return (SameIdentifierExpression(nary.Args[0], iLessThanC.Key) &&
- IsGlobalIdTimesConstant(nary.Args[1], iLessThanC.Value, impl)) ||
- (SameIdentifierExpression(nary.Args[1], iLessThanC.Key) &&
- IsGlobalIdTimesConstant(nary.Args[0], iLessThanC.Value, impl));
- }
-
- private bool IsGlobalIdTimesConstant(Expr maybeGlobalIdTimesConstant, Expr constant, Implementation impl) {
- if (!(maybeGlobalIdTimesConstant is NAryExpr)) {
- return false;
- }
- NAryExpr nary = maybeGlobalIdTimesConstant as NAryExpr;
- if (!nary.Fun.FunctionName.Equals("BV32_MUL")) {
- return false;
- }
-
- return
- (SameConstant(nary.Args[0], constant) && verifier.IsGlobalId(nary.Args[1], 0, impl)) ||
- (SameConstant(nary.Args[1], constant) && verifier.IsGlobalId(nary.Args[0], 0, impl));
- }
-
-
- private bool SameConstant(Expr expr, Expr constant) {
- if (constant is IdentifierExpr) {
- IdentifierExpr identifierExpr = constant as IdentifierExpr;
- Debug.Assert(identifierExpr.Decl is Constant);
- return expr is IdentifierExpr && (expr as IdentifierExpr).Decl is Constant && (expr as IdentifierExpr).Decl.Name.Equals(identifierExpr.Decl.Name);
- }
- else {
- Debug.Assert(constant is LiteralExpr);
- LiteralExpr literalExpr = constant as LiteralExpr;
- if (!(expr is LiteralExpr)) {
- return false;
- }
- if (!(literalExpr.Val is BvConst) || !((expr as LiteralExpr).Val is BvConst)) {
- return false;
- }
-
- return (literalExpr.Val as BvConst).Value.ToInt == ((expr as LiteralExpr).Val as BvConst).Value.ToInt;
- }
- }
-
- private bool SameIdentifierExpression(Expr expr, IdentifierExpr identifierExpr) {
- if (!(expr is IdentifierExpr)) {
- return false;
- }
- return (expr as IdentifierExpr).Decl.Name.Equals(identifierExpr.Name);
- }
-
- private KeyValuePair<IdentifierExpr, Expr> GetILessThanC(Expr expr) {
-
- if (expr is NAryExpr && (expr as NAryExpr).Fun.FunctionName.Equals("bv32_to_bool")) {
- expr = (expr as NAryExpr).Args[0];
- }
-
- if (!(expr is NAryExpr)) {
- return new KeyValuePair<IdentifierExpr, Expr>(null, null);
- }
-
- NAryExpr nary = expr as NAryExpr;
-
- if (!(nary.Fun.FunctionName.Equals("BV32_C_LT") || nary.Fun.FunctionName.Equals("BV32_LT"))) {
- return new KeyValuePair<IdentifierExpr, Expr>(null, null);
- }
-
- if (!(nary.Args[0] is IdentifierExpr)) {
- return new KeyValuePair<IdentifierExpr, Expr>(null, null);
- }
-
- if (!IsConstant(nary.Args[1])) {
- return new KeyValuePair<IdentifierExpr, Expr>(null, null);
- }
-
- return new KeyValuePair<IdentifierExpr, Expr>(nary.Args[0] as IdentifierExpr, nary.Args[1]);
-
- }
-
- private static bool IsConstant(Expr e) {
- return ((e is IdentifierExpr && (e as IdentifierExpr).Decl is Constant) || e is LiteralExpr);
- }
-
- private void AddReadOrWrittenOffsetIsThreadIdCandidateRequires(Procedure Proc, Variable v) {
- AddAccessedOffsetIsThreadLocalIdCandidateRequires(Proc, v, "WRITE", 1);
- AddAccessedOffsetIsThreadLocalIdCandidateRequires(Proc, v, "READ", 1);
- }
-
- private void AddReadOrWrittenOffsetIsThreadIdCandidateEnsures(Procedure Proc, Variable v) {
- AddAccessedOffsetIsThreadLocalIdCandidateEnsures(Proc, v, "WRITE", 1);
- AddAccessedOffsetIsThreadLocalIdCandidateEnsures(Proc, v, "READ", 1);
- }
-
- public void AddKernelPrecondition() {
- foreach (Variable v in NonLocalStateToCheck.getAllNonLocalArrays()) {
- AddRequiresNoPendingAccess(v);
- AddRequiresSourceAccessZero(v);
- }
- }
-
- public void AddRaceCheckingInstrumentation() {
-
- foreach (Declaration d in verifier.Program.TopLevelDeclarations) {
- if (d is Implementation) {
- AddRaceCheckCalls(d as Implementation);
- }
- }
-
- }
-
- private void AddRaceCheckingDecsAndProcsForVar(Variable v) {
- AddLogRaceDeclarations(v, "READ");
- AddLogRaceDeclarations(v, "WRITE");
- AddLogAccessProcedure(v, "READ");
- AddCheckAccessProcedure(v, "READ");
- AddLogAccessProcedure(v, "WRITE");
- AddCheckAccessProcedure(v, "WRITE");
- }
-
- private StmtList AddRaceCheckCalls(StmtList stmtList) {
- Contract.Requires(stmtList != null);
-
- StmtList result = new StmtList(new List<BigBlock>(), stmtList.EndCurly);
-
- foreach (BigBlock bodyBlock in stmtList.BigBlocks) {
- result.BigBlocks.Add(AddRaceCheckCalls(bodyBlock));
- }
- return result;
- }
-
- private Block AddRaceCheckCalls(Block b) {
- b.Cmds = AddRaceCheckCalls(b.Cmds);
- return b;
- }
-
- private void AddRaceCheckCalls(Implementation impl) {
- if (CommandLineOptions.Unstructured)
- impl.Blocks = impl.Blocks.Select(AddRaceCheckCalls).ToList();
- else
- impl.StructuredStmts = AddRaceCheckCalls(impl.StructuredStmts);
- }
-
- private CmdSeq AddRaceCheckCalls(CmdSeq cs) {
- var result = new CmdSeq();
- 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;
- }
- }
-
- if (c is AssignCmd) {
- AssignCmd assign = c as AssignCmd;
-
- ReadCollector rc = new ReadCollector(NonLocalStateToCheck);
- foreach (var rhs in assign.Rhss)
- rc.Visit(rhs);
- if (rc.accesses.Count > 0) {
- foreach (AccessRecord ar in rc.accesses) {
- AddLogAndCheckCalls(result, ar, "READ");
- }
- }
-
- foreach (var lhs in assign.Lhss) {
- WriteCollector wc = new WriteCollector(NonLocalStateToCheck);
- wc.Visit(lhs);
- if (wc.GetAccess() != null) {
- AccessRecord ar = wc.GetAccess();
- AddLogAndCheckCalls(result, ar, "WRITE");
- }
- }
- }
- }
- return result;
- }
-
- private void AddLogAndCheckCalls(CmdSeq result, AccessRecord ar, string Access) {
- ExprSeq inParamsLog = new ExprSeq();
- ExprSeq inParamsChk = new ExprSeq();
- inParamsChk.Add(ar.Index);
- inParamsLog.Add(ar.Index);
- inParamsLog.Add(new LiteralExpr(Token.NoToken, BigNum.FromInt(CurrStmtNo), 32));
-
- Procedure logProcedure = GetRaceCheckingProcedure(Token.NoToken, "_LOG_" + Access + "_" + ar.v.Name);
- Procedure checkProcedure = GetRaceCheckingProcedure(Token.NoToken, "_CHECK_" + Access + "_" + ar.v.Name);
-
- verifier.OnlyThread1.Add(logProcedure.Name);
- verifier.OnlyThread2.Add(checkProcedure.Name);
-
- CallCmd logAccessCallCmd = new CallCmd(Token.NoToken, logProcedure.Name, inParamsLog, new IdentifierExprSeq());
- logAccessCallCmd.Proc = logProcedure;
-
- CallCmd checkAccessCallCmd = new CallCmd(Token.NoToken, checkProcedure.Name, inParamsChk, new IdentifierExprSeq());
- checkAccessCallCmd.Proc = checkProcedure;
- checkAccessCallCmd.Attributes = SourceLocationAttributes;
-
- result.Add(logAccessCallCmd);
- result.Add(checkAccessCallCmd);
-
- string fname = QKeyValue.FindStringAttribute(SourceLocationAttributes, "fname");
-
- string Key = ar.v.Name;
- if (Access == "WRITE")
- {
- if (!WriteAccessSourceLocations.ContainsKey(Key))
- {
- WriteAccessSourceLocations.Add(Key, new List<int>());
- }
- WriteAccessSourceLocations[Key].Add(CurrStmtNo);
- }
- else if (Access == "READ")
- {
- if (!ReadAccessSourceLocations.ContainsKey(Key))
- {
- ReadAccessSourceLocations.Add(Key, new List<int>());
- }
- ReadAccessSourceLocations[Key].Add(CurrStmtNo);
- }
-
- if (fname != null)
- {
- writeSourceLocToFile(SourceLocationAttributes, Path.GetFileNameWithoutExtension(CommandLineOptions.inputFiles[0]) + ".loc");
- }
- else
- {
- Debug.Assert(false, "RaceInstrumenter.AddLogAndCheckCalls: Could not write sourceloc to file as filename could not be found.\n");
- }
- CurrStmtNo++;
- }
-
- private BigBlock AddRaceCheckCalls(BigBlock bb) {
- BigBlock result = new BigBlock(bb.tok, bb.LabelName, AddRaceCheckCalls(bb.simpleCmds), null, bb.tc);
-
- if (bb.ec is WhileCmd) {
- WhileCmd WhileCommand = bb.ec as WhileCmd;
- result.ec = new WhileCmd(WhileCommand.tok, WhileCommand.Guard,
- WhileCommand.Invariants, AddRaceCheckCalls(WhileCommand.Body));
- }
- else if (bb.ec is IfCmd) {
- IfCmd IfCommand = bb.ec as IfCmd;
- Debug.Assert(IfCommand.elseIf == null); // We don't handle else if yet
- result.ec = new IfCmd(IfCommand.tok, IfCommand.Guard, AddRaceCheckCalls(IfCommand.thn), IfCommand.elseIf, IfCommand.elseBlock != null ? AddRaceCheckCalls(IfCommand.elseBlock) : null);
- }
- else if (bb.ec is BreakCmd) {
- result.ec = bb.ec;
- }
- else {
- Debug.Assert(bb.ec == null);
- }
-
- return result;
- }
-
- private Procedure GetRaceCheckingProcedure(IToken tok, string name) {
- if (RaceCheckingProcedures.ContainsKey(name)) {
- return RaceCheckingProcedures[name];
- }
- Procedure newProcedure = new Procedure(tok, name, new TypeVariableSeq(), new VariableSeq(), new VariableSeq(), new RequiresSeq(), new IdentifierExprSeq(), new EnsuresSeq());
- RaceCheckingProcedures[name] = newProcedure;
- return newProcedure;
- }
-
-
- public BigBlock MakeResetReadWriteSetStatements(Variable v, int Thread) {
- BigBlock result = new BigBlock(Token.NoToken, null, new CmdSeq(), null, null);
- if (Thread == 2) {
- return result;
- }
-
- Expr ResetReadAssumeGuard = Expr.Not(new IdentifierExpr(Token.NoToken,
- new VariableDualiser(1, null, null).VisitVariable(GPUVerifier.MakeAccessHasOccurredVariable(v.Name, "READ"))));
- Expr ResetWriteAssumeGuard = Expr.Not(new IdentifierExpr(Token.NoToken,
- new VariableDualiser(1, null, null).VisitVariable(GPUVerifier.MakeAccessHasOccurredVariable(v.Name, "WRITE"))));
-
- if (verifier.KernelArrayInfo.getGlobalArrays().Contains(v)) {
- ResetReadAssumeGuard = Expr.Imp(GPUVerifier.ThreadsInSameGroup(), ResetReadAssumeGuard);
- ResetWriteAssumeGuard = Expr.Imp(GPUVerifier.ThreadsInSameGroup(), ResetWriteAssumeGuard);
- }
-
- result.simpleCmds.Add(new AssumeCmd(Token.NoToken, ResetReadAssumeGuard));
- result.simpleCmds.Add(new AssumeCmd(Token.NoToken, ResetWriteAssumeGuard));
- return result;
- }
-
- protected Procedure MakeLogAccessProcedureHeader(Variable v, string ReadOrWrite) {
- VariableSeq inParams = new VariableSeq();
-
- Variable PredicateParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_P", Microsoft.Boogie.Type.Bool));
-
- Debug.Assert(v.TypedIdent.Type is MapType);
- MapType mt = v.TypedIdent.Type as MapType;
- Debug.Assert(mt.Arguments.Length == 1);
- Variable OffsetParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_offset", mt.Arguments[0]));
- Variable SourceParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_source", mt.Arguments[0]));
- Debug.Assert(!(mt.Result is MapType));
-
- inParams.Add(new VariableDualiser(1, null, null).VisitVariable(PredicateParameter.Clone() as Variable));
- inParams.Add(new VariableDualiser(1, null, null).VisitVariable(OffsetParameter.Clone() as Variable));
- inParams.Add(new VariableDualiser(1, null, null).VisitVariable(SourceParameter.Clone() as Variable));
-
- string LogProcedureName = "_LOG_" + ReadOrWrite + "_" + v.Name;
-
- Procedure result = GetRaceCheckingProcedure(v.tok, LogProcedureName);
-
- result.InParams = inParams;
-
- result.AddAttribute("inline", new object[] { new LiteralExpr(v.tok, BigNum.FromInt(1)) });
-
- return result;
- }
-
- protected Procedure MakeCheckAccessProcedureHeader(Variable v, string ReadOrWrite) {
- VariableSeq inParams = new VariableSeq();
-
- Variable PredicateParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_P", Microsoft.Boogie.Type.Bool));
-
- Debug.Assert(v.TypedIdent.Type is MapType);
- MapType mt = v.TypedIdent.Type as MapType;
- Debug.Assert(mt.Arguments.Length == 1);
- Variable OffsetParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_offset", mt.Arguments[0]));
- Debug.Assert(!(mt.Result is MapType));
-
- inParams.Add(new VariableDualiser(2, null, null).VisitVariable(PredicateParameter.Clone() as Variable));
- inParams.Add(new VariableDualiser(2, null, null).VisitVariable(OffsetParameter.Clone() as Variable));
-
- string CheckProcedureName = "_CHECK_" + ReadOrWrite + "_" + v.Name;
-
- Procedure result = GetRaceCheckingProcedure(v.tok, CheckProcedureName);
-
- result.InParams = inParams;
-
- result.AddAttribute("inline", new object[] { new LiteralExpr(v.tok, BigNum.FromInt(1)) });
-
- return result;
- }
-
- public void AddRaceCheckingCandidateRequires(Procedure Proc) {
- foreach (Variable v in NonLocalStateToCheck.getAllNonLocalArrays()) {
- AddNoReadOrWriteCandidateRequires(Proc, v);
- AddReadOrWrittenOffsetIsThreadIdCandidateRequires(Proc, v);
- }
-
- DoHoudiniPointerAnalysis(Proc);
-
- }
-
- private void DoHoudiniPointerAnalysis(Procedure Proc) {
- HashSet<string> alreadyConsidered = new HashSet<string>();
-
- foreach (Variable v in Proc.InParams) {
- string strippedVarName = GPUVerifier.StripThreadIdentifier(v.Name);
- if (alreadyConsidered.Contains(strippedVarName)) {
- continue;
- }
- alreadyConsidered.Add(strippedVarName);
- if (v.TypedIdent.Type is CtorType) {
- CtorType ct = v.TypedIdent.Type as CtorType;
- if (ct.Decl.Name.Equals("ptr")) {
- foreach (var arrayCollection in new ICollection<Variable>[] {
- verifier.KernelArrayInfo.getGlobalArrays(), verifier.KernelArrayInfo.getGroupSharedArrays(),
- verifier.KernelArrayInfo.getPrivateArrays() }) {
- if (arrayCollection.Count == 0) {
- continue;
- }
-
- // This will need to be adapted to work with uniformity analysis
- foreach (string thread in new string[] { "1", "2" }) {
- Expr DisjunctionOverPointerSet = null;
- foreach (var array in arrayCollection) {
- Expr PointerSetDisjunct = Expr.Eq(MakePtrBaseExpr(v, strippedVarName, thread), MakeArrayIdExpr(array));
- DisjunctionOverPointerSet = (DisjunctionOverPointerSet == null ? PointerSetDisjunct : Expr.Or(DisjunctionOverPointerSet, PointerSetDisjunct));
- verifier.AddCandidateRequires(Proc,
- Expr.Imp(new IdentifierExpr(Token.NoToken, "_P$" + thread, Microsoft.Boogie.Type.Bool),
- Expr.Neq(MakePtrBaseExpr(v, strippedVarName, thread), MakeArrayIdExpr(array))));
- }
- Debug.Assert(DisjunctionOverPointerSet != null);
- verifier.AddCandidateRequires(Proc,
- Expr.Imp(new IdentifierExpr(Token.NoToken, "_P$" + thread, Microsoft.Boogie.Type.Bool),
- DisjunctionOverPointerSet));
- verifier.AddCandidateRequires(Proc,
- Expr.Imp(new IdentifierExpr(Token.NoToken, "_P$" + thread, Microsoft.Boogie.Type.Bool),
- Expr.Eq(MakePtrOffsetExpr(v, strippedVarName, thread), GPUVerifier.ZeroBV())));
- }
- }
- }
- }
- }
- }
-
- private static IdentifierExpr MakeArrayIdExpr(Variable array) {
- return new IdentifierExpr(Token.NoToken, "$arrayId" + array.Name, null);
- }
-
- private static NAryExpr MakePtrBaseExpr(Variable v, string strippedVarName, string thread) {
- return new NAryExpr(Token.NoToken, new FunctionCall(new IdentifierExpr(Token.NoToken, "base#MKPTR", v.TypedIdent.Type)),
- new ExprSeq(new Expr[] { new IdentifierExpr(Token.NoToken, strippedVarName + "$" + thread, v.TypedIdent.Type) }));
- }
-
- private static NAryExpr MakePtrOffsetExpr(Variable v, string strippedVarName, string thread) {
- return new NAryExpr(Token.NoToken, new FunctionCall(new IdentifierExpr(Token.NoToken, "offset#MKPTR", v.TypedIdent.Type)),
- new ExprSeq(new Expr[] { new IdentifierExpr(Token.NoToken, strippedVarName + "$" + thread, v.TypedIdent.Type) }));
- }
-
- public void AddRaceCheckingCandidateEnsures(Procedure Proc) {
- foreach (Variable v in NonLocalStateToCheck.getAllNonLocalArrays()) {
- AddNoReadOrWriteCandidateEnsures(Proc, v);
- AddReadOrWrittenOffsetIsThreadIdCandidateEnsures(Proc, v);
- }
- }
-
- private void AddNoReadOrWriteCandidateRequires(Procedure Proc, Variable v, string ReadOrWrite, string OneOrTwo) {
- verifier.AddCandidateRequires(Proc, NoReadOrWriteExpr(v, ReadOrWrite, OneOrTwo));
- }
-
- private void AddNoReadOrWriteCandidateEnsures(Procedure Proc, Variable v, string ReadOrWrite, string OneOrTwo) {
- verifier.AddCandidateEnsures(Proc, NoReadOrWriteExpr(v, ReadOrWrite, OneOrTwo));
- }
-
- private HashSet<Expr> GetOffsetsAccessed(IRegion region, Variable v, string AccessType) {
- HashSet<Expr> result = new HashSet<Expr>();
-
- foreach (Cmd c in region.Cmds()) {
- if (c is CallCmd) {
- CallCmd call = c as CallCmd;
-
- if (call.callee == "_LOG_" + AccessType + "_" + v.Name) {
- // Ins[0] is thread 1's predicate,
- // Ins[1] is the offset to be read
- // If Ins[1] has the form BV32_ADD(offset#construct...(P), offset),
- // we are looking for the second parameter to this BV32_ADD
- Expr offset = call.Ins[1];
- if (offset is NAryExpr) {
- var nExpr = (NAryExpr)offset;
- if (nExpr.Fun.FunctionName == "BV32_ADD" &&
- nExpr.Args[0] is NAryExpr) {
- var n0Expr = (NAryExpr)nExpr.Args[0];
- if (n0Expr.Fun.FunctionName.StartsWith("offset#"))
- offset = nExpr.Args[1];
- }
- }
- result.Add(offset);
- }
-
- }
-
- }
-
- return result;
- }
-
- public void AddRaceCheckingDeclarations() {
- foreach (Variable v in NonLocalStateToCheck.getAllNonLocalArrays()) {
- AddRaceCheckingDecsAndProcsForVar(v);
- }
- }
-
- protected void AddLogAccessProcedure(Variable v, string Access) {
- Procedure LogAccessProcedure = MakeLogAccessProcedureHeader(v, Access);
-
- Variable AccessHasOccurredVariable = GPUVerifier.MakeAccessHasOccurredVariable(v.Name, Access);
- Variable AccessOffsetXVariable = GPUVerifier.MakeOffsetVariable(v.Name, Access);
- Variable AccessSourceVariable = GPUVerifier.MakeSourceVariable(v.Name, Access);
-
- Variable PredicateParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_P", Microsoft.Boogie.Type.Bool));
-
- Debug.Assert(v.TypedIdent.Type is MapType);
- MapType mt = v.TypedIdent.Type as MapType;
- Debug.Assert(mt.Arguments.Length == 1);
- Variable OffsetParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_offset", mt.Arguments[0]));
- Variable SourceParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_source", mt.Arguments[0]));
- Debug.Assert(!(mt.Result is MapType));
-
- VariableSeq locals = new VariableSeq();
- Variable TrackVariable = new LocalVariable(v.tok, new TypedIdent(v.tok, "track", Microsoft.Boogie.Type.Bool));
- locals.Add(TrackVariable);
-
- List<BigBlock> bigblocks = new List<BigBlock>();
-
- CmdSeq simpleCmds = new CmdSeq();
-
- simpleCmds.Add(new HavocCmd(v.tok, new IdentifierExprSeq(new IdentifierExpr[] { new IdentifierExpr(v.tok, TrackVariable) })));
-
- simpleCmds.Add(MakeConditionalAssignment(VariableForThread(1, AccessHasOccurredVariable),
- Expr.And(new IdentifierExpr(v.tok, VariableForThread(1, PredicateParameter)), new IdentifierExpr(v.tok, TrackVariable)), Expr.True));
- simpleCmds.Add(MakeConditionalAssignment(VariableForThread(1, AccessOffsetXVariable),
- Expr.And(new IdentifierExpr(v.tok, VariableForThread(1, PredicateParameter)), new IdentifierExpr(v.tok, TrackVariable)),
- new IdentifierExpr(v.tok, VariableForThread(1, OffsetParameter))));
- simpleCmds.Add(MakeConditionalAssignment(VariableForThread(1, AccessSourceVariable),
- Expr.And(new IdentifierExpr(v.tok, VariableForThread(1, PredicateParameter)), new IdentifierExpr(v.tok, TrackVariable)),
- new IdentifierExpr(v.tok, VariableForThread(1, SourceParameter))));
-
- bigblocks.Add(new BigBlock(v.tok, "_LOG_" + Access + "", simpleCmds, null, null));
-
- LogAccessProcedure.Modifies.Add(new IdentifierExpr(Token.NoToken, VariableForThread(1, AccessHasOccurredVariable)));
- LogAccessProcedure.Modifies.Add(new IdentifierExpr(Token.NoToken, VariableForThread(1, AccessOffsetXVariable)));
-
- Implementation LogAccessImplementation = new Implementation(v.tok, "_LOG_" + Access + "_" + v.Name, new TypeVariableSeq(), LogAccessProcedure.InParams, new VariableSeq(), locals, new StmtList(bigblocks, v.tok));
- LogAccessImplementation.AddAttribute("inline", new object[] { new LiteralExpr(v.tok, BigNum.FromInt(1)) });
-
- LogAccessImplementation.Proc = LogAccessProcedure;
-
- verifier.Program.TopLevelDeclarations.Add(LogAccessProcedure);
- verifier.Program.TopLevelDeclarations.Add(LogAccessImplementation);
- }
-
-
- protected void AddCheckAccessProcedure(Variable v, string Access) {
- Procedure CheckAccessProcedure = MakeCheckAccessProcedureHeader(v, Access);
-
- Variable AccessHasOccurredVariable = GPUVerifier.MakeAccessHasOccurredVariable(v.Name, Access);
- Variable AccessOffsetXVariable = GPUVerifier.MakeOffsetVariable(v.Name, Access);
-
- Variable PredicateParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_P", Microsoft.Boogie.Type.Bool));
-
- Debug.Assert(v.TypedIdent.Type is MapType);
- MapType mt = v.TypedIdent.Type as MapType;
- Debug.Assert(mt.Arguments.Length == 1);
- Variable OffsetParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_offset", mt.Arguments[0]));
- Debug.Assert(!(mt.Result is MapType));
-
- if (Access.Equals("READ")) {
- // Check read by thread 2 does not conflict with write by thread 1
- Variable WriteHasOccurredVariable = GPUVerifier.MakeAccessHasOccurredVariable(v.Name, "WRITE");
- Variable WriteOffsetVariable = GPUVerifier.MakeOffsetVariable(v.Name, "WRITE");
- Expr WriteReadGuard = new IdentifierExpr(Token.NoToken, VariableForThread(2, PredicateParameter));
- WriteReadGuard = Expr.And(WriteReadGuard, new IdentifierExpr(Token.NoToken, VariableForThread(1, WriteHasOccurredVariable)));
- WriteReadGuard = Expr.And(WriteReadGuard, Expr.Eq(new IdentifierExpr(Token.NoToken, VariableForThread(1, WriteOffsetVariable)),
- new IdentifierExpr(Token.NoToken, VariableForThread(2, OffsetParameter))));
-
- if (!verifier.ArrayModelledAdversarially(v)) {
- WriteReadGuard = Expr.And(WriteReadGuard, Expr.Neq(
- new VariableDualiser(1, null, null).VisitExpr(
- MakeAccessedIndex(v, new IdentifierExpr(Token.NoToken, WriteOffsetVariable), "WRITE")),
- new VariableDualiser(2, null, null).VisitExpr(
- MakeAccessedIndex(v, new IdentifierExpr(Token.NoToken, OffsetParameter), "READ"))
- ));
- }
-
- if (verifier.KernelArrayInfo.getGroupSharedArrays().Contains(v)) {
- WriteReadGuard = Expr.And(WriteReadGuard, GPUVerifier.ThreadsInSameGroup());
- }
-
- WriteReadGuard = Expr.Not(WriteReadGuard);
-
- Requires NoWriteReadRaceRequires = new Requires(false, WriteReadGuard);
- QKeyValue kv = new QKeyValue(Token.NoToken, "write_read", new List<object>(), null);
- NoWriteReadRaceRequires.Attributes = new QKeyValue(Token.NoToken, "race", new List<object>(), kv);
- CheckAccessProcedure.Requires.Add(NoWriteReadRaceRequires);
- }
- else {
- Debug.Assert(Access.Equals("WRITE"));
-
- // Check write by thread 2 does not conflict with write by thread 1
- Variable WriteHasOccurredVariable = GPUVerifier.MakeAccessHasOccurredVariable(v.Name, "WRITE");
- Variable WriteOffsetVariable = GPUVerifier.MakeOffsetVariable(v.Name, "WRITE");
-
- Expr WriteWriteGuard = new IdentifierExpr(Token.NoToken, VariableForThread(2, PredicateParameter));
- WriteWriteGuard = Expr.And(WriteWriteGuard, new IdentifierExpr(Token.NoToken, VariableForThread(1, WriteHasOccurredVariable)));
- WriteWriteGuard = Expr.And(WriteWriteGuard, Expr.Eq(new IdentifierExpr(Token.NoToken, VariableForThread(1, WriteOffsetVariable)),
- new IdentifierExpr(Token.NoToken, VariableForThread(2, OffsetParameter))));
- if (!verifier.ArrayModelledAdversarially(v)) {
- WriteWriteGuard = Expr.And(WriteWriteGuard, Expr.Neq(
- new VariableDualiser(1, null, null).VisitExpr(
- MakeAccessedIndex(v, new IdentifierExpr(Token.NoToken, WriteOffsetVariable), "WRITE")),
- new VariableDualiser(2, null, null).VisitExpr(
- MakeAccessedIndex(v, new IdentifierExpr(Token.NoToken, OffsetParameter), "WRITE"))
- ));
- }
-
- if (verifier.KernelArrayInfo.getGroupSharedArrays().Contains(v)) {
- WriteWriteGuard = Expr.And(WriteWriteGuard, GPUVerifier.ThreadsInSameGroup());
- }
-
- WriteWriteGuard = Expr.Not(WriteWriteGuard);
- Requires NoWriteWriteRaceRequires = new Requires(false, WriteWriteGuard);
- QKeyValue kv = new QKeyValue(Token.NoToken, "write_write", new List<object>(), null);
- NoWriteWriteRaceRequires.Attributes = new QKeyValue(Token.NoToken, "race", new List<object>(), kv);
- CheckAccessProcedure.Requires.Add(NoWriteWriteRaceRequires);
-
- // Check write by thread 2 does not conflict with read by thread 1
- Variable ReadHasOccurredVariable = GPUVerifier.MakeAccessHasOccurredVariable(v.Name, "READ");
- Variable ReadOffsetVariable = GPUVerifier.MakeOffsetVariable(v.Name, "READ");
-
- Expr ReadWriteGuard = new IdentifierExpr(Token.NoToken, VariableForThread(2, PredicateParameter));
- ReadWriteGuard = Expr.And(ReadWriteGuard, new IdentifierExpr(Token.NoToken, VariableForThread(1, ReadHasOccurredVariable)));
- ReadWriteGuard = Expr.And(ReadWriteGuard, Expr.Eq(new IdentifierExpr(Token.NoToken, VariableForThread(1, ReadOffsetVariable)),
- new IdentifierExpr(Token.NoToken, VariableForThread(2, OffsetParameter))));
- if (!verifier.ArrayModelledAdversarially(v)) {
- ReadWriteGuard = Expr.And(ReadWriteGuard, Expr.Neq(
- new VariableDualiser(1, null, null).VisitExpr(
- MakeAccessedIndex(v, new IdentifierExpr(Token.NoToken, ReadOffsetVariable), "WRITE")),
- new VariableDualiser(2, null, null).VisitExpr(
- MakeAccessedIndex(v, new IdentifierExpr(Token.NoToken, OffsetParameter), "READ"))
- ));
- }
-
- if (verifier.KernelArrayInfo.getGroupSharedArrays().Contains(v)) {
- ReadWriteGuard = Expr.And(ReadWriteGuard, GPUVerifier.ThreadsInSameGroup());
- }
-
- ReadWriteGuard = Expr.Not(ReadWriteGuard);
- Requires NoReadWriteRaceRequires = new Requires(false, ReadWriteGuard);
- kv = new QKeyValue(Token.NoToken, "read_write", new List<object>(), null);
- NoReadWriteRaceRequires.Attributes = new QKeyValue(Token.NoToken, "race", new List<object>(), kv);
- CheckAccessProcedure.Requires.Add(NoReadWriteRaceRequires);
-
- }
- verifier.Program.TopLevelDeclarations.Add(CheckAccessProcedure);
- }
-
-
-
- private Variable VariableForThread(int thread, Variable v) {
- return new VariableDualiser(thread, null, null).VisitVariable(v.Clone() as Variable);
- }
-
- protected void AddLogRaceDeclarations(Variable v, String ReadOrWrite) {
- verifier.FindOrCreateAccessHasOccurredVariable(v.Name, ReadOrWrite);
-
- Debug.Assert(v.TypedIdent.Type is MapType);
- MapType mt = v.TypedIdent.Type as MapType;
- Debug.Assert(mt.Arguments.Length == 1);
-
- verifier.FindOrCreateOffsetVariable(v.Name, ReadOrWrite);
- verifier.FindOrCreateSourceVariable(v.Name, ReadOrWrite);
-
- }
-
-
- private static AssignCmd MakeConditionalAssignment(Variable lhs, Expr condition, Expr rhs) {
- List<AssignLhs> lhss = new List<AssignLhs>();
- List<Expr> rhss = new List<Expr>();
- lhss.Add(new SimpleAssignLhs(lhs.tok, new IdentifierExpr(lhs.tok, lhs)));
- rhss.Add(new NAryExpr(rhs.tok, new IfThenElse(rhs.tok), new ExprSeq(new Expr[] { condition, rhs, new IdentifierExpr(lhs.tok, lhs) })));
- return new AssignCmd(lhs.tok, lhss, rhss);
- }
-
- private Expr MakeAccessedIndex(Variable v, Expr offsetExpr, string AccessType) {
- Expr result = new IdentifierExpr(v.tok, v.Clone() as Variable);
- Debug.Assert(v.TypedIdent.Type is MapType);
- MapType mt = v.TypedIdent.Type as MapType;
- Debug.Assert(mt.Arguments.Length == 1);
-
- result = Expr.Select(result,
- new Expr[] { offsetExpr });
- Debug.Assert(!(mt.Result is MapType));
- return result;
- }
-
- protected void AddRequiresNoPendingAccess(Variable v) {
- IdentifierExpr ReadAccessOccurred1 = new IdentifierExpr(v.tok, new VariableDualiser(1, null, null).VisitVariable(GPUVerifier.MakeAccessHasOccurredVariable(v.Name, "READ")));
- IdentifierExpr WriteAccessOccurred1 = new IdentifierExpr(v.tok, new VariableDualiser(1, null, null).VisitVariable(GPUVerifier.MakeAccessHasOccurredVariable(v.Name, "WRITE")));
-
- verifier.KernelProcedure.Requires.Add(new Requires(false, Expr.And(Expr.Not(ReadAccessOccurred1), Expr.Not(WriteAccessOccurred1))));
- }
-
- private void AddRequiresSourceAccessZero(Variable v)
- {
- verifier.KernelProcedure.Requires.Add(new Requires(false, Expr.Eq(new IdentifierExpr(Token.NoToken, verifier.FindOrCreateSourceVariable(v.Name, "READ")),
- GPUVerifier.ZeroBV())));
- verifier.KernelProcedure.Requires.Add(new Requires(false, Expr.Eq(new IdentifierExpr(Token.NoToken, verifier.FindOrCreateSourceVariable(v.Name, "WRITE")),
- GPUVerifier.ZeroBV())));
- }
-
- public void AddSourceLocationLoopInvariants(Implementation impl, IRegion region)
- {
- foreach (string key in WriteAccessSourceLocations.Keys.Union(ReadAccessSourceLocations.Keys))
- {
- region.AddInvariant(BuildNoAccessInvariant(key, "WRITE"));
- region.AddInvariant(BuildNoAccessInvariant(key, "READ"));
-
- if (WriteAccessSourceLocations.ContainsKey(key))
- {
- region.AddInvariant(BuildPossibleSourceLocationsInvariant(key, "WRITE"));
- }
- else
- {
- region.AddInvariant(BuildAccessOccurredFalseInvariant(key, "WRITE"));
- }
-
- if (ReadAccessSourceLocations.ContainsKey(key))
- {
- region.AddInvariant(BuildPossibleSourceLocationsInvariant(key, "READ"));
- }
- else
- {
- region.AddInvariant(BuildAccessOccurredFalseInvariant(key, "READ"));
- }
- }
- }
-
- public void AddStandardSourceVariablePreconditions()
- {
- foreach (Declaration D in verifier.Program.TopLevelDeclarations.ToList())
- {
- if (!(D is Procedure))
- {
- continue;
- }
- Procedure Proc = D as Procedure;
- foreach (string key in WriteAccessSourceLocations.Keys.Union(ReadAccessSourceLocations.Keys))
- {
- Proc.Requires.Add(new Requires(false, BuildNoAccessExpr(key, "WRITE")));
- Proc.Requires.Add(new Requires(false, BuildNoAccessExpr(key, "READ")));
-
- if (WriteAccessSourceLocations.ContainsKey(key))
- {
- Proc.Requires.Add(new Requires(false, BuildPossibleSourceLocationsExpr(key, "WRITE")));
- }
- else
- {
- Proc.Requires.Add(new Requires(false, BuildAccessOccurredFalseExpr(key, "WRITE")));
- }
-
- if (ReadAccessSourceLocations.ContainsKey(key))
- {
- Proc.Requires.Add(new Requires(false, BuildPossibleSourceLocationsExpr(key, "READ")));
- }
- else
- {
- Proc.Requires.Add(new Requires(false, BuildAccessOccurredFalseExpr(key, "READ")));
- }
- }
- }
- }
-
- public void AddStandardSourceVariablePostconditions()
- {
- foreach (Declaration D in verifier.Program.TopLevelDeclarations.ToList())
- {
- if (!(D is Procedure))
- {
- continue;
- }
- Procedure Proc = D as Procedure;
- foreach (string key in WriteAccessSourceLocations.Keys.Union(ReadAccessSourceLocations.Keys))
- {
- Proc.Ensures.Add(new Ensures(false, BuildNoAccessExpr(key, "WRITE")));
- Proc.Ensures.Add(new Ensures(false, BuildNoAccessExpr(key, "READ")));
-
- if (WriteAccessSourceLocations.ContainsKey(key))
- {
- Proc.Ensures.Add(new Ensures(false, BuildPossibleSourceLocationsExpr(key, "WRITE")));
- }
- else
- {
- Proc.Ensures.Add(new Ensures(false, BuildAccessOccurredFalseExpr(key, "WRITE")));
- }
-
- if (ReadAccessSourceLocations.ContainsKey(key))
- {
- Proc.Ensures.Add(new Ensures(false, BuildPossibleSourceLocationsExpr(key, "READ")));
- }
- else
- {
- Proc.Ensures.Add(new Ensures(false, BuildAccessOccurredFalseExpr(key, "READ")));
- }
- }
- }
- }
-
- private Expr BuildAccessOccurredFalseExpr(string name, string AccessType)
- {
- return Expr.Imp(new IdentifierExpr(Token.NoToken, verifier.FindOrCreateAccessHasOccurredVariable(name, AccessType)),
- Expr.False);
- }
-
- private AssertCmd BuildAccessOccurredFalseInvariant(string name, string AccessType)
- {
- return new AssertCmd(Token.NoToken, BuildAccessOccurredFalseExpr(name, AccessType));
- }
-
- private Expr BuildNoAccessExpr(string name, string AccessType)
- {
- return Expr.Imp(Expr.Not(new IdentifierExpr(Token.NoToken, verifier.FindOrCreateAccessHasOccurredVariable(name, AccessType))),
- Expr.Eq(new IdentifierExpr(Token.NoToken, verifier.FindOrCreateSourceVariable(name, AccessType)),
- new LiteralExpr(Token.NoToken, BigNum.FromInt(0), 32)));
- }
-
- private AssertCmd BuildNoAccessInvariant(string name, string AccessType)
- {
- return new AssertCmd(Token.NoToken, BuildNoAccessExpr(name, AccessType));
- }
-
- private Expr BuildPossibleSourceLocationsExpr(string name, string AccessType)
- {
- return Expr.Imp(new IdentifierExpr(Token.NoToken, verifier.FindOrCreateAccessHasOccurredVariable(name, AccessType)),
- BuildDisjunctionFromAccessSourceLocations(name, AccessType));
- }
-
- private AssertCmd BuildPossibleSourceLocationsInvariant(string name, string AccessType)
- {
- return new AssertCmd(Token.NoToken, BuildPossibleSourceLocationsExpr(name, AccessType));
- }
-
- private Expr BuildDisjunctionFromAccessSourceLocations(string key, string AccessType)
- {
- List<Expr> sourceLocExprs = new List<Expr>();
- Dictionary<string, List<int>> AccessSourceLocations = (AccessType.Equals("WRITE")) ? WriteAccessSourceLocations : ReadAccessSourceLocations;
- foreach (int loc in AccessSourceLocations[key])
- {
- sourceLocExprs.Add(Expr.Eq(new IdentifierExpr(Token.NoToken, verifier.FindOrCreateSourceVariable(key, AccessType)),
- new LiteralExpr(Token.NoToken, BigNum.FromInt(loc), 32)));
- }
- return sourceLocExprs.Aggregate(Expr.Or);
- }
-
- protected Expr NoReadOrWriteExpr(Variable v, string ReadOrWrite, string OneOrTwo) {
- Variable ReadOrWriteHasOccurred = GPUVerifier.MakeAccessHasOccurredVariable(v.Name, ReadOrWrite);
- ReadOrWriteHasOccurred.Name = ReadOrWriteHasOccurred.Name + "$" + OneOrTwo;
- ReadOrWriteHasOccurred.TypedIdent.Name = ReadOrWriteHasOccurred.TypedIdent.Name + "$" + OneOrTwo;
- Expr expr = Expr.Not(new IdentifierExpr(v.tok, ReadOrWriteHasOccurred));
- return expr;
- }
-
-
- protected void AddOffsetsSatisfyPredicatesCandidateInvariant(IRegion region, Variable v, string ReadOrWrite, List<Expr> preds) {
- if (preds.Count != 0) {
- Expr expr = AccessedOffsetsSatisfyPredicatesExpr(v, preds, ReadOrWrite, 1);
- verifier.AddCandidateInvariant(region, expr, "accessed offsets satisfy predicates");
- }
- }
-
- private Expr AccessedOffsetsSatisfyPredicatesExpr(Variable v, IEnumerable<Expr> offsets, string ReadOrWrite, int Thread) {
- return Expr.Imp(
- new IdentifierExpr(Token.NoToken, new VariableDualiser(Thread, null, null).VisitVariable(GPUVerifier.MakeAccessHasOccurredVariable(v.Name, ReadOrWrite))),
- offsets.Aggregate(Expr.Or));
- }
-
- private Expr AccessedOffsetIsThreadLocalIdExpr(Variable v, string ReadOrWrite, int Thread) {
- return Expr.Imp(
- new IdentifierExpr(v.tok, new VariableDualiser(Thread, null, null).VisitVariable(GPUVerifier.MakeAccessHasOccurredVariable(v.Name, ReadOrWrite))),
- Expr.Eq(new IdentifierExpr(v.tok, new VariableDualiser(Thread, null, null).VisitVariable(GPUVerifier.MakeOffsetVariable(v.Name, ReadOrWrite))), new IdentifierExpr(v.tok, verifier.MakeThreadId(v.tok, "X", Thread))));
- }
-
- private Expr GlobalIdExpr(string dimension, int Thread) {
- return new VariableDualiser(Thread, null, null).VisitExpr(verifier.GlobalIdExpr(dimension).Clone() as Expr);
- }
-
- protected void AddAccessedOffsetInRangeCTimesLocalIdToCTimesLocalIdPlusC(IRegion region, Variable v, Expr constant, string ReadOrWrite) {
- Expr expr = MakeCTimesLocalIdRangeExpression(v, constant, ReadOrWrite, 1);
- verifier.AddCandidateInvariant(region,
- expr, "accessed offset in range [ C*local_id, (C+1)*local_id )");
- }
-
- private Expr MakeCTimesLocalIdRangeExpression(Variable v, Expr constant, string ReadOrWrite, int Thread) {
- Expr CTimesLocalId = verifier.MakeBVMul(constant.Clone() as Expr,
- new IdentifierExpr(Token.NoToken, verifier.MakeThreadId(Token.NoToken, "X", Thread)));
-
- Expr CTimesLocalIdPlusC = verifier.MakeBVAdd(verifier.MakeBVMul(constant.Clone() as Expr,
- new IdentifierExpr(Token.NoToken, verifier.MakeThreadId(Token.NoToken, "X", Thread))), constant.Clone() as Expr);
-
- Expr CTimesLocalIdLeqAccessedOffset = GPUVerifier.MakeBitVectorBinaryBoolean("BV32_LEQ", CTimesLocalId, OffsetXExpr(v, ReadOrWrite, Thread));
-
- Expr AccessedOffsetLtCTimesLocalIdPlusC = verifier.MakeBVSlt(OffsetXExpr(v, ReadOrWrite, Thread), CTimesLocalIdPlusC);
-
- return Expr.Imp(
- AccessHasOccurred(v, ReadOrWrite, Thread),
- Expr.And(CTimesLocalIdLeqAccessedOffset, AccessedOffsetLtCTimesLocalIdPlusC));
- }
-
- private static IdentifierExpr AccessHasOccurred(Variable v, string ReadOrWrite, int Thread) {
- return new IdentifierExpr(v.tok, new VariableDualiser(Thread, null, null).VisitVariable(GPUVerifier.MakeAccessHasOccurredVariable(v.Name, ReadOrWrite)));
- }
-
- private static IdentifierExpr OffsetXExpr(Variable v, string ReadOrWrite, int Thread) {
- return new IdentifierExpr(v.tok, new VariableDualiser(Thread, null, null).VisitVariable(GPUVerifier.MakeOffsetVariable(v.Name, ReadOrWrite)));
- }
-
- protected void AddAccessedOffsetInRangeCTimesGlobalIdToCTimesGlobalIdPlusC(IRegion region, Variable v, Expr constant, string ReadOrWrite) {
- Expr expr = MakeCTimesGloalIdRangeExpr(v, constant, ReadOrWrite, 1);
- verifier.AddCandidateInvariant(region,
- expr, "accessed offset in range [ C*global_id, (C+1)*global_id )");
- }
-
- private Expr MakeCTimesGloalIdRangeExpr(Variable v, Expr constant, string ReadOrWrite, int Thread) {
- Expr CTimesGlobalId = verifier.MakeBVMul(constant.Clone() as Expr,
- GlobalIdExpr("X", Thread));
-
- Expr CTimesGlobalIdPlusC = verifier.MakeBVAdd(verifier.MakeBVMul(constant.Clone() as Expr,
- GlobalIdExpr("X", Thread)), constant.Clone() as Expr);
-
- Expr CTimesGlobalIdLeqAccessedOffset = GPUVerifier.MakeBitVectorBinaryBoolean("BV32_LEQ", CTimesGlobalId, OffsetXExpr(v, ReadOrWrite, Thread));
-
- Expr AccessedOffsetLtCTimesGlobalIdPlusC = verifier.MakeBVSlt(OffsetXExpr(v, ReadOrWrite, Thread), CTimesGlobalIdPlusC);
-
- Expr implication = Expr.Imp(
- AccessHasOccurred(v, ReadOrWrite, Thread),
- Expr.And(CTimesGlobalIdLeqAccessedOffset, AccessedOffsetLtCTimesGlobalIdPlusC));
- return implication;
- }
-
- private void writeSourceLocToFile(QKeyValue kv, string path) {
- TextWriter tw = new StreamWriter(path, true);
- tw.Write("\n" + QKeyValue.FindIntAttribute(SourceLocationAttributes, "line", -1)
- + "#" + QKeyValue.FindIntAttribute(SourceLocationAttributes, "col", -1)
- + "#" + QKeyValue.FindStringAttribute(SourceLocationAttributes, "fname")
- + "#" + QKeyValue.FindStringAttribute(SourceLocationAttributes, "dir"));
- tw.Close();
- }
-
- protected void AddAccessedOffsetIsThreadLocalIdCandidateRequires(Procedure Proc, Variable v, string ReadOrWrite, int Thread) {
- verifier.AddCandidateRequires(Proc, AccessedOffsetIsThreadLocalIdExpr(v, ReadOrWrite, Thread));
- }
-
- protected void AddAccessedOffsetIsThreadLocalIdCandidateEnsures(Procedure Proc, Variable v, string ReadOrWrite, int Thread) {
- verifier.AddCandidateEnsures(Proc, AccessedOffsetIsThreadLocalIdExpr(v, ReadOrWrite, Thread));
- }
-
-
-
- }
-
-
-
- class FindReferencesToNamedVariableVisitor : StandardVisitor {
- internal bool found = false;
- private string name;
-
- internal FindReferencesToNamedVariableVisitor(string name) {
- this.name = name;
- }
-
- public override Variable VisitVariable(Variable node) {
- if (GPUVerifier.StripThreadIdentifier(node.Name).Equals(name)) {
- found = true;
- }
- return base.VisitVariable(node);
- }
- }
-
-
-
-}
+using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Diagnostics; +using System.Diagnostics.Contracts; +using Microsoft.Boogie; +using Microsoft.Basetypes; + +namespace GPUVerify { + class RaceInstrumenter : IRaceInstrumenter { + protected GPUVerifier verifier; + + private QKeyValue SourceLocationAttributes = null; + + private int CurrStmtNo = 1; + + private Dictionary<string, List<int>> ReadAccessSourceLocations = new Dictionary<string, List<int>>(); + + private Dictionary<string, List<int>> WriteAccessSourceLocations = new Dictionary<string, List<int>>(); + + public IKernelArrayInfo NonLocalStateToCheck; + + private Dictionary<string, Procedure> RaceCheckingProcedures = new Dictionary<string, Procedure>(); + + public void setVerifier(GPUVerifier verifier) { + this.verifier = verifier; + NonLocalStateToCheck = new KernelArrayInfoLists(); + foreach (Variable v in verifier.KernelArrayInfo.getGlobalArrays()) { + NonLocalStateToCheck.getGlobalArrays().Add(v); + } + foreach (Variable v in verifier.KernelArrayInfo.getGroupSharedArrays()) { + NonLocalStateToCheck.getGroupSharedArrays().Add(v); + } + } + + private void AddNoReadOrWriteCandidateInvariants(IRegion region, Variable v) { + // Reasoning: if READ_HAS_OCCURRED_v is not in the modifies set for the + // loop then there is no point adding an invariant + // + // If READ_HAS_OCCURRED_v is in the modifies set, but the loop does not + // contain a barrier, then it is almost certain that a read CAN be + // pending at the loop head, so the invariant will not hold + // + // If there is a barrier in the loop body then READ_HAS_OCCURRED_v will + // be in the modifies set, but there may not be a live read at the loop + // head, so it is worth adding the loop invariant candidate. + // + // The same reasoning applies for WRITE + + if (verifier.ContainsBarrierCall(region)) { + if (verifier.ContainsNamedVariable( + LoopInvariantGenerator.GetModifiedVariables(region), GPUVerifier.MakeAccessHasOccurredVariableName(v.Name, "READ"))) { + AddNoReadOrWriteCandidateInvariant(region, v, "READ"); + } + + if (verifier.ContainsNamedVariable( + LoopInvariantGenerator.GetModifiedVariables(region), GPUVerifier.MakeAccessHasOccurredVariableName(v.Name, "WRITE"))) { + AddNoReadOrWriteCandidateInvariant(region, v, "WRITE"); + } + } + } + + private void AddNoReadOrWriteCandidateRequires(Procedure Proc, Variable v) { + AddNoReadOrWriteCandidateRequires(Proc, v, "READ", "1"); + AddNoReadOrWriteCandidateRequires(Proc, v, "WRITE", "1"); + } + + private void AddNoReadOrWriteCandidateEnsures(Procedure Proc, Variable v) { + AddNoReadOrWriteCandidateEnsures(Proc, v, "READ", "1"); + AddNoReadOrWriteCandidateEnsures(Proc, v, "WRITE", "1"); + } + + private void AddNoReadOrWriteCandidateInvariant(IRegion region, Variable v, string ReadOrWrite) { + Expr candidate = NoReadOrWriteExpr(v, ReadOrWrite, "1"); + verifier.AddCandidateInvariant(region, candidate, "no " + ReadOrWrite.ToLower()); + } + + public void AddRaceCheckingCandidateInvariants(Implementation impl, IRegion region) { + List<Expr> offsetPredicatesRead = new List<Expr>(); + List<Expr> offsetPredicatesWrite = new List<Expr>(); + foreach (Variable v in NonLocalStateToCheck.getAllNonLocalArrays()) { + AddNoReadOrWriteCandidateInvariants(region, v); + AddReadOrWrittenOffsetIsThreadIdCandidateInvariants(impl, region, v, "READ"); + AddReadOrWrittenOffsetIsThreadIdCandidateInvariants(impl, region, v, "WRITE"); + offsetPredicatesRead = CollectOffsetPredicates(impl, region, v, "READ"); + offsetPredicatesWrite = CollectOffsetPredicates(impl, region, v, "WRITE"); + AddOffsetsSatisfyPredicatesCandidateInvariant(region, v, "READ", offsetPredicatesRead); + AddOffsetsSatisfyPredicatesCandidateInvariant(region, v, "WRITE", offsetPredicatesWrite); + AddOffsetsSatisfyPredicatesCandidateInvariant(region, v, "READ", new List<Expr>(offsetPredicatesRead.Zip(CollectSourceLocPredicates(region, v, "READ"), Expr.And))); + AddOffsetsSatisfyPredicatesCandidateInvariant(region, v, "WRITE", new List<Expr>(offsetPredicatesWrite.Zip(CollectSourceLocPredicates(region, v, "WRITE"), Expr.And))); + } + } + + private void AddAccessRelatedCandidateInvariant(IRegion region, string accessKind, Expr candidateInvariantExpr, string procName, string tag) { + Expr candidate = new VariableDualiser(1, verifier.uniformityAnalyser, procName).VisitExpr(candidateInvariantExpr.Clone() as Expr); + verifier.AddCandidateInvariant(region, candidate, tag); + } + + private bool DoesNotReferTo(Expr expr, string v) { + FindReferencesToNamedVariableVisitor visitor = new FindReferencesToNamedVariableVisitor(v); + visitor.VisitExpr(expr); + return !visitor.found; + } + + private List<Expr> CollectSourceLocPredicates(IRegion region, Variable v, string accessType) { + var sourceVar = verifier.FindOrCreateSourceVariable(v.Name, accessType); + var sourceExpr = new IdentifierExpr(Token.NoToken, sourceVar); + var sourcePreds = new List<Expr>(); + + foreach (Cmd c in region.Cmds()) { + if (c is CallCmd) { + CallCmd call = c as CallCmd; + if (call.callee == "_LOG_" + accessType + "_" + v.Name) { + sourcePreds.Add(Expr.Eq(sourceExpr, call.Ins[2])); + } + } + } + + return sourcePreds; + } + private List<Expr> CollectOffsetPredicates(Implementation impl, IRegion region, Variable v, string accessType) { + var offsetVar = new VariableDualiser(1, null, null).VisitVariable(GPUVerifier.MakeOffsetVariable(v.Name, accessType)); + var offsetExpr = new IdentifierExpr(Token.NoToken, offsetVar); + var offsetPreds = new List<Expr>(); + + foreach (var offset in GetOffsetsAccessed(region, v, accessType)) { + bool isConstant; + var def = verifier.varDefAnalyses[impl].SubstDefinitions(offset, impl.Name, out isConstant); + if (def == null) + continue; + + if (isConstant) { + offsetPreds.Add(Expr.Eq(offsetExpr, def)); + } + else { + var sc = StrideConstraint.FromExpr(verifier, impl, def); + var pred = sc.MaybeBuildPredicate(verifier, offsetExpr); + if (pred != null) + offsetPreds.Add(pred); + } + } + + return offsetPreds; + } + + private void AddReadOrWrittenOffsetIsThreadIdCandidateInvariants(Implementation impl, IRegion region, Variable v, string accessType) { + KeyValuePair<IdentifierExpr, Expr> iLessThanC = GetILessThanC(region.Guard()); + if (iLessThanC.Key != null) { + foreach (Expr e in GetOffsetsAccessed(region, v, accessType)) { + if (HasFormIPlusLocalIdTimesC(e, iLessThanC, impl)) { + AddAccessedOffsetInRangeCTimesLocalIdToCTimesLocalIdPlusC(region, v, iLessThanC.Value, accessType); + break; + } + } + + foreach (Expr e in GetOffsetsAccessed(region, v, accessType)) { + if (HasFormIPlusGlobalIdTimesC(e, iLessThanC, impl)) { + AddAccessedOffsetInRangeCTimesGlobalIdToCTimesGlobalIdPlusC(region, v, iLessThanC.Value, accessType); + break; + } + } + + } + + + } + + private bool HasFormIPlusLocalIdTimesC(Expr e, KeyValuePair<IdentifierExpr, Expr> iLessThanC, Implementation impl) { + if (!(e is NAryExpr)) { + return false; + } + + NAryExpr nary = e as NAryExpr; + + if (!nary.Fun.FunctionName.Equals("BV32_ADD")) { + return false; + } + + return (SameIdentifierExpression(nary.Args[0], iLessThanC.Key) && + IsLocalIdTimesConstant(nary.Args[1], iLessThanC.Value, impl)) || + (SameIdentifierExpression(nary.Args[1], iLessThanC.Key) && + IsLocalIdTimesConstant(nary.Args[0], iLessThanC.Value, impl)); + } + + private bool IsLocalIdTimesConstant(Expr maybeLocalIdTimesConstant, Expr constant, Implementation impl) { + if (!(maybeLocalIdTimesConstant is NAryExpr)) { + return false; + } + NAryExpr nary = maybeLocalIdTimesConstant as NAryExpr; + if (!nary.Fun.FunctionName.Equals("BV32_MUL")) { + return false; + } + + return + (SameConstant(nary.Args[0], constant) && verifier.IsLocalId(nary.Args[1], 0, impl)) || + (SameConstant(nary.Args[1], constant) && verifier.IsLocalId(nary.Args[0], 0, impl)); + } + + + private bool HasFormIPlusGlobalIdTimesC(Expr e, KeyValuePair<IdentifierExpr, Expr> iLessThanC, Implementation impl) { + if (!(e is NAryExpr)) { + return false; + } + + NAryExpr nary = e as NAryExpr; + + if (!nary.Fun.FunctionName.Equals("BV32_ADD")) { + return false; + } + + return (SameIdentifierExpression(nary.Args[0], iLessThanC.Key) && + IsGlobalIdTimesConstant(nary.Args[1], iLessThanC.Value, impl)) || + (SameIdentifierExpression(nary.Args[1], iLessThanC.Key) && + IsGlobalIdTimesConstant(nary.Args[0], iLessThanC.Value, impl)); + } + + private bool IsGlobalIdTimesConstant(Expr maybeGlobalIdTimesConstant, Expr constant, Implementation impl) { + if (!(maybeGlobalIdTimesConstant is NAryExpr)) { + return false; + } + NAryExpr nary = maybeGlobalIdTimesConstant as NAryExpr; + if (!nary.Fun.FunctionName.Equals("BV32_MUL")) { + return false; + } + + return + (SameConstant(nary.Args[0], constant) && verifier.IsGlobalId(nary.Args[1], 0, impl)) || + (SameConstant(nary.Args[1], constant) && verifier.IsGlobalId(nary.Args[0], 0, impl)); + } + + + private bool SameConstant(Expr expr, Expr constant) { + if (constant is IdentifierExpr) { + IdentifierExpr identifierExpr = constant as IdentifierExpr; + Debug.Assert(identifierExpr.Decl is Constant); + return expr is IdentifierExpr && (expr as IdentifierExpr).Decl is Constant && (expr as IdentifierExpr).Decl.Name.Equals(identifierExpr.Decl.Name); + } + else { + Debug.Assert(constant is LiteralExpr); + LiteralExpr literalExpr = constant as LiteralExpr; + if (!(expr is LiteralExpr)) { + return false; + } + if (!(literalExpr.Val is BvConst) || !((expr as LiteralExpr).Val is BvConst)) { + return false; + } + + return (literalExpr.Val as BvConst).Value.ToInt == ((expr as LiteralExpr).Val as BvConst).Value.ToInt; + } + } + + private bool SameIdentifierExpression(Expr expr, IdentifierExpr identifierExpr) { + if (!(expr is IdentifierExpr)) { + return false; + } + return (expr as IdentifierExpr).Decl.Name.Equals(identifierExpr.Name); + } + + private KeyValuePair<IdentifierExpr, Expr> GetILessThanC(Expr expr) { + + if (expr is NAryExpr && (expr as NAryExpr).Fun.FunctionName.Equals("bv32_to_bool")) { + expr = (expr as NAryExpr).Args[0]; + } + + if (!(expr is NAryExpr)) { + return new KeyValuePair<IdentifierExpr, Expr>(null, null); + } + + NAryExpr nary = expr as NAryExpr; + + if (!(nary.Fun.FunctionName.Equals("BV32_C_LT") || nary.Fun.FunctionName.Equals("BV32_LT"))) { + return new KeyValuePair<IdentifierExpr, Expr>(null, null); + } + + if (!(nary.Args[0] is IdentifierExpr)) { + return new KeyValuePair<IdentifierExpr, Expr>(null, null); + } + + if (!IsConstant(nary.Args[1])) { + return new KeyValuePair<IdentifierExpr, Expr>(null, null); + } + + return new KeyValuePair<IdentifierExpr, Expr>(nary.Args[0] as IdentifierExpr, nary.Args[1]); + + } + + private static bool IsConstant(Expr e) { + return ((e is IdentifierExpr && (e as IdentifierExpr).Decl is Constant) || e is LiteralExpr); + } + + private void AddReadOrWrittenOffsetIsThreadIdCandidateRequires(Procedure Proc, Variable v) { + AddAccessedOffsetIsThreadLocalIdCandidateRequires(Proc, v, "WRITE", 1); + AddAccessedOffsetIsThreadLocalIdCandidateRequires(Proc, v, "READ", 1); + } + + private void AddReadOrWrittenOffsetIsThreadIdCandidateEnsures(Procedure Proc, Variable v) { + AddAccessedOffsetIsThreadLocalIdCandidateEnsures(Proc, v, "WRITE", 1); + AddAccessedOffsetIsThreadLocalIdCandidateEnsures(Proc, v, "READ", 1); + } + + public void AddKernelPrecondition() { + foreach (Variable v in NonLocalStateToCheck.getAllNonLocalArrays()) { + AddRequiresNoPendingAccess(v); + AddRequiresSourceAccessZero(v); + } + } + + public void AddRaceCheckingInstrumentation() { + + foreach (Declaration d in verifier.Program.TopLevelDeclarations) { + if (d is Implementation) { + AddRaceCheckCalls(d as Implementation); + } + } + + } + + private void AddRaceCheckingDecsAndProcsForVar(Variable v) { + AddLogRaceDeclarations(v, "READ"); + AddLogRaceDeclarations(v, "WRITE"); + AddLogAccessProcedure(v, "READ"); + AddCheckAccessProcedure(v, "READ"); + AddLogAccessProcedure(v, "WRITE"); + AddCheckAccessProcedure(v, "WRITE"); + } + + private StmtList AddRaceCheckCalls(StmtList stmtList) { + Contract.Requires(stmtList != null); + + StmtList result = new StmtList(new List<BigBlock>(), stmtList.EndCurly); + + foreach (BigBlock bodyBlock in stmtList.BigBlocks) { + result.BigBlocks.Add(AddRaceCheckCalls(bodyBlock)); + } + return result; + } + + private Block AddRaceCheckCalls(Block b) { + b.Cmds = AddRaceCheckCalls(b.Cmds); + return b; + } + + private void AddRaceCheckCalls(Implementation impl) { + if (CommandLineOptions.Unstructured) + impl.Blocks = impl.Blocks.Select(AddRaceCheckCalls).ToList(); + else + impl.StructuredStmts = AddRaceCheckCalls(impl.StructuredStmts); + } + + private CmdSeq AddRaceCheckCalls(CmdSeq cs) { + var result = new CmdSeq(); + 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; + } + } + + if (c is AssignCmd) { + AssignCmd assign = c as AssignCmd; + + ReadCollector rc = new ReadCollector(NonLocalStateToCheck); + foreach (var rhs in assign.Rhss) + rc.Visit(rhs); + if (rc.accesses.Count > 0) { + foreach (AccessRecord ar in rc.accesses) { + AddLogAndCheckCalls(result, ar, "READ"); + } + } + + foreach (var lhs in assign.Lhss) { + WriteCollector wc = new WriteCollector(NonLocalStateToCheck); + wc.Visit(lhs); + if (wc.GetAccess() != null) { + AccessRecord ar = wc.GetAccess(); + AddLogAndCheckCalls(result, ar, "WRITE"); + } + } + } + } + return result; + } + + private void AddLogAndCheckCalls(CmdSeq result, AccessRecord ar, string Access) { + ExprSeq inParamsLog = new ExprSeq(); + ExprSeq inParamsChk = new ExprSeq(); + inParamsChk.Add(ar.Index); + inParamsLog.Add(ar.Index); + inParamsLog.Add(new LiteralExpr(Token.NoToken, BigNum.FromInt(CurrStmtNo), 32)); + + Procedure logProcedure = GetRaceCheckingProcedure(Token.NoToken, "_LOG_" + Access + "_" + ar.v.Name); + Procedure checkProcedure = GetRaceCheckingProcedure(Token.NoToken, "_CHECK_" + Access + "_" + ar.v.Name); + + verifier.OnlyThread1.Add(logProcedure.Name); + verifier.OnlyThread2.Add(checkProcedure.Name); + + CallCmd logAccessCallCmd = new CallCmd(Token.NoToken, logProcedure.Name, inParamsLog, new IdentifierExprSeq()); + logAccessCallCmd.Proc = logProcedure; + + CallCmd checkAccessCallCmd = new CallCmd(Token.NoToken, checkProcedure.Name, inParamsChk, new IdentifierExprSeq()); + checkAccessCallCmd.Proc = checkProcedure; + checkAccessCallCmd.Attributes = SourceLocationAttributes; + + result.Add(logAccessCallCmd); + result.Add(checkAccessCallCmd); + + string fname = QKeyValue.FindStringAttribute(SourceLocationAttributes, "fname"); + + string Key = ar.v.Name; + if (Access == "WRITE") + { + if (!WriteAccessSourceLocations.ContainsKey(Key)) + { + WriteAccessSourceLocations.Add(Key, new List<int>()); + } + WriteAccessSourceLocations[Key].Add(CurrStmtNo); + } + else if (Access == "READ") + { + if (!ReadAccessSourceLocations.ContainsKey(Key)) + { + ReadAccessSourceLocations.Add(Key, new List<int>()); + } + ReadAccessSourceLocations[Key].Add(CurrStmtNo); + } + + if (fname != null) + { + writeSourceLocToFile(SourceLocationAttributes, Path.GetFileNameWithoutExtension(CommandLineOptions.inputFiles[0]) + ".loc"); + } + else + { + Debug.Assert(false, "RaceInstrumenter.AddLogAndCheckCalls: Could not write sourceloc to file as filename could not be found.\n"); + } + CurrStmtNo++; + } + + private BigBlock AddRaceCheckCalls(BigBlock bb) { + BigBlock result = new BigBlock(bb.tok, bb.LabelName, AddRaceCheckCalls(bb.simpleCmds), null, bb.tc); + + if (bb.ec is WhileCmd) { + WhileCmd WhileCommand = bb.ec as WhileCmd; + result.ec = new WhileCmd(WhileCommand.tok, WhileCommand.Guard, + WhileCommand.Invariants, AddRaceCheckCalls(WhileCommand.Body)); + } + else if (bb.ec is IfCmd) { + IfCmd IfCommand = bb.ec as IfCmd; + Debug.Assert(IfCommand.elseIf == null); // We don't handle else if yet + result.ec = new IfCmd(IfCommand.tok, IfCommand.Guard, AddRaceCheckCalls(IfCommand.thn), IfCommand.elseIf, IfCommand.elseBlock != null ? AddRaceCheckCalls(IfCommand.elseBlock) : null); + } + else if (bb.ec is BreakCmd) { + result.ec = bb.ec; + } + else { + Debug.Assert(bb.ec == null); + } + + return result; + } + + private Procedure GetRaceCheckingProcedure(IToken tok, string name) { + if (RaceCheckingProcedures.ContainsKey(name)) { + return RaceCheckingProcedures[name]; + } + Procedure newProcedure = new Procedure(tok, name, new TypeVariableSeq(), new VariableSeq(), new VariableSeq(), new RequiresSeq(), new IdentifierExprSeq(), new EnsuresSeq()); + RaceCheckingProcedures[name] = newProcedure; + return newProcedure; + } + + + public BigBlock MakeResetReadWriteSetStatements(Variable v, int Thread) { + BigBlock result = new BigBlock(Token.NoToken, null, new CmdSeq(), null, null); + if (Thread == 2) { + return result; + } + + Expr ResetReadAssumeGuard = Expr.Not(new IdentifierExpr(Token.NoToken, + new VariableDualiser(1, null, null).VisitVariable(GPUVerifier.MakeAccessHasOccurredVariable(v.Name, "READ")))); + Expr ResetWriteAssumeGuard = Expr.Not(new IdentifierExpr(Token.NoToken, + new VariableDualiser(1, null, null).VisitVariable(GPUVerifier.MakeAccessHasOccurredVariable(v.Name, "WRITE")))); + + if (verifier.KernelArrayInfo.getGlobalArrays().Contains(v)) { + ResetReadAssumeGuard = Expr.Imp(GPUVerifier.ThreadsInSameGroup(), ResetReadAssumeGuard); + ResetWriteAssumeGuard = Expr.Imp(GPUVerifier.ThreadsInSameGroup(), ResetWriteAssumeGuard); + } + + result.simpleCmds.Add(new AssumeCmd(Token.NoToken, ResetReadAssumeGuard)); + result.simpleCmds.Add(new AssumeCmd(Token.NoToken, ResetWriteAssumeGuard)); + return result; + } + + protected Procedure MakeLogAccessProcedureHeader(Variable v, string ReadOrWrite) { + VariableSeq inParams = new VariableSeq(); + + Variable PredicateParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_P", Microsoft.Boogie.Type.Bool)); + + Debug.Assert(v.TypedIdent.Type is MapType); + MapType mt = v.TypedIdent.Type as MapType; + Debug.Assert(mt.Arguments.Length == 1); + Variable OffsetParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_offset", mt.Arguments[0])); + Variable SourceParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_source", mt.Arguments[0])); + Debug.Assert(!(mt.Result is MapType)); + + inParams.Add(new VariableDualiser(1, null, null).VisitVariable(PredicateParameter.Clone() as Variable)); + inParams.Add(new VariableDualiser(1, null, null).VisitVariable(OffsetParameter.Clone() as Variable)); + inParams.Add(new VariableDualiser(1, null, null).VisitVariable(SourceParameter.Clone() as Variable)); + + string LogProcedureName = "_LOG_" + ReadOrWrite + "_" + v.Name; + + Procedure result = GetRaceCheckingProcedure(v.tok, LogProcedureName); + + result.InParams = inParams; + + result.AddAttribute("inline", new object[] { new LiteralExpr(v.tok, BigNum.FromInt(1)) }); + + return result; + } + + protected Procedure MakeCheckAccessProcedureHeader(Variable v, string ReadOrWrite) { + VariableSeq inParams = new VariableSeq(); + + Variable PredicateParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_P", Microsoft.Boogie.Type.Bool)); + + Debug.Assert(v.TypedIdent.Type is MapType); + MapType mt = v.TypedIdent.Type as MapType; + Debug.Assert(mt.Arguments.Length == 1); + Variable OffsetParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_offset", mt.Arguments[0])); + Debug.Assert(!(mt.Result is MapType)); + + inParams.Add(new VariableDualiser(2, null, null).VisitVariable(PredicateParameter.Clone() as Variable)); + inParams.Add(new VariableDualiser(2, null, null).VisitVariable(OffsetParameter.Clone() as Variable)); + + string CheckProcedureName = "_CHECK_" + ReadOrWrite + "_" + v.Name; + + Procedure result = GetRaceCheckingProcedure(v.tok, CheckProcedureName); + + result.InParams = inParams; + + result.AddAttribute("inline", new object[] { new LiteralExpr(v.tok, BigNum.FromInt(1)) }); + + return result; + } + + public void AddRaceCheckingCandidateRequires(Procedure Proc) { + foreach (Variable v in NonLocalStateToCheck.getAllNonLocalArrays()) { + AddNoReadOrWriteCandidateRequires(Proc, v); + AddReadOrWrittenOffsetIsThreadIdCandidateRequires(Proc, v); + } + } + + public void DoHoudiniPointerAnalysis(Procedure Proc) { + foreach (Variable v in Proc.InParams) { + if (v.TypedIdent.Type is CtorType) { + CtorType ct = v.TypedIdent.Type as CtorType; + if (ct.Decl.Name.Equals("ptr")) { + foreach (var arrayCollection in new ICollection<Variable>[] { + verifier.KernelArrayInfo.getGlobalArrays(), verifier.KernelArrayInfo.getGroupSharedArrays(), + verifier.KernelArrayInfo.getPrivateArrays() }) { + if (arrayCollection.Count == 0) { + continue; + } + + Expr DisjunctionOverPointerSet = null; + foreach (var array in arrayCollection) { + Expr PointerSetDisjunct = Expr.Eq(MakePtrBaseExpr(v), MakeArrayIdExpr(array)); + DisjunctionOverPointerSet = (DisjunctionOverPointerSet == null ? PointerSetDisjunct : Expr.Or(DisjunctionOverPointerSet, PointerSetDisjunct)); + verifier.AddCandidateRequires(Proc, + Expr.Neq(MakePtrBaseExpr(v), MakeArrayIdExpr(array))); + } + Debug.Assert(DisjunctionOverPointerSet != null); + verifier.AddCandidateRequires(Proc, DisjunctionOverPointerSet); + verifier.AddCandidateRequires(Proc, Expr.Eq(MakePtrOffsetExpr(v), GPUVerifier.ZeroBV())); + } + } + } + } + } + + private IdentifierExpr MakeArrayIdExpr(Variable array) { + var arrayId = verifier.ResContext.LookUpVariable("$arrayId" + array.Name); + return new IdentifierExpr(Token.NoToken, arrayId); + } + + private NAryExpr MakePtrBaseExpr(Variable v) { + var baseSel = (Function)verifier.ResContext.LookUpProcedure("base#MKPTR"); + return new NAryExpr(Token.NoToken, new FunctionCall(baseSel), + new ExprSeq(new Expr[] { Expr.Ident(v) })); + } + + private NAryExpr MakePtrOffsetExpr(Variable v) { + var offsetSel = (Function)verifier.ResContext.LookUpProcedure("offset#MKPTR"); + return new NAryExpr(Token.NoToken, new FunctionCall(offsetSel), + new ExprSeq(new Expr[] { Expr.Ident(v) })); + } + + public void AddRaceCheckingCandidateEnsures(Procedure Proc) { + foreach (Variable v in NonLocalStateToCheck.getAllNonLocalArrays()) { + AddNoReadOrWriteCandidateEnsures(Proc, v); + AddReadOrWrittenOffsetIsThreadIdCandidateEnsures(Proc, v); + } + } + + private void AddNoReadOrWriteCandidateRequires(Procedure Proc, Variable v, string ReadOrWrite, string OneOrTwo) { + verifier.AddCandidateRequires(Proc, NoReadOrWriteExpr(v, ReadOrWrite, OneOrTwo)); + } + + private void AddNoReadOrWriteCandidateEnsures(Procedure Proc, Variable v, string ReadOrWrite, string OneOrTwo) { + verifier.AddCandidateEnsures(Proc, NoReadOrWriteExpr(v, ReadOrWrite, OneOrTwo)); + } + + private HashSet<Expr> GetOffsetsAccessed(IRegion region, Variable v, string AccessType) { + HashSet<Expr> result = new HashSet<Expr>(); + + foreach (Cmd c in region.Cmds()) { + if (c is CallCmd) { + CallCmd call = c as CallCmd; + + if (call.callee == "_LOG_" + AccessType + "_" + v.Name) { + // Ins[0] is thread 1's predicate, + // Ins[1] is the offset to be read + // If Ins[1] has the form BV32_ADD(offset#construct...(P), offset), + // we are looking for the second parameter to this BV32_ADD + Expr offset = call.Ins[1]; + if (offset is NAryExpr) { + var nExpr = (NAryExpr)offset; + if (nExpr.Fun.FunctionName == "BV32_ADD" && + nExpr.Args[0] is NAryExpr) { + var n0Expr = (NAryExpr)nExpr.Args[0]; + if (n0Expr.Fun.FunctionName.StartsWith("offset#")) + offset = nExpr.Args[1]; + } + } + result.Add(offset); + } + + } + + } + + return result; + } + + public void AddRaceCheckingDeclarations() { + foreach (Variable v in NonLocalStateToCheck.getAllNonLocalArrays()) { + AddRaceCheckingDecsAndProcsForVar(v); + } + } + + protected void AddLogAccessProcedure(Variable v, string Access) { + Procedure LogAccessProcedure = MakeLogAccessProcedureHeader(v, Access); + + Variable AccessHasOccurredVariable = GPUVerifier.MakeAccessHasOccurredVariable(v.Name, Access); + Variable AccessOffsetXVariable = GPUVerifier.MakeOffsetVariable(v.Name, Access); + Variable AccessSourceVariable = GPUVerifier.MakeSourceVariable(v.Name, Access); + + Variable PredicateParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_P", Microsoft.Boogie.Type.Bool)); + + Debug.Assert(v.TypedIdent.Type is MapType); + MapType mt = v.TypedIdent.Type as MapType; + Debug.Assert(mt.Arguments.Length == 1); + Variable OffsetParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_offset", mt.Arguments[0])); + Variable SourceParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_source", mt.Arguments[0])); + Debug.Assert(!(mt.Result is MapType)); + + VariableSeq locals = new VariableSeq(); + Variable TrackVariable = new LocalVariable(v.tok, new TypedIdent(v.tok, "track", Microsoft.Boogie.Type.Bool)); + locals.Add(TrackVariable); + + List<BigBlock> bigblocks = new List<BigBlock>(); + + CmdSeq simpleCmds = new CmdSeq(); + + simpleCmds.Add(new HavocCmd(v.tok, new IdentifierExprSeq(new IdentifierExpr[] { new IdentifierExpr(v.tok, TrackVariable) }))); + + simpleCmds.Add(MakeConditionalAssignment(VariableForThread(1, AccessHasOccurredVariable), + Expr.And(new IdentifierExpr(v.tok, VariableForThread(1, PredicateParameter)), new IdentifierExpr(v.tok, TrackVariable)), Expr.True)); + simpleCmds.Add(MakeConditionalAssignment(VariableForThread(1, AccessOffsetXVariable), + Expr.And(new IdentifierExpr(v.tok, VariableForThread(1, PredicateParameter)), new IdentifierExpr(v.tok, TrackVariable)), + new IdentifierExpr(v.tok, VariableForThread(1, OffsetParameter)))); + simpleCmds.Add(MakeConditionalAssignment(VariableForThread(1, AccessSourceVariable), + Expr.And(new IdentifierExpr(v.tok, VariableForThread(1, PredicateParameter)), new IdentifierExpr(v.tok, TrackVariable)), + new IdentifierExpr(v.tok, VariableForThread(1, SourceParameter)))); + + bigblocks.Add(new BigBlock(v.tok, "_LOG_" + Access + "", simpleCmds, null, null)); + + LogAccessProcedure.Modifies.Add(new IdentifierExpr(Token.NoToken, VariableForThread(1, AccessHasOccurredVariable))); + LogAccessProcedure.Modifies.Add(new IdentifierExpr(Token.NoToken, VariableForThread(1, AccessOffsetXVariable))); + + Implementation LogAccessImplementation = new Implementation(v.tok, "_LOG_" + Access + "_" + v.Name, new TypeVariableSeq(), LogAccessProcedure.InParams, new VariableSeq(), locals, new StmtList(bigblocks, v.tok)); + LogAccessImplementation.AddAttribute("inline", new object[] { new LiteralExpr(v.tok, BigNum.FromInt(1)) }); + + LogAccessImplementation.Proc = LogAccessProcedure; + + verifier.Program.TopLevelDeclarations.Add(LogAccessProcedure); + verifier.Program.TopLevelDeclarations.Add(LogAccessImplementation); + } + + + protected void AddCheckAccessProcedure(Variable v, string Access) { + Procedure CheckAccessProcedure = MakeCheckAccessProcedureHeader(v, Access); + + Variable AccessHasOccurredVariable = GPUVerifier.MakeAccessHasOccurredVariable(v.Name, Access); + Variable AccessOffsetXVariable = GPUVerifier.MakeOffsetVariable(v.Name, Access); + + Variable PredicateParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_P", Microsoft.Boogie.Type.Bool)); + + Debug.Assert(v.TypedIdent.Type is MapType); + MapType mt = v.TypedIdent.Type as MapType; + Debug.Assert(mt.Arguments.Length == 1); + Variable OffsetParameter = new LocalVariable(v.tok, new TypedIdent(v.tok, "_offset", mt.Arguments[0])); + Debug.Assert(!(mt.Result is MapType)); + + if (Access.Equals("READ")) { + // Check read by thread 2 does not conflict with write by thread 1 + Variable WriteHasOccurredVariable = GPUVerifier.MakeAccessHasOccurredVariable(v.Name, "WRITE"); + Variable WriteOffsetVariable = GPUVerifier.MakeOffsetVariable(v.Name, "WRITE"); + Expr WriteReadGuard = new IdentifierExpr(Token.NoToken, VariableForThread(2, PredicateParameter)); + WriteReadGuard = Expr.And(WriteReadGuard, new IdentifierExpr(Token.NoToken, VariableForThread(1, WriteHasOccurredVariable))); + WriteReadGuard = Expr.And(WriteReadGuard, Expr.Eq(new IdentifierExpr(Token.NoToken, VariableForThread(1, WriteOffsetVariable)), + new IdentifierExpr(Token.NoToken, VariableForThread(2, OffsetParameter)))); + + if (!verifier.ArrayModelledAdversarially(v)) { + WriteReadGuard = Expr.And(WriteReadGuard, Expr.Neq( + new VariableDualiser(1, null, null).VisitExpr( + MakeAccessedIndex(v, new IdentifierExpr(Token.NoToken, WriteOffsetVariable), "WRITE")), + new VariableDualiser(2, null, null).VisitExpr( + MakeAccessedIndex(v, new IdentifierExpr(Token.NoToken, OffsetParameter), "READ")) + )); + } + + if (verifier.KernelArrayInfo.getGroupSharedArrays().Contains(v)) { + WriteReadGuard = Expr.And(WriteReadGuard, GPUVerifier.ThreadsInSameGroup()); + } + + WriteReadGuard = Expr.Not(WriteReadGuard); + + Requires NoWriteReadRaceRequires = new Requires(false, WriteReadGuard); + QKeyValue kv = new QKeyValue(Token.NoToken, "write_read", new List<object>(), null); + NoWriteReadRaceRequires.Attributes = new QKeyValue(Token.NoToken, "race", new List<object>(), kv); + CheckAccessProcedure.Requires.Add(NoWriteReadRaceRequires); + } + else { + Debug.Assert(Access.Equals("WRITE")); + + // Check write by thread 2 does not conflict with write by thread 1 + Variable WriteHasOccurredVariable = GPUVerifier.MakeAccessHasOccurredVariable(v.Name, "WRITE"); + Variable WriteOffsetVariable = GPUVerifier.MakeOffsetVariable(v.Name, "WRITE"); + + Expr WriteWriteGuard = new IdentifierExpr(Token.NoToken, VariableForThread(2, PredicateParameter)); + WriteWriteGuard = Expr.And(WriteWriteGuard, new IdentifierExpr(Token.NoToken, VariableForThread(1, WriteHasOccurredVariable))); + WriteWriteGuard = Expr.And(WriteWriteGuard, Expr.Eq(new IdentifierExpr(Token.NoToken, VariableForThread(1, WriteOffsetVariable)), + new IdentifierExpr(Token.NoToken, VariableForThread(2, OffsetParameter)))); + if (!verifier.ArrayModelledAdversarially(v)) { + WriteWriteGuard = Expr.And(WriteWriteGuard, Expr.Neq( + new VariableDualiser(1, null, null).VisitExpr( + MakeAccessedIndex(v, new IdentifierExpr(Token.NoToken, WriteOffsetVariable), "WRITE")), + new VariableDualiser(2, null, null).VisitExpr( + MakeAccessedIndex(v, new IdentifierExpr(Token.NoToken, OffsetParameter), "WRITE")) + )); + } + + if (verifier.KernelArrayInfo.getGroupSharedArrays().Contains(v)) { + WriteWriteGuard = Expr.And(WriteWriteGuard, GPUVerifier.ThreadsInSameGroup()); + } + + WriteWriteGuard = Expr.Not(WriteWriteGuard); + Requires NoWriteWriteRaceRequires = new Requires(false, WriteWriteGuard); + QKeyValue kv = new QKeyValue(Token.NoToken, "write_write", new List<object>(), null); + NoWriteWriteRaceRequires.Attributes = new QKeyValue(Token.NoToken, "race", new List<object>(), kv); + CheckAccessProcedure.Requires.Add(NoWriteWriteRaceRequires); + + // Check write by thread 2 does not conflict with read by thread 1 + Variable ReadHasOccurredVariable = GPUVerifier.MakeAccessHasOccurredVariable(v.Name, "READ"); + Variable ReadOffsetVariable = GPUVerifier.MakeOffsetVariable(v.Name, "READ"); + + Expr ReadWriteGuard = new IdentifierExpr(Token.NoToken, VariableForThread(2, PredicateParameter)); + ReadWriteGuard = Expr.And(ReadWriteGuard, new IdentifierExpr(Token.NoToken, VariableForThread(1, ReadHasOccurredVariable))); + ReadWriteGuard = Expr.And(ReadWriteGuard, Expr.Eq(new IdentifierExpr(Token.NoToken, VariableForThread(1, ReadOffsetVariable)), + new IdentifierExpr(Token.NoToken, VariableForThread(2, OffsetParameter)))); + if (!verifier.ArrayModelledAdversarially(v)) { + ReadWriteGuard = Expr.And(ReadWriteGuard, Expr.Neq( + new VariableDualiser(1, null, null).VisitExpr( + MakeAccessedIndex(v, new IdentifierExpr(Token.NoToken, ReadOffsetVariable), "WRITE")), + new VariableDualiser(2, null, null).VisitExpr( + MakeAccessedIndex(v, new IdentifierExpr(Token.NoToken, OffsetParameter), "READ")) + )); + } + + if (verifier.KernelArrayInfo.getGroupSharedArrays().Contains(v)) { + ReadWriteGuard = Expr.And(ReadWriteGuard, GPUVerifier.ThreadsInSameGroup()); + } + + ReadWriteGuard = Expr.Not(ReadWriteGuard); + Requires NoReadWriteRaceRequires = new Requires(false, ReadWriteGuard); + kv = new QKeyValue(Token.NoToken, "read_write", new List<object>(), null); + NoReadWriteRaceRequires.Attributes = new QKeyValue(Token.NoToken, "race", new List<object>(), kv); + CheckAccessProcedure.Requires.Add(NoReadWriteRaceRequires); + + } + verifier.Program.TopLevelDeclarations.Add(CheckAccessProcedure); + } + + + + private Variable VariableForThread(int thread, Variable v) { + return new VariableDualiser(thread, null, null).VisitVariable(v.Clone() as Variable); + } + + protected void AddLogRaceDeclarations(Variable v, String ReadOrWrite) { + verifier.FindOrCreateAccessHasOccurredVariable(v.Name, ReadOrWrite); + + Debug.Assert(v.TypedIdent.Type is MapType); + MapType mt = v.TypedIdent.Type as MapType; + Debug.Assert(mt.Arguments.Length == 1); + + verifier.FindOrCreateOffsetVariable(v.Name, ReadOrWrite); + verifier.FindOrCreateSourceVariable(v.Name, ReadOrWrite); + + } + + + private static AssignCmd MakeConditionalAssignment(Variable lhs, Expr condition, Expr rhs) { + List<AssignLhs> lhss = new List<AssignLhs>(); + List<Expr> rhss = new List<Expr>(); + lhss.Add(new SimpleAssignLhs(lhs.tok, new IdentifierExpr(lhs.tok, lhs))); + rhss.Add(new NAryExpr(rhs.tok, new IfThenElse(rhs.tok), new ExprSeq(new Expr[] { condition, rhs, new IdentifierExpr(lhs.tok, lhs) }))); + return new AssignCmd(lhs.tok, lhss, rhss); + } + + private Expr MakeAccessedIndex(Variable v, Expr offsetExpr, string AccessType) { + Expr result = new IdentifierExpr(v.tok, v.Clone() as Variable); + Debug.Assert(v.TypedIdent.Type is MapType); + MapType mt = v.TypedIdent.Type as MapType; + Debug.Assert(mt.Arguments.Length == 1); + + result = Expr.Select(result, + new Expr[] { offsetExpr }); + Debug.Assert(!(mt.Result is MapType)); + return result; + } + + protected void AddRequiresNoPendingAccess(Variable v) { + IdentifierExpr ReadAccessOccurred1 = new IdentifierExpr(v.tok, new VariableDualiser(1, null, null).VisitVariable(GPUVerifier.MakeAccessHasOccurredVariable(v.Name, "READ"))); + IdentifierExpr WriteAccessOccurred1 = new IdentifierExpr(v.tok, new VariableDualiser(1, null, null).VisitVariable(GPUVerifier.MakeAccessHasOccurredVariable(v.Name, "WRITE"))); + + verifier.KernelProcedure.Requires.Add(new Requires(false, Expr.And(Expr.Not(ReadAccessOccurred1), Expr.Not(WriteAccessOccurred1)))); + } + + private void AddRequiresSourceAccessZero(Variable v) + { + verifier.KernelProcedure.Requires.Add(new Requires(false, Expr.Eq(new IdentifierExpr(Token.NoToken, verifier.FindOrCreateSourceVariable(v.Name, "READ")), + GPUVerifier.ZeroBV()))); + verifier.KernelProcedure.Requires.Add(new Requires(false, Expr.Eq(new IdentifierExpr(Token.NoToken, verifier.FindOrCreateSourceVariable(v.Name, "WRITE")), + GPUVerifier.ZeroBV()))); + } + + public void AddSourceLocationLoopInvariants(Implementation impl, IRegion region) + { + foreach (string key in WriteAccessSourceLocations.Keys.Union(ReadAccessSourceLocations.Keys)) + { + region.AddInvariant(BuildNoAccessInvariant(key, "WRITE")); + region.AddInvariant(BuildNoAccessInvariant(key, "READ")); + + if (WriteAccessSourceLocations.ContainsKey(key)) + { + region.AddInvariant(BuildPossibleSourceLocationsInvariant(key, "WRITE")); + } + else + { + region.AddInvariant(BuildAccessOccurredFalseInvariant(key, "WRITE")); + } + + if (ReadAccessSourceLocations.ContainsKey(key)) + { + region.AddInvariant(BuildPossibleSourceLocationsInvariant(key, "READ")); + } + else + { + region.AddInvariant(BuildAccessOccurredFalseInvariant(key, "READ")); + } + } + } + + public void AddStandardSourceVariablePreconditions() + { + foreach (Declaration D in verifier.Program.TopLevelDeclarations.ToList()) + { + if (!(D is Procedure)) + { + continue; + } + Procedure Proc = D as Procedure; + foreach (string key in WriteAccessSourceLocations.Keys.Union(ReadAccessSourceLocations.Keys)) + { + Proc.Requires.Add(new Requires(false, BuildNoAccessExpr(key, "WRITE"))); + Proc.Requires.Add(new Requires(false, BuildNoAccessExpr(key, "READ"))); + + if (WriteAccessSourceLocations.ContainsKey(key)) + { + Proc.Requires.Add(new Requires(false, BuildPossibleSourceLocationsExpr(key, "WRITE"))); + } + else + { + Proc.Requires.Add(new Requires(false, BuildAccessOccurredFalseExpr(key, "WRITE"))); + } + + if (ReadAccessSourceLocations.ContainsKey(key)) + { + Proc.Requires.Add(new Requires(false, BuildPossibleSourceLocationsExpr(key, "READ"))); + } + else + { + Proc.Requires.Add(new Requires(false, BuildAccessOccurredFalseExpr(key, "READ"))); + } + } + } + } + + public void AddStandardSourceVariablePostconditions() + { + foreach (Declaration D in verifier.Program.TopLevelDeclarations.ToList()) + { + if (!(D is Procedure)) + { + continue; + } + Procedure Proc = D as Procedure; + foreach (string key in WriteAccessSourceLocations.Keys.Union(ReadAccessSourceLocations.Keys)) + { + Proc.Ensures.Add(new Ensures(false, BuildNoAccessExpr(key, "WRITE"))); + Proc.Ensures.Add(new Ensures(false, BuildNoAccessExpr(key, "READ"))); + + if (WriteAccessSourceLocations.ContainsKey(key)) + { + Proc.Ensures.Add(new Ensures(false, BuildPossibleSourceLocationsExpr(key, "WRITE"))); + } + else + { + Proc.Ensures.Add(new Ensures(false, BuildAccessOccurredFalseExpr(key, "WRITE"))); + } + + if (ReadAccessSourceLocations.ContainsKey(key)) + { + Proc.Ensures.Add(new Ensures(false, BuildPossibleSourceLocationsExpr(key, "READ"))); + } + else + { + Proc.Ensures.Add(new Ensures(false, BuildAccessOccurredFalseExpr(key, "READ"))); + } + } + } + } + + private Expr BuildAccessOccurredFalseExpr(string name, string AccessType) + { + return Expr.Imp(new IdentifierExpr(Token.NoToken, verifier.FindOrCreateAccessHasOccurredVariable(name, AccessType)), + Expr.False); + } + + private AssertCmd BuildAccessOccurredFalseInvariant(string name, string AccessType) + { + return new AssertCmd(Token.NoToken, BuildAccessOccurredFalseExpr(name, AccessType)); + } + + private Expr BuildNoAccessExpr(string name, string AccessType) + { + return Expr.Imp(Expr.Not(new IdentifierExpr(Token.NoToken, verifier.FindOrCreateAccessHasOccurredVariable(name, AccessType))), + Expr.Eq(new IdentifierExpr(Token.NoToken, verifier.FindOrCreateSourceVariable(name, AccessType)), + new LiteralExpr(Token.NoToken, BigNum.FromInt(0), 32))); + } + + private AssertCmd BuildNoAccessInvariant(string name, string AccessType) + { + return new AssertCmd(Token.NoToken, BuildNoAccessExpr(name, AccessType)); + } + + private Expr BuildPossibleSourceLocationsExpr(string name, string AccessType) + { + return Expr.Imp(new IdentifierExpr(Token.NoToken, verifier.FindOrCreateAccessHasOccurredVariable(name, AccessType)), + BuildDisjunctionFromAccessSourceLocations(name, AccessType)); + } + + private AssertCmd BuildPossibleSourceLocationsInvariant(string name, string AccessType) + { + return new AssertCmd(Token.NoToken, BuildPossibleSourceLocationsExpr(name, AccessType)); + } + + private Expr BuildDisjunctionFromAccessSourceLocations(string key, string AccessType) + { + List<Expr> sourceLocExprs = new List<Expr>(); + Dictionary<string, List<int>> AccessSourceLocations = (AccessType.Equals("WRITE")) ? WriteAccessSourceLocations : ReadAccessSourceLocations; + foreach (int loc in AccessSourceLocations[key]) + { + sourceLocExprs.Add(Expr.Eq(new IdentifierExpr(Token.NoToken, verifier.FindOrCreateSourceVariable(key, AccessType)), + new LiteralExpr(Token.NoToken, BigNum.FromInt(loc), 32))); + } + return sourceLocExprs.Aggregate(Expr.Or); + } + + protected Expr NoReadOrWriteExpr(Variable v, string ReadOrWrite, string OneOrTwo) { + Variable ReadOrWriteHasOccurred = GPUVerifier.MakeAccessHasOccurredVariable(v.Name, ReadOrWrite); + ReadOrWriteHasOccurred.Name = ReadOrWriteHasOccurred.Name + "$" + OneOrTwo; + ReadOrWriteHasOccurred.TypedIdent.Name = ReadOrWriteHasOccurred.TypedIdent.Name + "$" + OneOrTwo; + Expr expr = Expr.Not(new IdentifierExpr(v.tok, ReadOrWriteHasOccurred)); + return expr; + } + + + protected void AddOffsetsSatisfyPredicatesCandidateInvariant(IRegion region, Variable v, string ReadOrWrite, List<Expr> preds) { + if (preds.Count != 0) { + Expr expr = AccessedOffsetsSatisfyPredicatesExpr(v, preds, ReadOrWrite, 1); + verifier.AddCandidateInvariant(region, expr, "accessed offsets satisfy predicates"); + } + } + + private Expr AccessedOffsetsSatisfyPredicatesExpr(Variable v, IEnumerable<Expr> offsets, string ReadOrWrite, int Thread) { + return Expr.Imp( + new IdentifierExpr(Token.NoToken, new VariableDualiser(Thread, null, null).VisitVariable(GPUVerifier.MakeAccessHasOccurredVariable(v.Name, ReadOrWrite))), + offsets.Aggregate(Expr.Or)); + } + + private Expr AccessedOffsetIsThreadLocalIdExpr(Variable v, string ReadOrWrite, int Thread) { + return Expr.Imp( + new IdentifierExpr(v.tok, new VariableDualiser(Thread, null, null).VisitVariable(GPUVerifier.MakeAccessHasOccurredVariable(v.Name, ReadOrWrite))), + Expr.Eq(new IdentifierExpr(v.tok, new VariableDualiser(Thread, null, null).VisitVariable(GPUVerifier.MakeOffsetVariable(v.Name, ReadOrWrite))), new IdentifierExpr(v.tok, verifier.MakeThreadId(v.tok, "X", Thread)))); + } + + private Expr GlobalIdExpr(string dimension, int Thread) { + return new VariableDualiser(Thread, null, null).VisitExpr(verifier.GlobalIdExpr(dimension).Clone() as Expr); + } + + protected void AddAccessedOffsetInRangeCTimesLocalIdToCTimesLocalIdPlusC(IRegion region, Variable v, Expr constant, string ReadOrWrite) { + Expr expr = MakeCTimesLocalIdRangeExpression(v, constant, ReadOrWrite, 1); + verifier.AddCandidateInvariant(region, + expr, "accessed offset in range [ C*local_id, (C+1)*local_id )"); + } + + private Expr MakeCTimesLocalIdRangeExpression(Variable v, Expr constant, string ReadOrWrite, int Thread) { + Expr CTimesLocalId = verifier.MakeBVMul(constant.Clone() as Expr, + new IdentifierExpr(Token.NoToken, verifier.MakeThreadId(Token.NoToken, "X", Thread))); + + Expr CTimesLocalIdPlusC = verifier.MakeBVAdd(verifier.MakeBVMul(constant.Clone() as Expr, + new IdentifierExpr(Token.NoToken, verifier.MakeThreadId(Token.NoToken, "X", Thread))), constant.Clone() as Expr); + + Expr CTimesLocalIdLeqAccessedOffset = GPUVerifier.MakeBitVectorBinaryBoolean("BV32_LEQ", CTimesLocalId, OffsetXExpr(v, ReadOrWrite, Thread)); + + Expr AccessedOffsetLtCTimesLocalIdPlusC = verifier.MakeBVSlt(OffsetXExpr(v, ReadOrWrite, Thread), CTimesLocalIdPlusC); + + return Expr.Imp( + AccessHasOccurred(v, ReadOrWrite, Thread), + Expr.And(CTimesLocalIdLeqAccessedOffset, AccessedOffsetLtCTimesLocalIdPlusC)); + } + + private static IdentifierExpr AccessHasOccurred(Variable v, string ReadOrWrite, int Thread) { + return new IdentifierExpr(v.tok, new VariableDualiser(Thread, null, null).VisitVariable(GPUVerifier.MakeAccessHasOccurredVariable(v.Name, ReadOrWrite))); + } + + private static IdentifierExpr OffsetXExpr(Variable v, string ReadOrWrite, int Thread) { + return new IdentifierExpr(v.tok, new VariableDualiser(Thread, null, null).VisitVariable(GPUVerifier.MakeOffsetVariable(v.Name, ReadOrWrite))); + } + + protected void AddAccessedOffsetInRangeCTimesGlobalIdToCTimesGlobalIdPlusC(IRegion region, Variable v, Expr constant, string ReadOrWrite) { + Expr expr = MakeCTimesGloalIdRangeExpr(v, constant, ReadOrWrite, 1); + verifier.AddCandidateInvariant(region, + expr, "accessed offset in range [ C*global_id, (C+1)*global_id )"); + } + + private Expr MakeCTimesGloalIdRangeExpr(Variable v, Expr constant, string ReadOrWrite, int Thread) { + Expr CTimesGlobalId = verifier.MakeBVMul(constant.Clone() as Expr, + GlobalIdExpr("X", Thread)); + + Expr CTimesGlobalIdPlusC = verifier.MakeBVAdd(verifier.MakeBVMul(constant.Clone() as Expr, + GlobalIdExpr("X", Thread)), constant.Clone() as Expr); + + Expr CTimesGlobalIdLeqAccessedOffset = GPUVerifier.MakeBitVectorBinaryBoolean("BV32_LEQ", CTimesGlobalId, OffsetXExpr(v, ReadOrWrite, Thread)); + + Expr AccessedOffsetLtCTimesGlobalIdPlusC = verifier.MakeBVSlt(OffsetXExpr(v, ReadOrWrite, Thread), CTimesGlobalIdPlusC); + + Expr implication = Expr.Imp( + AccessHasOccurred(v, ReadOrWrite, Thread), + Expr.And(CTimesGlobalIdLeqAccessedOffset, AccessedOffsetLtCTimesGlobalIdPlusC)); + return implication; + } + + private void writeSourceLocToFile(QKeyValue kv, string path) { + TextWriter tw = new StreamWriter(path, true); + tw.Write("\n" + QKeyValue.FindIntAttribute(SourceLocationAttributes, "line", -1) + + "#" + QKeyValue.FindIntAttribute(SourceLocationAttributes, "col", -1) + + "#" + QKeyValue.FindStringAttribute(SourceLocationAttributes, "fname") + + "#" + QKeyValue.FindStringAttribute(SourceLocationAttributes, "dir")); + tw.Close(); + } + + protected void AddAccessedOffsetIsThreadLocalIdCandidateRequires(Procedure Proc, Variable v, string ReadOrWrite, int Thread) { + verifier.AddCandidateRequires(Proc, AccessedOffsetIsThreadLocalIdExpr(v, ReadOrWrite, Thread)); + } + + protected void AddAccessedOffsetIsThreadLocalIdCandidateEnsures(Procedure Proc, Variable v, string ReadOrWrite, int Thread) { + verifier.AddCandidateEnsures(Proc, AccessedOffsetIsThreadLocalIdExpr(v, ReadOrWrite, Thread)); + } + + + + } + + + + class FindReferencesToNamedVariableVisitor : StandardVisitor { + internal bool found = false; + private string name; + + internal FindReferencesToNamedVariableVisitor(string name) { + this.name = name; + } + + public override Variable VisitVariable(Variable node) { + if (GPUVerifier.StripThreadIdentifier(node.Name).Equals(name)) { + found = true; + } + return base.VisitVariable(node); + } + } + + + +} diff --git a/Source/GPUVerify/UniformExpressionAnalysisVisitor.cs b/Source/GPUVerify/UniformExpressionAnalysisVisitor.cs deleted file mode 100644 index 76f6b5de..00000000 --- a/Source/GPUVerify/UniformExpressionAnalysisVisitor.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Microsoft.Boogie;
-
-namespace GPUVerify
-{
- class UniformExpressionAnalysisVisitor : StandardVisitor
- {
-
- private bool isUniform = true;
- private Dictionary<string, bool> uniformityInfo;
-
- public UniformExpressionAnalysisVisitor(Dictionary<string, bool> uniformityInfo)
- {
- this.uniformityInfo = uniformityInfo;
- }
-
- public override Variable VisitVariable(Variable v)
- {
- if (!uniformityInfo.ContainsKey(v.Name))
- {
- isUniform = isUniform && (v is Constant);
- }
- else if (!uniformityInfo[v.Name])
- {
- isUniform = false;
- }
-
- return v;
- }
-
- internal bool IsUniform()
- {
- return isUniform;
- }
- }
-}
diff --git a/Source/Graph/Graph.cs b/Source/Graph/Graph.cs index 654360f4..2d2eb90b 100644 --- a/Source/Graph/Graph.cs +++ b/Source/Graph/Graph.cs @@ -1,948 +1,965 @@ -//-----------------------------------------------------------------------------
-//
-// Copyright (C) Microsoft Corporation. All Rights Reserved.
-//
-//-----------------------------------------------------------------------------
-using System;
-using System.Collections.Generic;
-using System.Text; // for StringBuilder
-using System.Diagnostics.Contracts;
-namespace Graphing {
-
- internal static class Util {
- private static string/*!*/ ListToString<T>(IEnumerable<T> xs) {
- Contract.Ensures(Contract.Result<string>() != null);
- StringBuilder sb = new StringBuilder();
- sb.Append("[");
- bool first = true;
- foreach (T/*!*/ x in xs) {
- Contract.Assert(x != null);
- if (!first)
- sb.Append(", ");
- sb.Append(x.ToString());
- first = false;
- }
- sb.Append("]");
- return sb.ToString();
- }
- public static string/*!*/ MapToString<Node>(Dictionary<Node, List<Node>> d) {
- Contract.Ensures(Contract.Result<string>() != null);
- StringBuilder sb = new StringBuilder();
- sb.Append("{");
- bool first = true;
- foreach (KeyValuePair<Node, List<Node>> de in d) {
- if (!first)
- sb.Append(", ");
- Contract.Assert(!object.Equals(de.Key,default(Node)));
- sb.Append(de.Key.ToString());
- sb.Append("~>");
- sb.Append(ListToString(de.Value));
- first = false;
- }
- sb.Append("}");
- return sb.ToString();
- }
- }
-
- // own struct to represent possibly undefined values, because Mono does
- // not like arrays with element type T! or T?
- public struct Maybe<T> {
- private T Value;
- public bool IsSet; // initialised with false by the default ctor
- public T Val {
- get {
- Contract.Assume(IsSet);
- return Value;
- }
- set {
- Value = value;
- IsSet = true;
- }
- }
- public void UnSet() {
- IsSet = false;
- }
- }
-
- public class DomRelation<Node> {
- // doms maps (unique) node numbers to the node numbers of the immediate dominator
- // to use it on Nodes, one needs the two way mapping between nodes and their numbers.
- private int[] doms; // 0 is unused: means undefined
- // here are the two mappings
- private Maybe<Node>[] postOrderNumberToNode;
- private Dictionary<Node, int> nodeToPostOrderNumber;
- private int sourceNum; // (number for) root of the graph
- private Node source; // root of the graph
- private Graph<Node> graph;
- private Dictionary<Node, List<Node>> immediateDominatorMap;
-
- [NotDelayed]
- internal DomRelation(Graph<Node> g, Node source) {
- this.graph = g;
- // slot 0 not used: nodes are numbered from 1 to n so zero
- // can represent undefined.
- this.source = source;
- //:base();
- this.NewComputeDominators();
- }
- public Dictionary<Node, List<Node>> ImmediateDominatorMap {
- get {
- Contract.Assume(this.immediateDominatorMap != null);
- return this.immediateDominatorMap;
- }
- }
- public bool DominatedBy(Node dominee, Node dominator) {
- Contract.Assume(this.nodeToPostOrderNumber != null);
- Contract.Assume(this.doms != null);
- int domineeNum = this.nodeToPostOrderNumber[dominee];
- int dominatorNum = this.nodeToPostOrderNumber[dominator];
- if (domineeNum == dominatorNum)
- return true;
- int currentNodeNum = this.doms[domineeNum];
- while (true) {
- if (currentNodeNum == dominatorNum)
- return true;
- if (currentNodeNum == this.sourceNum)
- return false;
- currentNodeNum = this.doms[currentNodeNum];
- }
- }
- private Dictionary<Node, List<Node>> domMap = null;
- [Pure]
- public override string ToString() {
- Contract.Assume(this.doms != null);
- int[] localDoms = this.doms;
- Contract.Assume(this.postOrderNumberToNode != null);
- if (domMap == null) {
- domMap = new Dictionary<Node, List<Node>>();
- for (int i = 1; i < localDoms.Length; i++) { // 0 slot is not used
- int domineeNum = i;
- int currentNodeNum = domineeNum;
- List<Node> dominators = new List<Node>();
- while (currentNodeNum != this.sourceNum) {
- dominators.Add(this.postOrderNumberToNode[currentNodeNum].Val);
- currentNodeNum = this.doms[currentNodeNum];
- }
- dominators.Add(this.postOrderNumberToNode[this.sourceNum].Val);
- domMap.Add(this.postOrderNumberToNode[i].Val, dominators);
- }
- }
- StringBuilder sb = new StringBuilder();
- sb.Append("{");
- bool first = true;
- foreach (KeyValuePair<Node, List<Node>> de in domMap) {
- if (!first)
- sb.Append(", ");
- Contract.Assert(!object.Equals(de.Key, default(Node)));
- sb.Append(de.Key.ToString());
- sb.Append("~>");
- sb.Append(ListToString(de.Value));
- first = false;
- }
- sb.Append("}");
- return sb.ToString();
- }
- private void PrintIntArray(int[] xs) {
- Console.Write("[");
- for (int i = 0; i < xs.Length; i++) {
- if (0 < i)
- Console.Write(", ");
- Console.Write(xs[i]);
- }
- Console.WriteLine("]");
- }
- public void PrintList<T>(IEnumerable<T> xs) {
- Console.Write("[");
- int i = 0;
- foreach (T/*!*/ x in xs) {
- Contract.Assert(x != null);
- if (0 < i)
- Console.Write(", ");
- Console.Write(x.ToString());
- i++;
- }
- Console.WriteLine("]");
- }
- public string/*!*/ ListToString<T>(IEnumerable<T> xs) {
- Contract.Ensures(Contract.Result<string>() != null);
- StringBuilder sb = new StringBuilder();
- sb.Append("[");
- bool first = true;
- foreach (T/*!*/ x in xs) {
- Contract.Assert(x != null);
- if (!first)
- sb.Append(", ");
- sb.Append(x.ToString());
- first = false;
- }
- sb.Append("]");
- return sb.ToString();
- }
-
- // Keith D. Cooper, Timothy J. Harvey, Ken Kennedy, "A Simple, Fast Dominance Algorithm ", Software Practice and Experience, 2001.
- // http://citeseer.ist.psu.edu/cooper01simple.html
- private void NewComputeDominators() {
- int n = this.graph.Nodes.Count;
- this.postOrderNumberToNode = new Maybe<Node>[n + 1];
- this.nodeToPostOrderNumber = new Dictionary<Node, int>();
- //HashSet<Node> visited = new HashSet<Node>();
- //int currentNumber = 1;
- Contract.Assume(this.source != null);
- //this.PostOrderVisit(this.source, visited, ref currentNumber);
- this.PostOrderVisitIterative(this.source);
- this.sourceNum = this.nodeToPostOrderNumber[source];
- // for (int i = 1; i <= n; i++){ Console.WriteLine(postOrderNumberToNode[i]); }
- this.doms = new int[n + 1]; // 0 is unused: means undefined
- Node start_node = this.source;
- this.doms[this.nodeToPostOrderNumber[start_node]] = this.nodeToPostOrderNumber[start_node];
- bool changed = true;
- // PrintIntArray(doms);
- while (changed) {
- changed = false;
- // for all nodes, b, in reverse postorder (except start_node)
- for (int nodeNum = n - 1; 1 <= nodeNum; nodeNum--) {
- Node b = this.postOrderNumberToNode[nodeNum].Val;
- IEnumerable<Node> predecessors = this.graph.Predecessors(b);
- // find a predecessor (i.e., a higher number) for which
- // the doms array has been set
- int new_idom = 0;
- int first_processed_predecessor = 0;
- #region new_idom <- number of first (processed) predecessor of b (pick one)
- foreach (Node p in predecessors) {
- if (this.doms[this.nodeToPostOrderNumber[p]] != 0) {
- int x = this.nodeToPostOrderNumber[p];
- new_idom = x;
- first_processed_predecessor = x;
- break;
- }
- }
- #endregion
- #region for all other predecessors, p, of b
- foreach (Node p in predecessors) {
- if (this.nodeToPostOrderNumber[p] == first_processed_predecessor) {
- continue;
- }
- if (this.doms[this.nodeToPostOrderNumber[p]] != 0)
- new_idom = intersect(this.nodeToPostOrderNumber[p], new_idom, this.doms);
- }
- #endregion
- if (this.doms[this.nodeToPostOrderNumber[b]] != new_idom) {
- this.doms[this.nodeToPostOrderNumber[b]] = new_idom;
- changed = true;
- }
- }
- }
- #region Populate the Immediate Dominator Map
- int sourceNum = this.nodeToPostOrderNumber[this.source];
- immediateDominatorMap = new Dictionary<Node, List<Node>>();
- for (int i = 1; i <= n; i++) {
- Node node = this.postOrderNumberToNode[i].Val;
- Node idomNode = this.postOrderNumberToNode[this.doms[i]].Val;
- if (i == sourceNum && this.doms[i] == sourceNum) {
- continue;
- }
- if (immediateDominatorMap.ContainsKey(idomNode)) {
- immediateDominatorMap[idomNode].Add(node);
- } else {
- List<Node> l = new List<Node>();
- l.Add(node);
- immediateDominatorMap.Add(idomNode, l);
- }
- }
- #endregion
- }
- private int intersect(int b1, int b2, int[] doms) {
- int finger1 = b1;
- int finger2 = b2;
- while (finger1 != finger2) {
- while (finger1 < finger2) {
- finger1 = doms[finger1];
- }
- while (finger2 < finger1) {
- finger2 = doms[finger2];
- }
- }
- return finger1;
- }
- private void PostOrderVisit(Node/*!*/ n, HashSet<Node> visited, ref int currentNumber) {
- Contract.Requires(n != null);
- if (visited.Contains(n))
- return;
- visited.Add(n);
- foreach (Node/*!*/ child in this.graph.Successors(n)) {
- Contract.Assert(child != null);
- PostOrderVisit(child, visited, ref currentNumber);
- }
- Contract.Assume(this.postOrderNumberToNode != null);
- Contract.Assume(this.nodeToPostOrderNumber != null);
- this.postOrderNumberToNode[currentNumber].Val = n;
- this.nodeToPostOrderNumber[n] = currentNumber;
- currentNumber++;
- return;
- }
- // Iterative version: mimics the above recursive procedure
- private void PostOrderVisitIterative(Node n)
- {
- Contract.Requires(n != null);
- var visited = new HashSet<Node>();
- var grey = new HashSet<Node>();
- var stack = new Stack<Node>();
-
- int currentNumber = 1;
-
- stack.Push(n);
- visited.Add(n);
-
- while (stack.Count != 0)
- {
- var curr = stack.Pop();
-
- if (grey.Contains(curr))
- {
- Contract.Assume(this.postOrderNumberToNode != null);
- Contract.Assume(this.nodeToPostOrderNumber != null);
- this.postOrderNumberToNode[currentNumber].Val = curr;
- this.nodeToPostOrderNumber[curr] = currentNumber;
- currentNumber++;
- }
- else
- {
- grey.Add(curr);
- stack.Push(curr);
- foreach (Node/*!*/ child in this.graph.Successors(curr))
- {
- Contract.Assert(child != null);
- if (!visited.Contains(child))
- {
- visited.Add(child);
- stack.Push(child);
- }
- }
- }
-
- }
-
-
- }
- }
-
- public class Graph<Node> {
- private HashSet<Tuple<Node/*!*/, Node/*!*/>> es;
- private HashSet<Node> ns;
- private Node source;
- private bool reducible;
- private HashSet<Node> headers;
- private Dictionary<Node, HashSet<Node>> backEdgeNodes;
- private Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>> naturalLoops;
- private HashSet<Node> splitCandidates;
-
- private DomRelation<Node> dominatorMap = null;
- private Dictionary<Node, HashSet<Node>> predCache = new Dictionary<Node, HashSet<Node>>();
- private Dictionary<Node, HashSet<Node>> succCache = new Dictionary<Node, HashSet<Node>>();
- private bool predComputed;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(es == null || Contract.ForAll(es, p => p.Item1 != null && p.Item2 != null));
- Contract.Invariant(naturalLoops == null || Contract.ForAll(naturalLoops.Keys, p => p.Item2 != null && p.Item1 != null));
- }
-
- private class PreHeader {
- Node/*!*/ myHeader;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(myHeader != null);
- }
-
- internal PreHeader(Node/*!*/ h) {
- Contract.Requires(h != null);
- myHeader = h;
- }
-
- [Pure]
- public override string/*!*/ ToString() {
- Contract.Ensures(Contract.Result<string>() != null);
- return "#" + myHeader.ToString();
- }
- }
-
- public Graph(HashSet<Tuple<Node/*!*/, Node/*!*/>> edges) {
-
- Contract.Requires(cce.NonNullElements(edges) && Contract.ForAll(edges, p => p.Item1 != null && p.Item2 != null));
- es = edges;
-
- // original A#
- //ns = Set<Node>{ x : <x,y> in es } + Set<Node>{ y : <x,y> in es };
-
- // closest Spec#
- //ns = new Set<Node>{ Tuple<Node,Node> p in edges; p.Item1 } + new Set<Node>{ Tuple<Node,Node> p in edges; p.Item2 };
-
- //
- HashSet<Node> temp = new HashSet<Node>();
- foreach (Tuple<Node/*!*/, Node/*!*/> p in edges) {
- Contract.Assert(p.Item1 != null);
- temp.Add(p.Item1);
- Contract.Assert(p.Item2 != null);
- temp.Add(p.Item2);
- }
- ns = temp;
- }
- public Graph() {
- es = new HashSet<Tuple<Node/*!*/, Node/*!*/>>();
- ns = new HashSet<Node>();
- }
-
- // BUGBUG: Set<T>.ToString() should return a non-null string
- [Pure]
- public override string/*!*/ ToString() {
- return "" + es.ToString();
- }
-
- public void AddSource(Node/*!*/ x) {
- Contract.Requires(x != null);
- // BUGBUG: This generates bad code in the compiler
- //ns += new Set<Node>{x};
- ns.Add(x);
- source = x;
- }
-
- public void AddEdge(Node/*!*/ source, Node/*!*/ dest) {
- Contract.Requires(source != null);
- Contract.Requires(dest != null);
- //es += Set<Edge>{<source,dest>};
- //ns += Set<Node>{source, dest};
- es.Add(new Tuple<Node/*!*/, Node/*!*/>(source, dest));
- ns.Add(source);
- ns.Add(dest);
- predComputed = false;
- }
-
- public HashSet<Node> Nodes {
- get {
- return ns;
- }
- }
- public IEnumerable<Tuple<Node/*!*/, Node/*!*/>> Edges {
- get {
- Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerable<Tuple<Node, Node>>>())
- && Contract.ForAll(Contract.Result<IEnumerable<Tuple<Node, Node>>>(), n =>
- n.Item1 != null && n.Item2 != null));
- return es;
- }
- }
-
- public bool Edge(Node/*!*/ x, Node/*!*/ y) {
- Contract.Requires(x != null);
- Contract.Requires(y != null);
- // original A#
- // return <x,y> in es;
- return es.Contains(new Tuple<Node/*!*/, Node/*!*/>(x, y));
- }
-
- private void ComputePredSuccCaches() {
- if (predComputed)
- return;
- predComputed = true;
- predCache = new Dictionary<Node, HashSet<Node>>();
- succCache = new Dictionary<Node, HashSet<Node>>();
-
- foreach (Node n in Nodes) {
- predCache[n] = new HashSet<Node>();
- succCache[n] = new HashSet<Node>();
- }
-
- foreach (Tuple<Node/*!*/, Node/*!*/> p in Edges) {
- Contract.Assert(p.Item1 != null);
- Contract.Assert(p.Item2 != null);
- HashSet<Node> tmp;
-
- tmp = predCache[p.Item2];
- tmp.Add(p.Item1);
- predCache[p.Item2] = tmp;
-
- tmp = succCache[p.Item1];
- tmp.Add(p.Item2);
- succCache[p.Item1] = tmp;
- }
- }
-
- public IEnumerable<Node> Predecessors(Node n) {
- // original A#
- //Set<Node> result = Set{ x : x in Nodes, Edge(x,n) };
-
- ComputePredSuccCaches();
- return predCache[n];
- }
-
- public IEnumerable<Node> Successors(Node n) {
- ComputePredSuccCaches();
- return succCache[n];
- }
-
- public List<Node> SuccessorsAsList(Node n) {
- ComputePredSuccCaches();
- List<Node> ret = new List<Node>();
- foreach (Node s in succCache[n])
- ret.Add(s);
- return ret;
- }
-
- public DomRelation<Node> /*Map<Node,Set<Node>>*/ DominatorMap {
- get {
- Contract.Assert(source != null);
- if (this.dominatorMap == null) {
- this.dominatorMap = new DomRelation<Node>(this, this.source);
- }
- return this.dominatorMap;
- }
- }
-
- public Dictionary<Node, List<Node>> ImmediateDominatorMap {
- get {
- Contract.Assert(source != null);
- if (this.dominatorMap == null) {
- this.dominatorMap = new DomRelation<Node>(this, this.source);
- }
- return this.dominatorMap.ImmediateDominatorMap;
- }
- }
- public List<Node> ImmediatelyDominatedBy(Node/*!*/ n) {
- Contract.Requires(n != null);
- List<Node> dominees;
- this.ImmediateDominatorMap.TryGetValue(n, out dominees);
- return dominees == null ? new List<Node>() : dominees;
- }
-
- public IEnumerable<Node/*?*/> TopologicalSort() {
- bool acyclic;
- List<Node> sortedList;
- this.TarjanTopSort(out acyclic, out sortedList);
- return acyclic ? sortedList : new List<Node>();
- }
- // From Tarjan 1972
- public void TarjanTopSort(out bool acyclic, out List<Node> sortedNodes) {
- int n = this.Nodes.Count;
- if (n == 0) {
- acyclic = true;
- sortedNodes = new List<Node>();
- return;
- }
- int[] incomingEdges = new int[n];
- // need an arbitrary numbering for the nodes to use as indices into
- // the arrays used within this algorithm
- Dictionary<Node, int> nodeToNumber = new Dictionary<Node, int>(n);
- Maybe<Node>[] numberToNode = new Maybe<Node>[n];
- int counter = 0;
- foreach (Node node in this.Nodes) {
- numberToNode[counter].Val = node;
- nodeToNumber[node] = counter;
- counter++;
- }
- foreach (Tuple<Node/*!*/, Node/*!*/> e in this.Edges) {
- Contract.Assert(e.Item1 != null);
- Contract.Assert(e.Item2 != null);
- Node/*!*/ target = e.Item2;
- incomingEdges[nodeToNumber[target]]++;
- }
- List<Node> sorted = new List<Node>();
- int sortedIndex = 0;
- while (sortedIndex < n) {
- // find a root (i.e., its index)
- int rootIndex = -1;
- for (int i = 0; i < n; i++) {
- if (incomingEdges[i] == 0) {
- rootIndex = i;
- break;
- }
- }
- if (rootIndex == -1) {
- acyclic = false;
- sortedNodes = new List<Node>();
- return;
- }
- // mark root so it won't be used again
- incomingEdges[rootIndex] = -1;
- Node root = numberToNode[rootIndex].Val;
- sorted.Add(root);
- ++sortedIndex;
- foreach (Node s in this.Successors(root)) {
- incomingEdges[nodeToNumber[s]]--;
- }
- }
- acyclic = true;
- sortedNodes = sorted;
- return;
- }
- private IEnumerable<Node> OldTopologicalSort() {
- Tuple<bool, List<Node>> result = this.TopSort();
- return result.Item1 ? result.Item2 : (IEnumerable<Node>)new List<Node>();
- }
- // From AsmL distribution example
- private Tuple<bool, List<Node>> TopSort()
- {
- List<Node> S = new List<Node>();
- HashSet<Node> V = this.Nodes;
- HashSet<Node> X = new HashSet<Node>();
- foreach (Node/*!*/ n in V) {
- Contract.Assert(n != null);
- X.Add(n);
- }
- bool change = true;
- while (change)
- // invariant: X = V - S
- {
- change = false;
- if (X.Count > 0) {
- foreach (Node/*!*/ n in X) {
- Contract.Assert(n != null);
- // see if n has any incoming edges from any other node in X
- bool inDegreeZero = true;
- foreach (Node/*!*/ u in X) {
- Contract.Assert(u != null);
- if (this.Edge(u, n)) {
- inDegreeZero = false;
- break; // no point looking further
- }
- }
- if (inDegreeZero) {
- S.Add(n);
- X.Remove(n);
- change = true;
- break; // might as well go back and start looking through X from the beginning
- }
- }
- // Then we made it all the way through X without finding a source node
- if (!change) {
- return new Tuple<bool, List<Node>>(false, new List<Node>());
- }
- }
- }
- return new Tuple<bool, List<Node>>(true, S);
- }
-
- public static bool Acyclic(Graph<Node> g, Node source) {
- bool acyclic;
- List<Node> sortedList;
- g.TarjanTopSort(out acyclic, out sortedList);
- return acyclic;
- }
-
- // [Dragon, Fig. 10.15, p. 604. Algorithm for constructing the natural loop.]
- static HashSet<Node> NaturalLoop(Graph<Node> g, Tuple<Node/*!*/, Node/*!*/> backEdge)
- {
- Contract.Requires(backEdge.Item1 != null && backEdge.Item2 != null);
- Node/*!*/ n = backEdge.Item1;
- Node/*!*/ d = backEdge.Item2;
- Stack<Node> stack = new Stack<Node>();
- HashSet<Node> loop = new HashSet<Node>();
- loop.Add(d);
- if (!n.Equals(d)) // then n is not in loop
- {
- loop.Add(n);
- stack.Push(n); // push n onto stack
- }
- while (stack.Count > 0) // not empty
- {
- Node m = stack.Peek();
- stack.Pop(); // pop stack
- foreach (Node/*!*/ p in g.Predecessors(m)) {
- Contract.Assert(p != null);
- if (!(loop.Contains(p))) {
- loop.Add(p);
- stack.Push(p); // push p onto stack
- }
- }
- }
- return loop;
- }
-
- internal struct ReducibleResult {
- internal bool reducible;
- internal HashSet<Node> headers;
- internal Dictionary<Node, HashSet<Node>> backEdgeNodes;
- internal Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>> naturalLoops;
- internal HashSet<Node> splitCandidates;
- [ContractInvariantMethod]
- void ObjectInvariant() {
- Contract.Invariant(Contract.ForAll(naturalLoops.Keys, p => p.Item1 != null && p.Item2 != null));
- }
-
- internal ReducibleResult(bool b, HashSet<Node> headers, Dictionary<Node, HashSet<Node>> backEdgeNodes, Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>> naturalLoops, HashSet<Node> splitCandidates)
- {
- Contract.Requires(naturalLoops == null || Contract.ForAll(naturalLoops.Keys, Key => Key.Item1 != null && Key.Item2 != null));
- this.reducible = b;
- this.headers = headers;
- this.backEdgeNodes = backEdgeNodes;
- this.naturalLoops = naturalLoops;
- this.splitCandidates = splitCandidates;
- }
-
- }
-
- // [Dragon, p. 606]
- static ReducibleResult ComputeReducible(Graph<Node> g, Node source) {
- // first, compute the dom relation
- DomRelation<Node> /*Map<Node,Set<Node>>*/ D = g.DominatorMap;
- return ComputeReducible(g, source, D);
- }
-
- static HashSet<Node> FindCycle(Graph<Node> g, Node source) {
- Stack<Tuple<Node, List<Node>>> stack = new Stack<Tuple<Node, List<Node>>>();
- HashSet<Node> stackAsSet = new HashSet<Node>();
- HashSet<Node> visited = new HashSet<Node>();
- stack.Push(new Tuple<Node, List<Node>>(source, g.SuccessorsAsList(source)));
- stackAsSet.Add(source);
- while (stack.Count > 0) {
- Tuple<Node, List<Node>> tuple = stack.Peek();
- List<Node> children = tuple.Item2;
- if (children.Count == 0) {
- stack.Pop();
- stackAsSet.Remove(tuple.Item1);
- continue;
- }
- Node n = children[0];
- children.RemoveAt(0);
- if (stackAsSet.Contains(n)) {
- HashSet<Node> ret = new HashSet<Node>();
- ret.Add(n);
- while (true) {
- Node x = stack.Pop().Item1;
- if (x.Equals(n))
- return ret;
- }
- }
- if (visited.Contains(n))
- continue;
- stack.Push(new Tuple<Node, List<Node>>(n, g.SuccessorsAsList(n)));
- visited.Add(n);
- stackAsSet.Add(n);
- System.Diagnostics.Debug.Assert(stack.Count == stackAsSet.Count);
- }
- return new HashSet<Node>();
- }
-
- // [Dragon, p. 606]
- static ReducibleResult ComputeReducible(Graph<Node> g,
- Node source,
- DomRelation<Node>/*!*/ DomRelation) {
- Contract.Requires(DomRelation != null);
-
- //Console.WriteLine("[" + DateTime.Now +"]: begin ComputeReducible");
- IEnumerable<Tuple<Node/*!*/, Node/*!*/>> edges = g.Edges;
- Contract.Assert(Contract.ForAll(edges, n => n.Item1 != null && n.Item2 != null));
- HashSet<Tuple<Node/*!*/, Node/*!*/>> backEdges = new HashSet<Tuple<Node/*!*/, Node/*!*/>>();
- HashSet<Tuple<Node/*!*/, Node/*!*/>> nonBackEdges = new HashSet<Tuple<Node/*!*/, Node/*!*/>>();
- foreach (Tuple<Node/*!*/, Node/*!*/> e in edges) {
- Contract.Assert(e.Item1 != null);
- Contract.Assert(e.Item2 != null);
- Node x = e.Item1;
- Node y = e.Item2; // so there is an edge from x to y
- if (DomRelation.DominatedBy(x, y)) { // y dom x: which means y dominates x
- backEdges.Add(e);
- } else {
- nonBackEdges.Add(e);
- }
- }
- Graph<Node> withoutBackEdges = new Graph<Node>(nonBackEdges);
- if (!Acyclic(withoutBackEdges, source)) {
- return new ReducibleResult(false,
- new HashSet<Node>(),
- new Dictionary<Node, HashSet<Node>>(),
- new Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>>(),
- FindCycle(withoutBackEdges, source));
- } else {
- // original A#:
- //Set<Node> headers = Set{ d : <n,d> in backEdges };
- HashSet<Node> headers = new HashSet<Node>();
- foreach (Tuple<Node/*!*/, Node/*!*/> e in backEdges) {
-
- Contract.Assert(e.Item1 != null);
- Contract.Assert(e.Item2 != null);
- headers.Add(e.Item2);
- }
- // original A#:
- //Map<Node,Set<Node>> backEdgeNodes = Map{ h -> bs : h in headers, bs = Set<Node>{ b : <b,x> in backEdges, x == h } };
- Dictionary<Node, HashSet<Node>> backEdgeNodes = new Dictionary<Node, HashSet<Node>>();
- foreach (Node/*!*/ h in headers) {
- Contract.Assert(h != null);
- HashSet<Node> bs = new HashSet<Node>();
- foreach (Tuple<Node, Node> backedge in backEdges) {
- Contract.Assert(backedge.Item1 != null);
- Contract.Assert(backedge.Item2 != null);
- if (backedge.Item2.Equals(h)) {
- bs.Add(backedge.Item1);
- }
- }
- backEdgeNodes.Add(h, bs);
- }
-
- // original A#:
- //Map<Tuple<Node,Node>,Set<Node>> naturalLoops = Map{ e -> NaturalLoop(g,e) : e in backEdges };
- Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>> naturalLoops = new Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>>();
- foreach (Tuple<Node/*!*/, Node/*!*/> e in backEdges) {
- Contract.Assert(e.Item1 != null && e.Item2 != null);
- naturalLoops.Add(e, NaturalLoop(g, e));
- }
-
- //Console.WriteLine("[" + DateTime.Now +"]: end ComputeReducible");
- return new ReducibleResult(true, headers, backEdgeNodes, naturalLoops, new HashSet<Node>());
- }
- }
-
- public bool Reducible {
- get {
- return reducible;
- }
- }
- public IEnumerable<Node> Headers {
- get {
- return headers;
- }
- }
- public IEnumerable<Node> BackEdgeNodes(Node/*!*/ h) {
- Contract.Requires(h != null);
- // original A#:
- //return h in backEdgeNodes ? backEdgeNodes[h] : null;
- return (backEdgeNodes.ContainsKey(h) ? backEdgeNodes[h] : (IEnumerable<Node>)new List<Node>());
- }
- public IEnumerable<Node> NaturalLoops(Node/*!*/ header, Node/*!*/ backEdgeNode) {
- Contract.Requires(header != null);
- Contract.Requires(backEdgeNode != null);
- Tuple<Node/*!*/, Node/*!*/> e = new Tuple<Node/*!*/, Node/*!*/>(backEdgeNode, header);
- return naturalLoops.ContainsKey(e) ? naturalLoops[e] : (IEnumerable<Node>)new List<Node>();
- }
- public HashSet<Node> SplitCandidates {
- get {
- return splitCandidates;
- }
- }
- public void ComputeLoops() {
- ReducibleResult r = ComputeReducible(this, this.source);
- this.reducible = r.reducible;
- this.headers = r.headers;
- this.backEdgeNodes = r.backEdgeNodes;
- this.naturalLoops = r.naturalLoops;
- this.splitCandidates = r.splitCandidates;
- return;
- }
-
- public IEnumerable<Node> SortHeadersByDominance()
- {
- Graph<Node> dag = new Graph<Node>();
- foreach (Node b in headers)
- {
- dag.AddSource(b);
- foreach (Node c in headers)
- {
- if (b.Equals(c)) continue;
- if (DominatorMap.DominatedBy(b, c))
- {
- System.Diagnostics.Debug.Assert(!DominatorMap.DominatedBy(c, b));
- dag.AddEdge(b, c);
- }
- }
- }
- return dag.TopologicalSort();
- }
-
- public string ToDot(Func<Node, string> NodeLabel = null, Func<Node, string> NodeStyle = null) {
- NodeLabel = NodeLabel ?? (n => n.ToString());
- NodeStyle = NodeStyle ?? (n => "[shape=box]");
- var s = new StringBuilder();
- s.AppendLine("digraph G {");
- foreach (var n in Nodes)
- s.AppendLine(" \"" + NodeLabel(n) + "\" " + NodeStyle(n) + ";");
- foreach (var e in Edges)
- s.AppendLine(" \"" + NodeLabel(e.Item1) + "\" -> \"" + NodeLabel(e.Item2) + "\";");
- s.AppendLine("}");
- return s.ToString();
- }
- } // end: class Graph
-
- public class GraphProgram {
- static void TestGraph<T>(T/*!*/ source, params Tuple<T/*!*/, T/*!*/>[] edges) {
- Contract.Requires(source != null);
- Contract.Requires(Contract.ForAll(edges, pair => pair.Item1 != null && pair.Item2 != null));
- HashSet<Tuple<T/*!*/, T/*!*/>> es = new HashSet<Tuple<T/*!*/, T/*!*/>>();
- foreach (Tuple<T/*!*/, T/*!*/> e in edges) {
- Contract.Assert(e.Item1 != null && e.Item2 != null);
- es.Add(e);
- }
- Graph<T> g = new Graph<T>(es);
- g.AddSource(source);
- Console.WriteLine("G = " + g);
- g.ComputeLoops();
- Console.WriteLine("G's Dominator Map = " + g.DominatorMap);
- Console.WriteLine("G's Immediate Dominator Map = " + Util.MapToString(g.ImmediateDominatorMap));
- Console.WriteLine("G is reducible: " + (g.Reducible ? "yes" : "no"));
- }
-
- static void Main(string[] args)
- //requires forall{string s in args; s != null};
- {
- Console.WriteLine("Spec# says hello!");
- // This generates bad IL -- need to fix a bug in the compiler
- //Graph<int> g = new Graph<int>(new Set<Tuple<int,int>>{ new Tuple<int,int>(1,2), new Tuple<int,int>(1,3), new Tuple<int,int>(2,3) });
-
- Console.WriteLine("");
- TestGraph<char>('a',
- new Tuple<char, char>('a', 'b'),
- new Tuple<char, char>('a', 'c'),
- new Tuple<char, char>('b', 'c')
- );
-
- Console.WriteLine("");
- TestGraph<char>('a',
- new Tuple<char, char>('a', 'b'),
- new Tuple<char, char>('a', 'c'),
- new Tuple<char, char>('b', 'd'),
- new Tuple<char, char>('c', 'e'),
- new Tuple<char, char>('c', 'f'),
- new Tuple<char, char>('d', 'e'),
- new Tuple<char, char>('e', 'd'),
- new Tuple<char, char>('e', 'f'),
- new Tuple<char, char>('f', 'e')
- );
-
- Console.WriteLine("");
- TestGraph<char>('a',
- new Tuple<char, char>('a', 'b'),
- new Tuple<char, char>('a', 'c'),
- new Tuple<char, char>('b', 'c'),
- new Tuple<char, char>('c', 'b')
- );
-
- Console.WriteLine("");
- TestGraph<int>(1,
- new Tuple<int, int>(1, 2),
- new Tuple<int, int>(1, 3),
- new Tuple<int, int>(2, 3)
- );
-
- Console.WriteLine("");
- TestGraph<int>(1,
- new Tuple<int, int>(1, 2),
- new Tuple<int, int>(1, 3),
- new Tuple<int, int>(2, 3),
- new Tuple<int, int>(3, 2)
- );
-
- Console.WriteLine("");
- TestGraph<int>(2,
- new Tuple<int, int>(2, 3),
- new Tuple<int, int>(2, 4),
- new Tuple<int, int>(3, 2)
- );
-
- Console.WriteLine("");
- TestGraph<char>('a',
- new Tuple<char, char>('a', 'b'),
- new Tuple<char, char>('a', 'c'),
- new Tuple<char, char>('b', 'c'),
- new Tuple<char, char>('b', 'b')
- );
-
-
- }
- }
-
-}
+//----------------------------------------------------------------------------- +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +//----------------------------------------------------------------------------- +using System; +using System.Collections.Generic; +using System.Text; // for StringBuilder +using System.Diagnostics.Contracts; +namespace Graphing { + + internal static class Util { + private static string/*!*/ ListToString<T>(IEnumerable<T> xs) { + Contract.Ensures(Contract.Result<string>() != null); + StringBuilder sb = new StringBuilder(); + sb.Append("["); + bool first = true; + foreach (T/*!*/ x in xs) { + Contract.Assert(x != null); + if (!first) + sb.Append(", "); + sb.Append(x.ToString()); + first = false; + } + sb.Append("]"); + return sb.ToString(); + } + public static string/*!*/ MapToString<Node>(Dictionary<Node, List<Node>> d) { + Contract.Ensures(Contract.Result<string>() != null); + StringBuilder sb = new StringBuilder(); + sb.Append("{"); + bool first = true; + foreach (KeyValuePair<Node, List<Node>> de in d) { + if (!first) + sb.Append(", "); + Contract.Assert(!object.Equals(de.Key,default(Node))); + sb.Append(de.Key.ToString()); + sb.Append("~>"); + sb.Append(ListToString(de.Value)); + first = false; + } + sb.Append("}"); + return sb.ToString(); + } + } + + // own struct to represent possibly undefined values, because Mono does + // not like arrays with element type T! or T? + public struct Maybe<T> { + private T Value; + public bool IsSet; // initialised with false by the default ctor + public T Val { + get { + Contract.Assume(IsSet); + return Value; + } + set { + Value = value; + IsSet = true; + } + } + public void UnSet() { + IsSet = false; + } + } + + public class DomRelation<Node> { + // doms maps (unique) node numbers to the node numbers of the immediate dominator + // to use it on Nodes, one needs the two way mapping between nodes and their numbers. + private int[] doms; // 0 is unused: means undefined + // here are the two mappings + private Maybe<Node>[] postOrderNumberToNode; + private Dictionary<Node, int> nodeToPostOrderNumber; + private int sourceNum; // (number for) root of the graph + private Node source; // root of the graph + private Graph<Node> graph; + private Dictionary<Node, List<Node>> immediateDominatorMap; + + [NotDelayed] + internal DomRelation(Graph<Node> g, Node source) { + this.graph = g; + // slot 0 not used: nodes are numbered from 1 to n so zero + // can represent undefined. + this.source = source; + //:base(); + this.NewComputeDominators(); + } + public Dictionary<Node, List<Node>> ImmediateDominatorMap { + get { + Contract.Assume(this.immediateDominatorMap != null); + return this.immediateDominatorMap; + } + } + public bool DominatedBy(Node dominee, Node dominator, List<Node> path = null) { + Contract.Assume(this.nodeToPostOrderNumber != null); + Contract.Assume(this.doms != null); + int domineeNum = this.nodeToPostOrderNumber[dominee]; + int dominatorNum = this.nodeToPostOrderNumber[dominator]; + if (domineeNum == dominatorNum) + return true; + int currentNodeNum = this.doms[domineeNum]; + while (true) { + if (currentNodeNum == dominatorNum) + return true; + if (currentNodeNum == this.sourceNum) + return false; + if (path != null) + path.Add(postOrderNumberToNode[currentNodeNum].Val); + currentNodeNum = this.doms[currentNodeNum]; + } + } + private Dictionary<Node, List<Node>> domMap = null; + [Pure] + public override string ToString() { + Contract.Assume(this.doms != null); + int[] localDoms = this.doms; + Contract.Assume(this.postOrderNumberToNode != null); + if (domMap == null) { + domMap = new Dictionary<Node, List<Node>>(); + for (int i = 1; i < localDoms.Length; i++) { // 0 slot is not used + int domineeNum = i; + int currentNodeNum = domineeNum; + List<Node> dominators = new List<Node>(); + while (currentNodeNum != this.sourceNum) { + dominators.Add(this.postOrderNumberToNode[currentNodeNum].Val); + currentNodeNum = this.doms[currentNodeNum]; + } + dominators.Add(this.postOrderNumberToNode[this.sourceNum].Val); + domMap.Add(this.postOrderNumberToNode[i].Val, dominators); + } + } + StringBuilder sb = new StringBuilder(); + sb.Append("{"); + bool first = true; + foreach (KeyValuePair<Node, List<Node>> de in domMap) { + if (!first) + sb.Append(", "); + Contract.Assert(!object.Equals(de.Key, default(Node))); + sb.Append(de.Key.ToString()); + sb.Append("~>"); + sb.Append(ListToString(de.Value)); + first = false; + } + sb.Append("}"); + return sb.ToString(); + } + private void PrintIntArray(int[] xs) { + Console.Write("["); + for (int i = 0; i < xs.Length; i++) { + if (0 < i) + Console.Write(", "); + Console.Write(xs[i]); + } + Console.WriteLine("]"); + } + public void PrintList<T>(IEnumerable<T> xs) { + Console.Write("["); + int i = 0; + foreach (T/*!*/ x in xs) { + Contract.Assert(x != null); + if (0 < i) + Console.Write(", "); + Console.Write(x.ToString()); + i++; + } + Console.WriteLine("]"); + } + public string/*!*/ ListToString<T>(IEnumerable<T> xs) { + Contract.Ensures(Contract.Result<string>() != null); + StringBuilder sb = new StringBuilder(); + sb.Append("["); + bool first = true; + foreach (T/*!*/ x in xs) { + Contract.Assert(x != null); + if (!first) + sb.Append(", "); + sb.Append(x.ToString()); + first = false; + } + sb.Append("]"); + return sb.ToString(); + } + + // Keith D. Cooper, Timothy J. Harvey, Ken Kennedy, "A Simple, Fast Dominance Algorithm ", Software Practice and Experience, 2001. + // http://citeseer.ist.psu.edu/cooper01simple.html + private void NewComputeDominators() { + int n = this.graph.Nodes.Count; + this.postOrderNumberToNode = new Maybe<Node>[n + 1]; + this.nodeToPostOrderNumber = new Dictionary<Node, int>(); + //HashSet<Node> visited = new HashSet<Node>(); + //int currentNumber = 1; + Contract.Assume(this.source != null); + //this.PostOrderVisit(this.source, visited, ref currentNumber); + this.PostOrderVisitIterative(this.source); + this.sourceNum = this.nodeToPostOrderNumber[source]; + // for (int i = 1; i <= n; i++){ Console.WriteLine(postOrderNumberToNode[i]); } + this.doms = new int[n + 1]; // 0 is unused: means undefined + Node start_node = this.source; + this.doms[this.nodeToPostOrderNumber[start_node]] = this.nodeToPostOrderNumber[start_node]; + bool changed = true; + // PrintIntArray(doms); + while (changed) { + changed = false; + // for all nodes, b, in reverse postorder (except start_node) + for (int nodeNum = n - 1; 1 <= nodeNum; nodeNum--) { + Node b = this.postOrderNumberToNode[nodeNum].Val; + IEnumerable<Node> predecessors = this.graph.Predecessors(b); + // find a predecessor (i.e., a higher number) for which + // the doms array has been set + int new_idom = 0; + int first_processed_predecessor = 0; + #region new_idom <- number of first (processed) predecessor of b (pick one) + foreach (Node p in predecessors) { + if (this.doms[this.nodeToPostOrderNumber[p]] != 0) { + int x = this.nodeToPostOrderNumber[p]; + new_idom = x; + first_processed_predecessor = x; + break; + } + } + #endregion + #region for all other predecessors, p, of b + foreach (Node p in predecessors) { + if (this.nodeToPostOrderNumber[p] == first_processed_predecessor) { + continue; + } + if (this.doms[this.nodeToPostOrderNumber[p]] != 0) + new_idom = intersect(this.nodeToPostOrderNumber[p], new_idom, this.doms); + } + #endregion + if (this.doms[this.nodeToPostOrderNumber[b]] != new_idom) { + this.doms[this.nodeToPostOrderNumber[b]] = new_idom; + changed = true; + } + } + } + #region Populate the Immediate Dominator Map + int sourceNum = this.nodeToPostOrderNumber[this.source]; + immediateDominatorMap = new Dictionary<Node, List<Node>>(); + for (int i = 1; i <= n; i++) { + Node node = this.postOrderNumberToNode[i].Val; + Node idomNode = this.postOrderNumberToNode[this.doms[i]].Val; + if (i == sourceNum && this.doms[i] == sourceNum) { + continue; + } + if (immediateDominatorMap.ContainsKey(idomNode)) { + immediateDominatorMap[idomNode].Add(node); + } else { + List<Node> l = new List<Node>(); + l.Add(node); + immediateDominatorMap.Add(idomNode, l); + } + } + #endregion + } + private int intersect(int b1, int b2, int[] doms) { + int finger1 = b1; + int finger2 = b2; + while (finger1 != finger2) { + while (finger1 < finger2) { + finger1 = doms[finger1]; + } + while (finger2 < finger1) { + finger2 = doms[finger2]; + } + } + return finger1; + } + private void PostOrderVisit(Node/*!*/ n, HashSet<Node> visited, ref int currentNumber) { + Contract.Requires(n != null); + if (visited.Contains(n)) + return; + visited.Add(n); + foreach (Node/*!*/ child in this.graph.Successors(n)) { + Contract.Assert(child != null); + PostOrderVisit(child, visited, ref currentNumber); + } + Contract.Assume(this.postOrderNumberToNode != null); + Contract.Assume(this.nodeToPostOrderNumber != null); + this.postOrderNumberToNode[currentNumber].Val = n; + this.nodeToPostOrderNumber[n] = currentNumber; + currentNumber++; + return; + } + // Iterative version: mimics the above recursive procedure + private void PostOrderVisitIterative(Node n) + { + Contract.Requires(n != null); + var visited = new HashSet<Node>(); + var grey = new HashSet<Node>(); + var stack = new Stack<Node>(); + + int currentNumber = 1; + + stack.Push(n); + visited.Add(n); + + while (stack.Count != 0) + { + var curr = stack.Pop(); + + if (grey.Contains(curr)) + { + Contract.Assume(this.postOrderNumberToNode != null); + Contract.Assume(this.nodeToPostOrderNumber != null); + this.postOrderNumberToNode[currentNumber].Val = curr; + this.nodeToPostOrderNumber[curr] = currentNumber; + currentNumber++; + } + else + { + grey.Add(curr); + stack.Push(curr); + foreach (Node/*!*/ child in this.graph.Successors(curr)) + { + Contract.Assert(child != null); + if (!visited.Contains(child)) + { + visited.Add(child); + stack.Push(child); + } + } + } + + } + + + } + + public Node LeastCommonAncestor(Node n1, Node n2) + { + var nums = new HashSet<int>(); + int num1 = nodeToPostOrderNumber[n1], num2 = nodeToPostOrderNumber[n2]; + + while (true) + { + if (!nums.Add(num1)) + return postOrderNumberToNode[num1].Val; + if (!nums.Add(num2)) + return postOrderNumberToNode[num2].Val; + num1 = doms[num1]; num2 = doms[num2]; + } + } + } + + public class Graph<Node> { + private HashSet<Tuple<Node/*!*/, Node/*!*/>> es; + private HashSet<Node> ns; + private Node source; + private bool reducible; + private HashSet<Node> headers; + private Dictionary<Node, HashSet<Node>> backEdgeNodes; + private Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>> naturalLoops; + private HashSet<Node> splitCandidates; + + private DomRelation<Node> dominatorMap = null; + private Dictionary<Node, HashSet<Node>> predCache = new Dictionary<Node, HashSet<Node>>(); + private Dictionary<Node, HashSet<Node>> succCache = new Dictionary<Node, HashSet<Node>>(); + private bool predComputed; + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(es == null || Contract.ForAll(es, p => p.Item1 != null && p.Item2 != null)); + Contract.Invariant(naturalLoops == null || Contract.ForAll(naturalLoops.Keys, p => p.Item2 != null && p.Item1 != null)); + } + + private class PreHeader { + Node/*!*/ myHeader; + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(myHeader != null); + } + + internal PreHeader(Node/*!*/ h) { + Contract.Requires(h != null); + myHeader = h; + } + + [Pure] + public override string/*!*/ ToString() { + Contract.Ensures(Contract.Result<string>() != null); + return "#" + myHeader.ToString(); + } + } + + public Graph(HashSet<Tuple<Node/*!*/, Node/*!*/>> edges) { + + Contract.Requires(cce.NonNullElements(edges) && Contract.ForAll(edges, p => p.Item1 != null && p.Item2 != null)); + es = edges; + + // original A# + //ns = Set<Node>{ x : <x,y> in es } + Set<Node>{ y : <x,y> in es }; + + // closest Spec# + //ns = new Set<Node>{ Tuple<Node,Node> p in edges; p.Item1 } + new Set<Node>{ Tuple<Node,Node> p in edges; p.Item2 }; + + // + HashSet<Node> temp = new HashSet<Node>(); + foreach (Tuple<Node/*!*/, Node/*!*/> p in edges) { + Contract.Assert(p.Item1 != null); + temp.Add(p.Item1); + Contract.Assert(p.Item2 != null); + temp.Add(p.Item2); + } + ns = temp; + } + public Graph() { + es = new HashSet<Tuple<Node/*!*/, Node/*!*/>>(); + ns = new HashSet<Node>(); + } + + // BUGBUG: Set<T>.ToString() should return a non-null string + [Pure] + public override string/*!*/ ToString() { + return "" + es.ToString(); + } + + public void AddSource(Node/*!*/ x) { + Contract.Requires(x != null); + // BUGBUG: This generates bad code in the compiler + //ns += new Set<Node>{x}; + ns.Add(x); + source = x; + } + + public void AddEdge(Node/*!*/ source, Node/*!*/ dest) { + Contract.Requires(source != null); + Contract.Requires(dest != null); + //es += Set<Edge>{<source,dest>}; + //ns += Set<Node>{source, dest}; + es.Add(new Tuple<Node/*!*/, Node/*!*/>(source, dest)); + ns.Add(source); + ns.Add(dest); + predComputed = false; + } + + public HashSet<Node> Nodes { + get { + return ns; + } + } + public IEnumerable<Tuple<Node/*!*/, Node/*!*/>> Edges { + get { + Contract.Ensures(cce.NonNullElements(Contract.Result<IEnumerable<Tuple<Node, Node>>>()) + && Contract.ForAll(Contract.Result<IEnumerable<Tuple<Node, Node>>>(), n => + n.Item1 != null && n.Item2 != null)); + return es; + } + } + + public bool Edge(Node/*!*/ x, Node/*!*/ y) { + Contract.Requires(x != null); + Contract.Requires(y != null); + // original A# + // return <x,y> in es; + return es.Contains(new Tuple<Node/*!*/, Node/*!*/>(x, y)); + } + + private void ComputePredSuccCaches() { + if (predComputed) + return; + predComputed = true; + predCache = new Dictionary<Node, HashSet<Node>>(); + succCache = new Dictionary<Node, HashSet<Node>>(); + + foreach (Node n in Nodes) { + predCache[n] = new HashSet<Node>(); + succCache[n] = new HashSet<Node>(); + } + + foreach (Tuple<Node/*!*/, Node/*!*/> p in Edges) { + Contract.Assert(p.Item1 != null); + Contract.Assert(p.Item2 != null); + HashSet<Node> tmp; + + tmp = predCache[p.Item2]; + tmp.Add(p.Item1); + predCache[p.Item2] = tmp; + + tmp = succCache[p.Item1]; + tmp.Add(p.Item2); + succCache[p.Item1] = tmp; + } + } + + public IEnumerable<Node> Predecessors(Node n) { + // original A# + //Set<Node> result = Set{ x : x in Nodes, Edge(x,n) }; + + ComputePredSuccCaches(); + return predCache[n]; + } + + public IEnumerable<Node> Successors(Node n) { + ComputePredSuccCaches(); + return succCache[n]; + } + + public List<Node> SuccessorsAsList(Node n) { + ComputePredSuccCaches(); + List<Node> ret = new List<Node>(); + foreach (Node s in succCache[n]) + ret.Add(s); + return ret; + } + + public DomRelation<Node> /*Map<Node,Set<Node>>*/ DominatorMap { + get { + Contract.Assert(source != null); + if (this.dominatorMap == null) { + this.dominatorMap = new DomRelation<Node>(this, this.source); + } + return this.dominatorMap; + } + } + + public Dictionary<Node, List<Node>> ImmediateDominatorMap { + get { + Contract.Assert(source != null); + if (this.dominatorMap == null) { + this.dominatorMap = new DomRelation<Node>(this, this.source); + } + return this.dominatorMap.ImmediateDominatorMap; + } + } + public List<Node> ImmediatelyDominatedBy(Node/*!*/ n) { + Contract.Requires(n != null); + List<Node> dominees; + this.ImmediateDominatorMap.TryGetValue(n, out dominees); + return dominees == null ? new List<Node>() : dominees; + } + + public IEnumerable<Node/*?*/> TopologicalSort() { + bool acyclic; + List<Node> sortedList; + this.TarjanTopSort(out acyclic, out sortedList); + return acyclic ? sortedList : new List<Node>(); + } + // From Tarjan 1972 + public void TarjanTopSort(out bool acyclic, out List<Node> sortedNodes) { + int n = this.Nodes.Count; + if (n == 0) { + acyclic = true; + sortedNodes = new List<Node>(); + return; + } + int[] incomingEdges = new int[n]; + // need an arbitrary numbering for the nodes to use as indices into + // the arrays used within this algorithm + Dictionary<Node, int> nodeToNumber = new Dictionary<Node, int>(n); + Maybe<Node>[] numberToNode = new Maybe<Node>[n]; + int counter = 0; + foreach (Node node in this.Nodes) { + numberToNode[counter].Val = node; + nodeToNumber[node] = counter; + counter++; + } + foreach (Tuple<Node/*!*/, Node/*!*/> e in this.Edges) { + Contract.Assert(e.Item1 != null); + Contract.Assert(e.Item2 != null); + Node/*!*/ target = e.Item2; + incomingEdges[nodeToNumber[target]]++; + } + List<Node> sorted = new List<Node>(); + int sortedIndex = 0; + while (sortedIndex < n) { + // find a root (i.e., its index) + int rootIndex = -1; + for (int i = 0; i < n; i++) { + if (incomingEdges[i] == 0) { + rootIndex = i; + break; + } + } + if (rootIndex == -1) { + acyclic = false; + sortedNodes = new List<Node>(); + return; + } + // mark root so it won't be used again + incomingEdges[rootIndex] = -1; + Node root = numberToNode[rootIndex].Val; + sorted.Add(root); + ++sortedIndex; + foreach (Node s in this.Successors(root)) { + incomingEdges[nodeToNumber[s]]--; + } + } + acyclic = true; + sortedNodes = sorted; + return; + } + private IEnumerable<Node> OldTopologicalSort() { + Tuple<bool, List<Node>> result = this.TopSort(); + return result.Item1 ? result.Item2 : (IEnumerable<Node>)new List<Node>(); + } + // From AsmL distribution example + private Tuple<bool, List<Node>> TopSort() + { + List<Node> S = new List<Node>(); + HashSet<Node> V = this.Nodes; + HashSet<Node> X = new HashSet<Node>(); + foreach (Node/*!*/ n in V) { + Contract.Assert(n != null); + X.Add(n); + } + bool change = true; + while (change) + // invariant: X = V - S + { + change = false; + if (X.Count > 0) { + foreach (Node/*!*/ n in X) { + Contract.Assert(n != null); + // see if n has any incoming edges from any other node in X + bool inDegreeZero = true; + foreach (Node/*!*/ u in X) { + Contract.Assert(u != null); + if (this.Edge(u, n)) { + inDegreeZero = false; + break; // no point looking further + } + } + if (inDegreeZero) { + S.Add(n); + X.Remove(n); + change = true; + break; // might as well go back and start looking through X from the beginning + } + } + // Then we made it all the way through X without finding a source node + if (!change) { + return new Tuple<bool, List<Node>>(false, new List<Node>()); + } + } + } + return new Tuple<bool, List<Node>>(true, S); + } + + public static bool Acyclic(Graph<Node> g, Node source) { + bool acyclic; + List<Node> sortedList; + g.TarjanTopSort(out acyclic, out sortedList); + return acyclic; + } + + // [Dragon, Fig. 10.15, p. 604. Algorithm for constructing the natural loop.] + static HashSet<Node> NaturalLoop(Graph<Node> g, Tuple<Node/*!*/, Node/*!*/> backEdge) + { + Contract.Requires(backEdge.Item1 != null && backEdge.Item2 != null); + Node/*!*/ n = backEdge.Item1; + Node/*!*/ d = backEdge.Item2; + Stack<Node> stack = new Stack<Node>(); + HashSet<Node> loop = new HashSet<Node>(); + loop.Add(d); + if (!n.Equals(d)) // then n is not in loop + { + loop.Add(n); + stack.Push(n); // push n onto stack + } + while (stack.Count > 0) // not empty + { + Node m = stack.Peek(); + stack.Pop(); // pop stack + foreach (Node/*!*/ p in g.Predecessors(m)) { + Contract.Assert(p != null); + if (!(loop.Contains(p))) { + loop.Add(p); + stack.Push(p); // push p onto stack + } + } + } + return loop; + } + + internal struct ReducibleResult { + internal bool reducible; + internal HashSet<Node> headers; + internal Dictionary<Node, HashSet<Node>> backEdgeNodes; + internal Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>> naturalLoops; + internal HashSet<Node> splitCandidates; + [ContractInvariantMethod] + void ObjectInvariant() { + Contract.Invariant(Contract.ForAll(naturalLoops.Keys, p => p.Item1 != null && p.Item2 != null)); + } + + internal ReducibleResult(bool b, HashSet<Node> headers, Dictionary<Node, HashSet<Node>> backEdgeNodes, Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>> naturalLoops, HashSet<Node> splitCandidates) + { + Contract.Requires(naturalLoops == null || Contract.ForAll(naturalLoops.Keys, Key => Key.Item1 != null && Key.Item2 != null)); + this.reducible = b; + this.headers = headers; + this.backEdgeNodes = backEdgeNodes; + this.naturalLoops = naturalLoops; + this.splitCandidates = splitCandidates; + } + + } + + // [Dragon, p. 606] + static ReducibleResult ComputeReducible(Graph<Node> g, Node source) { + // first, compute the dom relation + DomRelation<Node> /*Map<Node,Set<Node>>*/ D = g.DominatorMap; + return ComputeReducible(g, source, D); + } + + static HashSet<Node> FindCycle(Graph<Node> g, Node source) { + Stack<Tuple<Node, List<Node>>> stack = new Stack<Tuple<Node, List<Node>>>(); + HashSet<Node> stackAsSet = new HashSet<Node>(); + HashSet<Node> visited = new HashSet<Node>(); + stack.Push(new Tuple<Node, List<Node>>(source, g.SuccessorsAsList(source))); + stackAsSet.Add(source); + while (stack.Count > 0) { + Tuple<Node, List<Node>> tuple = stack.Peek(); + List<Node> children = tuple.Item2; + if (children.Count == 0) { + stack.Pop(); + stackAsSet.Remove(tuple.Item1); + continue; + } + Node n = children[0]; + children.RemoveAt(0); + if (stackAsSet.Contains(n)) { + HashSet<Node> ret = new HashSet<Node>(); + ret.Add(n); + while (true) { + Node x = stack.Pop().Item1; + if (x.Equals(n)) + return ret; + } + } + if (visited.Contains(n)) + continue; + stack.Push(new Tuple<Node, List<Node>>(n, g.SuccessorsAsList(n))); + visited.Add(n); + stackAsSet.Add(n); + System.Diagnostics.Debug.Assert(stack.Count == stackAsSet.Count); + } + return new HashSet<Node>(); + } + + // [Dragon, p. 606] + static ReducibleResult ComputeReducible(Graph<Node> g, + Node source, + DomRelation<Node>/*!*/ DomRelation) { + Contract.Requires(DomRelation != null); + + //Console.WriteLine("[" + DateTime.Now +"]: begin ComputeReducible"); + IEnumerable<Tuple<Node/*!*/, Node/*!*/>> edges = g.Edges; + Contract.Assert(Contract.ForAll(edges, n => n.Item1 != null && n.Item2 != null)); + HashSet<Tuple<Node/*!*/, Node/*!*/>> backEdges = new HashSet<Tuple<Node/*!*/, Node/*!*/>>(); + HashSet<Tuple<Node/*!*/, Node/*!*/>> nonBackEdges = new HashSet<Tuple<Node/*!*/, Node/*!*/>>(); + foreach (Tuple<Node/*!*/, Node/*!*/> e in edges) { + Contract.Assert(e.Item1 != null); + Contract.Assert(e.Item2 != null); + Node x = e.Item1; + Node y = e.Item2; // so there is an edge from x to y + if (DomRelation.DominatedBy(x, y)) { // y dom x: which means y dominates x + backEdges.Add(e); + } else { + nonBackEdges.Add(e); + } + } + Graph<Node> withoutBackEdges = new Graph<Node>(nonBackEdges); + if (!Acyclic(withoutBackEdges, source)) { + return new ReducibleResult(false, + new HashSet<Node>(), + new Dictionary<Node, HashSet<Node>>(), + new Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>>(), + FindCycle(withoutBackEdges, source)); + } else { + // original A#: + //Set<Node> headers = Set{ d : <n,d> in backEdges }; + HashSet<Node> headers = new HashSet<Node>(); + foreach (Tuple<Node/*!*/, Node/*!*/> e in backEdges) { + + Contract.Assert(e.Item1 != null); + Contract.Assert(e.Item2 != null); + headers.Add(e.Item2); + } + // original A#: + //Map<Node,Set<Node>> backEdgeNodes = Map{ h -> bs : h in headers, bs = Set<Node>{ b : <b,x> in backEdges, x == h } }; + Dictionary<Node, HashSet<Node>> backEdgeNodes = new Dictionary<Node, HashSet<Node>>(); + foreach (Node/*!*/ h in headers) { + Contract.Assert(h != null); + HashSet<Node> bs = new HashSet<Node>(); + foreach (Tuple<Node, Node> backedge in backEdges) { + Contract.Assert(backedge.Item1 != null); + Contract.Assert(backedge.Item2 != null); + if (backedge.Item2.Equals(h)) { + bs.Add(backedge.Item1); + } + } + backEdgeNodes.Add(h, bs); + } + + // original A#: + //Map<Tuple<Node,Node>,Set<Node>> naturalLoops = Map{ e -> NaturalLoop(g,e) : e in backEdges }; + Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>> naturalLoops = new Dictionary<Tuple<Node/*!*/, Node/*!*/>, HashSet<Node>>(); + foreach (Tuple<Node/*!*/, Node/*!*/> e in backEdges) { + Contract.Assert(e.Item1 != null && e.Item2 != null); + naturalLoops.Add(e, NaturalLoop(g, e)); + } + + //Console.WriteLine("[" + DateTime.Now +"]: end ComputeReducible"); + return new ReducibleResult(true, headers, backEdgeNodes, naturalLoops, new HashSet<Node>()); + } + } + + public bool Reducible { + get { + return reducible; + } + } + public IEnumerable<Node> Headers { + get { + return headers; + } + } + public IEnumerable<Node> BackEdgeNodes(Node/*!*/ h) { + Contract.Requires(h != null); + // original A#: + //return h in backEdgeNodes ? backEdgeNodes[h] : null; + return (backEdgeNodes.ContainsKey(h) ? backEdgeNodes[h] : (IEnumerable<Node>)new List<Node>()); + } + public IEnumerable<Node> NaturalLoops(Node/*!*/ header, Node/*!*/ backEdgeNode) { + Contract.Requires(header != null); + Contract.Requires(backEdgeNode != null); + Tuple<Node/*!*/, Node/*!*/> e = new Tuple<Node/*!*/, Node/*!*/>(backEdgeNode, header); + return naturalLoops.ContainsKey(e) ? naturalLoops[e] : (IEnumerable<Node>)new List<Node>(); + } + public HashSet<Node> SplitCandidates { + get { + return splitCandidates; + } + } + public void ComputeLoops() { + ReducibleResult r = ComputeReducible(this, this.source); + this.reducible = r.reducible; + this.headers = r.headers; + this.backEdgeNodes = r.backEdgeNodes; + this.naturalLoops = r.naturalLoops; + this.splitCandidates = r.splitCandidates; + return; + } + + public IEnumerable<Node> SortHeadersByDominance() + { + Graph<Node> dag = new Graph<Node>(); + foreach (Node b in headers) + { + dag.AddSource(b); + foreach (Node c in headers) + { + if (b.Equals(c)) continue; + if (DominatorMap.DominatedBy(b, c)) + { + System.Diagnostics.Debug.Assert(!DominatorMap.DominatedBy(c, b)); + dag.AddEdge(b, c); + } + } + } + return dag.TopologicalSort(); + } + + public string ToDot(Func<Node, string> NodeLabel = null, Func<Node, string> NodeStyle = null) { + NodeLabel = NodeLabel ?? (n => n.ToString()); + NodeStyle = NodeStyle ?? (n => "[shape=box]"); + var s = new StringBuilder(); + s.AppendLine("digraph G {"); + foreach (var n in Nodes) + s.AppendLine(" \"" + NodeLabel(n) + "\" " + NodeStyle(n) + ";"); + foreach (var e in Edges) + s.AppendLine(" \"" + NodeLabel(e.Item1) + "\" -> \"" + NodeLabel(e.Item2) + "\";"); + s.AppendLine("}"); + return s.ToString(); + } + } // end: class Graph + + public class GraphProgram { + static void TestGraph<T>(T/*!*/ source, params Tuple<T/*!*/, T/*!*/>[] edges) { + Contract.Requires(source != null); + Contract.Requires(Contract.ForAll(edges, pair => pair.Item1 != null && pair.Item2 != null)); + HashSet<Tuple<T/*!*/, T/*!*/>> es = new HashSet<Tuple<T/*!*/, T/*!*/>>(); + foreach (Tuple<T/*!*/, T/*!*/> e in edges) { + Contract.Assert(e.Item1 != null && e.Item2 != null); + es.Add(e); + } + Graph<T> g = new Graph<T>(es); + g.AddSource(source); + Console.WriteLine("G = " + g); + g.ComputeLoops(); + Console.WriteLine("G's Dominator Map = " + g.DominatorMap); + Console.WriteLine("G's Immediate Dominator Map = " + Util.MapToString(g.ImmediateDominatorMap)); + Console.WriteLine("G is reducible: " + (g.Reducible ? "yes" : "no")); + } + + static void Main(string[] args) + //requires forall{string s in args; s != null}; + { + Console.WriteLine("Spec# says hello!"); + // This generates bad IL -- need to fix a bug in the compiler + //Graph<int> g = new Graph<int>(new Set<Tuple<int,int>>{ new Tuple<int,int>(1,2), new Tuple<int,int>(1,3), new Tuple<int,int>(2,3) }); + + Console.WriteLine(""); + TestGraph<char>('a', + new Tuple<char, char>('a', 'b'), + new Tuple<char, char>('a', 'c'), + new Tuple<char, char>('b', 'c') + ); + + Console.WriteLine(""); + TestGraph<char>('a', + new Tuple<char, char>('a', 'b'), + new Tuple<char, char>('a', 'c'), + new Tuple<char, char>('b', 'd'), + new Tuple<char, char>('c', 'e'), + new Tuple<char, char>('c', 'f'), + new Tuple<char, char>('d', 'e'), + new Tuple<char, char>('e', 'd'), + new Tuple<char, char>('e', 'f'), + new Tuple<char, char>('f', 'e') + ); + + Console.WriteLine(""); + TestGraph<char>('a', + new Tuple<char, char>('a', 'b'), + new Tuple<char, char>('a', 'c'), + new Tuple<char, char>('b', 'c'), + new Tuple<char, char>('c', 'b') + ); + + Console.WriteLine(""); + TestGraph<int>(1, + new Tuple<int, int>(1, 2), + new Tuple<int, int>(1, 3), + new Tuple<int, int>(2, 3) + ); + + Console.WriteLine(""); + TestGraph<int>(1, + new Tuple<int, int>(1, 2), + new Tuple<int, int>(1, 3), + new Tuple<int, int>(2, 3), + new Tuple<int, int>(3, 2) + ); + + Console.WriteLine(""); + TestGraph<int>(2, + new Tuple<int, int>(2, 3), + new Tuple<int, int>(2, 4), + new Tuple<int, int>(3, 2) + ); + + Console.WriteLine(""); + TestGraph<char>('a', + new Tuple<char, char>('a', 'b'), + new Tuple<char, char>('a', 'c'), + new Tuple<char, char>('b', 'c'), + new Tuple<char, char>('b', 'b') + ); + + + } + } + +} diff --git a/Source/VCGeneration/GraphAlgorithms.cs b/Source/VCGeneration/GraphAlgorithms.cs index 1a8ab9b1..006a923f 100644 --- a/Source/VCGeneration/GraphAlgorithms.cs +++ b/Source/VCGeneration/GraphAlgorithms.cs @@ -93,6 +93,34 @@ public static class GraphAlgorithms { return sortedNodes; } + + // Algorithm from Jeanne Ferrante, Karl J. Ottenstein, Joe D. Warren, + // "The Program Dependence Graph and Its Use in Optimization" + public static Dictionary<Node, HashSet<Node>> ControlDependence<Node>(this Graph<Node> g) where Node : class, new() { + Graph<Node> dual = g.Dual(new Node()); + DomRelation<Node> pdom = dual.DominatorMap; + var result = new Dictionary<Node, HashSet<Node>>(); + + var S = g.Edges.Where(e => !pdom.DominatedBy(e.Item1, e.Item2)); + foreach (var edge in S) { + var L = pdom.LeastCommonAncestor(edge.Item1, edge.Item2); + var deps = new List<Node>(); + if (L == edge.Item1) { + pdom.DominatedBy(edge.Item2, edge.Item1, deps); + deps.Add(edge.Item2); + deps.Add(edge.Item1); + } else { + pdom.DominatedBy(edge.Item2, L, deps); + deps.Add(edge.Item2); + } + if (result.ContainsKey(edge.Item1)) { + result[edge.Item1].UnionWith(deps); + } else { + result[edge.Item1] = new HashSet<Node>(deps); + } + } + return result; + } } diff --git a/Source/VCGeneration/SmartBlockPredicator.cs b/Source/VCGeneration/SmartBlockPredicator.cs index f769822c..9dada1a5 100644 --- a/Source/VCGeneration/SmartBlockPredicator.cs +++ b/Source/VCGeneration/SmartBlockPredicator.cs @@ -1,469 +1,523 @@ -using Graphing;
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Diagnostics.Contracts;
-using System.Linq;
-
-namespace Microsoft.Boogie {
-
-public class SmartBlockPredicator {
-
- Program prog;
- Implementation impl;
- Graph<Block> blockGraph;
- List<Tuple<Block, bool>> sortedBlocks;
-
- bool useProcedurePredicates = true;
-
- Dictionary<Block, Variable> predMap, defMap;
- Dictionary<Block, HashSet<Variable>> ownedMap;
- Dictionary<Block, Block> parentMap;
- Dictionary<Block, PartInfo> partInfo;
-
- IdentifierExpr fp;
- Dictionary<Microsoft.Boogie.Type, IdentifierExpr> havocVars =
- new Dictionary<Microsoft.Boogie.Type, IdentifierExpr>();
- Dictionary<Block, Expr> blockIds = new Dictionary<Block, Expr>();
- HashSet<Block> doneBlocks = new HashSet<Block>();
-
- SmartBlockPredicator(Program p, Implementation i, bool upp) {
- prog = p;
- impl = i;
- useProcedurePredicates = upp;
- }
-
- void PredicateCmd(Expr p, List<Block> blocks, Block block, Cmd cmd, out Block nextBlock) {
- if (!useProcedurePredicates && cmd is CallCmd) {
- var trueBlock = new Block();
- blocks.Add(trueBlock);
- trueBlock.Label = block.Label + ".call.true";
- trueBlock.Cmds.Add(new AssumeCmd(Token.NoToken, p));
- trueBlock.Cmds.Add(cmd);
-
- var falseBlock = new Block();
- blocks.Add(falseBlock);
- falseBlock.Label = block.Label + ".call.false";
- falseBlock.Cmds.Add(new AssumeCmd(Token.NoToken, Expr.Not(p)));
-
- var contBlock = new Block();
- blocks.Add(contBlock);
- contBlock.Label = block.Label + ".call.cont";
-
- block.TransferCmd =
- new GotoCmd(Token.NoToken, new BlockSeq(trueBlock, falseBlock));
- trueBlock.TransferCmd = falseBlock.TransferCmd =
- new GotoCmd(Token.NoToken, new BlockSeq(contBlock));
- nextBlock = contBlock;
- } else {
- PredicateCmd(p, block.Cmds, cmd);
- nextBlock = block;
- }
- }
-
- void PredicateCmd(Expr p, CmdSeq cmdSeq, Cmd cmd) {
- if (p == null) {
- cmdSeq.Add(cmd);
- return;
- }
-
- if (cmd is AssignCmd) {
- var aCmd = (AssignCmd)cmd;
- cmdSeq.Add(new AssignCmd(Token.NoToken, aCmd.Lhss,
- new List<Expr>(aCmd.Lhss.Zip(aCmd.Rhss, (lhs, rhs) =>
- new NAryExpr(Token.NoToken,
- new IfThenElse(Token.NoToken),
- new ExprSeq(p, rhs, lhs.AsExpr))))));
- } else if (cmd is AssertCmd) {
- var aCmd = (AssertCmd)cmd;
- Expr newExpr = new EnabledReplacementVisitor(p).VisitExpr(aCmd.Expr);
- aCmd.Expr = QKeyValue.FindBoolAttribute(aCmd.Attributes, "do_not_predicate") ? newExpr : Expr.Imp(p, newExpr);
- cmdSeq.Add(aCmd);
- } else if (cmd is AssumeCmd) {
- var aCmd = (AssumeCmd)cmd;
- cmdSeq.Add(new AssumeCmd(Token.NoToken, Expr.Imp(p, aCmd.Expr)));
- } else if (cmd is HavocCmd) {
- var hCmd = (HavocCmd)cmd;
- foreach (IdentifierExpr v in hCmd.Vars) {
- Microsoft.Boogie.Type type = v.Decl.TypedIdent.Type;
- Contract.Assert(type != null);
-
- IdentifierExpr havocTempExpr;
- if (havocVars.ContainsKey(type)) {
- havocTempExpr = havocVars[type];
- } else {
- var havocVar = new LocalVariable(Token.NoToken,
- new TypedIdent(Token.NoToken,
- "_HAVOC_" + type.ToString(), type));
- impl.LocVars.Add(havocVar);
- havocVars[type] = havocTempExpr =
- new IdentifierExpr(Token.NoToken, havocVar);
- }
- cmdSeq.Add(new HavocCmd(Token.NoToken,
- new IdentifierExprSeq(havocTempExpr)));
- cmdSeq.Add(Cmd.SimpleAssign(Token.NoToken, v,
- new NAryExpr(Token.NoToken,
- new IfThenElse(Token.NoToken),
- new ExprSeq(p, havocTempExpr, v))));
- }
- } else if (cmd is CallCmd) {
- Debug.Assert(useProcedurePredicates);
- var cCmd = (CallCmd)cmd;
- cCmd.Ins.Insert(0, p);
- cmdSeq.Add(cCmd);
- }
- else if (cmd is CommentCmd) {
- // skip
- }
- else if (cmd is StateCmd) {
- var sCmd = (StateCmd)cmd;
- var newCmdSeq = new CmdSeq();
- foreach (Cmd c in sCmd.Cmds)
- PredicateCmd(p, newCmdSeq, c);
- sCmd.Cmds = newCmdSeq;
- cmdSeq.Add(sCmd);
- }
- else {
- Console.WriteLine("Unsupported cmd: " + cmd.GetType().ToString());
- }
- }
-
- void PredicateTransferCmd(Expr p, Block src, CmdSeq cmdSeq, TransferCmd cmd) {
- if (cmd is GotoCmd) {
- var gCmd = (GotoCmd)cmd;
- if (gCmd.labelTargets.Length == 1) {
- if (defMap.ContainsKey(gCmd.labelTargets[0]))
- PredicateCmd(p, cmdSeq,
- Cmd.SimpleAssign(Token.NoToken,
- Expr.Ident(predMap[gCmd.labelTargets[0]]), Expr.True));
- } else {
- Debug.Assert(gCmd.labelTargets.Length > 1);
- Debug.Assert(gCmd.labelTargets.Cast<Block>().All(t => partInfo.ContainsKey(t)));
- foreach (Block target in gCmd.labelTargets) {
- var part = partInfo[target];
- if (defMap.ContainsKey(part.realDest))
- PredicateCmd(p, 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, 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());
- }
- }
-
- Variable FreshPredicate(ref int predCount) {
- var pVar = new LocalVariable(Token.NoToken,
- new TypedIdent(Token.NoToken,
- "p" + predCount++,
- Microsoft.Boogie.Type.Bool));
- impl.LocVars.Add(pVar);
- return pVar;
- }
-
- void AssignPredicates(Graph<Block> blockGraph,
- DomRelation<Block> dom,
- DomRelation<Block> pdom,
- IEnumerator<Tuple<Block, bool>> i,
- Variable headPredicate,
- ref int predCount) {
- var header = i.Current.Item1;
- var regionPreds = new List<Tuple<Block, Variable>>();
- var ownedPreds = new HashSet<Variable>();
- ownedMap[header] = ownedPreds;
-
- predMap[header] = headPredicate;
- defMap[header] = headPredicate;
- regionPreds.Add(new Tuple<Block, Variable>(header, headPredicate));
-
- while (i.MoveNext()) {
- var block = i.Current;
- if (block.Item2) {
- if (block.Item1 == header)
- return;
- } else {
- if (blockGraph.Headers.Contains(block.Item1)) {
- parentMap[block.Item1] = header;
- var loopPred = FreshPredicate(ref predCount);
- ownedPreds.Add(loopPred);
- AssignPredicates(blockGraph, dom, pdom, i, loopPred, ref predCount);
- } else {
- bool foundExisting = false;
- foreach (var regionPred in regionPreds) {
- if (dom.DominatedBy(block.Item1, regionPred.Item1) &&
- pdom.DominatedBy(regionPred.Item1, block.Item1)) {
- predMap[block.Item1] = regionPred.Item2;
- foundExisting = true;
- break;
- }
- }
- if (!foundExisting) {
- var condPred = FreshPredicate(ref predCount);
- predMap[block.Item1] = condPred;
- defMap[block.Item1] = condPred;
- ownedPreds.Add(condPred);
- regionPreds.Add(new Tuple<Block, Variable>(block.Item1, condPred));
- }
- }
- }
- }
- }
-
- void AssignPredicates() {
- DomRelation<Block> dom = blockGraph.DominatorMap;
-
- Graph<Block> dualGraph = blockGraph.Dual(new Block());
- DomRelation<Block> pdom = dualGraph.DominatorMap;
-
- var iter = sortedBlocks.GetEnumerator();
- if (!iter.MoveNext()) {
- predMap = defMap = null;
- ownedMap = null;
- return;
- }
-
- int predCount = 0;
- predMap = new Dictionary<Block, Variable>();
- defMap = new Dictionary<Block, Variable>();
- ownedMap = new Dictionary<Block, HashSet<Variable>>();
- parentMap = new Dictionary<Block, Block>();
- AssignPredicates(blockGraph, dom, pdom, iter,
- useProcedurePredicates ? impl.InParams[0] : null,
- ref predCount);
- }
-
- IEnumerable<Block> LoopsExited(Block src, Block dest) {
- var i = sortedBlocks.GetEnumerator();
- while (i.MoveNext()) {
- var b = i.Current;
- if (b.Item1 == src) {
- return LoopsExitedForwardEdge(dest, i);
- } else if (b.Item1 == dest) {
- return LoopsExitedBackEdge(src, i);
- }
- }
- Debug.Assert(false);
- return null;
- }
-
- private IEnumerable<Block> LoopsExitedBackEdge(Block src, IEnumerator<Tuple<Block, bool>> i) {
- var headsSeen = new HashSet<Block>();
- while (i.MoveNext()) {
- var b = i.Current;
- if (!b.Item2 && blockGraph.Headers.Contains(b.Item1))
- headsSeen.Add(b.Item1);
- else if (b.Item2)
- headsSeen.Remove(b.Item1);
- if (b.Item1 == src)
- return headsSeen;
- }
- Debug.Assert(false);
- return null;
- }
-
- private IEnumerable<Block> LoopsExitedForwardEdge(Block dest, IEnumerator<Tuple<Block, bool>> i) {
- var headsSeen = new HashSet<Block>();
- while (i.MoveNext()) {
- var b = i.Current;
- if (b.Item1 == dest)
- yield break;
- else if (!b.Item2 && blockGraph.Headers.Contains(b.Item1))
- headsSeen.Add(b.Item1);
- else if (b.Item2 && !headsSeen.Contains(b.Item1))
- yield return b.Item1;
- }
- Debug.Assert(false);
- }
-
- class PartInfo {
- public PartInfo(Expr p, Block r) { pred = p; realDest = r; }
- public Expr pred;
- public Block realDest;
- }
-
- Dictionary<Block, PartInfo> BuildPartitionInfo() {
- var partInfo = new Dictionary<Block, PartInfo>();
- foreach (var block in blockGraph.Nodes) {
- var parts = block.Cmds.Cast<Cmd>().TakeWhile(
- c => c is AssumeCmd &&
- QKeyValue.FindBoolAttribute(((AssumeCmd)c).Attributes, "partition"));
-
- Expr pred = null;
- if (parts.Count() > 0) {
- pred = parts.Select(a => ((AssumeCmd)a).Expr).Aggregate(Expr.And);
- block.Cmds =
- new CmdSeq(block.Cmds.Cast<Cmd>().Skip(parts.Count()).ToArray());
- } else {
- continue;
- }
-
- Block realDest = block;
- if (block.Cmds.Length == 0) {
- var gc = block.TransferCmd as GotoCmd;
- if (gc != null && gc.labelTargets.Length == 1)
- realDest = gc.labelTargets[0];
- }
- partInfo[block] = new PartInfo(pred, realDest);
- }
-
- return partInfo;
- }
-
- void PredicateImplementation() {
- blockGraph = prog.ProcessLoops(impl);
- sortedBlocks = blockGraph.LoopyTopSort();
-
- AssignPredicates();
- partInfo = BuildPartitionInfo();
-
- if (useProcedurePredicates)
- fp = Expr.Ident(impl.InParams[0]);
-
- var newBlocks = new List<Block>();
- Block prevBlock = null;
- foreach (var n in sortedBlocks) {
- var p = predMap[n.Item1];
- var pExpr = Expr.Ident(p);
-
- if (n.Item2) {
- var backedgeBlock = new Block();
- newBlocks.Add(backedgeBlock);
-
- backedgeBlock.Label = n.Item1.Label + ".backedge";
- backedgeBlock.Cmds = new CmdSeq(new AssumeCmd(Token.NoToken, pExpr,
- new QKeyValue(Token.NoToken, "backedge", new List<object>(), null)));
- backedgeBlock.TransferCmd = new GotoCmd(Token.NoToken,
- new BlockSeq(n.Item1));
-
- var tailBlock = new Block();
- newBlocks.Add(tailBlock);
-
- tailBlock.Label = n.Item1.Label + ".tail";
- tailBlock.Cmds = new CmdSeq(new AssumeCmd(Token.NoToken,
- Expr.Not(pExpr)));
-
- if (prevBlock != null)
- prevBlock.TransferCmd = new GotoCmd(Token.NoToken,
- new BlockSeq(backedgeBlock, tailBlock));
- prevBlock = tailBlock;
- } else {
- var runBlock = n.Item1;
- var oldCmdSeq = runBlock.Cmds;
- runBlock.Cmds = new CmdSeq();
- newBlocks.Add(runBlock);
- if (prevBlock != null)
- prevBlock.TransferCmd = new GotoCmd(Token.NoToken,
- new BlockSeq(runBlock));
-
- if (parentMap.ContainsKey(runBlock)) {
- var parent = parentMap[runBlock];
- if (predMap.ContainsKey(parent)) {
- var parentPred = predMap[parent];
- if (parentPred != null) {
- runBlock.Cmds.Add(new AssertCmd(Token.NoToken,
- Expr.Imp(pExpr, Expr.Ident(parentPred))));
- }
- }
- }
-
- var transferCmd = runBlock.TransferCmd;
- foreach (Cmd cmd in oldCmdSeq)
- PredicateCmd(pExpr, newBlocks, runBlock, cmd, out runBlock);
-
- if (ownedMap.ContainsKey(n.Item1)) {
- var owned = ownedMap[n.Item1];
- foreach (var v in owned)
- runBlock.Cmds.Add(Cmd.SimpleAssign(Token.NoToken, Expr.Ident(v), Expr.False));
- }
-
- PredicateTransferCmd(pExpr, runBlock, runBlock.Cmds, transferCmd);
-
- prevBlock = runBlock;
- doneBlocks.Add(runBlock);
- }
- }
-
- prevBlock.TransferCmd = new ReturnCmd(Token.NoToken);
- impl.Blocks = newBlocks;
- }
-
- private Expr CreateIfFPThenElse(Expr then, Expr eElse) {
- if (useProcedurePredicates) {
- return new NAryExpr(Token.NoToken,
- new IfThenElse(Token.NoToken),
- new ExprSeq(fp, then, eElse));
- } else {
- return then;
- }
- }
-
- public static void Predicate(Program p,
- bool useProcedurePredicates = true) {
- foreach (var decl in p.TopLevelDeclarations.ToList()) {
- if (useProcedurePredicates && decl is DeclWithFormals && !(decl is Function)) {
- var dwf = (DeclWithFormals)decl;
- var fpVar = new Formal(Token.NoToken,
- new TypedIdent(Token.NoToken, "_P",
- Microsoft.Boogie.Type.Bool),
- /*incoming=*/true);
- dwf.InParams = new VariableSeq(
- (new Variable[] {fpVar}.Concat(dwf.InParams.Cast<Variable>()))
- .ToArray());
-
- if (dwf is Procedure)
- {
- var proc = (Procedure)dwf;
- var newRequires = new RequiresSeq();
- foreach (Requires r in proc.Requires)
- {
- newRequires.Add(new Requires(r.Free,
- new EnabledReplacementVisitor(new IdentifierExpr(Token.NoToken, fpVar)).VisitExpr(r.Condition)));
- }
- var newEnsures = new EnsuresSeq();
- foreach (Ensures e in proc.Ensures)
- {
- newEnsures.Add(new Ensures(e.Free,
- new EnabledReplacementVisitor(new IdentifierExpr(Token.NoToken, fpVar)).VisitExpr(e.Condition)));
- }
- }
-
- }
-
- try {
- var impl = decl as Implementation;
- if (impl != null)
- new SmartBlockPredicator(p, impl, useProcedurePredicates).PredicateImplementation();
- }
- catch (Program.IrreducibleLoopException) { }
- }
- }
-
- public static void Predicate(Program p, Implementation impl) {
- try {
- new SmartBlockPredicator(p, impl, false).PredicateImplementation();
- }
- catch (Program.IrreducibleLoopException) { }
- }
-
-}
-
-}
+using Graphing; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.Contracts; +using System.Linq; + +namespace Microsoft.Boogie { + +public class SmartBlockPredicator { + + Program prog; + Implementation impl; + Graph<Block> blockGraph; + List<Tuple<Block, bool>> sortedBlocks; + + Func<Procedure, bool> useProcedurePredicates; + + Dictionary<Block, Variable> predMap, defMap; + Dictionary<Block, HashSet<Variable>> ownedMap; + Dictionary<Block, Block> parentMap; + Dictionary<Block, PartInfo> partInfo; + + IdentifierExpr fp; + Dictionary<Microsoft.Boogie.Type, IdentifierExpr> havocVars = + new Dictionary<Microsoft.Boogie.Type, IdentifierExpr>(); + Dictionary<Block, Expr> blockIds = new Dictionary<Block, Expr>(); + HashSet<Block> doneBlocks = new HashSet<Block>(); + bool myUseProcedurePredicates; + UniformityAnalyser uni; + + SmartBlockPredicator(Program p, Implementation i, Func<Procedure, bool> upp, UniformityAnalyser u) { + prog = p; + impl = i; + useProcedurePredicates = upp; + myUseProcedurePredicates = useProcedurePredicates(i.Proc); + uni = u; + } + + void PredicateCmd(Expr p, List<Block> blocks, Block block, Cmd cmd, out Block nextBlock) { + var cCmd = cmd as CallCmd; + if (cCmd != null && !useProcedurePredicates(cCmd.Proc)) { + if (p == null) { + block.Cmds.Add(cmd); + nextBlock = block; + return; + } + + var trueBlock = new Block(); + blocks.Add(trueBlock); + trueBlock.Label = block.Label + ".call.true"; + trueBlock.Cmds.Add(new AssumeCmd(Token.NoToken, p)); + trueBlock.Cmds.Add(cmd); + + var falseBlock = new Block(); + blocks.Add(falseBlock); + falseBlock.Label = block.Label + ".call.false"; + falseBlock.Cmds.Add(new AssumeCmd(Token.NoToken, Expr.Not(p))); + + var contBlock = new Block(); + blocks.Add(contBlock); + contBlock.Label = block.Label + ".call.cont"; + + block.TransferCmd = + new GotoCmd(Token.NoToken, new BlockSeq(trueBlock, falseBlock)); + trueBlock.TransferCmd = falseBlock.TransferCmd = + new GotoCmd(Token.NoToken, new BlockSeq(contBlock)); + nextBlock = contBlock; + } else { + PredicateCmd(p, block.Cmds, cmd); + nextBlock = block; + } + } + + void PredicateCmd(Expr p, CmdSeq cmdSeq, Cmd cmd) { + if (cmd is CallCmd) { + var cCmd = (CallCmd)cmd; + Debug.Assert(useProcedurePredicates(cCmd.Proc)); + cCmd.Ins.Insert(0, p != null ? p : Expr.True); + cmdSeq.Add(cCmd); + } else if (p == null) { + cmdSeq.Add(cmd); + } else if (cmd is AssignCmd) { + var aCmd = (AssignCmd)cmd; + cmdSeq.Add(new AssignCmd(Token.NoToken, aCmd.Lhss, + new List<Expr>(aCmd.Lhss.Zip(aCmd.Rhss, (lhs, rhs) => + new NAryExpr(Token.NoToken, + new IfThenElse(Token.NoToken), + new ExprSeq(p, rhs, lhs.AsExpr)))))); + } else if (cmd is AssertCmd) { + var aCmd = (AssertCmd)cmd; + Expr newExpr = new EnabledReplacementVisitor(p).VisitExpr(aCmd.Expr); + aCmd.Expr = QKeyValue.FindBoolAttribute(aCmd.Attributes, "do_not_predicate") ? newExpr : Expr.Imp(p, newExpr); + cmdSeq.Add(aCmd); + } else if (cmd is AssumeCmd) { + var aCmd = (AssumeCmd)cmd; + cmdSeq.Add(new AssumeCmd(Token.NoToken, Expr.Imp(p, aCmd.Expr))); + } else if (cmd is HavocCmd) { + var hCmd = (HavocCmd)cmd; + foreach (IdentifierExpr v in hCmd.Vars) { + Microsoft.Boogie.Type type = v.Decl.TypedIdent.Type; + Contract.Assert(type != null); + + IdentifierExpr havocTempExpr; + if (havocVars.ContainsKey(type)) { + havocTempExpr = havocVars[type]; + } else { + var havocVar = new LocalVariable(Token.NoToken, + new TypedIdent(Token.NoToken, + "_HAVOC_" + type.ToString(), type)); + impl.LocVars.Add(havocVar); + havocVars[type] = havocTempExpr = + new IdentifierExpr(Token.NoToken, havocVar); + } + cmdSeq.Add(new HavocCmd(Token.NoToken, + new IdentifierExprSeq(havocTempExpr))); + cmdSeq.Add(Cmd.SimpleAssign(Token.NoToken, v, + new NAryExpr(Token.NoToken, + new IfThenElse(Token.NoToken), + new ExprSeq(p, havocTempExpr, v)))); + } + } else if (cmd is CommentCmd) { + // skip + } else if (cmd is StateCmd) { + var sCmd = (StateCmd)cmd; + var newCmdSeq = new CmdSeq(); + foreach (Cmd c in sCmd.Cmds) + PredicateCmd(p, newCmdSeq, c); + sCmd.Cmds = newCmdSeq; + cmdSeq.Add(sCmd); + } else { + Console.WriteLine("Unsupported cmd: " + cmd.GetType().ToString()); + } + } + + // 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, CmdSeq 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.Length == 1) { + if (defMap.ContainsKey(gCmd.labelTargets[0])) + PredicateCmd(p, cmdSeq, + Cmd.SimpleAssign(Token.NoToken, + Expr.Ident(predMap[gCmd.labelTargets[0]]), Expr.True)); + } else { + Debug.Assert(gCmd.labelTargets.Length > 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; + + var part = partInfo[target]; + if (defMap.ContainsKey(part.realDest)) + PredicateCmd(p, 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, 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()); + } + } + + Variable FreshPredicate(ref int predCount) { + var pVar = new LocalVariable(Token.NoToken, + new TypedIdent(Token.NoToken, + "p" + predCount++, + Microsoft.Boogie.Type.Bool)); + impl.LocVars.Add(pVar); + return pVar; + } + + void AssignPredicates(Graph<Block> blockGraph, + DomRelation<Block> dom, + DomRelation<Block> pdom, + IEnumerator<Tuple<Block, bool>> i, + Variable headPredicate, + ref int predCount) { + var header = i.Current.Item1; + var regionPreds = new List<Tuple<Block, Variable>>(); + var ownedPreds = new HashSet<Variable>(); + ownedMap[header] = ownedPreds; + + if (headPredicate != null) { + predMap[header] = headPredicate; + defMap[header] = headPredicate; + regionPreds.Add(new Tuple<Block, Variable>(header, headPredicate)); + } + + while (i.MoveNext()) { + var block = i.Current; + if (uni != null && uni.IsUniform(impl.Name, block.Item1)) + continue; + if (block.Item2) { + if (block.Item1 == header) + return; + } else { + if (blockGraph.Headers.Contains(block.Item1)) { + parentMap[block.Item1] = header; + var loopPred = FreshPredicate(ref predCount); + ownedPreds.Add(loopPred); + AssignPredicates(blockGraph, dom, pdom, i, loopPred, ref predCount); + } else { + bool foundExisting = false; + foreach (var regionPred in regionPreds) { + if (dom.DominatedBy(block.Item1, regionPred.Item1) && + pdom.DominatedBy(regionPred.Item1, block.Item1)) { + predMap[block.Item1] = regionPred.Item2; + foundExisting = true; + break; + } + } + if (!foundExisting) { + var condPred = FreshPredicate(ref predCount); + predMap[block.Item1] = condPred; + defMap[block.Item1] = condPred; + ownedPreds.Add(condPred); + regionPreds.Add(new Tuple<Block, Variable>(block.Item1, condPred)); + } + } + } + } + } + + void AssignPredicates() { + DomRelation<Block> dom = blockGraph.DominatorMap; + + Graph<Block> dualGraph = blockGraph.Dual(new Block()); + DomRelation<Block> pdom = dualGraph.DominatorMap; + + var iter = sortedBlocks.GetEnumerator(); + if (!iter.MoveNext()) { + predMap = defMap = null; + ownedMap = null; + return; + } + + int predCount = 0; + predMap = new Dictionary<Block, Variable>(); + defMap = new Dictionary<Block, Variable>(); + ownedMap = new Dictionary<Block, HashSet<Variable>>(); + parentMap = new Dictionary<Block, Block>(); + AssignPredicates(blockGraph, dom, pdom, iter, + myUseProcedurePredicates ? impl.InParams[0] : null, + ref predCount); + } + + IEnumerable<Block> LoopsExited(Block src, Block dest) { + var i = sortedBlocks.GetEnumerator(); + while (i.MoveNext()) { + var b = i.Current; + if (b.Item1 == src) { + return LoopsExitedForwardEdge(dest, i); + } else if (b.Item1 == dest) { + return LoopsExitedBackEdge(src, i); + } + } + Debug.Assert(false); + return null; + } + + private IEnumerable<Block> LoopsExitedBackEdge(Block src, IEnumerator<Tuple<Block, bool>> i) { + var headsSeen = new HashSet<Block>(); + while (i.MoveNext()) { + var b = i.Current; + if (!b.Item2 && blockGraph.Headers.Contains(b.Item1)) + headsSeen.Add(b.Item1); + else if (b.Item2) + headsSeen.Remove(b.Item1); + if (b.Item1 == src) + return headsSeen; + } + Debug.Assert(false); + return null; + } + + private IEnumerable<Block> LoopsExitedForwardEdge(Block dest, IEnumerator<Tuple<Block, bool>> i) { + var headsSeen = new HashSet<Block>(); + while (i.MoveNext()) { + var b = i.Current; + if (b.Item1 == dest) + yield break; + else if (!b.Item2 && blockGraph.Headers.Contains(b.Item1)) + headsSeen.Add(b.Item1); + else if (b.Item2 && !headsSeen.Contains(b.Item1)) + yield return b.Item1; + } + Debug.Assert(false); + } + + class PartInfo { + public PartInfo(Expr p, Block r) { pred = p; realDest = r; } + public Expr pred; + public Block realDest; + } + + Dictionary<Block, PartInfo> BuildPartitionInfo() { + var partInfo = new Dictionary<Block, PartInfo>(); + foreach (var block in blockGraph.Nodes) { + if (uni.IsUniform(impl.Name, block)) + continue; + + var parts = block.Cmds.Cast<Cmd>().TakeWhile( + c => c is AssumeCmd && + QKeyValue.FindBoolAttribute(((AssumeCmd)c).Attributes, "partition")); + + Expr pred = null; + if (parts.Count() > 0) { + pred = parts.Select(a => ((AssumeCmd)a).Expr).Aggregate(Expr.And); + block.Cmds = + new CmdSeq(block.Cmds.Cast<Cmd>().Skip(parts.Count()).ToArray()); + } else { + continue; + } + + Block realDest = block; + if (block.Cmds.Length == 0) { + var gc = block.TransferCmd as GotoCmd; + if (gc != null && gc.labelTargets.Length == 1) + realDest = gc.labelTargets[0]; + } + partInfo[block] = new PartInfo(pred, realDest); + } + + return partInfo; + } + + 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 backedgeBlock = new Block(); + newBlocks.Add(backedgeBlock); + + backedgeBlock.Label = n.Item1.Label + ".backedge"; + backedgeBlock.Cmds = new CmdSeq(new AssumeCmd(Token.NoToken, pExpr, + new QKeyValue(Token.NoToken, "backedge", new List<object>(), null))); + backedgeBlock.TransferCmd = new GotoCmd(Token.NoToken, + new BlockSeq(n.Item1)); + + var tailBlock = new Block(); + newBlocks.Add(tailBlock); + + tailBlock.Label = n.Item1.Label + ".tail"; + tailBlock.Cmds = new CmdSeq(new AssumeCmd(Token.NoToken, + Expr.Not(pExpr))); + + if (prevBlock != null) + prevBlock.TransferCmd = new GotoCmd(Token.NoToken, + new BlockSeq(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; + } + + private void PredicateBlock(Expr pExpr, Block block, List<Block> newBlocks, ref Block prevBlock) { + var firstBlock = block; + + var oldCmdSeq = block.Cmds; + block.Cmds = new CmdSeq(); + newBlocks.Add(block); + if (prevBlock != null) { + prevBlock.TransferCmd = new GotoCmd(Token.NoToken, new BlockSeq(block)); + } + + if (parentMap.ContainsKey(block)) { + var parent = parentMap[block]; + if (predMap.ContainsKey(parent)) { + var parentPred = predMap[parent]; + if (parentPred != null) { + block.Cmds.Add(new AssertCmd(Token.NoToken, + pExpr != null ? (Expr)Expr.Imp(pExpr, Expr.Ident(parentPred)) + : Expr.Ident(parentPred))); + } + } + } + + var transferCmd = block.TransferCmd; + foreach (Cmd cmd in oldCmdSeq) + PredicateCmd(pExpr, newBlocks, block, cmd, out block); + + if (ownedMap.ContainsKey(firstBlock)) { + var owned = ownedMap[firstBlock]; + foreach (var v in owned) + block.Cmds.Add(Cmd.SimpleAssign(Token.NoToken, Expr.Ident(v), Expr.False)); + } + + bool hasPredicatedRegion; + PredicateTransferCmd(pExpr, block, block.Cmds, transferCmd, out hasPredicatedRegion); + + if (hasPredicatedRegion) + prevBlock = block; + else + prevBlock = null; + + doneBlocks.Add(block); + } + + private Expr CreateIfFPThenElse(Expr then, Expr eElse) { + if (myUseProcedurePredicates) { + return new NAryExpr(Token.NoToken, + new IfThenElse(Token.NoToken), + new ExprSeq(fp, then, eElse)); + } else { + return then; + } + } + + public static void Predicate(Program p, + Func<Procedure, bool> useProcedurePredicates = null, + UniformityAnalyser uni = null) { + useProcedurePredicates = useProcedurePredicates ?? (proc => false); + if (uni != null) { + var oldUPP = useProcedurePredicates; + useProcedurePredicates = proc => oldUPP(proc) && !uni.IsUniform(proc.Name); + } + + foreach (var decl in p.TopLevelDeclarations.ToList()) { + if (decl is Procedure || decl is Implementation) { + var proc = decl as Procedure; + Implementation impl = null; + if (proc == null) { + impl = (Implementation)decl; + proc = impl.Proc; + } + + bool upp = useProcedurePredicates(proc); + if (upp) { + var dwf = (DeclWithFormals)decl; + var fpVar = new Formal(Token.NoToken, + new TypedIdent(Token.NoToken, "_P", + Microsoft.Boogie.Type.Bool), + /*incoming=*/true); + dwf.InParams = new VariableSeq( + (new Variable[] {fpVar}.Concat(dwf.InParams.Cast<Variable>())) + .ToArray()); + + if (impl == null) { + var newRequires = new RequiresSeq(); + foreach (Requires r in proc.Requires) { + newRequires.Add(new Requires(r.Free, + new EnabledReplacementVisitor(new IdentifierExpr(Token.NoToken, fpVar)).VisitExpr(r.Condition))); + } + var newEnsures = new EnsuresSeq(); + foreach (Ensures e in proc.Ensures) { + newEnsures.Add(new Ensures(e.Free, + new EnabledReplacementVisitor(new IdentifierExpr(Token.NoToken, fpVar)).VisitExpr(e.Condition))); + } + } + } + + if (impl != null) { + try { + new SmartBlockPredicator(p, impl, useProcedurePredicates, uni).PredicateImplementation(); + } catch (Program.IrreducibleLoopException) { } + } + } + } + } + + public static void Predicate(Program p, Implementation impl) { + try { + new SmartBlockPredicator(p, impl, proc => false, null).PredicateImplementation(); + } + catch (Program.IrreducibleLoopException) { } + } + +} + +} diff --git a/Source/GPUVerify/UniformityAnalyser.cs b/Source/VCGeneration/UniformityAnalyser.cs index 35f297ed..e5647a21 100644 --- a/Source/GPUVerify/UniformityAnalyser.cs +++ b/Source/VCGeneration/UniformityAnalyser.cs @@ -1,425 +1,539 @@ -using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Microsoft.Boogie;
-using System.Diagnostics;
-
-namespace GPUVerify
-{
-
- class UniformityAnalyser
- {
- private GPUVerifier verifier;
-
- private bool ProcedureChanged;
-
- private Dictionary<string, KeyValuePair<bool, Dictionary<string, bool>>> uniformityInfo;
-
- private Dictionary<string, HashSet<int>> nonUniformLoops;
-
- private Dictionary<string, HashSet<int>> loopsWithNonuniformReturn;
-
- private Dictionary<string, List<string>> inParameters;
-
- private Dictionary<string, List<string>> outParameters;
-
- private List<WhileCmd> loopStack;
-
- private bool hitNonuniformReturn;
-
- public UniformityAnalyser(GPUVerifier verifier)
- {
- this.verifier = verifier;
- uniformityInfo = new Dictionary<string, KeyValuePair<bool, Dictionary<string, bool>>>();
- nonUniformLoops = new Dictionary<string, HashSet<int>>();
- loopsWithNonuniformReturn = new Dictionary<string, HashSet<int>>();
- inParameters = new Dictionary<string, List<string>>();
- outParameters = new Dictionary<string, List<string>>();
- loopStack = new List<WhileCmd>();
- }
-
- internal void Analyse()
- {
- if (CommandLineOptions.Unstructured)
- return;
-
- foreach (Declaration D in verifier.Program.TopLevelDeclarations)
- {
- if(D is Implementation)
+using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Boogie; +using System.Diagnostics; +using Graphing; + +namespace Microsoft.Boogie +{ + + public class UniformityAnalyser + { + private Program prog; + + private bool doAnalysis, unstructured; + + private ISet<Implementation> entryPoints; + + private IEnumerable<Variable> nonUniformVars; + + private bool ProcedureChanged; + + private Dictionary<string, KeyValuePair<bool, Dictionary<string, bool>>> uniformityInfo; + + private Dictionary<string, HashSet<int>> nonUniformLoops; + + private Dictionary<string, HashSet<Block>> nonUniformBlocks; + + private Dictionary<string, HashSet<int>> loopsWithNonuniformReturn; + + private Dictionary<string, List<string>> inParameters; + + private Dictionary<string, List<string>> outParameters; + + private List<WhileCmd> loopStack; + + private bool hitNonuniformReturn; + + public UniformityAnalyser(Program prog, bool doAnalysis, bool unstructured, ISet<Implementation> entryPoints, IEnumerable<Variable> nonUniformVars) + { + this.prog = prog; + this.doAnalysis = doAnalysis; + this.unstructured = unstructured; + this.entryPoints = entryPoints; + this.nonUniformVars = nonUniformVars; + uniformityInfo = new Dictionary<string, KeyValuePair<bool, Dictionary<string, bool>>>(); + nonUniformLoops = new Dictionary<string, HashSet<int>>(); + nonUniformBlocks = new Dictionary<string, HashSet<Block>>(); + loopsWithNonuniformReturn = new Dictionary<string, HashSet<int>>(); + inParameters = new Dictionary<string, List<string>>(); + outParameters = new Dictionary<string, List<string>>(); + loopStack = new List<WhileCmd>(); + } + + public void Analyse() + { + var impls = prog.TopLevelDeclarations.OfType<Implementation>(); + + foreach (var Impl in impls) + { + bool uniformProcedure = doAnalysis || entryPoints.Contains(Impl); + + uniformityInfo.Add(Impl.Name, new KeyValuePair<bool, Dictionary<string, bool>> + (uniformProcedure, new Dictionary<string, bool> ())); + + nonUniformLoops.Add(Impl.Name, new HashSet<int>()); + loopsWithNonuniformReturn.Add(Impl.Name, new HashSet<int>()); + + foreach (var v in nonUniformVars) + SetNonUniform(Impl.Name, v.Name); + + foreach (Variable v in Impl.LocVars) + { + if (doAnalysis) + { + SetUniform(Impl.Name, v.Name); + } + else + { + SetNonUniform(Impl.Name, v.Name); + } + } + + inParameters[Impl.Name] = new List<string>(); + + foreach (Variable v in Impl.InParams) + { + inParameters[Impl.Name].Add(v.Name); + if (doAnalysis) + { + SetUniform(Impl.Name, v.Name); + } + else + { + SetNonUniform(Impl.Name, v.Name); + } + } + + outParameters[Impl.Name] = new List<string>(); + foreach (Variable v in Impl.OutParams) + { + outParameters[Impl.Name].Add(v.Name); + if (doAnalysis) + { + SetUniform(Impl.Name, v.Name); + } + else + { + SetNonUniform(Impl.Name, v.Name); + } + } + + ProcedureChanged = true; + } + + if (doAnalysis) + { + while (ProcedureChanged) {
- bool uniformProcedure =
- (D == verifier.KernelImplementation
- || CommandLineOptions.DoUniformityAnalysis);
-
- Implementation Impl = D as Implementation;
- uniformityInfo.Add(Impl.Name, new KeyValuePair<bool, Dictionary<string, bool>>
- (uniformProcedure, new Dictionary<string, bool> ()));
-
- nonUniformLoops.Add(Impl.Name, new HashSet<int>());
- loopsWithNonuniformReturn.Add(Impl.Name, new HashSet<int>());
-
- SetNonUniform(Impl.Name, GPUVerifier._X.Name);
- SetNonUniform(Impl.Name, GPUVerifier._Y.Name);
- SetNonUniform(Impl.Name, GPUVerifier._Z.Name);
-
- SetNonUniform(Impl.Name, GPUVerifier._GROUP_X.Name);
- SetNonUniform(Impl.Name, GPUVerifier._GROUP_Y.Name);
- SetNonUniform(Impl.Name, GPUVerifier._GROUP_Z.Name);
-
- foreach (Variable v in Impl.LocVars)
- {
- if (CommandLineOptions.DoUniformityAnalysis)
- {
- SetUniform(Impl.Name, v.Name);
- }
- else
- {
- SetNonUniform(Impl.Name, v.Name);
- }
- }
-
- inParameters[Impl.Name] = new List<string>();
-
- foreach (Variable v in Impl.InParams)
- {
- inParameters[Impl.Name].Add(v.Name);
- if (CommandLineOptions.DoUniformityAnalysis)
- {
- SetUniform(Impl.Name, v.Name);
- }
- else
- {
- SetNonUniform(Impl.Name, v.Name);
- }
+ ProcedureChanged = false; + + foreach (var Impl in impls) + { + hitNonuniformReturn = false; + Analyse(Impl, uniformityInfo[Impl.Name].Key); + } + } + } + + foreach (var Impl in impls) + { + if (!IsUniform (Impl.Name)) + { + List<string> newIns = new List<String>(); + newIns.Add("_P"); + foreach (string s in inParameters[Impl.Name]) + { + newIns.Add(s); + } + inParameters[Impl.Name] = newIns; + } + } + } + + private void Analyse(Implementation Impl, bool ControlFlowIsUniform) + { + if (unstructured) + {
+ if (!ControlFlowIsUniform) + { + nonUniformBlocks[Impl.Name] = new HashSet<Block>(Impl.Blocks); + + foreach (Variable v in Impl.LocVars) { + if (IsUniform(Impl.Name, v.Name)) { + SetNonUniform(Impl.Name, v.Name); + } }
- outParameters[Impl.Name] = new List<string>();
- foreach (Variable v in Impl.OutParams)
- {
- outParameters[Impl.Name].Add(v.Name);
- if (CommandLineOptions.DoUniformityAnalysis)
- {
- SetUniform(Impl.Name, v.Name);
- }
- else
- {
+ foreach (Variable v in Impl.InParams) {
+ if (IsUniform(Impl.Name, v.Name)) {
SetNonUniform(Impl.Name, v.Name);
}
}
- ProcedureChanged = true;
- }
- }
-
- if (CommandLineOptions.DoUniformityAnalysis)
- {
- while (ProcedureChanged)
- {
- ProcedureChanged = false;
-
- foreach (Declaration D in verifier.Program.TopLevelDeclarations)
- {
- if (D is Implementation)
- {
- hitNonuniformReturn = false;
- Implementation Impl = D as Implementation;
- Analyse(Impl, uniformityInfo[Impl.Name].Key);
- }
+ foreach (Variable v in Impl.OutParams) {
+ if (IsUniform(Impl.Name, v.Name)) {
+ SetNonUniform(Impl.Name, v.Name);
+ }
}
- }
- }
-
- foreach (Declaration D in verifier.Program.TopLevelDeclarations)
- {
- if (D is Implementation)
- {
- Implementation Impl = D as Implementation;
- if (!IsUniform (Impl.Name))
- {
- List<string> newIns = new List<String>();
- newIns.Add("_P");
- foreach (string s in inParameters[Impl.Name])
- {
- newIns.Add(s);
- }
- inParameters[Impl.Name] = newIns;
+ + return; + } + + Graph<Block> blockGraph = prog.ProcessLoops(Impl); + var ctrlDep = blockGraph.ControlDependence(); + + // Compute transitive closure of control dependence info. + bool changed; + do + { + changed = false; + foreach (var depEntry in ctrlDep) + { + var newDepSet = new HashSet<Block>(depEntry.Value); + foreach (var dep in depEntry.Value) + { + if (ctrlDep.ContainsKey(dep)) + newDepSet.UnionWith(ctrlDep[dep]); + } + if (newDepSet.Count != depEntry.Value.Count) + { + depEntry.Value.UnionWith(newDepSet); + changed = true; + } + } + } while (changed); + + var nonUniformBlockSet = new HashSet<Block>(); + nonUniformBlocks[Impl.Name] = nonUniformBlockSet;
+
+ do {
+ changed = false;
+ foreach (var block in Impl.Blocks) {
+ bool uniform = !nonUniformBlockSet.Contains(block);
+ bool newUniform = Analyse(Impl, block.Cmds, uniform);
+ if (uniform && !newUniform) {
+ changed = true;
+ nonUniformBlockSet.Add(block);
+ Block pred = blockGraph.Predecessors(block).Single();
+ if (ctrlDep.ContainsKey(pred))
+ nonUniformBlockSet.UnionWith(ctrlDep[pred]);
}
- }
- }
-
- if (CommandLineOptions.ShowUniformityAnalysis)
- {
- dump();
- }
- }
-
- private void Analyse(Implementation Impl, bool ControlFlowIsUniform)
- {
- Analyse(Impl, Impl.StructuredStmts, ControlFlowIsUniform);
- }
-
-
- private void Analyse(Implementation impl, StmtList stmtList, bool ControlFlowIsUniform)
- {
- ControlFlowIsUniform &= !hitNonuniformReturn;
- foreach (BigBlock bb in stmtList.BigBlocks)
- {
- Analyse(impl, bb, ControlFlowIsUniform);
- }
- }
-
- private void Analyse(Implementation impl, BigBlock bb, bool ControlFlowIsUniform)
- {
- ControlFlowIsUniform &= !hitNonuniformReturn;
- foreach (Cmd c in bb.simpleCmds)
- {
- if (c is AssignCmd)
- {
- AssignCmd assignCmd = c as AssignCmd;
- Debug.Assert(assignCmd.Lhss.Count == 1);
- Debug.Assert(assignCmd.Rhss.Count == 1);
- if (assignCmd.Lhss[0] is SimpleAssignLhs)
+ }
+ } while (changed);
+ } + else + { + Analyse(Impl, Impl.StructuredStmts, ControlFlowIsUniform); + } + } + + + private void Analyse(Implementation impl, StmtList stmtList, bool ControlFlowIsUniform) + { + ControlFlowIsUniform &= !hitNonuniformReturn; + foreach (BigBlock bb in stmtList.BigBlocks) + { + Analyse(impl, bb, ControlFlowIsUniform); + } + } + + private Implementation GetImplementation(string procedureName) + { + foreach (Declaration D in prog.TopLevelDeclarations) + { + if (D is Implementation && ((D as Implementation).Name == procedureName)) + { + return D as Implementation; + } + } + return null; + } + + private void Analyse(Implementation impl, BigBlock bb, bool ControlFlowIsUniform) + { + ControlFlowIsUniform &= !hitNonuniformReturn; + Analyse(impl, bb.simpleCmds, ControlFlowIsUniform); + + if (bb.ec is WhileCmd) + { + WhileCmd wc = bb.ec as WhileCmd; + loopStack.Add(wc); + Analyse(impl, wc.Body, ControlFlowIsUniform && IsUniform(impl.Name, wc.Guard) && + !nonUniformLoops[impl.Name].Contains(GetLoopId(wc))); + loopStack.RemoveAt(loopStack.Count - 1); + } + else if (bb.ec is IfCmd) + { + IfCmd ifCmd = bb.ec as IfCmd; + Analyse(impl, ifCmd.thn, ControlFlowIsUniform && IsUniform(impl.Name, ifCmd.Guard)); + if (ifCmd.elseBlock != null) + { + Analyse(impl, ifCmd.elseBlock, ControlFlowIsUniform && IsUniform(impl.Name, ifCmd.Guard)); + } + Debug.Assert(ifCmd.elseIf == null); + } + else if (bb.ec is BreakCmd) + { + if (!ControlFlowIsUniform && !nonUniformLoops[impl.Name].Contains(GetLoopId(loopStack[loopStack.Count - 1]))) + { + SetNonUniform(impl.Name, loopStack[loopStack.Count - 1]); + } + } + + if (bb.tc is ReturnCmd && !ControlFlowIsUniform) + { + hitNonuniformReturn = true; + if (loopStack.Count > 0 && !nonUniformLoops[impl.Name].Contains(GetLoopId(loopStack[0]))) + { + SetNonUniform(impl.Name, loopStack[0]); + loopsWithNonuniformReturn[impl.Name].Add(GetLoopId(loopStack[0])); + } + } + + + } + + private bool Analyse(Implementation impl, CmdSeq cmdSeq, bool ControlFlowIsUniform) + { + foreach (Cmd c in cmdSeq) + { + if (c is AssignCmd) + { + AssignCmd assignCmd = c as AssignCmd; + foreach (var a in assignCmd.Lhss.Zip(assignCmd.Rhss)) {
- SimpleAssignLhs lhs = assignCmd.Lhss[0] as SimpleAssignLhs;
- Expr rhs = assignCmd.Rhss[0];
-
- if (IsUniform(impl.Name, lhs.AssignedVariable.Name) &&
- (!ControlFlowIsUniform || !IsUniform(impl.Name, rhs)))
- {
- SetNonUniform(impl.Name, lhs.AssignedVariable.Name);
- }
-
- }
- }
- else if (c is CallCmd)
- {
- CallCmd callCmd = c as CallCmd;
-
- if (callCmd.callee != verifier.BarrierProcedure.Name)
- {
-
- if (!ControlFlowIsUniform)
- {
- if (IsUniform(callCmd.callee))
- {
- SetNonUniform(callCmd.callee);
- }
- }
- Implementation CalleeImplementation = verifier.GetImplementation(callCmd.callee);
- for (int i = 0; i < CalleeImplementation.InParams.Length; i++)
- {
- if (IsUniform(callCmd.callee, CalleeImplementation.InParams[i].Name)
- && !IsUniform(impl.Name, callCmd.Ins[i]))
+ + if (a.Item1 is SimpleAssignLhs) + { + SimpleAssignLhs lhs = a.Item1 as SimpleAssignLhs;
+ Expr rhs = a.Item2;
+ if (IsUniform(impl.Name, lhs.AssignedVariable.Name) && + (!ControlFlowIsUniform || !IsUniform(impl.Name, rhs))) {
- SetNonUniform(callCmd.callee, CalleeImplementation.InParams[i].Name);
+ SetNonUniform(impl.Name, lhs.AssignedVariable.Name); }
- }
-
- for (int i = 0; i < CalleeImplementation.OutParams.Length; i++)
- {
- if (IsUniform(impl.Name, callCmd.Outs[i].Name)
- && !IsUniform(callCmd.callee, CalleeImplementation.OutParams[i].Name))
- {
- SetNonUniform(impl.Name, callCmd.Outs[i].Name);
- }
- }
-
- }
- }
- }
-
- if (bb.ec is WhileCmd)
- {
- WhileCmd wc = bb.ec as WhileCmd;
- loopStack.Add(wc);
- Analyse(impl, wc.Body, ControlFlowIsUniform && IsUniform(impl.Name, wc.Guard) &&
- !nonUniformLoops[impl.Name].Contains(GetLoopId(wc)));
- loopStack.RemoveAt(loopStack.Count - 1);
- }
- else if (bb.ec is IfCmd)
- {
- IfCmd ifCmd = bb.ec as IfCmd;
- Analyse(impl, ifCmd.thn, ControlFlowIsUniform && IsUniform(impl.Name, ifCmd.Guard));
- if (ifCmd.elseBlock != null)
- {
- Analyse(impl, ifCmd.elseBlock, ControlFlowIsUniform && IsUniform(impl.Name, ifCmd.Guard));
- }
- Debug.Assert(ifCmd.elseIf == null);
- }
- else if (bb.ec is BreakCmd)
- {
- if (!ControlFlowIsUniform && !nonUniformLoops[impl.Name].Contains(GetLoopId(loopStack[loopStack.Count - 1])))
- {
- SetNonUniform(impl.Name, loopStack[loopStack.Count - 1]);
- }
- }
-
- if (bb.tc is ReturnCmd && !ControlFlowIsUniform)
- {
- hitNonuniformReturn = true;
- if (loopStack.Count > 0 && !nonUniformLoops[impl.Name].Contains(GetLoopId(loopStack[0])))
- {
- SetNonUniform(impl.Name, loopStack[0]);
- loopsWithNonuniformReturn[impl.Name].Add(GetLoopId(loopStack[0]));
- }
- }
-
-
- }
-
- private int GetLoopId(WhileCmd wc)
- {
- AssertCmd inv = wc.Invariants[0] as AssertCmd;
- Debug.Assert(inv.Attributes.Key.Contains("loophead_"));
- return Convert.ToInt32(inv.Attributes.Key.Substring("loophead_".Length));
- }
-
- private void SetNonUniform(string procedureName)
- {
- uniformityInfo[procedureName] = new KeyValuePair<bool,Dictionary<string,bool>>
- (false, uniformityInfo[procedureName].Value);
- RecordProcedureChanged();
- }
-
- private void SetNonUniform(string procedureName, WhileCmd wc)
- {
- nonUniformLoops[procedureName].Add(GetLoopId(wc));
- RecordProcedureChanged();
- }
-
- internal bool IsUniform(string procedureName)
- {
- if (CommandLineOptions.Unstructured)
- return false;
-
- if (!uniformityInfo.ContainsKey(procedureName))
- {
- return false;
- }
- return uniformityInfo[procedureName].Key;
- }
- internal bool IsUniform(string procedureName, Expr expr)
- {
- if (CommandLineOptions.Unstructured)
- return false;
-
- UniformExpressionAnalysisVisitor visitor = new UniformExpressionAnalysisVisitor(uniformityInfo[procedureName].Value);
- visitor.VisitExpr(expr);
- return visitor.IsUniform();
- }
-
- internal bool IsUniform(string procedureName, string v)
- {
- if (CommandLineOptions.Unstructured)
- return false;
-
- if (!uniformityInfo.ContainsKey(procedureName))
- {
- return false;
- }
-
- if (!uniformityInfo[procedureName].Value.ContainsKey(v))
- {
- return false;
- }
- return uniformityInfo[procedureName].Value[v];
- }
-
- private void SetUniform(string procedureName, string v)
- {
- uniformityInfo[procedureName].Value[v] = true;
- RecordProcedureChanged();
- }
-
- private void RecordProcedureChanged()
- {
- ProcedureChanged = true;
- }
-
- private void SetNonUniform(string procedureName, string v)
- {
- uniformityInfo[procedureName].Value[v] = false;
- RecordProcedureChanged();
- }
-
- private void dump()
- {
- foreach (string p in uniformityInfo.Keys)
- {
- Console.WriteLine("Procedure " + p + ": "
- + (uniformityInfo[p].Key ? "uniform" : "nonuniform"));
- foreach (string v in uniformityInfo[p].Value.Keys)
- {
- Console.WriteLine(" " + v + ": " +
- (uniformityInfo[p].Value[v] ? "uniform" : "nonuniform"));
- }
- Console.Write("Ins [");
- for (int i = 0; i < inParameters[p].Count; i++)
- {
- Console.Write((i == 0 ? "" : ", ") + inParameters[p][i]);
- }
- Console.WriteLine("]");
- Console.Write("Outs [");
- for (int i = 0; i < outParameters[p].Count; i++)
- {
- Console.Write((i == 0 ? "" : ", ") + outParameters[p][i]);
- }
- Console.WriteLine("]");
- Console.Write("Non-uniform loops:");
- foreach (int l in nonUniformLoops[p])
- {
- Console.Write(" " + l);
- }
- Console.WriteLine();
- }
- }
-
-
- internal string GetInParameter(string procName, int i)
- {
- if (CommandLineOptions.Unstructured)
- return null;
-
- return inParameters[procName][i];
- }
-
- internal string GetOutParameter(string procName, int i)
- {
- if (CommandLineOptions.Unstructured)
- return null;
-
- return outParameters[procName][i];
- }
-
-
- internal bool knowsOf(string p)
- {
- return uniformityInfo.ContainsKey(p);
- }
-
- internal void AddNonUniform(string proc, string v)
- {
- if (uniformityInfo.ContainsKey(proc))
- {
- Debug.Assert(!uniformityInfo[proc].Value.ContainsKey(v));
- uniformityInfo[proc].Value[v] = false;
- }
- }
-
- internal bool IsUniform(string proc, WhileCmd wc)
- {
- if (CommandLineOptions.Unstructured)
- return false;
-
- return !nonUniformLoops[proc].Contains(GetLoopId(wc));
- }
-
- internal bool HasNonuniformReturn(string proc, WhileCmd whileCmd)
- {
- return loopsWithNonuniformReturn[proc].Contains(GetLoopId(whileCmd));
- }
- }
-
-}
+ } + } + } + else if (c is CallCmd) + { + CallCmd callCmd = c as CallCmd; + Implementation CalleeImplementation = GetImplementation(callCmd.callee); + + if (CalleeImplementation != null) + { + + if (!ControlFlowIsUniform) + { + if (IsUniform(callCmd.callee)) + { + SetNonUniform(callCmd.callee); + } + } + for (int i = 0; i < CalleeImplementation.InParams.Length; i++) + { + if (IsUniform(callCmd.callee, CalleeImplementation.InParams[i].Name) + && !IsUniform(impl.Name, callCmd.Ins[i])) + { + SetNonUniform(callCmd.callee, CalleeImplementation.InParams[i].Name); + } + } + + for (int i = 0; i < CalleeImplementation.OutParams.Length; i++) + { + if (IsUniform(impl.Name, callCmd.Outs[i].Name) + && !IsUniform(callCmd.callee, CalleeImplementation.OutParams[i].Name)) + { + SetNonUniform(impl.Name, callCmd.Outs[i].Name); + } + } + + } + } + else if (c is AssumeCmd) + { + var ac = (AssumeCmd)c; + if (ControlFlowIsUniform && QKeyValue.FindBoolAttribute(ac.Attributes, "partition") && + !IsUniform(impl.Name, ac.Expr)) + {
+ ControlFlowIsUniform = false;
+ } + } + } + + return ControlFlowIsUniform; + } + + private int GetLoopId(WhileCmd wc) + { + AssertCmd inv = wc.Invariants[0] as AssertCmd; + Debug.Assert(inv.Attributes.Key.Contains("loophead_")); + return Convert.ToInt32(inv.Attributes.Key.Substring("loophead_".Length)); + } + + private void SetNonUniform(string procedureName) + { + uniformityInfo[procedureName] = new KeyValuePair<bool,Dictionary<string,bool>> + (false, uniformityInfo[procedureName].Value); + RecordProcedureChanged(); + } + + private void SetNonUniform(string procedureName, WhileCmd wc) + { + nonUniformLoops[procedureName].Add(GetLoopId(wc)); + RecordProcedureChanged(); + } + + public bool IsUniform(string procedureName) + { + if (!uniformityInfo.ContainsKey(procedureName)) + { + return false; + } + return uniformityInfo[procedureName].Key; + } + + public bool IsUniform(string procedureName, Block b) + { + if (!nonUniformBlocks.ContainsKey(procedureName)) + { + return false; + } + return !nonUniformBlocks[procedureName].Contains(b); + } + + class UniformExpressionAnalysisVisitor : StandardVisitor { + + private bool isUniform = true; + private Dictionary<string, bool> uniformityInfo; + + public UniformExpressionAnalysisVisitor(Dictionary<string, bool> uniformityInfo) { + this.uniformityInfo = uniformityInfo; + } + + public override Variable VisitVariable(Variable v) { + if (!uniformityInfo.ContainsKey(v.Name)) { + isUniform = isUniform && (v is Constant); + } else if (!uniformityInfo[v.Name]) { + isUniform = false; + } + + return v; + } + + internal bool IsUniform() { + return isUniform; + } + } + + public bool IsUniform(string procedureName, Expr expr) + { + UniformExpressionAnalysisVisitor visitor = new UniformExpressionAnalysisVisitor(uniformityInfo[procedureName].Value); + visitor.VisitExpr(expr); + return visitor.IsUniform(); + } + + public bool IsUniform(string procedureName, string v) + { + if (!uniformityInfo.ContainsKey(procedureName)) + { + return false; + } + + if (!uniformityInfo[procedureName].Value.ContainsKey(v)) + { + return false; + } + return uniformityInfo[procedureName].Value[v]; + } + + private void SetUniform(string procedureName, string v) + { + uniformityInfo[procedureName].Value[v] = true; + RecordProcedureChanged(); + } + + private void RecordProcedureChanged() + { + ProcedureChanged = true; + } + + private void SetNonUniform(string procedureName, string v) + { + uniformityInfo[procedureName].Value[v] = false; + RecordProcedureChanged(); + } + + public void dump() + { + foreach (string p in uniformityInfo.Keys) + { + Console.WriteLine("Procedure " + p + ": " + + (uniformityInfo[p].Key ? "uniform" : "nonuniform")); + foreach (string v in uniformityInfo[p].Value.Keys) + { + Console.WriteLine(" " + v + ": " + + (uniformityInfo[p].Value[v] ? "uniform" : "nonuniform")); + } + Console.Write("Ins ["); + for (int i = 0; i < inParameters[p].Count; i++) + { + Console.Write((i == 0 ? "" : ", ") + inParameters[p][i]); + } + Console.WriteLine("]"); + Console.Write("Outs ["); + for (int i = 0; i < outParameters[p].Count; i++) + { + Console.Write((i == 0 ? "" : ", ") + outParameters[p][i]); + } + Console.WriteLine("]"); + Console.Write("Non-uniform loops:"); + foreach (int l in nonUniformLoops[p]) + { + Console.Write(" " + l); + } + Console.WriteLine(); + Console.Write("Non-uniform blocks:"); + foreach (Block b in nonUniformBlocks[p]) + { + Console.Write(" " + b.Label); + } + Console.WriteLine(); + } + } + + + public string GetInParameter(string procName, int i) + { + return inParameters[procName][i]; + } + + public string GetOutParameter(string procName, int i) + { + return outParameters[procName][i]; + } + + + public bool knowsOf(string p) + { + return uniformityInfo.ContainsKey(p); + } + + public void AddNonUniform(string proc, string v) + { + if (uniformityInfo.ContainsKey(proc)) + { + Debug.Assert(!uniformityInfo[proc].Value.ContainsKey(v)); + uniformityInfo[proc].Value[v] = false; + } + } + + public bool IsUniform(string proc, WhileCmd wc) + { + if (unstructured) + return false; + + return !nonUniformLoops[proc].Contains(GetLoopId(wc)); + } + + public bool HasNonuniformReturn(string proc, WhileCmd whileCmd) + { + return loopsWithNonuniformReturn[proc].Contains(GetLoopId(whileCmd)); + } + } + +} diff --git a/Source/VCGeneration/VCGeneration.csproj b/Source/VCGeneration/VCGeneration.csproj index 780e4891..fe7ddc70 100644 --- a/Source/VCGeneration/VCGeneration.csproj +++ b/Source/VCGeneration/VCGeneration.csproj @@ -1,227 +1,228 @@ -<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>9.0.21022</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</ProjectGuid>
- <OutputType>Library</OutputType>
- <AppDesignerFolder>Properties</AppDesignerFolder>
- <RootNamespace>VCGeneration</RootNamespace>
- <AssemblyName>VCGeneration</AssemblyName>
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <FileAlignment>512</FileAlignment>
- <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
- <SignAssembly>true</SignAssembly>
- <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile>
- <FileUpgradeFlags>
- </FileUpgradeFlags>
- <OldToolsVersion>3.5</OldToolsVersion>
- <UpgradeBackupLocation />
- <PublishUrl>publish\</PublishUrl>
- <Install>true</Install>
- <InstallFrom>Disk</InstallFrom>
- <UpdateEnabled>false</UpdateEnabled>
- <UpdateMode>Foreground</UpdateMode>
- <UpdateInterval>7</UpdateInterval>
- <UpdateIntervalUnits>Days</UpdateIntervalUnits>
- <UpdatePeriodically>false</UpdatePeriodically>
- <UpdateRequired>false</UpdateRequired>
- <MapFileExtensions>true</MapFileExtensions>
- <ApplicationRevision>0</ApplicationRevision>
- <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
- <IsWebBootstrapper>false</IsWebBootstrapper>
- <UseApplicationTrust>false</UseApplicationTrust>
- <BootstrapperEnabled>true</BootstrapperEnabled>
- <TargetFrameworkProfile>Client</TargetFrameworkProfile>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <DebugType>full</DebugType>
- <Optimize>false</Optimize>
- <OutputPath>bin\Debug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly>
- </CodeContractsCustomRewriterAssembly>
- <CodeContractsCustomRewriterClass>
- </CodeContractsCustomRewriterClass>
- <CodeContractsLibPaths>
- </CodeContractsLibPaths>
- <CodeContractsExtraRewriteOptions>
- </CodeContractsExtraRewriteOptions>
- <CodeContractsExtraAnalysisOptions>
- </CodeContractsExtraAnalysisOptions>
- <CodeContractsBaseLineFile>
- </CodeContractsBaseLineFile>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <DebugType>pdbonly</DebugType>
- <Optimize>true</Optimize>
- <OutputPath>bin\Release\</OutputPath>
- <DefineConstants>TRACE</DefineConstants>
- <ErrorReport>prompt</ErrorReport>
- <WarningLevel>4</WarningLevel>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' ">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\z3apidebug\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisRuleAssemblies>
- </CodeAnalysisRuleAssemblies>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>Migrated rules for VCGeneration.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'">
- <DebugSymbols>true</DebugSymbols>
- <OutputPath>bin\Checked\</OutputPath>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DebugType>full</DebugType>
- <PlatformTarget>AnyCPU</PlatformTarget>
- <CodeAnalysisLogFile>bin\Debug\VCGeneration.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
- <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
- <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
- <ErrorReport>prompt</ErrorReport>
- <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
- <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
- <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
- <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
- <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
- <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
- <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
- <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
- <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
- <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
- <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
- <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
- <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
- <CodeContractsPointerObligations>False</CodeContractsPointerObligations>
- <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
- <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
- <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
- <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
- <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
- <CodeContractsCustomRewriterAssembly />
- <CodeContractsCustomRewriterClass />
- <CodeContractsLibPaths />
- <CodeContractsExtraRewriteOptions />
- <CodeContractsExtraAnalysisOptions />
- <CodeContractsBaseLineFile />
- <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
- <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
- <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
- <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System" />
- <Reference Include="System.Data" />
- <Reference Include="System.Xml" />
- </ItemGroup>
- <ItemGroup>
- <Compile Include="BlockPredicator.cs" />
- <Compile Include="Check.cs" />
- <Compile Include="ConditionGeneration.cs" />
- <Compile Include="Context.cs" />
- <Compile Include="DoomCheck.cs" />
- <Compile Include="DoomedLoopUnrolling.cs" />
- <Compile Include="DoomedStrategy.cs" />
- <Compile Include="DoomErrorHandler.cs" />
- <Compile Include="GraphAlgorithms.cs" />
- <Compile Include="HasseDiagram.cs" />
- <Compile Include="OrderingAxioms.cs" />
- <Compile Include="SmartBlockPredicator.cs" />
- <Compile Include="StratifiedVC.cs" />
- <Compile Include="VC.cs" />
- <Compile Include="VCDoomed.cs" />
- <Compile Include="..\version.cs" />
- <Compile Include="Wlp.cs" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\AIFramework\AIFramework.csproj">
- <Project>{39B0658D-C955-41C5-9A43-48C97A1EF5FD}</Project>
- <Name>AIFramework</Name>
- </ProjectReference>
- <ProjectReference Include="..\Basetypes\Basetypes.csproj">
- <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project>
- <Name>Basetypes</Name>
- </ProjectReference>
- <ProjectReference Include="..\CodeContractsExtender\CodeContractsExtender.csproj">
- <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project>
- <Name>CodeContractsExtender</Name>
- </ProjectReference>
- <ProjectReference Include="..\Core\Core.csproj">
- <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project>
- <Name>Core</Name>
- </ProjectReference>
- <ProjectReference Include="..\Graph\Graph.csproj">
- <Project>{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}</Project>
- <Name>Graph</Name>
- </ProjectReference>
- <ProjectReference Include="..\Model\Model.csproj">
- <Project>{ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}</Project>
- <Name>Model</Name>
- </ProjectReference>
- <ProjectReference Include="..\ParserHelper\ParserHelper.csproj">
- <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project>
- <Name>ParserHelper</Name>
- </ProjectReference>
- <ProjectReference Include="..\VCExpr\VCExpr.csproj">
- <Project>{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}</Project>
- <Name>VCExpr</Name>
- </ProjectReference>
- </ItemGroup>
- <ItemGroup>
- <Folder Include="Properties\" />
- </ItemGroup>
- <ItemGroup>
- <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
- <Install>false</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
- <Visible>False</Visible>
- <ProductName>.NET Framework 3.5 SP1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
- <Visible>False</Visible>
- <ProductName>Windows Installer 3.1</ProductName>
- <Install>true</Install>
- </BootstrapperPackage>
- </ItemGroup>
- <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
- Other similar extension points exist, see Microsoft.Common.targets.
- <Target Name="BeforeBuild">
- </Target>
- <Target Name="AfterBuild">
- </Target>
- -->
-</Project>
+<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion>9.0.21022</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{E1F10180-C7B9-4147-B51F-FA1B701966DC}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>VCGeneration</RootNamespace> + <AssemblyName>VCGeneration</AssemblyName> + <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode> + <SignAssembly>true</SignAssembly> + <AssemblyOriginatorKeyFile>..\InterimKey.snk</AssemblyOriginatorKeyFile> + <FileUpgradeFlags> + </FileUpgradeFlags> + <OldToolsVersion>3.5</OldToolsVersion> + <UpgradeBackupLocation /> + <PublishUrl>publish\</PublishUrl> + <Install>true</Install> + <InstallFrom>Disk</InstallFrom> + <UpdateEnabled>false</UpdateEnabled> + <UpdateMode>Foreground</UpdateMode> + <UpdateInterval>7</UpdateInterval> + <UpdateIntervalUnits>Days</UpdateIntervalUnits> + <UpdatePeriodically>false</UpdatePeriodically> + <UpdateRequired>false</UpdateRequired> + <MapFileExtensions>true</MapFileExtensions> + <ApplicationRevision>0</ApplicationRevision> + <ApplicationVersion>1.0.0.%2a</ApplicationVersion> + <IsWebBootstrapper>false</IsWebBootstrapper> + <UseApplicationTrust>false</UseApplicationTrust> + <BootstrapperEnabled>true</BootstrapperEnabled> + <TargetFrameworkProfile>Client</TargetFrameworkProfile> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking> + <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface> + <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure> + <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires> + <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis> + <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations> + <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations> + <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations> + <CodeContractsPointerObligations>False</CodeContractsPointerObligations> + <CodeContractsContainerAnalysis>False</CodeContractsContainerAnalysis> + <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions> + <CodeContractsRunInBackground>True</CodeContractsRunInBackground> + <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies> + <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine> + <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs> + <CodeContractsCustomRewriterAssembly> + </CodeContractsCustomRewriterAssembly> + <CodeContractsCustomRewriterClass> + </CodeContractsCustomRewriterClass> + <CodeContractsLibPaths> + </CodeContractsLibPaths> + <CodeContractsExtraRewriteOptions> + </CodeContractsExtraRewriteOptions> + <CodeContractsExtraAnalysisOptions> + </CodeContractsExtraAnalysisOptions> + <CodeContractsBaseLineFile> + </CodeContractsBaseLineFile> + <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel> + <CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly> + <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'z3apidebug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <OutputPath>bin\z3apidebug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <DebugType>full</DebugType> + <PlatformTarget>AnyCPU</PlatformTarget> + <CodeAnalysisRuleAssemblies> + </CodeAnalysisRuleAssemblies> + <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression> + <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile> + <ErrorReport>prompt</ErrorReport> + <CodeAnalysisRuleSet>Migrated rules for VCGeneration.ruleset</CodeAnalysisRuleSet> + <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Checked|AnyCPU'"> + <DebugSymbols>true</DebugSymbols> + <OutputPath>bin\Checked\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <DebugType>full</DebugType> + <PlatformTarget>AnyCPU</PlatformTarget> + <CodeAnalysisLogFile>bin\Debug\VCGeneration.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile> + <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression> + <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile> + <ErrorReport>prompt</ErrorReport> + <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> + <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories> + <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories> + <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking> + <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface> + <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure> + <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires> + <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers> + <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis> + <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations> + <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations> + <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations> + <CodeContractsEnumObligations>False</CodeContractsEnumObligations> + <CodeContractsPointerObligations>False</CodeContractsPointerObligations> + <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions> + <CodeContractsRunInBackground>True</CodeContractsRunInBackground> + <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies> + <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine> + <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs> + <CodeContractsCustomRewriterAssembly /> + <CodeContractsCustomRewriterClass /> + <CodeContractsLibPaths /> + <CodeContractsExtraRewriteOptions /> + <CodeContractsExtraAnalysisOptions /> + <CodeContractsBaseLineFile /> + <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults> + <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel> + <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly> + <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Data" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="BlockPredicator.cs" /> + <Compile Include="Check.cs" /> + <Compile Include="ConditionGeneration.cs" /> + <Compile Include="Context.cs" /> + <Compile Include="DoomCheck.cs" /> + <Compile Include="DoomedLoopUnrolling.cs" /> + <Compile Include="DoomedStrategy.cs" /> + <Compile Include="DoomErrorHandler.cs" /> + <Compile Include="GraphAlgorithms.cs" /> + <Compile Include="HasseDiagram.cs" /> + <Compile Include="OrderingAxioms.cs" /> + <Compile Include="SmartBlockPredicator.cs" /> + <Compile Include="StratifiedVC.cs" /> + <Compile Include="UniformityAnalyser.cs" /> + <Compile Include="VC.cs" /> + <Compile Include="VCDoomed.cs" /> + <Compile Include="..\version.cs" /> + <Compile Include="Wlp.cs" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\AIFramework\AIFramework.csproj"> + <Project>{39B0658D-C955-41C5-9A43-48C97A1EF5FD}</Project> + <Name>AIFramework</Name> + </ProjectReference> + <ProjectReference Include="..\Basetypes\Basetypes.csproj"> + <Project>{43DFAD18-3E35-4558-9BE2-CAFF6B5BA8A0}</Project> + <Name>Basetypes</Name> + </ProjectReference> + <ProjectReference Include="..\CodeContractsExtender\CodeContractsExtender.csproj"> + <Project>{ACCC0156-0921-43ED-8F67-AD8BDC8CDE31}</Project> + <Name>CodeContractsExtender</Name> + </ProjectReference> + <ProjectReference Include="..\Core\Core.csproj"> + <Project>{B230A69C-C466-4065-B9C1-84D80E76D802}</Project> + <Name>Core</Name> + </ProjectReference> + <ProjectReference Include="..\Graph\Graph.csproj"> + <Project>{69A2B0B8-BCAC-4101-AE7A-556FCC58C06E}</Project> + <Name>Graph</Name> + </ProjectReference> + <ProjectReference Include="..\Model\Model.csproj"> + <Project>{ACEF88D5-DADD-46DA-BAE1-2144D63F4C83}</Project> + <Name>Model</Name> + </ProjectReference> + <ProjectReference Include="..\ParserHelper\ParserHelper.csproj"> + <Project>{FCD3AC7F-9DFD-46C8-AB1E-09F0B0F16DC5}</Project> + <Name>ParserHelper</Name> + </ProjectReference> + <ProjectReference Include="..\VCExpr\VCExpr.csproj"> + <Project>{56FFDBCA-7D14-43B8-A6CA-22A20E417EE1}</Project> + <Name>VCExpr</Name> + </ProjectReference> + </ItemGroup> + <ItemGroup> + <Folder Include="Properties\" /> + </ItemGroup> + <ItemGroup> + <BootstrapperPackage Include="Microsoft.Net.Client.3.5"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName> + <Install>false</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1"> + <Visible>False</Visible> + <ProductName>.NET Framework 3.5 SP1</ProductName> + <Install>true</Install> + </BootstrapperPackage> + <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1"> + <Visible>False</Visible> + <ProductName>Windows Installer 3.1</ProductName> + <Install>true</Install> + </BootstrapperPackage> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> +</Project>
\ No newline at end of file |