@@ -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)
727730# # Add control-flow
728731
729732iscf (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
849919end
0 commit comments