make tests green again

This commit is contained in:
Andreas Rumpf 2019-01-21 19:46:06 +01:00
commit 1b0372c6e9

View file

@ -188,6 +188,35 @@ proc isHarmlessVar*(s: PSym; c: Con): bool =
discard "we do not perform an abstract interpretation yet" discard "we do not perform an abstract interpretation yet"
result = usages <= 1 result = usages <= 1
proc isLastRead(s: PSym; c: var Con; pc, comesFrom: int): int =
var pc = pc
while pc < c.g.len:
case c.g[pc].kind
of def:
if c.g[pc].sym == s:
# the path lead to a redefinition of 's' --> abandon it.
return pc
inc pc
of use:
if c.g[pc].sym == s:
c.otherRead = c.g[pc].n
return -1
inc pc
of goto:
pc = pc + c.g[pc].dest
of fork:
# every branch must lead to the last read of the location:
let variantA = isLastRead(s, c, pc+1, pc)
if variantA < 0: return -1
let variantB = isLastRead(s, c, pc + c.g[pc].dest, pc)
if variantB < 0: return -1
pc = variantA+1
of InstrKind.join:
let dest = pc + c.g[pc].dest
if dest == comesFrom: return pc
inc pc
return pc
proc isLastRead(n: PNode; c: var Con): bool = proc isLastRead(n: PNode; c: var Con): bool =
# first we need to search for the instruction that belongs to 'n': # first we need to search for the instruction that belongs to 'n':
doAssert n.kind == nkSym doAssert n.kind == nkSym
@ -195,61 +224,63 @@ proc isLastRead(n: PNode; c: var Con): bool =
var instr = -1 var instr = -1
for i in 0..<c.g.len: for i in 0..<c.g.len:
if c.g[i].n == n: if c.g[i].n == n:
if instr < 0: instr = i if instr < 0:
else: instr = i
# eh, we found two positions that belong to 'n'? break
# better return 'false' then:
return false
if instr < 0: return false if instr < 0: return false
# we go through all paths beginning from 'instr+1' and need to # we go through all paths beginning from 'instr+1' and need to
# ensure that we don't find another 'use X' instruction. # ensure that we don't find another 'use X' instruction.
if instr+1 >= c.g.len: return true if instr+1 >= c.g.len: return true
let s = n.sym when false:
var pcs: seq[int] = @[instr+1] result = isLastRead(n.sym, c, 0, -1) >= 0
var takenGotos: IntSet else:
var takenForks = initIntSet() let s = n.sym
while pcs.len > 0: var pcs: seq[int] = @[instr+1]
var pc = pcs.pop var takenGotos: IntSet
var takenForks = initIntSet()
while pcs.len > 0:
var pc = pcs.pop
takenGotos = initIntSet() takenGotos = initIntSet()
while pc < c.g.len: while pc < c.g.len:
case c.g[pc].kind case c.g[pc].kind
of def: of def:
if c.g[pc].sym == s: if c.g[pc].sym == s:
# the path lead to a redefinition of 's' --> abandon it. # the path lead to a redefinition of 's' --> abandon it.
when false: when false:
# Too complex thinking ahead: In reality it is enough to find # Too complex thinking ahead: In reality it is enough to find
# the 'def x' here on the current path to make the 'use x' valid. # the 'def x' here on the current path to make the 'use x' valid.
# but for this the definition needs to dominate the usage: # but for this the definition needs to dominate the usage:
var dominates = true var dominates = true
for j in pc+1 .. instr: for j in pc+1 .. instr:
# not within the same basic block? # not within the same basic block?
if c.g[j].kind in {goto, fork} and (j + c.g[j].dest) in (pc+1 .. instr): if c.g[j].kind in {goto, fork} and (j + c.g[j].dest) in (pc+1 .. instr):
#if j in c.jumpTargets: #if j in c.jumpTargets:
dominates = false dominates = false
if dominates: break if dominates: break
break break
inc pc
of use:
if c.g[pc].sym == s:
c.otherRead = c.g[pc].n
return false
inc pc
of goto:
# we must leave endless loops eventually:
if not takenGotos.containsOrIncl(pc):
pc = pc + c.g[pc].dest
else:
inc pc inc pc
of fork: of use:
# we follow the next instruction but push the dest onto our "work" stack: if c.g[pc].sym == s:
if not takenForks.containsOrIncl(pc): c.otherRead = c.g[pc].n
pcs.add pc + c.g[pc].dest return false
inc pc inc pc
of InstrKind.join: of goto:
inc pc # we must leave endless loops eventually:
#echo c.graph.config $ n.info, " last read here!" if not takenGotos.containsOrIncl(pc):
return true pc = pc + c.g[pc].dest
else:
inc pc
of fork:
# we follow the next instruction but push the dest onto our "work" stack:
if not takenForks.containsOrIncl(pc):
pcs.add pc + c.g[pc].dest
inc pc
of InstrKind.join:
inc pc
#echo c.graph.config $ n.info, " last read here!"
return true
template interestingSym(s: PSym): bool = template interestingSym(s: PSym): bool =
s.owner == c.owner and s.kind in InterestingSyms and hasDestructor(s.typ) s.owner == c.owner and s.kind in InterestingSyms and hasDestructor(s.typ)