Skip to content

Don't split resumable code #17076

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/release-notes/.FSharp.Compiler.Service/8.0.400.md
Original file line number Diff line number Diff line change
Expand Up @@ -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))
13 changes: 12 additions & 1 deletion src/Compiler/Optimize/Optimizer.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 () ->
Expand All @@ -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 _
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,61 @@ let compute () =
for i in 1 .. 100 do
compute().Wait ()
"""
|> withOptimize
|> compileExeAndRun
|> shouldSucceed

[<Fact>] // 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 ""
()
}

[<EntryPoint>]
let main _ =
test () |> ignore
printfn "Hello, World!"
0
"""
|> ignoreWarnings
|> withOptimize
|> compileExeAndRun
|> shouldSucceed