Skip to content

Commit 9e18254

Browse files
authored
Iterate control-flow graph to convergence (#73)
We only analyze a block if it's needed, but that means that we need to repeat the analysis until we stop adding new blocks. Future work might optimize this if it proves to be a performance bottleneck, but until then this solution is easy.
1 parent 05f25a1 commit 9e18254

File tree

2 files changed

+48
-24
lines changed

2 files changed

+48
-24
lines changed

src/codeedges.jl

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -720,32 +720,37 @@ function add_control_flow!(isrequired, cfg, norequire)
720720
changed = false
721721
blocks = cfg.blocks
722722
nblocks = length(blocks)
723-
for (ibb, bb) in enumerate(blocks)
724-
r = rng(bb)
725-
if any(view(isrequired, r))
726-
if ibb != nblocks
727-
idxlast = r[end]
728-
idxlast norequire && continue
729-
changed |= !isrequired[idxlast]
730-
isrequired[idxlast] = true
731-
end
732-
for ibbp in bb.preds
733-
ibbp > 0 || continue # see Core.Compiler.compute_basic_blocks, near comment re :enter
734-
rpred = rng(blocks[ibbp])
735-
idxlast = rpred[end]
736-
idxlast norequire && continue
737-
changed |= !isrequired[idxlast]
738-
isrequired[idxlast] = true
739-
end
740-
for ibbs in bb.succs
741-
ibbs == nblocks && continue
742-
rpred = rng(blocks[ibbs])
743-
idxlast = rpred[end]
744-
idxlast norequire && continue
745-
changed |= !isrequired[idxlast]
746-
isrequired[idxlast] = true
723+
_changed = true
724+
while _changed
725+
_changed = false
726+
for (ibb, bb) in enumerate(blocks)
727+
r = rng(bb)
728+
if any(view(isrequired, r))
729+
if ibb != nblocks
730+
idxlast = r[end]
731+
idxlast norequire && continue
732+
_changed |= !isrequired[idxlast]
733+
isrequired[idxlast] = true
734+
end
735+
for ibbp in bb.preds
736+
ibbp > 0 || continue # see Core.Compiler.compute_basic_blocks, near comment re :enter
737+
rpred = rng(blocks[ibbp])
738+
idxlast = rpred[end]
739+
idxlast norequire && continue
740+
_changed |= !isrequired[idxlast]
741+
isrequired[idxlast] = true
742+
end
743+
for ibbs in bb.succs
744+
ibbs == nblocks && continue
745+
rpred = rng(blocks[ibbs])
746+
idxlast = rpred[end]
747+
idxlast norequire && continue
748+
_changed |= !isrequired[idxlast]
749+
isrequired[idxlast] = true
750+
end
747751
end
748752
end
753+
changed |= _changed
749754
end
750755
return changed
751756
end

test/codeedges.jl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,25 @@ end
128128
@test ModSelective.a3 === ModEval.a3 == 2
129129
@test allmissing(ModSelective, (:z3, :x3, :y3))
130130

131+
ex = quote
132+
if Sys.iswindows()
133+
const ONLY_ON_WINDOWS = true
134+
end
135+
c_os = if Sys.iswindows()
136+
ONLY_ON_WINDOWS
137+
else
138+
false
139+
end
140+
end
141+
frame = Frame(ModSelective, ex)
142+
src = frame.framecode.src
143+
edges = CodeEdges(src)
144+
isrequired = lines_required(:c_os, src, edges)
145+
@test sum(isrequired) >= length(isrequired) - 2
146+
selective_eval_fromstart!(frame, isrequired)
147+
Core.eval(ModEval, ex)
148+
@test ModSelective.c_os === ModEval.c_os == Sys.iswindows()
149+
131150
# Capturing dependencies of an `@eval` statement
132151
interpT = Expr(:$, :T) # $T that won't get parsed during file-loading
133152
ex = quote

0 commit comments

Comments
 (0)