module Language.QBE.Analysis.CDG
( CDG (..),
build,
edges,
ctrlDeps,
)
where
import Data.Bifunctor (second)
import Data.IntMap (IntMap)
import Data.IntMap qualified as M
import Data.IntSet (IntSet)
import Data.IntSet qualified as S
import Data.List (find)
import Data.Maybe (fromMaybe)
import Language.QBE.Analysis.CFG qualified as CFG
import Language.QBE.Analysis.Graph qualified as G
data CDG
= CDG
{
CDG -> CFG
cdgCfg :: CFG.CFG,
CDG -> Node
cdgRoot :: CFG.Label,
CDG -> Graph
cdgGraph :: G.Graph
}
edges :: CDG -> [(CFG.Label, CFG.Label)]
edges :: CDG -> [(Node, Node)]
edges CDG
cdg = ([(Node, Node)] -> (Node, IntSet) -> [(Node, Node)])
-> [(Node, Node)] -> [(Node, IntSet)] -> [(Node, Node)]
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl [(Node, Node)] -> (Node, IntSet) -> [(Node, Node)]
forall {t}. [(t, Node)] -> (t, IntSet) -> [(t, Node)]
go [] ([(Node, IntSet)] -> [(Node, Node)])
-> [(Node, IntSet)] -> [(Node, Node)]
forall a b. (a -> b) -> a -> b
$ Graph -> [(Node, IntSet)]
forall a. IntMap a -> [(Node, a)]
M.toList (CDG -> Graph
cdgGraph CDG
cdg)
where
go :: [(t, Node)] -> (t, IntSet) -> [(t, Node)]
go [(t, Node)]
acc (t
p, IntSet
c) = [(t, Node)]
acc [(t, Node)] -> [(t, Node)] -> [(t, Node)]
forall a. [a] -> [a] -> [a]
++ (Node -> (t, Node)) -> [Node] -> [(t, Node)]
forall a b. (a -> b) -> [a] -> [b]
map (t
p,) (IntSet -> [Node]
S.toList IntSet
c)
ctrlDeps :: CDG -> CFG.Label -> Maybe IntSet
ctrlDeps :: CDG -> Node -> Maybe IntSet
ctrlDeps CDG {cdgGraph :: CDG -> Graph
cdgGraph = Graph
cDeps} = (Node -> Graph -> Maybe IntSet
forall a. Node -> IntMap a -> Maybe a
`M.lookup` Graph
cDeps)
build :: CFG.CFG -> CFG.Label -> CDG
build :: CFG -> Node -> CDG
build CFG
cfg Node
root =
CDG
{ cdgCfg :: CFG
cdgCfg = CFG
cfg,
cdgRoot :: Node
cdgRoot = Node
root,
cdgGraph :: Graph
cdgGraph = CFG -> Node -> Graph
build' CFG
cfg Node
root
}
build' :: CFG.CFG -> CFG.Label -> IntMap IntSet
build' :: CFG -> Node -> Graph
build' CFG
cfg Node
label =
let rooted :: (Node, Graph)
rooted = (Node
label, CFG -> Graph
CFG.asDomGraph CFG
cfg)
pdTree :: Tree Node
pdTree = (Node, Graph) -> Tree Node
G.pdomTree (Node, Graph)
rooted
pdtMap :: Graph
pdtMap = [(Node, IntSet)] -> Graph
forall a. [(Node, a)] -> IntMap a
M.fromList ([(Node, IntSet)] -> Graph) -> [(Node, IntSet)] -> Graph
forall a b. (a -> b) -> a -> b
$ ((Node, [Node]) -> (Node, IntSet))
-> [(Node, [Node])] -> [(Node, IntSet)]
forall a b. (a -> b) -> [a] -> [b]
map (([Node] -> IntSet) -> (Node, [Node]) -> (Node, IntSet)
forall b c a. (b -> c) -> (a, b) -> (a, c)
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second [Node] -> IntSet
S.fromList) ((Node, Graph) -> [(Node, [Node])]
G.pdom (Node, Graph)
rooted)
pdtAnc :: IntMap [Node]
pdtAnc = [(Node, [Node])] -> IntMap [Node]
forall a. [(Node, a)] -> IntMap a
M.fromList (Tree Node -> [(Node, [Node])]
forall a. Tree a -> [(a, [a])]
G.ancestors Tree Node
pdTree)
in ((Node, Node) -> Graph -> Graph)
-> Graph -> [(Node, Node)] -> Graph
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr ((Node -> Node -> Graph -> Graph) -> (Node, Node) -> Graph -> Graph
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry ((Node -> Node -> Graph -> Graph)
-> (Node, Node) -> Graph -> Graph)
-> (Node -> Node -> Graph -> Graph)
-> (Node, Node)
-> Graph
-> Graph
forall a b. (a -> b) -> a -> b
$ Graph -> IntMap [Node] -> Node -> Node -> Graph -> Graph
addCDGEdge Graph
pdtMap IntMap [Node]
pdtAnc) Graph
forall a. IntMap a
M.empty ([(Node, Node)] -> Graph) -> [(Node, Node)] -> Graph
forall a b. (a -> b) -> a -> b
$ CFG -> [(Node, Node)]
CFG.edges CFG
cfg
addCDGEdge ::
IntMap IntSet ->
IntMap [Int] ->
CFG.Label ->
CFG.Label ->
IntMap IntSet ->
IntMap IntSet
addCDGEdge :: Graph -> IntMap [Node] -> Node -> Node -> Graph -> Graph
addCDGEdge Graph
pdtMap IntMap [Node]
pdtAnc Node
a Node
b Graph
acc
| Node -> Node -> Bool
postdominates Node
b Node
a = Graph
acc
| Bool
otherwise =
case Node -> Node -> Maybe Node
commonAncestor Node
b Node
a of
Just Node
ac ->
let cdepsOnA :: IntSet
cdepsOnA = Node -> IntSet -> IntSet
S.insert Node
b ((Node -> Bool) -> IntSet -> IntSet
S.filter (Node -> Node -> Bool
forall a. Eq a => a -> a -> Bool
/= Node
ac) (IntSet -> IntSet) -> IntSet -> IntSet
forall a b. (a -> b) -> a -> b
$ Node -> IntSet
lookupSucc Node
b)
in (Node -> Graph -> Graph) -> Graph -> [Node] -> Graph
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Node -> Graph -> Graph
insertEdge Graph
acc (IntSet -> [Node]
S.toList IntSet
cdepsOnA)
Maybe Node
Nothing ->
let deps :: IntSet
deps = Node -> IntSet -> IntSet
S.insert Node
b (IntSet -> IntSet) -> IntSet -> IntSet
forall a b. (a -> b) -> a -> b
$ Node -> IntSet
lookupSucc Node
b
in (Node -> Graph -> Graph) -> Graph -> [Node] -> Graph
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Node -> Graph -> Graph
insertEdge Graph
acc (IntSet -> [Node]
S.toList IntSet
deps)
where
insertEdge :: CFG.Label -> IntMap IntSet -> IntMap IntSet
insertEdge :: Node -> Graph -> Graph
insertEdge Node
blk = (IntSet -> IntSet -> IntSet) -> Node -> IntSet -> Graph -> Graph
forall a. (a -> a -> a) -> Node -> a -> IntMap a -> IntMap a
M.insertWith IntSet -> IntSet -> IntSet
S.union Node
blk (Node -> IntSet
S.singleton Node
a)
lookupSucc :: CFG.Label -> IntSet
lookupSucc :: Node -> IntSet
lookupSucc Node
l = IntSet -> Maybe IntSet -> IntSet
forall a. a -> Maybe a -> a
fromMaybe IntSet
S.empty (Maybe IntSet -> IntSet) -> Maybe IntSet -> IntSet
forall a b. (a -> b) -> a -> b
$ Node -> Graph -> Maybe IntSet
forall a. Node -> IntMap a -> Maybe a
M.lookup Node
l Graph
pdtMap
postdominates :: CFG.Label -> CFG.Label -> Bool
postdominates :: Node -> Node -> Bool
postdominates Node
x Node
y = Bool -> (IntSet -> Bool) -> Maybe IntSet -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False (Node
x `S.member`) (Maybe IntSet -> Bool) -> Maybe IntSet -> Bool
forall a b. (a -> b) -> a -> b
$ Node -> Graph -> Maybe IntSet
forall a. Node -> IntMap a -> Maybe a
M.lookup Node
y Graph
pdtMap
commonAncestor :: G.Node -> G.Node -> Maybe G.Node
commonAncestor :: Node -> Node -> Maybe Node
commonAncestor Node
n1 Node
n2 = do
[Node]
a1 <- Node -> IntMap [Node] -> Maybe [Node]
forall a. Node -> IntMap a -> Maybe a
M.lookup Node
n1 IntMap [Node]
pdtAnc
[Node]
a2 <- Node -> IntMap [Node] -> Maybe [Node]
forall a. Node -> IntMap a -> Maybe a
M.lookup Node
n2 IntMap [Node]
pdtAnc
(Node -> Bool) -> [Node] -> Maybe Node
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find (Node -> [Node] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Node]
a1) [Node]
a2