Skip to content

Commit 0136a96

Browse files
Properly handle branching
1 parent 936ea57 commit 0136a96

File tree

4 files changed

+41
-33
lines changed

4 files changed

+41
-33
lines changed

src/Compiler/CodeGen/IlxGen.fs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2867,8 +2867,12 @@ and GenExprPreSteps (cenv: cenv) (cgbuf: CodeGenBuffer) eenv expr sequel =
28672867
None
28682868

28692869
match lowering with
2870-
| Some altExpr ->
2871-
GenExpr cenv cgbuf eenv altExpr sequel
2870+
| Some(LowerComputedCollectionExpressions.ComputedCollectionExprLowering.Expr initExpr) ->
2871+
GenExpr cenv cgbuf eenv initExpr sequel
2872+
true
2873+
| Some(LowerComputedCollectionExpressions.ComputedCollectionExprLowering.Either(branch1, branch2)) ->
2874+
GenExpr cenv cgbuf eenv branch1 (sequelIgnoreEndScopes sequel)
2875+
GenExpr cenv cgbuf eenv branch2 sequel
28722876
true
28732877
| None ->
28742878

src/Compiler/Optimize/LowerComputedCollections.fs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,11 @@ let (|Int32Range|_|) g expr =
269269
| ValApp g g.range_int32_op_vref ([], [start; Expr.Const (value = Const.Int32 1); finish], _), _ -> ValueSome (start, finish)
270270
| _ -> ValueNone
271271

272+
[<RequireQualifiedAccess>]
273+
type ComputedCollectionExprLowering =
274+
| Expr of initExpr: Expr
275+
| Either of branch1: Expr * branch2: Expr
276+
272277
let LowerComputedListOrArrayExpr tcVal (g: TcGlobals) amap overallExpr =
273278
// If ListCollector is in FSharp.Core then this optimization kicks in
274279
if g.ListCollector_tcr.CanDeref then
@@ -280,7 +285,7 @@ let LowerComputedListOrArrayExpr tcVal (g: TcGlobals) amap overallExpr =
280285
| SeqToList g (OptionalCoerce (OptionalSeq g amap (ConstInt32Range g (start, finish))), m) when
281286
start > finish
282287
->
283-
Some (mkUnionCaseExpr (g.nil_ucref, [g.int32_ty], [], m))
288+
Some (ComputedCollectionExprLowering.Expr (mkUnionCaseExpr (g.nil_ucref, [g.int32_ty], [], m)))
284289

285290
// [1..5] → [1; 2; 3; 4; 5] ≡ 1 :: 2 :: 3 :: 4 :: 5 :: []
286291
| SeqToList g (OptionalCoerce (OptionalSeq g amap (ConstInt32Range g (start, finish))), _) when
@@ -291,7 +296,7 @@ let LowerComputedListOrArrayExpr tcVal (g: TcGlobals) amap overallExpr =
291296
if n < start then acc
292297
else conses (mkCons g g.int32_ty (Expr.Const (Const.Int32 n, Text.Range.range0, g.int32_ty)) acc) (n - 1)
293298

294-
Some (conses (mkNil g Text.Range.range0 g.int32_ty) finish)
299+
Some (ComputedCollectionExprLowering.Expr (conses (mkNil g Text.Range.range0 g.int32_ty) finish))
295300

296301
// [start..finish] → if start <= finish then List.init (finish - start + 1) ((+) start) else []
297302
| SeqToList g (OptionalCoerce (OptionalSeq g amap (Int32Range g (start, finish))), m) ->
@@ -300,29 +305,30 @@ let LowerComputedListOrArrayExpr tcVal (g: TcGlobals) amap overallExpr =
300305
let v, e = mkCompGenLocal Text.Range.range0 "i" g.int32_ty
301306
let body = mkAsmExpr ([AI_add], [], [start; e], [g.int32_ty], Text.Range.range0)
302307
let initializer = mkLambda Text.Range.range0 v (body, g.int32_ty)
303-
let init = mkAsmExpr ([I_ret], [], [mkCallListInit g Text.Range.range0 g.int32_ty range initializer], [], Text.Range.range0)
308+
let init = mkCallListInit g Text.Range.range0 g.int32_ty range initializer
304309

305310
let emptyLabel = generateCodeLabel ()
306311
let empty = mkLabelled Text.Range.range0 emptyLabel (mkNil g Text.Range.range0 g.int32_ty)
307-
let breakToEmptyIfStartGtFinish = mkAsmExpr ([I_brcmp (BI_bgt, emptyLabel)], [], [start; finish], [g.int32_ty], Text.Range.range0)
312+
let breakToEmptyIfStartGtFinish = mkAsmExpr ([I_brcmp (BI_bgt, emptyLabel)], [], [start; finish], [mkListTy g g.int32_ty], Text.Range.range0)
308313

309-
Some (mkAsmExpr ([], [], [breakToEmptyIfStartGtFinish; init; empty], [], m))
314+
Some (ComputedCollectionExprLowering.Either (mkAsmExpr ([], [], [breakToEmptyIfStartGtFinish; init], [mkListTy g g.int32_ty], m), empty))
310315

311316
| SeqToList g (OptionalCoerce (OptionalSeq g amap (overallSeqExpr, overallElemTy)), m) ->
312317
let collectorTy = g.mk_ListCollector_ty overallElemTy
313318
LowerComputedListOrArraySeqExpr tcVal g amap m collectorTy overallSeqExpr
319+
|> Option.map ComputedCollectionExprLowering.Expr
314320

315321
// [|5..1|] → [||]
316322
| SeqToArray g (OptionalCoerce (OptionalSeq g amap (ConstInt32Range g (start, finish))), m) when
317323
start > finish
318324
->
319-
Some (mkArray (g.int32_ty, [], m))
325+
Some (ComputedCollectionExprLowering.Expr (mkArray (g.int32_ty, [], m)))
320326

321327
// [|1..5|] → [|1; 2; 3; 4; 5|]
322328
| SeqToArray g (OptionalCoerce (OptionalSeq g amap (ConstInt32Range g (start, finish))), m) when
323329
(finish - start) * sizeof<int32> < constArrayBytesThreshold
324330
->
325-
Some (mkArray (g.int32_ty, [for n in start..finish -> Expr.Const (Const.Int32 n, Text.Range.range0, g.int32_ty)], m))
331+
Some (ComputedCollectionExprLowering.Expr (mkArray (g.int32_ty, [for n in start..finish -> Expr.Const (Const.Int32 n, Text.Range.range0, g.int32_ty)], m)))
326332

327333
// [|start..finish|] → if start <= finish then Array.init (finish - start + 1) ((+) start) else [||]
328334
| SeqToArray g (OptionalCoerce (OptionalSeq g amap (Int32Range g (start, finish))), m) ->
@@ -331,17 +337,18 @@ let LowerComputedListOrArrayExpr tcVal (g: TcGlobals) amap overallExpr =
331337
let v, e = mkCompGenLocal Text.Range.range0 "i" g.int32_ty
332338
let body = mkAsmExpr ([AI_add], [], [start; e], [g.int32_ty], Text.Range.range0)
333339
let initializer = mkLambda Text.Range.range0 v (body, g.int32_ty)
334-
let init = mkAsmExpr ([I_ret], [], [mkCallArrayInit g Text.Range.range0 g.int32_ty range initializer], [], Text.Range.range0)
340+
let init = mkCallArrayInit g Text.Range.range0 g.int32_ty range initializer
335341

336342
let emptyLabel = generateCodeLabel ()
337343
let empty = mkLabelled Text.Range.range0 emptyLabel (mkArray (g.int32_ty, [], Text.Range.range0))
338-
let breakToEmptyIfStartGtFinish = mkAsmExpr ([I_brcmp (BI_bgt, emptyLabel)], [], [start; finish], [g.int32_ty], Text.Range.range0)
344+
let breakToEmptyIfStartGtFinish = mkAsmExpr ([I_brcmp (BI_bgt, emptyLabel)], [], [start; finish], [mkArrayType g g.int32_ty], Text.Range.range0)
339345

340-
Some (mkAsmExpr ([], [], [breakToEmptyIfStartGtFinish; init; empty], [], m))
346+
Some (ComputedCollectionExprLowering.Either (mkAsmExpr ([], [], [breakToEmptyIfStartGtFinish; init], [mkArrayType g g.int32_ty], m), empty))
341347

342348
| SeqToArray g (OptionalCoerce (OptionalSeq g amap (overallSeqExpr, overallElemTy)), m) ->
343349
let collectorTy = g.mk_ArrayCollector_ty overallElemTy
344350
LowerComputedListOrArraySeqExpr tcVal g amap m collectorTy overallSeqExpr
351+
|> Option.map ComputedCollectionExprLowering.Expr
345352

346353
| _ -> None
347354
else

src/Compiler/Optimize/LowerComputedCollections.fsi

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,10 @@ open FSharp.Compiler.Import
66
open FSharp.Compiler.TcGlobals
77
open FSharp.Compiler.TypedTree
88

9+
[<RequireQualifiedAccess>]
10+
type ComputedCollectionExprLowering =
11+
| Expr of initExpr: Expr
12+
| Either of branch1: Expr * branch2: Expr
13+
914
val LowerComputedListOrArrayExpr:
10-
tcVal: ConstraintSolver.TcValF -> g: TcGlobals -> amap: ImportMap -> Expr -> Expr option
15+
tcVal: ConstraintSolver.TcValF -> g: TcGlobals -> amap: ImportMap -> Expr -> ComputedCollectionExprLowering option

tests/fsharp/Compiler/Language/ComputedCollectionLoweringTests.fs

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ module ComputedCollectionLoweringTests =
252252
.maxstack 8
253253
IL_0000: ldc.i4.1
254254
IL_0001: ldc.i4 0x101
255-
IL_0006: bgt.s IL_001d
255+
IL_0006: bgt.s IL_001c
256256
257257
IL_0008: ldc.i4 0x101
258258
IL_000d: ldc.i4.1
@@ -264,10 +264,8 @@ module ComputedCollectionLoweringTests =
264264
class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32,!!0>)
265265
IL_001b: ret
266266
267-
IL_001c: ldnull
268-
IL_001d: call !!0[] [runtime]System.Array::Empty<int32>()
269-
IL_0022: ldnull
270-
IL_0023: ret
267+
IL_001c: call !!0[] [runtime]System.Array::Empty<int32>()
268+
IL_0021: ret
271269
}
272270
273271
}
@@ -366,7 +364,7 @@ module ComputedCollectionLoweringTests =
366364
.maxstack 8
367365
IL_0000: ldarg.0
368366
IL_0001: ldarg.1
369-
IL_0002: bgt.s IL_0016
367+
IL_0002: bgt.s IL_0015
370368
371369
IL_0004: ldarg.1
372370
IL_0005: ldarg.0
@@ -379,10 +377,8 @@ module ComputedCollectionLoweringTests =
379377
class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32,!!0>)
380378
IL_0014: ret
381379
382-
IL_0015: ldnull
383-
IL_0016: call !!0[] [runtime]System.Array::Empty<int32>()
384-
IL_001b: ldnull
385-
IL_001c: ret
380+
IL_0015: call !!0[] [runtime]System.Array::Empty<int32>()
381+
IL_001a: ret
386382
}
387383
388384
}
@@ -645,7 +641,7 @@ module ComputedCollectionLoweringTests =
645641
.maxstack 8
646642
IL_0000: ldc.i4.1
647643
IL_0001: ldc.i4.s 101
648-
IL_0003: bgt.s IL_0017
644+
IL_0003: bgt.s IL_0016
649645
650646
IL_0005: ldc.i4.s 101
651647
IL_0007: ldc.i4.1
@@ -657,10 +653,8 @@ module ComputedCollectionLoweringTests =
657653
class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32,!!0>)
658654
IL_0015: ret
659655
660-
IL_0016: ldnull
661-
IL_0017: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<!0> class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>::get_Empty()
662-
IL_001c: ldnull
663-
IL_001d: ret
656+
IL_0016: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<!0> class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>::get_Empty()
657+
IL_001b: ret
664658
}
665659
666660
}
@@ -760,7 +754,7 @@ module ComputedCollectionLoweringTests =
760754
.maxstack 8
761755
IL_0000: ldarg.0
762756
IL_0001: ldarg.1
763-
IL_0002: bgt.s IL_0016
757+
IL_0002: bgt.s IL_0015
764758
765759
IL_0004: ldarg.1
766760
IL_0005: ldarg.0
@@ -773,10 +767,8 @@ module ComputedCollectionLoweringTests =
773767
class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<int32,!!0>)
774768
IL_0014: ret
775769
776-
IL_0015: ldnull
777-
IL_0016: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<!0> class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>::get_Empty()
778-
IL_001b: ldnull
779-
IL_001c: ret
770+
IL_0015: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<!0> class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1<int32>::get_Empty()
771+
IL_001a: ret
780772
}
781773
782774
}

0 commit comments

Comments
 (0)