forked from sampsyo/bril
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSpec.hs
115 lines (103 loc) · 3.82 KB
/
Spec.hs
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
import Bril.CFG (IsCFG, IsNode, NodeOf)
import Bril.CFG qualified as CFG
import Bril.CFG.ByInstr qualified as ByInstr
import Bril.Dominator qualified as Dom
import Bril.Func (Func)
import Bril.Func qualified as Func
import Bril.Parse
import Bril.Program (Program (..))
import Control.Monad (forM_)
import Data.Function ((&))
import Data.Set (Set)
import Data.Set qualified as Set
import Data.String (fromString)
import Data.Traversable (forM)
import System.FilePath.Glob
import System.Process
import Test.Hspec
-- | @dominators cfg@ is an association list mapping every node to the
-- set of nodes that dominate it, using a naive algorithm. Used as a
-- reference implementation for hspec
dominators :: (IsCFG g, Ord (NodeOf g)) => g -> [(NodeOf g, Set (NodeOf g))]
dominators cfg = map (\b -> (b, dominatorsForNode b)) allNodes
where
allNodes = CFG.nodes cfg
dominatorsForNode b = Set.fromList $ filter (`dom` b) allNodes
dom a b =
case CFG.start cfg of
Nothing -> True
Just start ->
if b == start
then a == start
else not $ b `Set.member` CFG.reachableExcluding cfg (Set.singleton a) start
-- | Construct a dominator tree naively as a reference implementation
dominatorTree :: (IsCFG g, IsNode (NodeOf g), Ord (NodeOf g)) => g -> Dom.Tree (NodeOf g)
dominatorTree g =
case CFG.start g of
Nothing -> Dom.Empty
Just start -> Dom.Root $ build (Set.toList $ CFG.reachable start g) start
where
Dom.Relations {idom} = Dom.relations g
build univ node =
Dom.Node
{ node,
children =
univ
& filter (node `idom`)
& map (build univ)
& Set.fromList
}
-- | @verifyDominators cfg@ returns `True` iff the dataflow implementation
-- of dominators agrees with the naive, slow implementation of dominators
verifyDominators :: (Ord (NodeOf g), IsNode (NodeOf g), IsCFG g) => g -> Bool
verifyDominators g =
all (\(node, doms) -> doms == testDominators node) $ dominators g
where
testDominators = Dom.dominators g
verifyDominatorsForFunction :: Func -> Bool
verifyDominatorsForFunction func =
func
& Func.instrs
& ByInstr.fromList
& verifyDominators
verifyDominatorsForProgram :: Program -> Bool
verifyDominatorsForProgram (Program funcs) = all verifyDominatorsForFunction funcs
-- | @verifyDominatorTree cfg@ returns `True` iff the reference and test
-- implementations of dominator trees agree
verifyDominatorTree :: (Ord (NodeOf g), IsNode (NodeOf g), IsCFG g) => g -> Bool
verifyDominatorTree g = dominatorTree g == Dom.tree g
verifyDominatorTreeForFunction :: Func -> Bool
verifyDominatorTreeForFunction func =
func
& Func.instrs
& ByInstr.fromList
& verifyDominatorTree
verifyDominatorTreesForProgram :: Program -> Bool
verifyDominatorTreesForProgram (Program funcs) = all verifyDominatorTreeForFunction funcs
dominatorTests :: [(String, Program)] -> SpecWith ()
dominatorTests progs =
describe "Test Dominators" do
forM_ progs \(path, prog) -> do
it ("dominators for " ++ path) do
verifyDominatorsForProgram prog `shouldBe` True
dominatorTreeTests :: [(String, Program)] -> SpecWith ()
dominatorTreeTests progs =
describe "Test Dominator Trees" do
forM_ progs \(path, prog) -> do
it ("dominator trees for " ++ path) do
verifyDominatorTreesForProgram prog `shouldBe` True
-- | Associate every benchmark file path with its parsed Bril program
parsePrograms :: IO [(String, Program)]
parsePrograms = do
paths <- glob "../benchmarks/*/*.bril"
forM paths \path -> do
bril <- readProcess "cat" [path] []
json <- readProcess "bril2json" [] bril
prog <- decodeProgram $ fromString json
pure (path, prog)
main :: IO ()
main = do
progs <- parsePrograms
hspec $ describe "dominance utilities" do
dominatorTests progs
dominatorTreeTests progs