Skip to content

Commit

Permalink
Computed collections: optimize simple mappings with preludes (#17067)
Browse files Browse the repository at this point in the history
* Gather up any prelude & reapply after lowering

* E.g.,

  ```fsharp
  [let y = f () in for … in … -> …]
  ```

  and

  ```fsharp
  [f (); g (); for … in … -> …]
  ```

  are transformed into something like

  ```fsharp
  let y = f () in [for … in … -> …]
  ```

  and

  ```fsharp
  f (); g (); [for … in … -> …]
  ```

  so that the existing pattern recognition of simple mappings and
  integral ranges may succeed.
  • Loading branch information
brianrourkeboll authored May 7, 2024
1 parent 46aa5a9 commit fc42ec9
Show file tree
Hide file tree
Showing 19 changed files with 5,032 additions and 686 deletions.
1 change: 1 addition & 0 deletions docs/release-notes/.FSharp.Compiler.Service/8.0.400.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
### Fixed

* Optimize simple mappings with preludes in computed collections. ([PR #17067](https://github.com/dotnet/fsharp/pull/17067))
* Improve error reporting for abstract members when used in classes. ([PR #17063](https://github.com/dotnet/fsharp/pull/17063))
* Improve error reporting when property has same name as DU case. ([Issue #16646](https://github.com/dotnet/fsharp/issues/16646), [PR #17088](https://github.com/dotnet/fsharp/pull/17088))
* Make typechecking of indexed setters with tuples on the right more consistent. ([Issue #16987](https://github.com/dotnet/fsharp/issues/16987), [PR #17017](https://github.com/dotnet/fsharp/pull/17017))
Expand Down
265 changes: 211 additions & 54 deletions src/Compiler/Optimize/LowerComputedCollections.fs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,8 @@ let f25 f g h = [|for n in f ()..g ()..h () -> n|]
let f26 start step finish = [|for n in start..step..finish -> n, float n|]
let f27 start step finish = [|for n in start..step..finish -> struct (n, float n)|]
let f28 start step finish = [|for n in start..step..finish -> let x = n + 1 in n * n|]

let f29 f g = [|let y = f () in let z = g () in for x in 1..2..10 -> x + y + z|]
let f30 f g = [|let y = f () in g (); for x in 1..2..10 -> x + y|]
let f31 f g = [|f (); g (); for x in 1..2..10 -> x|]
let f32 f g = [|f (); let y = g () in for x in 1..2..10 -> x + y|]
Original file line number Diff line number Diff line change
Expand Up @@ -2431,6 +2431,242 @@
IL_007a: ret
}

.method public static int32[] f29(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,int32> f,
class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,int32> g) cil managed
{
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )

.maxstack 6
.locals init (int32 V_0,
int32 V_1,
int32[] V_2,
uint64 V_3,
int32 V_4,
int32 V_5)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldnull
IL_0003: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,int32>::Invoke(!0)
IL_0008: stloc.0
IL_0009: ldarg.1
IL_000a: ldnull
IL_000b: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,int32>::Invoke(!0)
IL_0010: stloc.1
IL_0011: ldc.i4.5
IL_0012: conv.i8
IL_0013: conv.ovf.i.un
IL_0014: newarr [runtime]System.Int32
IL_0019: stloc.2
IL_001a: ldc.i4.0
IL_001b: conv.i8
IL_001c: stloc.3
IL_001d: ldc.i4.1
IL_001e: stloc.s V_4
IL_0020: br.s IL_003b

IL_0022: ldloc.2
IL_0023: ldloc.3
IL_0024: conv.i
IL_0025: ldloc.s V_4
IL_0027: stloc.s V_5
IL_0029: ldloc.s V_5
IL_002b: ldloc.0
IL_002c: add
IL_002d: ldloc.1
IL_002e: add
IL_002f: stelem.i4
IL_0030: ldloc.s V_4
IL_0032: ldc.i4.2
IL_0033: add
IL_0034: stloc.s V_4
IL_0036: ldloc.3
IL_0037: ldc.i4.1
IL_0038: conv.i8
IL_0039: add
IL_003a: stloc.3
IL_003b: ldloc.3
IL_003c: ldc.i4.5
IL_003d: conv.i8
IL_003e: blt.un.s IL_0022

IL_0040: ldloc.2
IL_0041: ret
}

.method public static int32[] f30(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,int32> f,
class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit> g) cil managed
{
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )

.maxstack 6
.locals init (int32 V_0,
int32[] V_1,
uint64 V_2,
int32 V_3,
int32 V_4)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldnull
IL_0003: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,int32>::Invoke(!0)
IL_0008: stloc.0
IL_0009: ldarg.1
IL_000a: ldnull
IL_000b: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit>::Invoke(!0)
IL_0010: pop
IL_0011: ldc.i4.5
IL_0012: conv.i8
IL_0013: conv.ovf.i.un
IL_0014: newarr [runtime]System.Int32
IL_0019: stloc.1
IL_001a: ldc.i4.0
IL_001b: conv.i8
IL_001c: stloc.2
IL_001d: ldc.i4.1
IL_001e: stloc.3
IL_001f: br.s IL_0035

IL_0021: ldloc.1
IL_0022: ldloc.2
IL_0023: conv.i
IL_0024: ldloc.3
IL_0025: stloc.s V_4
IL_0027: ldloc.s V_4
IL_0029: ldloc.0
IL_002a: add
IL_002b: stelem.i4
IL_002c: ldloc.3
IL_002d: ldc.i4.2
IL_002e: add
IL_002f: stloc.3
IL_0030: ldloc.2
IL_0031: ldc.i4.1
IL_0032: conv.i8
IL_0033: add
IL_0034: stloc.2
IL_0035: ldloc.2
IL_0036: ldc.i4.5
IL_0037: conv.i8
IL_0038: blt.un.s IL_0021

IL_003a: ldloc.1
IL_003b: ret
}

.method public static int32[] f31(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit> f,
class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit> g) cil managed
{
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )

.maxstack 5
.locals init (int32[] V_0,
uint64 V_1,
int32 V_2,
int32 V_3)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldnull
IL_0003: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit>::Invoke(!0)
IL_0008: pop
IL_0009: ldarg.1
IL_000a: ldnull
IL_000b: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit>::Invoke(!0)
IL_0010: pop
IL_0011: ldc.i4.5
IL_0012: conv.i8
IL_0013: conv.ovf.i.un
IL_0014: newarr [runtime]System.Int32
IL_0019: stloc.0
IL_001a: ldc.i4.0
IL_001b: conv.i8
IL_001c: stloc.1
IL_001d: ldc.i4.1
IL_001e: stloc.2
IL_001f: br.s IL_0031

IL_0021: ldloc.0
IL_0022: ldloc.1
IL_0023: conv.i
IL_0024: ldloc.2
IL_0025: stloc.3
IL_0026: ldloc.3
IL_0027: stelem.i4
IL_0028: ldloc.2
IL_0029: ldc.i4.2
IL_002a: add
IL_002b: stloc.2
IL_002c: ldloc.1
IL_002d: ldc.i4.1
IL_002e: conv.i8
IL_002f: add
IL_0030: stloc.1
IL_0031: ldloc.1
IL_0032: ldc.i4.5
IL_0033: conv.i8
IL_0034: blt.un.s IL_0021

IL_0036: ldloc.0
IL_0037: ret
}

.method public static int32[] f32(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit> f,
class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,int32> g) cil managed
{
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationArgumentCountsAttribute::.ctor(int32[]) = ( 01 00 02 00 00 00 01 00 00 00 01 00 00 00 00 00 )

.maxstack 6
.locals init (int32 V_0,
int32[] V_1,
uint64 V_2,
int32 V_3,
int32 V_4)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldnull
IL_0003: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit>::Invoke(!0)
IL_0008: pop
IL_0009: ldarg.1
IL_000a: ldnull
IL_000b: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,int32>::Invoke(!0)
IL_0010: stloc.0
IL_0011: ldc.i4.5
IL_0012: conv.i8
IL_0013: conv.ovf.i.un
IL_0014: newarr [runtime]System.Int32
IL_0019: stloc.1
IL_001a: ldc.i4.0
IL_001b: conv.i8
IL_001c: stloc.2
IL_001d: ldc.i4.1
IL_001e: stloc.3
IL_001f: br.s IL_0035

IL_0021: ldloc.1
IL_0022: ldloc.2
IL_0023: conv.i
IL_0024: ldloc.3
IL_0025: stloc.s V_4
IL_0027: ldloc.s V_4
IL_0029: ldloc.0
IL_002a: add
IL_002b: stelem.i4
IL_002c: ldloc.3
IL_002d: ldc.i4.2
IL_002e: add
IL_002f: stloc.3
IL_0030: ldloc.2
IL_0031: ldc.i4.1
IL_0032: conv.i8
IL_0033: add
IL_0034: stloc.2
IL_0035: ldloc.2
IL_0036: ldc.i4.5
IL_0037: conv.i8
IL_0038: blt.un.s IL_0021

IL_003a: ldloc.1
IL_003b: ret
}

}

.class private abstract auto ansi sealed '<StartupCode$assembly>'.$assembly
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,8 @@ let f25 f g h = [for n in f ()..g ()..h () -> n]
let f26 start step finish = [for n in start..step..finish -> n, float n]
let f27 start step finish = [for n in start..step..finish -> struct (n, float n)]
let f28 start step finish = [for n in start..step..finish -> let x = n + 1 in n * n]

let f29 f g = [let y = f () in let z = g () in for x in 1..2..10 -> x + y + z]
let f30 f g = [let y = f () in g (); for x in 1..2..10 -> x + y]
let f31 f g = [f (); g (); for x in 1..2..10 -> x]
let f32 f g = [f (); let y = g () in for x in 1..2..10 -> x + y]
Loading

0 comments on commit fc42ec9

Please sign in to comment.