summaryrefslogtreecommitdiff
path: root/Source/GPUVerify/ReducedStrengthAnalysis.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Source/GPUVerify/ReducedStrengthAnalysis.cs')
-rw-r--r--Source/GPUVerify/ReducedStrengthAnalysis.cs166
1 files changed, 166 insertions, 0 deletions
diff --git a/Source/GPUVerify/ReducedStrengthAnalysis.cs b/Source/GPUVerify/ReducedStrengthAnalysis.cs
new file mode 100644
index 00000000..0e58ff7d
--- /dev/null
+++ b/Source/GPUVerify/ReducedStrengthAnalysis.cs
@@ -0,0 +1,166 @@
+using Microsoft.Boogie;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace GPUVerify {
+
+class ReducedStrengthAnalysis {
+
+ GPUVerifier verifier;
+ Implementation impl;
+ VariableDefinitionAnalysis varDefs;
+
+ Dictionary<Variable, List<Tuple<object, Expr>>> multiDefMap = new Dictionary<Variable, List<Tuple<object, Expr>>>();
+ Dictionary<string, ModStrideConstraint> strideConstraintMap = new Dictionary<string, ModStrideConstraint>();
+ Dictionary<object, List<string>> loopCounterMap = new Dictionary<object, List<string>>();
+
+ ReducedStrengthAnalysis(GPUVerifier v, Implementation i) {
+ verifier = v;
+ impl = i;
+ varDefs = verifier.varDefAnalyses[impl];
+ }
+
+ void AddAssignment(object regionId, AssignLhs lhs, Expr rhs) {
+ if (lhs is SimpleAssignLhs) {
+ var sLhs = (SimpleAssignLhs)lhs;
+ var theVar = sLhs.DeepAssignedVariable;
+ List<Tuple<object, Expr>> defs;
+ if (multiDefMap.ContainsKey(theVar))
+ defs = multiDefMap[theVar];
+ else
+ defs = multiDefMap[theVar] = new List<Tuple<object, Expr>>();
+ defs.Add(new Tuple<object, Expr>(regionId, rhs));
+ }
+ }
+
+ void AnalyseRegion(IRegion region) {
+ foreach (var c in region.CmdsChildRegions()) {
+ var ac = c as AssignCmd;
+ if (ac != null) {
+ foreach (var a in ac.Lhss.Zip(ac.Rhss)) {
+ AddAssignment(region.Identifier(), a.Item1, a.Item2);
+ }
+ }
+ var child = c as IRegion;
+ if (child != null)
+ AnalyseRegion(child);
+ }
+ }
+
+ void Analyse() {
+ AnalyseRegion(verifier.RootRegion(impl));
+ foreach (var v in multiDefMap.Keys) {
+ var defs = multiDefMap[v];
+ if (defs.Count != 2)
+ continue;
+ bool def0IsConst, def1IsConst;
+ var def0 = varDefs.SubstDefinitions(defs[0].Item2, impl.Name, out def0IsConst);
+ var def1 = varDefs.SubstDefinitions(defs[1].Item2, impl.Name, out def1IsConst);
+ if (def0IsConst && !def1IsConst) {
+ AddDefinitionPair(v, def0, def1, defs[1].Item1);
+ } else if (!def0IsConst && def1IsConst) {
+ AddDefinitionPair(v, def1, def0, defs[0].Item1);
+ }
+ }
+ multiDefMap = null;
+ }
+
+ private class StrideForm {
+ public StrideForm(Kind kind) { this.kind = kind; this.op = null; }
+ public StrideForm(Kind kind, Expr op) { this.kind = kind; this.op = op; }
+ public enum Kind { Bottom, Identity, Constant, Product, PowerMul, PowerDiv };
+ public Kind kind;
+ public Expr op;
+ }
+
+ private StrideForm ComputeStrideForm(Variable v, Expr e) {
+ Expr lhs, rhs;
+
+ if (e is LiteralExpr)
+ return new StrideForm(StrideForm.Kind.Constant, e);
+
+ var ie = e as IdentifierExpr;
+ if (ie != null) {
+ if (ie.Decl is Constant)
+ return new StrideForm(StrideForm.Kind.Constant, e);
+ if (ie.Decl == v)
+ return new StrideForm(StrideForm.Kind.Identity, e);
+ }
+
+ if (GPUVerifier.IsBVAdd(e, out lhs, out rhs)) {
+ var lhssf = ComputeStrideForm(v, lhs);
+ var rhssf = ComputeStrideForm(v, rhs);
+ if (lhssf.kind == StrideForm.Kind.Constant &&
+ rhssf.kind == StrideForm.Kind.Constant)
+ return new StrideForm(StrideForm.Kind.Constant, e);
+ else if (lhssf.kind == StrideForm.Kind.Constant &&
+ rhssf.kind == StrideForm.Kind.Identity)
+ return new StrideForm(StrideForm.Kind.Product, lhs);
+ else if (lhssf.kind == StrideForm.Kind.Identity &&
+ rhssf.kind == StrideForm.Kind.Constant)
+ return new StrideForm(StrideForm.Kind.Product, rhs);
+ else if (lhssf.kind == StrideForm.Kind.Constant &&
+ rhssf.kind == StrideForm.Kind.Product)
+ return new StrideForm(StrideForm.Kind.Product, verifier.MakeBVAdd(lhs, rhssf.op));
+ else if (lhssf.kind == StrideForm.Kind.Product &&
+ rhssf.kind == StrideForm.Kind.Constant)
+ return new StrideForm(StrideForm.Kind.Product, verifier.MakeBVAdd(lhssf.op, rhs));
+ else
+ return new StrideForm(StrideForm.Kind.Bottom);
+ }
+
+ var ne = e as NAryExpr;
+ if (ne != null) {
+ foreach (Expr op in ne.Args)
+ if (ComputeStrideForm(v, op).kind != StrideForm.Kind.Constant)
+ return new StrideForm(StrideForm.Kind.Bottom);
+ return new StrideForm(StrideForm.Kind.Constant, e);
+ }
+
+ return new StrideForm(StrideForm.Kind.Bottom);
+ }
+
+ private void AddDefinitionPair(Variable v, Expr constDef, Expr nonConstDef, object nonConstId) {
+ var sf = ComputeStrideForm(v, nonConstDef);
+ if (sf.kind == StrideForm.Kind.Product) {
+ var sc = new ModStrideConstraint(sf.op, constDef);
+ if (!sc.IsBottom()) {
+ strideConstraintMap[v.Name] = sc;
+ List<string> lcs;
+ if (loopCounterMap.ContainsKey(nonConstId))
+ lcs = loopCounterMap[nonConstId];
+ else
+ lcs = loopCounterMap[nonConstId] = new List<string>();
+ lcs.Add(v.Name);
+ }
+ }
+ }
+
+ public StrideConstraint GetStrideConstraint(string varName) {
+ int id;
+ var strippedVarName = GPUVerifier.StripThreadIdentifier(varName, out id);
+ if (!strideConstraintMap.ContainsKey(strippedVarName))
+ return null;
+
+ var msc = strideConstraintMap[strippedVarName];
+ if (id == 0)
+ return msc;
+ return new ModStrideConstraint(verifier.MaybeDualise(msc.mod, id, impl.Name),
+ verifier.MaybeDualise(msc.modEq, id, impl.Name));
+ }
+
+ public IEnumerable<string> StridedLoopCounters(object loopId) {
+ if (!loopCounterMap.ContainsKey(loopId))
+ return Enumerable.Empty<string>();
+ return loopCounterMap[loopId];
+ }
+
+ public static ReducedStrengthAnalysis Analyse(GPUVerifier verifier, Implementation impl) {
+ var a = new ReducedStrengthAnalysis(verifier, impl);
+ a.Analyse();
+ return a;
+ }
+}
+
+}