[SILOpt] experimental async demotion pass

For chains of async functions where suspensions can be statically
proven to never be required, this pass removes all suspensions and
turns the functions into synchronous functions.

For example, this function does not actually require any suspensions,
once the correct executor is acquired upon initial entry:

```
func fib(_ n: Int) async -> Int {
  if n <= 1 { return n }
  return await fib(n-1) + fib(n-2)
}
```

So we can turn the above into this for better performance:

```
func fib() async -> Int {
  return fib_sync()
}

func fib_sync(_ n: Int) -> Int {
  if n <= 1 { return n }
  return fib(n-1) + fib(n-2)
}
```

while rewriting callers of `fib` to use the `sync` entry-point
when we can prove that it will be invoked on a compatible executor.

This pass is currently experimental and under development. Thus, it
is disabled by default and you must use
`-enable-experimental-async-demotion` to try it.
This commit is contained in:
Kavon Farvardin
2023-08-31 14:15:09 -07:00
parent d0a9e78da0
commit b688a1f4a1
21 changed files with 879 additions and 2 deletions

View File

@@ -2212,6 +2212,7 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
Opts.EnableOSSAOptimizations &= !Args.hasArg(OPT_disable_ossa_opts);
Opts.EnableSILOpaqueValues |= Args.hasArg(OPT_enable_sil_opaque_values);
Opts.EnableSpeculativeDevirtualization |= Args.hasArg(OPT_enable_spec_devirt);
Opts.EnableAsyncDemotion |= Args.hasArg(OPT_enable_async_demotion);
Opts.EnableActorDataRaceChecks |= Args.hasFlag(
OPT_enable_actor_data_race_checks,
OPT_disable_actor_data_race_checks, /*default=*/false);