diff --git a/docs/release-notes/.FSharp.Compiler.Service/8.0.400.md b/docs/release-notes/.FSharp.Compiler.Service/8.0.400.md index 56eed1f56bc..16ead61175e 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/8.0.400.md +++ b/docs/release-notes/.FSharp.Compiler.Service/8.0.400.md @@ -8,4 +8,4 @@ * Files passed with -embed:relative/path/to/file are not embedded. ([Issue #16768](https://github.com/dotnet/fsharp/pull/17068)) * Fix bug in optimization of for-loops over integral ranges with steps and units of measure. ([Issue #17025](https://github.com/dotnet/fsharp/issues/17025), [PR #17040](https://github.com/dotnet/fsharp/pull/17040), [PR #17048](https://github.com/dotnet/fsharp/pull/17048)) * Fix calling an overridden virtual static method via the interface ([PR #17013](https://github.com/dotnet/fsharp/pull/17013)) - +* Fix state machines compilation, when big decision trees are involved, by removing code split when resumable code is detected ([PR #17076](https://github.com/dotnet/fsharp/pull/17076)) diff --git a/src/Compiler/Optimize/Optimizer.fs b/src/Compiler/Optimize/Optimizer.fs index fafb8184600..6a26f85ec6f 100644 --- a/src/Compiler/Optimize/Optimizer.fs +++ b/src/Compiler/Optimize/Optimizer.fs @@ -2314,7 +2314,7 @@ let IsILMethodRefSystemStringConcatArray (mref: ILMethodRef) = ilTy.IsNominal && ilTy.TypeRef.Name = "System.String" -> true | _ -> false)) - + let rec IsDebugPipeRightExpr cenv expr = let g = cenv.g match expr with @@ -2329,6 +2329,13 @@ let rec IsDebugPipeRightExpr cenv expr = else false | _ -> false +let inline IsStateMachineExpr g overallExpr = + //printfn "%s" (DebugPrint.showExpr overallExpr) + match overallExpr with + | Expr.App(funcExpr = Expr.Val(valRef = valRef)) -> + isReturnsResumableCodeTy g valRef.TauType + | _ -> false + /// Optimize/analyze an expression let rec OptimizeExpr cenv (env: IncrementalOptimizationEnv) expr = cenv.stackGuard.Guard <| fun () -> @@ -2343,6 +2350,10 @@ let rec OptimizeExpr cenv (env: IncrementalOptimizationEnv) expr = if IsDebugPipeRightExpr cenv expr then OptimizeDebugPipeRights cenv env expr else + let isStateMachineE = IsStateMachineExpr g expr + + let env = { env with disableMethodSplitting = env.disableMethodSplitting || isStateMachineE } + match expr with // treat the common linear cases to avoid stack overflows, using an explicit continuation | LinearOpExpr _ diff --git a/tests/FSharp.Compiler.ComponentTests/Language/StateMachineTests.fs b/tests/FSharp.Compiler.ComponentTests/Language/StateMachineTests.fs index dd031134f63..c4aed123505 100644 --- a/tests/FSharp.Compiler.ComponentTests/Language/StateMachineTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/Language/StateMachineTests.fs @@ -103,6 +103,61 @@ let compute () = for i in 1 .. 100 do compute().Wait () """ + |> withOptimize + |> compileExeAndRun + |> shouldSucceed + + [] // https://github.com/dotnet/fsharp/issues/16068 + let ``Decision tree with 32+ binds with nested expression is not getting splitted and state machine is successfully statically compiles``() = + FSharp """ +module Testing + +let test () = + task { + if true then + let c = failwith "" + let c = failwith "" + let c = failwith "" + let c = failwith "" + let c = failwith "" + let c = failwith "" + let c = failwith "" + let c = failwith "" + let c = failwith "" + let c = failwith "" + let c = failwith "" + let c = failwith "" + let c = failwith "" + let c = failwith "" + let c = failwith "" + let c = failwith "" + let c = failwith "" + let c = failwith "" + let c = failwith "" + let c = failwith "" + let c = failwith "" + let c = failwith "" + let c = failwith "" + let c = failwith "" + let c = failwith "" + let c = failwith "" + let c = failwith "" + let c = failwith "" + let c = failwith "" + let c = failwith "" + let c = failwith "" + let c = failwith "" + let c = failwith "" + () + } + +[] +let main _ = + test () |> ignore + printfn "Hello, World!" + 0 +""" + |> ignoreWarnings |> withOptimize |> compileExeAndRun |> shouldSucceed \ No newline at end of file