@@ -9,6 +9,7 @@ open Internal.Utilities.Collections
9
9
open Internal.Utilities .Library
10
10
open Internal.Utilities .Library .Extras
11
11
open FSharp.Compiler
12
+ open FSharp.Compiler .Caches
12
13
open FSharp.Compiler .AbstractIL .Diagnostics
13
14
open FSharp.Compiler .AbstractIL .IL
14
15
open FSharp.Compiler .AttributeChecking
@@ -36,6 +37,10 @@ open System.Collections.ObjectModel
36
37
37
38
let OptimizerStackGuardDepth = GetEnvInteger " FSHARP_Optimizer" 50
38
39
40
+ let getFreeLocalsCache =
41
+ let options = CacheOptions.getReferenceIdentity() |> CacheOptions.withNoEviction
42
+ WeakMap.getOrCreate <| fun _ -> new Cache<_, _>( options, " freeLocalsCache" )
43
+
39
44
let i_ldlen = [ I_ ldlen; ( AI_ conv DT_ I4) ]
40
45
41
46
/// size of a function call
@@ -2898,10 +2903,11 @@ and OptimizeLinearExpr cenv env expr contf =
2898
2903
2899
2904
let ( bindR , bindingInfo ), env = OptimizeBinding cenv false env bind
2900
2905
2901
- OptimizeLinearExpr cenv env body ( contf << ( fun ( bodyR , bodyInfo ) ->
2906
+ OptimizeLinearExpr cenv env body ( contf << ( fun ( bodyR , bodyInfo ) ->
2902
2907
// PERF: This call to ValueIsUsedOrHasEffect/freeInExpr amounts to 9% of all optimization time.
2903
2908
// 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
2905
2911
// Eliminate let bindings on the way back up
2906
2912
let exprR , adjust = TryEliminateLet cenv env bindR bodyR m
2907
2913
exprR,
0 commit comments