@@ -354,7 +354,8 @@ type OptimizationSettings =
354354 /// eliminate non-compiler generated immediate bindings
355355 member x.EliminateImmediatelyConsumedLocals () = x.localOpt ()
356356
357- /// expand "let x = (exp1, exp2, ...)" bind fields as prior tmps
357+ /// expand "let x = (exp1, exp2, ...)" bindings as prior tmps
358+ /// expand "let x = Some exp1" bindings as prior tmps
358359 member x.ExpandStructrualValues () = x.localOpt ()
359360
360361type cenv =
@@ -1552,6 +1553,8 @@ let rec CombineBoolLogic expr =
15521553// Similarly for other structural constructions, like records...
15531554// If the item is only projected from then the construction (allocation) can be eliminated.
15541555// This transform encourages that by allowing projections to be simplified.
1556+ //
1557+ // Apply the same to 'Some(x)' constructions
15551558//-------------------------------------------------------------------------
15561559
15571560let CanExpandStructuralBinding ( v : Val ) =
@@ -1562,7 +1565,13 @@ let CanExpandStructuralBinding (v: Val) =
15621565
15631566let ExprIsValue = function Expr.Val _ -> true | _ -> false
15641567
1568+ let MakeStructuralBindingTemp ( v : Val ) i ( arg : Expr ) argTy =
1569+ let name = v.LogicalName + " _" + string i
1570+ let v , ve = mkCompGenLocal arg.Range name argTy
1571+ ve, mkCompGenBind v arg
1572+
15651573let ExpandStructuralBindingRaw cenv expr =
1574+ assert cenv.settings.ExpandStructrualValues()
15661575 match expr with
15671576 | Expr.Let ( TBind( v, rhs, tgtSeqPtOpt), body, m, _)
15681577 when ( isRefTupleExpr rhs &&
@@ -1572,19 +1581,16 @@ let ExpandStructuralBindingRaw cenv expr =
15721581 expr (* avoid re-expanding when recursion hits original binding *)
15731582 else
15741583 let argTys = destRefTupleTy cenv.g v.Type
1575- let argBind i ( arg : Expr ) argTy =
1576- let name = v.LogicalName + " _" + string i
1577- let v , ve = mkCompGenLocal arg.Range name argTy
1578- ve, mkCompGenBind v arg
1579-
1580- let ves , binds = List.mapi2 argBind args argTys |> List.unzip
1584+ let ves , binds = List.mapi2 ( MakeStructuralBindingTemp v) args argTys |> List.unzip
15811585 let tuple = mkRefTupled cenv.g m ves argTys
15821586 mkLetsBind m binds ( mkLet tgtSeqPtOpt m v tuple body)
15831587 | expr -> expr
15841588
15851589// Moves outer tuple binding inside near the tupled expression:
1586- // let t = (let a0=v0 in let a1=v1 in ... in let an=vn in e0, e1, ..., em) in body
1587- // let a0=v0 in let a1=v1 in ... in let an=vn in (let t = e0, e1, ..., em in body)
1590+ // let t = (let a0=v0 in let a1=v1 in ... in let an=vn in e0, e1, ..., em) in body
1591+ // becomes
1592+ // let a0=v0 in let a1=v1 in ... in let an=vn in (let t = e0, e1, ..., em in body)
1593+ //
15881594// This way ExpandStructuralBinding can replace expressions in constants, t is directly bound
15891595// to a tuple expression so that other optimizations such as OptimizeTupleFieldGet work,
15901596// and the tuple allocation can be eliminated.
@@ -1600,6 +1606,7 @@ let rec RearrangeTupleBindings expr fin =
16001606 | _ -> None
16011607
16021608let ExpandStructuralBinding cenv expr =
1609+ assert cenv.settings.ExpandStructrualValues()
16031610 match expr with
16041611 | Expr.Let ( TBind( v, rhs, tgtSeqPtOpt), body, m, _)
16051612 when ( isRefTupleTy cenv.g v.Type &&
@@ -1608,7 +1615,20 @@ let ExpandStructuralBinding cenv expr =
16081615 match RearrangeTupleBindings rhs ( fun top -> mkLet tgtSeqPtOpt m v top body) with
16091616 | Some e -> ExpandStructuralBindingRaw cenv e
16101617 | None -> expr
1611- | e -> ExpandStructuralBindingRaw cenv e
1618+
1619+ // Expand 'let v = Some arg in ...' to 'let tmp = arg in let v = Some tp in ...'
1620+ // Used to give names to values of optional arguments prior as we inline.
1621+ | Expr.Let ( TBind( v, Expr.Op( TOp.UnionCase uc, _, [ arg], _), tgtSeqPtOpt), body, m, _)
1622+ when isOptionTy cenv.g v.Type &&
1623+ not ( ExprIsValue arg) &&
1624+ cenv.g.unionCaseRefEq uc ( mkSomeCase cenv.g) &&
1625+ CanExpandStructuralBinding v ->
1626+ let argTy = destOptionTy cenv.g v.Type
1627+ let ve , bind = MakeStructuralBindingTemp v 0 arg argTy
1628+ let newExpr = mkSome cenv.g argTy ve m
1629+ mkLetBind m bind ( mkLet tgtSeqPtOpt m v newExpr body)
1630+ | e ->
1631+ ExpandStructuralBindingRaw cenv e
16121632
16131633/// Detect a query { ... }
16141634let (| QueryRun | _ |) g expr =
0 commit comments