summaryrefslogtreecommitdiff
path: root/Source/GPUVerify/NoConflictingAccessOptimiser.cs
blob: f003a3a9ebca89418b7f27621ba5d42b3a2d6fd6 (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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Boogie;
using System.Diagnostics.Contracts;

namespace GPUVerify
{
    class NoConflictingAccessOptimiser
    {
        private Implementation impl;
        private IList<CallCmdPos> ccs;

        public NoConflictingAccessOptimiser(Implementation impl)
        {
            this.impl = impl;
            ccs = new List<CallCmdPos>();
            FindCallCmds();
        }

        private class CallCmdPos
        {
            public Block block;
            public int cmdIndex;
            public CallCmd cc;

            public CallCmdPos(Block block, int cmdIndex, CallCmd cc)
            {
                this.block = block;
                this.cmdIndex = cmdIndex;
                this.cc = cc;
            }
        }

        public int NumLogCalls()
        {
            return ccs.Count;
        }

        private void FindCallCmds()
        {
            foreach (Block b in impl.Blocks)
            {
                for(int i=0; i < b.Cmds.Length; i++)
                {
                    Cmd c = b.Cmds[i];
                    CallCmd cc = c as CallCmd;
                    if (cc != null)
                    {
                        if (cc.Proc.Name.Contains("_LOG"))
                        {
                            ccs.Add(new CallCmdPos(b, i, cc));
                        }
                    }
                }
            }
        }

        public bool HasConflicting()
        {
            Contract.Assert(ccs.Count == 2);

            return
                Reachable(ccs[0].block, ccs[0].cmdIndex, ccs[1].cc, new HashSet<Block>()) ||
                Reachable(ccs[1].block, ccs[1].cmdIndex, ccs[0].cc, new HashSet<Block>());
        }

        public bool Reachable(Block startBlock, int cmdStartIndex, CallCmd target, ISet<Block> visited)
        {
            Block currBlock = startBlock;
            int i = cmdStartIndex;

            if(i == 0)
            {
                visited.Add(currBlock);
            }

            while (i < currBlock.Cmds.Length)
            {
                CallCmd cc = currBlock.Cmds[i] as CallCmd;
                if (cc != null)
                {
                    if (cc.Proc.Name.Equals("BARRIER"))
                    {
                        return false;
                    }

                    if (target == cc)
                    {
                        return true;
                    }
                }
                i++;
            }
            
            
            //end of block
                
            GotoCmd gc = currBlock.TransferCmd as GotoCmd;
            Contract.Assert(gc != null);
            foreach (Block t in gc.labelTargets)
            {
                if(visited.Contains(t))
                    continue;

                if (Reachable(t, 0, target, visited))
                    return true;
            }

            return false;

        }

    }
}