summaryrefslogtreecommitdiff
path: root/Source/GPUVerify/UnstructuredRegion.cs
blob: 0da75cb435979220d3c0e335789ae9d5d65f6314 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Boogie;
using Graphing;

namespace GPUVerify {

class UnstructuredRegion : IRegion {
  Graph<Block> blockGraph;
  Block header;
  Dictionary<Block, HashSet<Block>> loopNodes = new Dictionary<Block, HashSet<Block>>();
  Dictionary<Block, Block> innermostHeader = new Dictionary<Block, Block>();
  Expr guard;

  public UnstructuredRegion(Program p, Implementation impl) {
    blockGraph = p.ProcessLoops(impl);
    header = null;
    foreach (var h in blockGraph.SortHeadersByDominance()) {
      var loopNodes = new HashSet<Block>();
      foreach (var b in blockGraph.BackEdgeNodes(h))
        loopNodes.UnionWith(blockGraph.NaturalLoops(h, b));
      this.loopNodes[h] = loopNodes;
      foreach (var n in loopNodes)
        if (n != h)
          innermostHeader[n] = h;
    }
    guard = null;
  }

  private UnstructuredRegion(UnstructuredRegion r, Block h) {
    blockGraph = r.blockGraph;
    header = h;
    loopNodes = r.loopNodes;
    innermostHeader = r.innermostHeader;
    guard = null;
  }

  public object Identifier() {
    return header;
  }

  private HashSet<Block> SubBlocks() {
    if (header != null) {
      return loopNodes[header];
    } else {
      return blockGraph.Nodes;
    }
  }

  public IEnumerable<Cmd> Cmds() {
    foreach (var b in SubBlocks())
      foreach (Cmd c in b.Cmds)
        yield return c;
  }

  public IEnumerable<object> CmdsChildRegions() {
    if (header != null)
      foreach (Cmd c in header.Cmds)
        yield return c;
    foreach (var b in SubBlocks()) {
      Block bHeader;
      innermostHeader.TryGetValue(b, out bHeader);
      if (header == bHeader) {
        if (blockGraph.Headers.Contains(b))
          yield return new UnstructuredRegion(this, b);
        else
          foreach (Cmd c in b.Cmds)
            yield return c;
      }
    }
  }

  public IEnumerable<IRegion> SubRegions() {
    return SubBlocks().Intersect(loopNodes.Keys).Select(b => new UnstructuredRegion(this, b));
  }

  public Expr Guard() {
    if (header == null)
      return null;
    if (guard == null) {
      var backedges = blockGraph.BackEdgeNodes(header);
      if (backedges.Count() != 1)
        return null;
      var assumes = backedges.Single().Cmds.Cast<Cmd>().OfType<AssumeCmd>();
      if (assumes.Count() != 1)
        return null;
      guard = assumes.Single().Expr;
    }
    return guard;
  }

  public void AddInvariant(PredicateCmd pc) {
    header.Cmds = new CmdSeq((new Cmd[] {pc}.Concat(header.Cmds.Cast<Cmd>())).ToArray());
  }
}

}