@@ -7748,86 +7748,120 @@ let (|RangeInt32Step|_|) g expr =
77487748
77497749 | _ -> None
77507750
7751- let (| ExtractTypeOfExpr | _ |) g expr = Some ( tyOfExpr g expr)
7751+ let (| GetEnumeratorCall | _ |) expr =
7752+ match expr with
7753+ | Expr.Op ( TOp.ILCall( _, _, _, _, _, _, _, iLMethodRef, _, _, _),_,[ Expr.Val( vref,_,_) | Expr.Op(_, _, [ Expr.Val( vref, ValUseFlag.NormalValUse, _)], _) ],_) ->
7754+ if iLMethodRef.Name = " GetEnumerator" then Some( vref)
7755+ else None
7756+ | _ -> None
7757+
7758+ let (| CompiledForEachExpr | _ |) g expr =
7759+ match expr with
7760+ | Let ( enumerableVar, enumerableExpr, _,
7761+ Let ( enumeratorVar, GetEnumeratorCall enumerableVar2, enumeratorBind,
7762+ TryFinally ( WhileLoopForCompiledForEachExpr (_, Let ( elemVar,_,_, bodyExpr), _), _)))
7763+ // Apply correctness conditions to ensure this really is a compiled for-each expression.
7764+ when valRefEq g ( mkLocalValRef enumerableVar) enumerableVar2 &&
7765+ enumerableVar.IsCompilerGenerated &&
7766+ enumeratorVar.IsCompilerGenerated &&
7767+ let fvs = ( freeInExpr CollectLocals bodyExpr)
7768+ not ( Zset.contains enumerableVar fvs.FreeLocals) &&
7769+ not ( Zset.contains enumeratorVar fvs.FreeLocals) ->
7770+
7771+ // Extract useful ranges
7772+ let m = enumerableExpr.Range
7773+ let mBody = bodyExpr.Range
7774+
7775+ let spForLoop , mForLoop = match enumeratorBind with SequencePointAtBinding( spStart) -> SequencePointAtForLoop( spStart), spStart | _ -> NoSequencePointAtForLoop, m
7776+ let spWhileLoop = match enumeratorBind with SequencePointAtBinding( spStart) -> SequencePointAtWhileLoop( spStart)| _ -> NoSequencePointAtWhileLoop
7777+ let enumerableTy = tyOfExpr g enumerableExpr
7778+
7779+ Some ( enumerableTy, enumerableExpr, elemVar, bodyExpr, ( m, mBody, spForLoop, mForLoop, spWhileLoop))
7780+ | _ -> None
7781+
7782+
7783+ let (| CompiledInt32RangeForEachExpr | _ |) g expr =
7784+ match expr with
7785+ | CompiledForEachExpr g (_, RangeInt32Step g ( startExpr, step, finishExpr), elemVar, bodyExpr, ranges) ->
7786+ Some ( startExpr, step, finishExpr, elemVar, bodyExpr, ranges)
7787+ | _ -> None
7788+ | _ -> None
7789+
77527790
77537791type OptimizeForExpressionOptions = OptimizeIntRangesOnly | OptimizeAllForExpressions
77547792
77557793let DetectAndOptimizeForExpression g option expr =
7756- match expr with
7757- | Let (_, enumerableExpr, _,
7758- Let (_, _, enumeratorBind,
7759- TryFinally ( WhileLoopForCompiledForEachExpr (_, Let ( elemVar,_,_, bodyExpr), _), _))) ->
7760-
7761- let m = enumerableExpr.Range
7762- let mBody = bodyExpr.Range
7763-
7764- let spForLoop , mForLoop = match enumeratorBind with SequencePointAtBinding( spStart) -> SequencePointAtForLoop( spStart), spStart | _ -> NoSequencePointAtForLoop, m
7765- let spWhileLoop = match enumeratorBind with SequencePointAtBinding( spStart) -> SequencePointAtWhileLoop( spStart)| _ -> NoSequencePointAtWhileLoop
7766-
7767- match option, enumerableExpr with
7768- | _, RangeInt32Step g ( startExpr, step, finishExpr) ->
7769- match step with
7770- | - 1 | 1 ->
7771- mkFastForLoop g ( spForLoop, m, elemVar, startExpr,( step = 1 ), finishExpr, bodyExpr)
7772- | _ -> expr
7773- | OptimizeAllForExpressions, ExtractTypeOfExpr g ty when isStringTy g ty ->
7774- // type is string, optimize for expression as:
7775- // let $str = enumerable
7776- // for $idx in 0..(str.Length - 1) do
7777- // let elem = str.[idx]
7778- // body elem
7779-
7780- let strVar , strExpr = mkCompGenLocal m " str" ty
7781- let idxVar , idxExpr = mkCompGenLocal m " idx" g.int32_ ty
7782-
7783- let lengthExpr = mkGetStringLength g m strExpr
7784- let charExpr = mkGetStringChar g m strExpr idxExpr
7785-
7786- let startExpr = mkZero g m
7787- let finishExpr = mkDecr g mForLoop lengthExpr
7788- let loopItemExpr = mkCoerceIfNeeded g elemVar.Type g.char_ ty charExpr // for compat reasons, loop item over string is sometimes object, not char
7789- let bodyExpr = mkCompGenLet mBody elemVar loopItemExpr bodyExpr
7790- let forExpr = mkFastForLoop g ( spForLoop, m, idxVar, startExpr, true , finishExpr, bodyExpr)
7791- let expr = mkCompGenLet m strVar enumerableExpr forExpr
7792-
7793- expr
7794- | OptimizeAllForExpressions, ExtractTypeOfExpr g ty when isListTy g ty ->
7795- // type is list, optimize for expression as:
7796- // let mutable $currentVar = listExpr
7797- // let mutable $nextVar = $tailOrNull
7798- // while $guardExpr do
7799- // let i = $headExpr
7800- // bodyExpr ()
7801- // $current <- $next
7802- // $next <- $tailOrNull
7803-
7804- let IndexHead = 0
7805- let IndexTail = 1
7806-
7807- let currentVar , currentExpr = mkMutableCompGenLocal m " current" ty
7808- let nextVar , nextExpr = mkMutableCompGenLocal m " next" ty
7809- let elemTy = destListTy g ty
7810-
7811- let guardExpr = mkNonNullTest g m nextExpr
7812- let headOrDefaultExpr = mkUnionCaseFieldGetUnproven( currentExpr, g.cons_ ucref,[ elemTy], IndexHead, m)
7813- let tailOrNullExpr = mkUnionCaseFieldGetUnproven( currentExpr, g.cons_ ucref,[ elemTy], IndexTail, mBody)
7814- let bodyExpr =
7815- mkCompGenLet m elemVar headOrDefaultExpr
7816- ( mkCompGenSequential mBody
7817- bodyExpr
7794+ match option, expr with
7795+ | _, CompiledInt32RangeForEachExpr g ( startExpr, ( 1 | - 1 as step), finishExpr, elemVar, bodyExpr, ranges) ->
7796+
7797+ let ( m , _mBody , spForLoop , _mForLoop , _spWhileLoop ) = ranges
7798+ mkFastForLoop g ( spForLoop, m, elemVar, startExpr,( step = 1 ), finishExpr, bodyExpr)
7799+
7800+ | OptimizeAllForExpressions, CompiledForEachExpr g ( enumerableTy, enumerableExpr, elemVar, bodyExpr, ranges) ->
7801+
7802+ let ( m , mBody , spForLoop , mForLoop , spWhileLoop ) = ranges
7803+
7804+ if isStringTy g enumerableTy then
7805+ // type is string, optimize for expression as:
7806+ // let $str = enumerable
7807+ // for $idx in 0..(str.Length - 1) do
7808+ // let elem = str.[idx]
7809+ // body elem
7810+
7811+ let strVar , strExpr = mkCompGenLocal m " str" enumerableTy
7812+ let idxVar , idxExpr = mkCompGenLocal m " idx" g.int32_ ty
7813+
7814+ let lengthExpr = mkGetStringLength g m strExpr
7815+ let charExpr = mkGetStringChar g m strExpr idxExpr
7816+
7817+ let startExpr = mkZero g m
7818+ let finishExpr = mkDecr g mForLoop lengthExpr
7819+ let loopItemExpr = mkCoerceIfNeeded g elemVar.Type g.char_ ty charExpr // for compat reasons, loop item over string is sometimes object, not char
7820+ let bodyExpr = mkCompGenLet mBody elemVar loopItemExpr bodyExpr
7821+ let forExpr = mkFastForLoop g ( spForLoop, m, idxVar, startExpr, true , finishExpr, bodyExpr)
7822+ let expr = mkCompGenLet m strVar enumerableExpr forExpr
7823+
7824+ expr
7825+
7826+ elif isListTy g enumerableTy then
7827+ // type is list, optimize for expression as:
7828+ // let mutable $currentVar = listExpr
7829+ // let mutable $nextVar = $tailOrNull
7830+ // while $guardExpr do
7831+ // let i = $headExpr
7832+ // bodyExpr ()
7833+ // $current <- $next
7834+ // $next <- $tailOrNull
7835+
7836+ let IndexHead = 0
7837+ let IndexTail = 1
7838+
7839+ let currentVar , currentExpr = mkMutableCompGenLocal m " current" enumerableTy
7840+ let nextVar , nextExpr = mkMutableCompGenLocal m " next" enumerableTy
7841+ let elemTy = destListTy g enumerableTy
7842+
7843+ let guardExpr = mkNonNullTest g m nextExpr
7844+ let headOrDefaultExpr = mkUnionCaseFieldGetUnproven( currentExpr, g.cons_ ucref,[ elemTy], IndexHead, m)
7845+ let tailOrNullExpr = mkUnionCaseFieldGetUnproven( currentExpr, g.cons_ ucref,[ elemTy], IndexTail, mBody)
7846+ let bodyExpr =
7847+ mkCompGenLet m elemVar headOrDefaultExpr
78187848 ( mkCompGenSequential mBody
7819- ( mkValSet mBody ( mkLocalValRef currentVar) nextExpr)
7820- ( mkValSet mBody ( mkLocalValRef nextVar) tailOrNullExpr)
7849+ bodyExpr
7850+ ( mkCompGenSequential mBody
7851+ ( mkValSet mBody ( mkLocalValRef currentVar) nextExpr)
7852+ ( mkValSet mBody ( mkLocalValRef nextVar) tailOrNullExpr)
7853+ )
78217854 )
7822- )
7823- let whileExpr = mkWhile g ( spWhileLoop, WhileLoopForCompiledForEachExprMarker, guardExpr, bodyExpr, m)
7855+ let whileExpr = mkWhile g ( spWhileLoop, WhileLoopForCompiledForEachExprMarker, guardExpr, bodyExpr, m)
78247856
7825- let expr =
7826- mkCompGenLet m currentVar enumerableExpr
7827- ( mkCompGenLet m nextVar tailOrNullExpr whileExpr)
7857+ let expr =
7858+ mkCompGenLet m currentVar enumerableExpr
7859+ ( mkCompGenLet m nextVar tailOrNullExpr whileExpr)
78287860
7829- expr
7830- | _ -> expr
7861+ expr
7862+
7863+ else
7864+ expr
78317865 | _ -> expr
78327866
78337867// Used to remove Expr.Link for inner expressions in pattern matches
0 commit comments