Skip to content

Commit 5d52462

Browse files
Handle simple sequential mappings
* Optimize simple mappings containing sequential expressions: ```fsharp [for n in start..finish do f (); …; yield n] ```
1 parent f53dbbc commit 5d52462

File tree

6 files changed

+254
-174
lines changed

6 files changed

+254
-174
lines changed

src/Compiler/Optimize/LowerComputedCollections.fs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -415,11 +415,29 @@ module Array =
415415
)
416416
)
417417

418+
/// f (); …; Seq.singleton x
419+
///
420+
/// E.g., in [for x in … do f (); …; yield x]
421+
[<return: Struct>]
422+
let (|SimpleSequential|_|) g expr =
423+
let rec loop expr cont =
424+
match expr with
425+
| Expr.Sequential (expr1, DebugPoints (ValApp g g.seq_singleton_vref (_, [body], _), debug), kind, m) ->
426+
ValueSome (cont (expr1, debug body, kind, m))
427+
428+
| Expr.Sequential (expr1, body, kind, m) ->
429+
loop body (cont >> fun body -> Expr.Sequential (expr1, body, kind, m))
430+
431+
| _ -> ValueNone
432+
433+
loop expr Expr.Sequential
434+
418435
/// for … in … -> …
419436
[<return: Struct>]
420437
let (|SimpleMapping|_|) g expr =
421438
match expr with
422-
| ValApp g g.seq_delay_vref (_, [Expr.Lambda (bodyExpr = ValApp g g.seq_map_vref ([ty1; ty2], [Expr.Lambda (valParams = [loopVal]; bodyExpr = body) as mapping; input], _))], _) ->
439+
| ValApp g g.seq_delay_vref (_, [Expr.Lambda (bodyExpr = ValApp g g.seq_map_vref ([ty1; ty2], [Expr.Lambda (valParams = [loopVal]; bodyExpr = body) as mapping; input], _))], _)
440+
| ValApp g g.seq_delay_vref (_, [Expr.Lambda (bodyExpr = ValApp g g.seq_collect_vref ([ty1; _; ty2], [Expr.Lambda (valParams = [loopVal]; bodyExpr = SimpleSequential g body) as mapping; input], _))], _) ->
423441
ValueSome (ty1, ty2, input, mapping, loopVal, body)
424442
| _ -> ValueNone
425443

tests/FSharp.Compiler.ComponentTests/EmittedIL/ComputedCollections/ForNInRangeArrays.fs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
let f0 f = [|for n in 1..10 do f (); yield n|]
2-
let f00 f = [|for n in 1..10 do f (); yield n; yield n + 1|]
3-
let f000 () = [|for n in 1..10 do yield n|]
2+
let f00 f g = [|for n in 1..10 do f (); g (); yield n|]
3+
let f000 f = [|for n in 1..10 do f (); yield n; yield n + 1|]
4+
let f0000 () = [|for n in 1..10 do yield n|]
45
let f1 () = [|for n in 1..10 -> n|]
56
let f2 () = [|for n in 10..1 -> n|]
67
let f3 () = [|for n in 1..1..10 -> n|]

tests/FSharp.Compiler.ComponentTests/EmittedIL/ComputedCollections/ForNInRangeArrays.fs.il.bsl

Lines changed: 98 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -46,66 +46,108 @@
4646
.method public static int32[] f0(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit> f) cil managed
4747
{
4848

49-
.maxstack 5
50-
.locals init (valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ArrayCollector`1<int32> V_0,
51-
class [runtime]System.Collections.Generic.IEnumerator`1<int32> V_1,
52-
class [runtime]System.Collections.Generic.IEnumerable`1<int32> V_2,
53-
int32 V_3,
54-
class [runtime]System.IDisposable V_4)
55-
IL_0000: nop
56-
IL_0001: ldc.i4.1
57-
IL_0002: ldc.i4.1
58-
IL_0003: ldc.i4.s 10
59-
IL_0005: call class [runtime]System.Collections.Generic.IEnumerable`1<int32> [FSharp.Core]Microsoft.FSharp.Core.Operators/OperatorIntrinsics::RangeInt32(int32,
60-
int32,
61-
int32)
62-
IL_000a: callvirt instance class [runtime]System.Collections.Generic.IEnumerator`1<!0> class [runtime]System.Collections.Generic.IEnumerable`1<int32>::GetEnumerator()
63-
IL_000f: stloc.1
64-
.try
65-
{
66-
IL_0010: br.s IL_002a
49+
.maxstack 6
50+
.locals init (int32[] V_0,
51+
uint64 V_1,
52+
int32 V_2,
53+
int32 V_3)
54+
IL_0000: ldc.i4.s 10
55+
IL_0002: conv.i8
56+
IL_0003: conv.ovf.i.un
57+
IL_0004: newarr [runtime]System.Int32
58+
IL_0009: stloc.0
59+
IL_000a: ldc.i4.0
60+
IL_000b: conv.i8
61+
IL_000c: stloc.1
62+
IL_000d: ldc.i4.1
63+
IL_000e: stloc.2
64+
IL_000f: br.s IL_0029
6765

68-
IL_0012: ldloc.1
69-
IL_0013: callvirt instance !0 class [runtime]System.Collections.Generic.IEnumerator`1<int32>::get_Current()
70-
IL_0018: stloc.3
71-
IL_0019: ldarg.0
72-
IL_001a: ldnull
73-
IL_001b: 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)
74-
IL_0020: pop
75-
IL_0021: ldloca.s V_0
76-
IL_0023: ldloc.3
77-
IL_0024: call instance void valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ArrayCollector`1<int32>::Add(!0)
78-
IL_0029: nop
79-
IL_002a: ldloc.1
80-
IL_002b: callvirt instance bool [runtime]System.Collections.IEnumerator::MoveNext()
81-
IL_0030: brtrue.s IL_0012
66+
IL_0011: ldloc.0
67+
IL_0012: ldloc.1
68+
IL_0013: conv.i
69+
IL_0014: ldloc.2
70+
IL_0015: stloc.3
71+
IL_0016: ldarg.0
72+
IL_0017: ldnull
73+
IL_0018: 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)
74+
IL_001d: pop
75+
IL_001e: ldloc.3
76+
IL_001f: stelem.i4
77+
IL_0020: ldloc.2
78+
IL_0021: ldc.i4.1
79+
IL_0022: add
80+
IL_0023: stloc.2
81+
IL_0024: ldloc.1
82+
IL_0025: ldc.i4.1
83+
IL_0026: conv.i8
84+
IL_0027: add
85+
IL_0028: stloc.1
86+
IL_0029: ldloc.1
87+
IL_002a: ldc.i4.s 10
88+
IL_002c: conv.i8
89+
IL_002d: blt.un.s IL_0011
8290

83-
IL_0032: ldnull
84-
IL_0033: stloc.2
85-
IL_0034: leave.s IL_004b
91+
IL_002f: ldloc.0
92+
IL_0030: ret
93+
}
8694

87-
}
88-
finally
89-
{
90-
IL_0036: ldloc.1
91-
IL_0037: isinst [runtime]System.IDisposable
92-
IL_003c: stloc.s V_4
93-
IL_003e: ldloc.s V_4
94-
IL_0040: brfalse.s IL_004a
95-
96-
IL_0042: ldloc.s V_4
97-
IL_0044: callvirt instance void [runtime]System.IDisposable::Dispose()
98-
IL_0049: endfinally
99-
IL_004a: endfinally
100-
}
101-
IL_004b: ldloc.2
102-
IL_004c: pop
103-
IL_004d: ldloca.s V_0
104-
IL_004f: call instance !0[] valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ArrayCollector`1<int32>::Close()
105-
IL_0054: ret
95+
.method public static int32[] f00(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit> f,
96+
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
97+
{
98+
.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 )
99+
100+
.maxstack 6
101+
.locals init (int32[] V_0,
102+
uint64 V_1,
103+
int32 V_2,
104+
int32 V_3)
105+
IL_0000: ldc.i4.s 10
106+
IL_0002: conv.i8
107+
IL_0003: conv.ovf.i.un
108+
IL_0004: newarr [runtime]System.Int32
109+
IL_0009: stloc.0
110+
IL_000a: ldc.i4.0
111+
IL_000b: conv.i8
112+
IL_000c: stloc.1
113+
IL_000d: ldc.i4.1
114+
IL_000e: stloc.2
115+
IL_000f: br.s IL_0031
116+
117+
IL_0011: ldloc.0
118+
IL_0012: ldloc.1
119+
IL_0013: conv.i
120+
IL_0014: ldloc.2
121+
IL_0015: stloc.3
122+
IL_0016: ldarg.0
123+
IL_0017: ldnull
124+
IL_0018: 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)
125+
IL_001d: pop
126+
IL_001e: ldarg.1
127+
IL_001f: ldnull
128+
IL_0020: 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)
129+
IL_0025: pop
130+
IL_0026: ldloc.3
131+
IL_0027: stelem.i4
132+
IL_0028: ldloc.2
133+
IL_0029: ldc.i4.1
134+
IL_002a: add
135+
IL_002b: stloc.2
136+
IL_002c: ldloc.1
137+
IL_002d: ldc.i4.1
138+
IL_002e: conv.i8
139+
IL_002f: add
140+
IL_0030: stloc.1
141+
IL_0031: ldloc.1
142+
IL_0032: ldc.i4.s 10
143+
IL_0034: conv.i8
144+
IL_0035: blt.un.s IL_0011
145+
146+
IL_0037: ldloc.0
147+
IL_0038: ret
106148
}
107149

108-
.method public static int32[] f00(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit> f) cil managed
150+
.method public static int32[] f000(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit> f) cil managed
109151
{
110152

111153
.maxstack 5
@@ -173,7 +215,7 @@
173215
IL_005f: ret
174216
}
175217

176-
.method public static int32[] f000() cil managed
218+
.method public static int32[] f0000() cil managed
177219
{
178220

179221
.maxstack 5

tests/FSharp.Compiler.ComponentTests/EmittedIL/ComputedCollections/ForNInRangeLists.fs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
let f0 f = [for n in 1..10 do f (); yield n]
2-
let f00 f = [for n in 1..10 do f (); yield n; yield n + 1]
3-
let f000 () = [for n in 1..10 do yield n]
2+
let f00 f g = [|for n in 1..10 do f (); g (); yield n|]
3+
let f000 f = [for n in 1..10 do f (); yield n; yield n + 1]
4+
let f0000 () = [for n in 1..10 do yield n]
45
let f1 () = [for n in 1..10 -> n]
56
let f2 () = [for n in 10..1 -> n]
67
let f3 () = [for n in 1..1..10 -> n]

tests/FSharp.Compiler.ComponentTests/EmittedIL/ComputedCollections/ForNInRangeLists.fs.il.bsl

Lines changed: 91 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -48,64 +48,101 @@
4848

4949
.maxstack 5
5050
.locals init (valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1<int32> V_0,
51-
class [runtime]System.Collections.Generic.IEnumerator`1<int32> V_1,
52-
class [runtime]System.Collections.Generic.IEnumerable`1<int32> V_2,
53-
int32 V_3,
54-
class [runtime]System.IDisposable V_4)
55-
IL_0000: nop
56-
IL_0001: ldc.i4.1
57-
IL_0002: ldc.i4.1
58-
IL_0003: ldc.i4.s 10
59-
IL_0005: call class [runtime]System.Collections.Generic.IEnumerable`1<int32> [FSharp.Core]Microsoft.FSharp.Core.Operators/OperatorIntrinsics::RangeInt32(int32,
60-
int32,
61-
int32)
62-
IL_000a: callvirt instance class [runtime]System.Collections.Generic.IEnumerator`1<!0> class [runtime]System.Collections.Generic.IEnumerable`1<int32>::GetEnumerator()
63-
IL_000f: stloc.1
64-
.try
65-
{
66-
IL_0010: br.s IL_002a
51+
uint64 V_1,
52+
int32 V_2,
53+
int32 V_3)
54+
IL_0000: ldc.i4.0
55+
IL_0001: conv.i8
56+
IL_0002: stloc.1
57+
IL_0003: ldc.i4.1
58+
IL_0004: stloc.2
59+
IL_0005: br.s IL_0023
6760

68-
IL_0012: ldloc.1
69-
IL_0013: callvirt instance !0 class [runtime]System.Collections.Generic.IEnumerator`1<int32>::get_Current()
70-
IL_0018: stloc.3
71-
IL_0019: ldarg.0
72-
IL_001a: ldnull
73-
IL_001b: 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)
74-
IL_0020: pop
75-
IL_0021: ldloca.s V_0
76-
IL_0023: ldloc.3
77-
IL_0024: call instance void valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1<int32>::Add(!0)
78-
IL_0029: nop
79-
IL_002a: ldloc.1
80-
IL_002b: callvirt instance bool [runtime]System.Collections.IEnumerator::MoveNext()
81-
IL_0030: brtrue.s IL_0012
61+
IL_0007: ldloca.s V_0
62+
IL_0009: ldloc.2
63+
IL_000a: stloc.3
64+
IL_000b: ldarg.0
65+
IL_000c: ldnull
66+
IL_000d: 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)
67+
IL_0012: pop
68+
IL_0013: ldloc.3
69+
IL_0014: call instance void valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1<int32>::Add(!0)
70+
IL_0019: nop
71+
IL_001a: ldloc.2
72+
IL_001b: ldc.i4.1
73+
IL_001c: add
74+
IL_001d: stloc.2
75+
IL_001e: ldloc.1
76+
IL_001f: ldc.i4.1
77+
IL_0020: conv.i8
78+
IL_0021: add
79+
IL_0022: stloc.1
80+
IL_0023: ldloc.1
81+
IL_0024: ldc.i4.s 10
82+
IL_0026: conv.i8
83+
IL_0027: blt.un.s IL_0007
8284

83-
IL_0032: ldnull
84-
IL_0033: stloc.2
85-
IL_0034: leave.s IL_004b
85+
IL_0029: ldloca.s V_0
86+
IL_002b: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<!0> valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1<int32>::Close()
87+
IL_0030: ret
88+
}
8689

87-
}
88-
finally
89-
{
90-
IL_0036: ldloc.1
91-
IL_0037: isinst [runtime]System.IDisposable
92-
IL_003c: stloc.s V_4
93-
IL_003e: ldloc.s V_4
94-
IL_0040: brfalse.s IL_004a
95-
96-
IL_0042: ldloc.s V_4
97-
IL_0044: callvirt instance void [runtime]System.IDisposable::Dispose()
98-
IL_0049: endfinally
99-
IL_004a: endfinally
100-
}
101-
IL_004b: ldloc.2
102-
IL_004c: pop
103-
IL_004d: ldloca.s V_0
104-
IL_004f: call instance class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<!0> valuetype [FSharp.Core]Microsoft.FSharp.Core.CompilerServices.ListCollector`1<int32>::Close()
105-
IL_0054: ret
90+
.method public static int32[] f00(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit> f,
91+
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
92+
{
93+
.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 )
94+
95+
.maxstack 6
96+
.locals init (int32[] V_0,
97+
uint64 V_1,
98+
int32 V_2,
99+
int32 V_3)
100+
IL_0000: ldc.i4.s 10
101+
IL_0002: conv.i8
102+
IL_0003: conv.ovf.i.un
103+
IL_0004: newarr [runtime]System.Int32
104+
IL_0009: stloc.0
105+
IL_000a: ldc.i4.0
106+
IL_000b: conv.i8
107+
IL_000c: stloc.1
108+
IL_000d: ldc.i4.1
109+
IL_000e: stloc.2
110+
IL_000f: br.s IL_0031
111+
112+
IL_0011: ldloc.0
113+
IL_0012: ldloc.1
114+
IL_0013: conv.i
115+
IL_0014: ldloc.2
116+
IL_0015: stloc.3
117+
IL_0016: ldarg.0
118+
IL_0017: ldnull
119+
IL_0018: 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)
120+
IL_001d: pop
121+
IL_001e: ldarg.1
122+
IL_001f: ldnull
123+
IL_0020: 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)
124+
IL_0025: pop
125+
IL_0026: ldloc.3
126+
IL_0027: stelem.i4
127+
IL_0028: ldloc.2
128+
IL_0029: ldc.i4.1
129+
IL_002a: add
130+
IL_002b: stloc.2
131+
IL_002c: ldloc.1
132+
IL_002d: ldc.i4.1
133+
IL_002e: conv.i8
134+
IL_002f: add
135+
IL_0030: stloc.1
136+
IL_0031: ldloc.1
137+
IL_0032: ldc.i4.s 10
138+
IL_0034: conv.i8
139+
IL_0035: blt.un.s IL_0011
140+
141+
IL_0037: ldloc.0
142+
IL_0038: ret
106143
}
107144

108-
.method public static class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32> f00(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit> f) cil managed
145+
.method public static class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32> f000(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit> f) cil managed
109146
{
110147

111148
.maxstack 5
@@ -173,7 +210,7 @@
173210
IL_005f: ret
174211
}
175212

176-
.method public static class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32> f000() cil managed
213+
.method public static class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32> f0000() cil managed
177214
{
178215

179216
.maxstack 4

0 commit comments

Comments
 (0)