@@ -547,7 +547,11 @@ function linear_pass!(ir::IRCode)
547
547
compact = IncrementalCompact (ir)
548
548
lifting_cache = IdDict {Pair{AnySSAValue, Any}, AnySSAValue} ()
549
549
local memory_opt = false # whether or not to run the memory_opt_pass! pass later
550
+ local imarray_memory_opt = false
550
551
for ((_, idx), stmt) in compact
552
+ # presence of arrayfreeze means possible copy elision opportunity, so run imarray_memoryopt_pass!
553
+ isa (stmt, GlobalRef) && stmt. name === :arrayfreeze && (imarray_memory_opt = true )
554
+
551
555
isa (stmt, Expr) || continue
552
556
field_ordering = :unspecified
553
557
if isexpr (stmt, :new )
@@ -663,7 +667,7 @@ function linear_pass!(ir::IRCode)
663
667
non_dce_finish! (compact)
664
668
simple_dce! (compact)
665
669
ir = complete (compact)
666
- return ir, memory_opt
670
+ return ir, memory_opt, imarray_memory_opt
667
671
end
668
672
669
673
function form_new_preserves (origex:: Expr , intermediates:: Vector{Int} , new_preserves:: Vector{Any} )
@@ -1761,76 +1765,21 @@ function cfg_simplify!(ir::IRCode)
1761
1765
return finish (compact)
1762
1766
end
1763
1767
1764
- function is_allocation (stmt)
1765
- isexpr (stmt, :foreigncall ) || return false
1766
- s = stmt. args[1 ]
1767
- isa (s, QuoteNode) && (s = s. value)
1768
- return s === :jl_alloc_array_1d
1769
- end
1770
-
1771
- function memory_opt! (ir:: IRCode )
1772
- compact = IncrementalCompact (ir, false )
1773
- uses = IdDict {Int, Vector{Int}} ()
1774
- relevant = IdSet {Int} ()
1775
- revisit = Int[]
1776
- function mark_val (val)
1777
- isa (val, SSAValue) || return
1778
- val. id in relevant && pop! (relevant, val. id)
1779
- end
1780
- for ((_, idx), stmt) in compact
1781
- if isa (stmt, ReturnNode)
1782
- isdefined (stmt, :val ) || continue
1783
- val = stmt. val
1784
- if isa (val, SSAValue) && val. id in relevant
1785
- (haskey (uses, val. id)) || (uses[val. id] = Int[])
1786
- push! (uses[val. id], idx)
1787
- end
1788
- continue
1789
- end
1790
- (isexpr (stmt, :call ) || isexpr (stmt, :foreigncall )) || continue
1791
- if is_allocation (stmt)
1792
- push! (relevant, idx)
1793
- # TODO : Mark everything else here
1794
- continue
1795
- end
1796
- # TODO : Replace this by interprocedural escape analysis
1797
- if is_known_call (stmt, arrayset, compact)
1798
- # The value being set escapes, everything else doesn't
1799
- mark_val (stmt. args[4 ])
1800
- arr = stmt. args[3 ]
1801
- if isa (arr, SSAValue) && arr. id in relevant
1802
- (haskey (uses, arr. id)) || (uses[arr. id] = Int[])
1803
- push! (uses[arr. id], idx)
1804
- end
1805
- elseif is_known_call (stmt, Core. arrayfreeze, compact) && isa (stmt. args[2 ], SSAValue)
1806
- push! (revisit, idx)
1807
- else
1808
- # For now we assume everything escapes
1809
- # TODO : We could handle PhiNodes specially and improve this
1810
- for ur in userefs (stmt)
1811
- mark_val (ur[])
1812
- end
1813
- end
1814
- end
1815
- ir = finish (compact)
1816
- isempty (revisit) && return ir
1817
- domtree = construct_domtree (ir. cfg. blocks)
1818
- for idx in revisit
1819
- # Make sure that the value we reference didn't escape
1820
- id = ir. stmts[idx][:inst ]. args[2 ]. id
1821
- (id in relevant) || continue
1822
-
1823
- # We're ok to steal the memory if we don't dominate any uses
1824
- ok = true
1825
- for use in uses[id]
1826
- if ssadominates (ir, domtree, idx, use)
1827
- ok = false
1828
- break
1768
+ function imarray_memoryopt_pass! (ir:: IRCode , estate:: EscapeState )
1769
+ # mark statements that possibly can be optimized
1770
+ for idx in 1 : length (ir. stmts)
1771
+ stmt = ir. stmts[idx][:inst ]
1772
+ isexpr (stmt, :call ) || continue
1773
+ if is_known_call (stmt, Core. arrayfreeze, ir)
1774
+ # array as SSA value might have been initialized within this frame
1775
+ # (thus potentially doesn't escape to anywhere)
1776
+ ary = stmt. args[2 ]
1777
+ if isa (ary, SSAValue)
1778
+ # if array doesn't escape, we can just change the tag and avoid allocation
1779
+ has_no_escape (estate[ary]) || continue
1780
+ stmt. args[1 ] = GlobalRef (Core, :mutating_arrayfreeze )
1829
1781
end
1830
1782
end
1831
- ok || continue
1832
-
1833
- ir. stmts[idx][:inst ]. args[1 ] = Core. mutating_arrayfreeze
1834
1783
end
1835
1784
return ir
1836
- end
1785
+ end
0 commit comments