@@ -640,6 +640,9 @@ function lines_required!(isrequired::AbstractVector{Union{Bool,Symbol}}, objs, s
640
640
iter = 0
641
641
while changed
642
642
changed = false
643
+ @show iter
644
+ print_with_code (stdout , src, isrequired)
645
+ println ()
643
646
644
647
# Handle ssa predecessors
645
648
changed |= add_ssa_preds! (isrequired, src, edges, norequire)
727
730
# # Add control-flow
728
731
729
732
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
730
740
731
741
"""
732
742
ispredecessor(blocks, i, j)
@@ -773,6 +783,13 @@ function add_control_flow!(isrequired, src, cfg, domtree, postdomtree)
773
783
r = rng (bb)
774
784
if block_internals_needed (isrequired, src, r)
775
785
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
776
793
# Check control flow that's needed to reach this block by walking up the dominators
777
794
jbb = ibb
778
795
while jbb != 1
@@ -783,9 +800,8 @@ function add_control_flow!(isrequired, src, cfg, domtree, postdomtree)
783
800
# Check the idom's successors; if jbb doesn't post-dominate, mark the last statement
784
801
for s in dbb. succs
785
802
if ! postdominates (postdomtree, jbb, s)
786
- if isrequired[idxlast] != true
803
+ if markcf! ( isrequired, src, idxlast)
787
804
_changed = true
788
- isrequired[idxlast] = true
789
805
break
790
806
end
791
807
end
@@ -796,8 +812,7 @@ function add_control_flow!(isrequired, src, cfg, domtree, postdomtree)
796
812
# Walk down the post-dominators, starting with self
797
813
jbb = ibb
798
814
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.
801
816
pdbb = blocks[jbb]
802
817
idxlast = rng (pdbb)[end ]
803
818
stmt = src. code[idxlast]
@@ -821,29 +836,84 @@ function add_control_flow!(isrequired, src, cfg, domtree, postdomtree)
821
836
end
822
837
changed |= _changed
823
838
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 )
827
843
for k in Iterators. drop (eachindex (marked), 1 )
828
844
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?
829
850
ok = false
830
851
ipbb = ibb
831
852
while ipbb < jbb
832
853
ipbb = postdomtree. idoms_bb[ipbb]
833
854
ipbb == 0 && break
834
855
idxlast = rng (blocks[ipbb])[end ]
835
- if isrequired[idxlast] != false
856
+ if iscf (src . code[idxlast]) && isrequired[idxlast] != false
836
857
ok = true
837
858
break
838
859
end
839
860
end
840
861
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]
845
913
end
914
+ println ()
846
915
end
916
+ jbb <= length (blocks) && @assert ok
847
917
end
848
918
return changed
849
919
end
0 commit comments