DFA works for simple examples

This commit is contained in:
Andreas Rumpf 2017-12-21 19:05:23 +01:00
commit c2d91771bc

View file

@ -344,20 +344,20 @@ proc dfa(code: seq[Instr]) =
case code[i].kind case code[i].kind
of use, useWithinCall: u[i].incl(code[i].sym.id) of use, useWithinCall: u[i].incl(code[i].sym.id)
of def: d[i].incl(code[i].sym.id) of def: d[i].incl(code[i].sym.id)
of fork: of fork, goto:
let d = i+code[i].dest let d = i+code[i].dest
backrefs.add(d, i) backrefs.add(d, i)
of goto: discard
var w = @[0] var w = @[0]
var maxIters = 50 var maxIters = 50
var someChange = true var someChange = true
while w.len > 0 and maxIters > 0 and someChange: var takenGotos = initIntSet()
while w.len > 0 and maxIters > 0: # and someChange:
dec maxIters dec maxIters
var pc = w.pop() # w[^1] var pc = w.pop() # w[^1]
var prevPc = -1 var prevPc = -1
# this simulates a single linear control flow execution: # this simulates a single linear control flow execution:
while pc < code.len and someChange: while pc < code.len:
# according to the paper, it is better to shrink the working set here # according to the paper, it is better to shrink the working set here
# in this inner loop: # in this inner loop:
#let widx = w.find(pc) #let widx = w.find(pc)
@ -386,17 +386,21 @@ proc dfa(code: seq[Instr]) =
if def notin d[prevPc]: if def notin d[prevPc]:
excl(intersect, def) excl(intersect, def)
someChange = true someChange = true
when defined(debugDfa):
echo "Excluding ", pc, " prev ", prevPc
assign d[pc], intersect assign d[pc], intersect
# our interpretation ![I!]: # our interpretation ![I!]:
prevPc = pc prevPc = pc
when defined(debugDfa):
echo "looking at ", pc
case code[pc].kind case code[pc].kind
of goto: of goto:
# we must leave endless loops eventually: # we must leave endless loops eventually:
#if someChange: if not takenGotos.containsOrIncl(pc) or someChange:
pc = pc + code[pc].dest pc = pc + code[pc].dest
#else: else:
# inc pc inc pc
of fork: of fork:
# we follow the next instruction but push the dest onto our "work" stack: # we follow the next instruction but push the dest onto our "work" stack:
#if someChange: #if someChange:
@ -405,6 +409,10 @@ proc dfa(code: seq[Instr]) =
of use, useWithinCall, def: of use, useWithinCall, def:
inc pc inc pc
when defined(useDfa) and defined(debugDfa):
for i in 0..<code.len:
echo "PC ", i, ": defs: ", d[i], "; uses ", u[i]
# now check the condition we're interested in: # now check the condition we're interested in:
for i in 0..<code.len: for i in 0..<code.len:
case code[i].kind case code[i].kind
@ -508,7 +516,7 @@ proc dfaUnused(code: seq[Instr]) =
proc dataflowAnalysis*(s: PSym; body: PNode) = proc dataflowAnalysis*(s: PSym; body: PNode) =
var c = Con(code: @[], blocks: @[]) var c = Con(code: @[], blocks: @[])
gen(c, body) gen(c, body)
#echoCfg(c.code) when defined(useDfa) and defined(debugDfa): echoCfg(c.code)
dfa(c.code) dfa(c.code)
proc constructCfg*(s: PSym; body: PNode): ControlFlowGraph = proc constructCfg*(s: PSym; body: PNode): ControlFlowGraph =