Skip to content

Commit e049fa9

Browse files
committed
More sophisticated cf marking
1 parent 047a273 commit e049fa9

File tree

1 file changed

+82
-12
lines changed

1 file changed

+82
-12
lines changed

src/codeedges.jl

Lines changed: 82 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,9 @@ function lines_required!(isrequired::AbstractVector{Union{Bool,Symbol}}, objs, s
640640
iter = 0
641641
while changed
642642
changed = false
643+
@show iter
644+
print_with_code(stdout, src, isrequired)
645+
println()
643646

644647
# Handle ssa predecessors
645648
changed |= add_ssa_preds!(isrequired, src, edges, norequire)
@@ -727,6 +730,13 @@ end
727730
## Add control-flow
728731

729732
iscf(stmt) = isa(stmt, Core.GotoNode) || isa(stmt, Core.GotoIfNot) || isa(stmt, Core.ReturnNode)
733+
function markcf!(isrequired, src, i)
734+
stmt = src.code[i]
735+
@assert iscf(stmt)
736+
isrequired[i] (true, :exit) && return false
737+
isrequired[i] = isa(stmt, Core.ReturnNode) ? :exit : true
738+
return true
739+
end
730740

731741
"""
732742
ispredecessor(blocks, i, j)
@@ -773,6 +783,13 @@ function add_control_flow!(isrequired, src, cfg, domtree, postdomtree)
773783
r = rng(bb)
774784
if block_internals_needed(isrequired, src, r)
775785
needed[ibb] = true
786+
# Check this blocks precessors and mark any that are just control-flow
787+
for p in bb.preds
788+
r = rng(blocks[p])
789+
if length(r) == 1 && iscf(src.code[r[1]])
790+
_changed |= markcf!(isrequired, src, r[1])
791+
end
792+
end
776793
# Check control flow that's needed to reach this block by walking up the dominators
777794
jbb = ibb
778795
while jbb != 1
@@ -783,9 +800,8 @@ function add_control_flow!(isrequired, src, cfg, domtree, postdomtree)
783800
# Check the idom's successors; if jbb doesn't post-dominate, mark the last statement
784801
for s in dbb.succs
785802
if !postdominates(postdomtree, jbb, s)
786-
if isrequired[idxlast] != true
803+
if markcf!(isrequired, src, idxlast)
787804
_changed = true
788-
isrequired[idxlast] = true
789805
break
790806
end
791807
end
@@ -796,8 +812,7 @@ function add_control_flow!(isrequired, src, cfg, domtree, postdomtree)
796812
# Walk down the post-dominators, starting with self
797813
jbb = ibb
798814
while jbb != 0
799-
empty!(cache)
800-
if ispredecessor(blocks, jbb, ibb, cache) # is post-dominator jbb also a predecessor of ibb? If so we have a loop.
815+
if ispredecessor(blocks, jbb, ibb, empty!(cache)) # is post-dominator jbb also a predecessor of ibb? If so we have a loop.
801816
pdbb = blocks[jbb]
802817
idxlast = rng(pdbb)[end]
803818
stmt = src.code[idxlast]
@@ -821,29 +836,84 @@ function add_control_flow!(isrequired, src, cfg, domtree, postdomtree)
821836
end
822837
changed |= _changed
823838
end
824-
# Now handle "exclusions": in code that would fall through during selective evaluation, find a post-dominator between the two
825-
# that is marked, or mark the end block
826-
marked = findall(needed)
839+
# Now handle "exclusions": in code that would inappropriately fall through
840+
# during selective evaluation, find a post-dominator between the two that is
841+
# marked, or mark one if absent.
842+
marked = push!(findall(needed), length(blocks)+1)
827843
for k in Iterators.drop(eachindex(marked), 1)
828844
ibb, jbb = marked[k-1], marked[k]
845+
if jbb <= length(blocks)
846+
# are ibb and jbb exclusive?
847+
ispredecessor(blocks, ibb, jbb, empty!(cache)) && continue
848+
end
849+
# Is there a required control-flow statement between ibb and jbb?
829850
ok = false
830851
ipbb = ibb
831852
while ipbb < jbb
832853
ipbb = postdomtree.idoms_bb[ipbb]
833854
ipbb == 0 && break
834855
idxlast = rng(blocks[ipbb])[end]
835-
if isrequired[idxlast] != false
856+
if iscf(src.code[idxlast]) && isrequired[idxlast] != false
836857
ok = true
837858
break
838859
end
839860
end
840861
if !ok
841-
idxlast = rng(blocks[ibb])[end]
842-
if isrequired[idxlast] != true
843-
isrequired[idxlast] = true
844-
changed = true
862+
# Mark a control-flow statement between ibb and jbb
863+
ipbb = ibb
864+
while ipbb < jbb
865+
ipbb = postdomtree.idoms_bb[ipbb]
866+
ipbb == 0 && break
867+
# Mark the ipostdom's predecessors...
868+
for k in blocks[ipbb].preds
869+
idxlast = rng(blocks[k])[end]
870+
if iscf(src.code[idxlast])
871+
if markcf!(isrequired, src, idxlast)
872+
changed = true
873+
ok = true
874+
end
875+
end
876+
end
877+
# ...or the ipostdom itself
878+
if !ok
879+
idxlast = rng(blocks[ipbb])[end]
880+
stmt = src.code[idxlast]
881+
if isa(stmt, Core.GotoNode) || isa(stmt, Core.ReturnNode) # unconditional jump
882+
if markcf!(isrequired, src, idxlast)
883+
changed = true
884+
ok = true
885+
end
886+
end
887+
# r = rng(blocks[ipbb])
888+
# if length(r) == 1 && iscf(src.code[r[1]])
889+
# if markcf!(isrequired, src, r[1])
890+
# changed = true
891+
# ok = true
892+
# end
893+
# end
894+
end
895+
# idxlast = rng(blocks[ipbb])[end]
896+
# if iscf(src.code[idxlast]) # ideally we might find an unconditional jump to prevent unnecessary evaluation of the conditional
897+
# if markcf!(isrequired, src, idxlast)
898+
# changed = true
899+
# ok = true
900+
# break
901+
# end
902+
# end
903+
end
904+
end
905+
if !ok
906+
print_with_code(stdout, src, isrequired)
907+
@show ibb jbb ipbb
908+
ipbb = postdomtree.idoms_bb[ibb]
909+
print("ibb postdoms: ")
910+
while ipbb != 0
911+
print(ipbb, " ")
912+
ipbb = postdomtree.idoms_bb[ipbb]
845913
end
914+
println()
846915
end
916+
jbb <= length(blocks) && @assert ok
847917
end
848918
return changed
849919
end

0 commit comments

Comments
 (0)