more thavlak.nim improvements
This commit is contained in:
parent
48eed1f522
commit
f07774d064
1 changed files with 51 additions and 78 deletions
|
|
@ -12,7 +12,7 @@ Found 1 loops (including artificial root node) (5)'''
|
||||||
|
|
||||||
# bug #3184
|
# bug #3184
|
||||||
|
|
||||||
import tables, sequtils, sets, strutils
|
import tables, sets
|
||||||
|
|
||||||
when not declared(withScratchRegion):
|
when not declared(withScratchRegion):
|
||||||
template withScratchRegion(body: untyped) = body
|
template withScratchRegion(body: untyped) = body
|
||||||
|
|
@ -24,10 +24,11 @@ type
|
||||||
name: int
|
name: int
|
||||||
|
|
||||||
proc newBasicBlock(name: int): ref BasicBlock =
|
proc newBasicBlock(name: int): ref BasicBlock =
|
||||||
new(result)
|
result = (ref BasicBlock)(
|
||||||
result.inEdges = newSeq[ref BasicBlock]()
|
inEdges: newSeq[ref BasicBlock](),
|
||||||
result.outEdges = newSeq[ref BasicBlock]()
|
outEdges: newSeq[ref BasicBlock](),
|
||||||
result.name = name
|
name: name
|
||||||
|
)
|
||||||
|
|
||||||
proc hash(x: ref BasicBlock): int {.inline.} =
|
proc hash(x: ref BasicBlock): int {.inline.} =
|
||||||
result = x.name
|
result = x.name
|
||||||
|
|
@ -43,8 +44,10 @@ type
|
||||||
startNode: ref BasicBlock
|
startNode: ref BasicBlock
|
||||||
|
|
||||||
proc newCfg(): Cfg =
|
proc newCfg(): Cfg =
|
||||||
result.basicBlockMap = initTable[int, ref BasicBlock]()
|
result = Cfg(
|
||||||
result.edgeList = newSeq[BasicBlockEdge]()
|
basicBlockMap: initTable[int, ref BasicBlock](),
|
||||||
|
edgeList: newSeq[BasicBlockEdge](),
|
||||||
|
startNode: nil)
|
||||||
|
|
||||||
proc createNode(self: var Cfg, name: int): ref BasicBlock =
|
proc createNode(self: var Cfg, name: int): ref BasicBlock =
|
||||||
result = self.basicBlockMap.getOrDefault(name)
|
result = self.basicBlockMap.getOrDefault(name)
|
||||||
|
|
@ -55,10 +58,7 @@ proc createNode(self: var Cfg, name: int): ref BasicBlock =
|
||||||
if self.startNode == nil:
|
if self.startNode == nil:
|
||||||
self.startNode = result
|
self.startNode = result
|
||||||
|
|
||||||
proc getNumNodes(self: Cfg): int =
|
proc newBasicBlockEdge(cfg: var Cfg, fromName, toName: int) =
|
||||||
self.basicBlockMap.len
|
|
||||||
|
|
||||||
proc newBasicBlockEdge(cfg: var Cfg, fromName: int, toName: int) =
|
|
||||||
var result = BasicBlockEdge(
|
var result = BasicBlockEdge(
|
||||||
fr: cfg.createNode(fromName),
|
fr: cfg.createNode(fromName),
|
||||||
to: cfg.createNode(toName)
|
to: cfg.createNode(toName)
|
||||||
|
|
@ -73,23 +73,8 @@ type
|
||||||
children: seq[ref SimpleLoop] # TODO: set here
|
children: seq[ref SimpleLoop] # TODO: set here
|
||||||
parent: ref SimpleLoop
|
parent: ref SimpleLoop
|
||||||
header: ref BasicBlock
|
header: ref BasicBlock
|
||||||
isRoot: bool
|
isRoot, isReducible: bool
|
||||||
isReducible: bool
|
counter, nestingLevel, depthLevel: int
|
||||||
counter: int
|
|
||||||
nestingLevel: int
|
|
||||||
depthLevel: int
|
|
||||||
|
|
||||||
proc newSimpleLoop(): ref SimpleLoop =
|
|
||||||
new(result)
|
|
||||||
result.basicBlocks = newSeq[ref BasicBlock]()
|
|
||||||
result.children = newSeq[ref SimpleLoop]()
|
|
||||||
result.parent = nil
|
|
||||||
result.header = nil
|
|
||||||
result.isRoot = false
|
|
||||||
result.isReducible = true
|
|
||||||
result.counter = 0
|
|
||||||
result.nestingLevel = 0
|
|
||||||
result.depthLevel = 0
|
|
||||||
|
|
||||||
proc setParent(self: ref SimpleLoop, parent: ref SimpleLoop) =
|
proc setParent(self: ref SimpleLoop, parent: ref SimpleLoop) =
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
|
|
@ -111,7 +96,10 @@ type
|
||||||
root: ref SimpleLoop
|
root: ref SimpleLoop
|
||||||
|
|
||||||
proc createNewLoop(self: var Lsg): ref SimpleLoop =
|
proc createNewLoop(self: var Lsg): ref SimpleLoop =
|
||||||
result = newSimpleLoop()
|
result = (ref SimpleLoop)(
|
||||||
|
basicBlocks: newSeq[ref BasicBlock](),
|
||||||
|
children: newSeq[ref SimpleLoop](),
|
||||||
|
isReducible: true)
|
||||||
loopCounter += 1
|
loopCounter += 1
|
||||||
result.counter = loopCounter
|
result.counter = loopCounter
|
||||||
|
|
||||||
|
|
@ -119,14 +107,11 @@ proc addLoop(self: var Lsg, l: ref SimpleLoop) =
|
||||||
self.loops.add l
|
self.loops.add l
|
||||||
|
|
||||||
proc newLsg(): Lsg =
|
proc newLsg(): Lsg =
|
||||||
result.loops = newSeq[ref SimpleLoop]()
|
result = Lsg(loops: newSeq[ref SimpleLoop](),
|
||||||
result.root = result.createNewLoop()
|
root: result.createNewLoop())
|
||||||
result.root.setNestingLevel(0)
|
result.root.setNestingLevel(0)
|
||||||
result.addLoop(result.root)
|
result.addLoop(result.root)
|
||||||
|
|
||||||
proc getNumLoops(self: Lsg): int =
|
|
||||||
self.loops.len
|
|
||||||
|
|
||||||
type
|
type
|
||||||
UnionFindNode = object
|
UnionFindNode = object
|
||||||
parent {.cursor.}: ref UnionFindNode
|
parent {.cursor.}: ref UnionFindNode
|
||||||
|
|
@ -134,14 +119,6 @@ type
|
||||||
l: ref SimpleLoop
|
l: ref SimpleLoop
|
||||||
dfsNumber: int
|
dfsNumber: int
|
||||||
|
|
||||||
proc newUnionFindNode(): ref UnionFindNode =
|
|
||||||
new(result)
|
|
||||||
when false:
|
|
||||||
result.parent = nil
|
|
||||||
result.bb = nil
|
|
||||||
result.l = nil
|
|
||||||
result.dfsNumber = 0
|
|
||||||
|
|
||||||
proc initNode(self: ref UnionFindNode, bb: ref BasicBlock, dfsNumber: int) =
|
proc initNode(self: ref UnionFindNode, bb: ref BasicBlock, dfsNumber: int) =
|
||||||
self.parent = self
|
self.parent = self
|
||||||
self.bb = bb
|
self.bb = bb
|
||||||
|
|
@ -149,27 +126,26 @@ proc initNode(self: ref UnionFindNode, bb: ref BasicBlock, dfsNumber: int) =
|
||||||
|
|
||||||
proc findSet(self: ref UnionFindNode): ref UnionFindNode =
|
proc findSet(self: ref UnionFindNode): ref UnionFindNode =
|
||||||
var nodeList = newSeq[ref UnionFindNode]()
|
var nodeList = newSeq[ref UnionFindNode]()
|
||||||
result = self
|
var it {.cursor.} = self
|
||||||
|
|
||||||
while result != result.parent:
|
while it != it.parent:
|
||||||
var parent = result.parent
|
var parent {.cursor.} = it.parent
|
||||||
if parent != parent.parent: nodeList.add result
|
if parent != parent.parent: nodeList.add it
|
||||||
result = parent
|
it = parent
|
||||||
|
|
||||||
for iter in nodeList: iter.parent = result.parent
|
for iter in nodeList: iter.parent = it.parent
|
||||||
|
result = it
|
||||||
|
|
||||||
proc union(self: ref UnionFindNode, unionFindNode: ref UnionFindNode) =
|
proc union(self: ref UnionFindNode, unionFindNode: ref UnionFindNode) =
|
||||||
self.parent = unionFindNode
|
self.parent = unionFindNode
|
||||||
|
|
||||||
|
|
||||||
const
|
const
|
||||||
BB_TOP = 0 # uninitialized
|
|
||||||
BB_NONHEADER = 1 # a regular BB
|
BB_NONHEADER = 1 # a regular BB
|
||||||
BB_REDUCIBLE = 2 # reducible loop
|
BB_REDUCIBLE = 2 # reducible loop
|
||||||
BB_SELF = 3 # single BB loop
|
BB_SELF = 3 # single BB loop
|
||||||
BB_IRREDUCIBLE = 4 # irreducible loop
|
BB_IRREDUCIBLE = 4 # irreducible loop
|
||||||
BB_DEAD = 5 # a dead BB
|
BB_DEAD = 5 # a dead BB
|
||||||
BB_LAST = 6 # Sentinel
|
|
||||||
|
|
||||||
# # Marker for uninitialized nodes.
|
# # Marker for uninitialized nodes.
|
||||||
UNVISITED = -1
|
UNVISITED = -1
|
||||||
|
|
@ -182,33 +158,31 @@ type
|
||||||
cfg: Cfg
|
cfg: Cfg
|
||||||
lsg: Lsg
|
lsg: Lsg
|
||||||
|
|
||||||
proc newHavlakLoopFinder(cfg: Cfg, lsg: Lsg): HavlakLoopFinder =
|
proc newHavlakLoopFinder(cfg: Cfg, lsg: sink Lsg): HavlakLoopFinder =
|
||||||
result.cfg = cfg
|
result = HavlakLoopFinder(cfg: cfg, lsg: lsg)
|
||||||
result.lsg = lsg
|
|
||||||
|
|
||||||
proc isAncestor(w: int, v: int, last: seq[int]): bool =
|
proc isAncestor(w: int, v: int, last: seq[int]): bool =
|
||||||
w <= v and v <= last[w]
|
w <= v and v <= last[w]
|
||||||
|
|
||||||
proc dfs(currentNode: ref BasicBlock, nodes: var seq[ref UnionFindNode],
|
proc dfs(currentNode: ref BasicBlock, nodes: var seq[ref UnionFindNode],
|
||||||
number: var Table[ref BasicBlock, int],
|
number: var Table[ref BasicBlock, int],
|
||||||
last: var seq[int], current: int): int =
|
last: var seq[int], current: int) =
|
||||||
var stack = @[(currentNode, current)]
|
var stack = @[(currentNode, current)]
|
||||||
while stack.len > 0:
|
while stack.len > 0:
|
||||||
let (currentNode, current) = stack.pop()
|
let (currentNode, current) = stack.pop()
|
||||||
nodes[current].initNode(currentNode, current)
|
nodes[current].initNode(currentNode, current)
|
||||||
number[currentNode] = current
|
number[currentNode] = current
|
||||||
|
|
||||||
result = current
|
|
||||||
for target in currentNode.outEdges:
|
for target in currentNode.outEdges:
|
||||||
if number[target] == UNVISITED:
|
if number[target] == UNVISITED:
|
||||||
stack.add((target, result+1))
|
stack.add((target, current+1))
|
||||||
#result = dfs(target, nodes, number, last, result + 1)
|
#result = dfs(target, nodes, number, last, result + 1)
|
||||||
last[number[currentNode]] = result
|
last[number[currentNode]] = current
|
||||||
|
|
||||||
proc findLoops(self: var HavlakLoopFinder): int =
|
proc findLoops(self: var HavlakLoopFinder): int =
|
||||||
var startNode = self.cfg.startNode
|
var startNode = self.cfg.startNode
|
||||||
if startNode == nil: return 0
|
if startNode == nil: return 0
|
||||||
var size = self.cfg.getNumNodes
|
var size = self.cfg.basicBlockMap.len
|
||||||
|
|
||||||
var nonBackPreds = newSeq[HashSet[int]]()
|
var nonBackPreds = newSeq[HashSet[int]]()
|
||||||
var backPreds = newSeq[seq[int]]()
|
var backPreds = newSeq[seq[int]]()
|
||||||
|
|
@ -219,9 +193,9 @@ proc findLoops(self: var HavlakLoopFinder): int =
|
||||||
var nodes = newSeq[ref UnionFindNode]()
|
var nodes = newSeq[ref UnionFindNode]()
|
||||||
|
|
||||||
for i in 1..size:
|
for i in 1..size:
|
||||||
nonBackPreds.add initSet[int](1)
|
nonBackPreds.add initHashSet[int](1)
|
||||||
backPreds.add newSeq[int]()
|
backPreds.add newSeq[int]()
|
||||||
nodes.add newUnionFindNode()
|
nodes.add((ref UnionFindNode)())
|
||||||
|
|
||||||
# Step a:
|
# Step a:
|
||||||
# - initialize all nodes as unvisited.
|
# - initialize all nodes as unvisited.
|
||||||
|
|
@ -229,7 +203,7 @@ proc findLoops(self: var HavlakLoopFinder): int =
|
||||||
# - unreached BB's are marked as dead.
|
# - unreached BB's are marked as dead.
|
||||||
#
|
#
|
||||||
for v in self.cfg.basicBlockMap.values: number[v] = UNVISITED
|
for v in self.cfg.basicBlockMap.values: number[v] = UNVISITED
|
||||||
var res = dfs(startNode, nodes, number, last, 0)
|
dfs(startNode, nodes, number, last, 0)
|
||||||
|
|
||||||
# Step b:
|
# Step b:
|
||||||
# - iterate over all nodes.
|
# - iterate over all nodes.
|
||||||
|
|
@ -362,7 +336,7 @@ proc findLoops(self: var HavlakLoopFinder): int =
|
||||||
|
|
||||||
self.lsg.addLoop(l)
|
self.lsg.addLoop(l)
|
||||||
|
|
||||||
result = self.lsg.getNumLoops
|
result = self.lsg.loops.len
|
||||||
|
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
@ -375,12 +349,11 @@ proc newLoopTesterApp(): LoopTesterApp =
|
||||||
result.lsg = newLsg()
|
result.lsg = newLsg()
|
||||||
|
|
||||||
proc buildDiamond(self: var LoopTesterApp, start: int): int =
|
proc buildDiamond(self: var LoopTesterApp, start: int): int =
|
||||||
var bb0 = start
|
newBasicBlockEdge(self.cfg, start, start + 1)
|
||||||
newBasicBlockEdge(self.cfg, bb0, bb0 + 1)
|
newBasicBlockEdge(self.cfg, start, start + 2)
|
||||||
newBasicBlockEdge(self.cfg, bb0, bb0 + 2)
|
newBasicBlockEdge(self.cfg, start + 1, start + 3)
|
||||||
newBasicBlockEdge(self.cfg, bb0 + 1, bb0 + 3)
|
newBasicBlockEdge(self.cfg, start + 2, start + 3)
|
||||||
newBasicBlockEdge(self.cfg, bb0 + 2, bb0 + 3)
|
result = start + 3
|
||||||
result = bb0 + 3
|
|
||||||
|
|
||||||
proc buildConnect(self: var LoopTesterApp, start1: int, end1: int) =
|
proc buildConnect(self: var LoopTesterApp, start1: int, end1: int) =
|
||||||
newBasicBlockEdge(self.cfg, start1, end1)
|
newBasicBlockEdge(self.cfg, start1, end1)
|
||||||
|
|
@ -391,11 +364,11 @@ proc buildStraight(self: var LoopTesterApp, start: int, n: int): int =
|
||||||
result = start + n
|
result = start + n
|
||||||
|
|
||||||
proc buildBaseLoop(self: var LoopTesterApp, from1: int): int =
|
proc buildBaseLoop(self: var LoopTesterApp, from1: int): int =
|
||||||
var header = self.buildStraight(from1, 1)
|
let header = self.buildStraight(from1, 1)
|
||||||
var diamond1 = self.buildDiamond(header)
|
let diamond1 = self.buildDiamond(header)
|
||||||
var d11 = self.buildStraight(diamond1, 1)
|
let d11 = self.buildStraight(diamond1, 1)
|
||||||
var diamond2 = self.buildDiamond(d11)
|
let diamond2 = self.buildDiamond(d11)
|
||||||
var footer = self.buildStraight(diamond2, 1)
|
let footer = self.buildStraight(diamond2, 1)
|
||||||
|
|
||||||
self.buildConnect(diamond2, d11)
|
self.buildConnect(diamond2, d11)
|
||||||
self.buildConnect(diamond1, header)
|
self.buildConnect(diamond1, header)
|
||||||
|
|
@ -406,9 +379,9 @@ proc run(self: var LoopTesterApp) =
|
||||||
echo "Welcome to LoopTesterApp, Nim edition"
|
echo "Welcome to LoopTesterApp, Nim edition"
|
||||||
echo "Constructing Simple CFG..."
|
echo "Constructing Simple CFG..."
|
||||||
|
|
||||||
var x1 = self.cfg.createNode(0)
|
discard self.cfg.createNode(0)
|
||||||
var x2 = self.buildBaseLoop(0)
|
discard self.buildBaseLoop(0)
|
||||||
var x3 = self.cfg.createNode(1)
|
discard self.cfg.createNode(1)
|
||||||
self.buildConnect(0, 2)
|
self.buildConnect(0, 2)
|
||||||
|
|
||||||
echo "15000 dummy loops"
|
echo "15000 dummy loops"
|
||||||
|
|
@ -416,13 +389,13 @@ proc run(self: var LoopTesterApp) =
|
||||||
for i in 1..15000:
|
for i in 1..15000:
|
||||||
withScratchRegion:
|
withScratchRegion:
|
||||||
var h = newHavlakLoopFinder(self.cfg, newLsg())
|
var h = newHavlakLoopFinder(self.cfg, newLsg())
|
||||||
var res = h.findLoops
|
discard h.findLoops
|
||||||
|
|
||||||
echo "Constructing CFG..."
|
echo "Constructing CFG..."
|
||||||
var n = 2
|
var n = 2
|
||||||
|
|
||||||
for parlooptrees in 1..10:
|
for parlooptrees in 1..10:
|
||||||
var x6 = self.cfg.createNode(n + 1)
|
discard self.cfg.createNode(n + 1)
|
||||||
self.buildConnect(2, n + 1)
|
self.buildConnect(2, n + 1)
|
||||||
n += 1
|
n += 1
|
||||||
for i in 1..100:
|
for i in 1..100:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue