@@ -9,6 +9,7 @@ open Internal.Utilities.Collections
99open Internal.Utilities .Library
1010open Internal.Utilities .Library .Extras
1111open FSharp.Compiler
12+ open FSharp.Compiler .Caches
1213open FSharp.Compiler .AbstractIL .Diagnostics
1314open FSharp.Compiler .AbstractIL .IL
1415open FSharp.Compiler .AttributeChecking
@@ -36,6 +37,10 @@ open System.Collections.ObjectModel
3637
3738let OptimizerStackGuardDepth = GetEnvInteger " FSHARP_Optimizer" 50
3839
40+ let getFreeLocalsCache =
41+ let options = CacheOptions.getReferenceIdentity() |> CacheOptions.withNoEviction
42+ WeakMap.getOrCreate <| fun _ -> new Cache<_, _>( options, " freeLocalsCache" )
43+
3944let i_ldlen = [ I_ ldlen; ( AI_ conv DT_ I4) ]
4045
4146/// size of a function call
@@ -2898,10 +2903,11 @@ and OptimizeLinearExpr cenv env expr contf =
28982903
28992904 let ( bindR , bindingInfo ), env = OptimizeBinding cenv false env bind
29002905
2901- OptimizeLinearExpr cenv env body ( contf << ( fun ( bodyR , bodyInfo ) ->
2906+ OptimizeLinearExpr cenv env body ( contf << ( fun ( bodyR , bodyInfo ) ->
29022907 // PERF: This call to ValueIsUsedOrHasEffect/freeInExpr amounts to 9% of all optimization time.
29032908 // Is it quadratic or quasi-quadratic?
2904- if ValueIsUsedOrHasEffect cenv ( fun () -> ( freeInExpr ( CollectLocalsWithStackGuard()) bodyR) .FreeLocals) ( bindR, bindingInfo) then
2909+ let collect expr = ( freeInExpr ( CollectLocalsWithStackGuard()) expr) .FreeLocals
2910+ if ValueIsUsedOrHasEffect cenv ( fun () -> ( getFreeLocalsCache cenv) .GetOrAdd( bodyR, collect)) ( bindR, bindingInfo) then
29052911 // Eliminate let bindings on the way back up
29062912 let exprR , adjust = TryEliminateLet cenv env bindR bodyR m
29072913 exprR,
0 commit comments