@@ -547,7 +547,11 @@ function linear_pass!(ir::IRCode)
547547 compact = IncrementalCompact (ir)
548548 lifting_cache = IdDict {Pair{AnySSAValue, Any}, AnySSAValue} ()
549549 local memory_opt = false # whether or not to run the memory_opt_pass! pass later
550+ local imarray_memory_opt = false
550551 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+
551555 isa (stmt, Expr) || continue
552556 field_ordering = :unspecified
553557 if isexpr (stmt, :new )
@@ -663,7 +667,7 @@ function linear_pass!(ir::IRCode)
663667 non_dce_finish! (compact)
664668 simple_dce! (compact)
665669 ir = complete (compact)
666- return ir, memory_opt
670+ return ir, memory_opt, imarray_memory_opt
667671end
668672
669673function form_new_preserves (origex:: Expr , intermediates:: Vector{Int} , new_preserves:: Vector{Any} )
@@ -1761,76 +1765,21 @@ function cfg_simplify!(ir::IRCode)
17611765 return finish (compact)
17621766end
17631767
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 )
18291781 end
18301782 end
1831- ok || continue
1832-
1833- ir. stmts[idx][:inst ]. args[1 ] = Core. mutating_arrayfreeze
18341783 end
18351784 return ir
1836- end
1785+ end
0 commit comments