-
Notifications
You must be signed in to change notification settings - Fork 790
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
for expression optimization #219
Closed
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1427,6 +1427,11 @@ let destArrayTy (g:TcGlobals) ty = | |
| [ty] -> ty | ||
| _ -> failwith "destArrayTy"; | ||
|
||
let destListTy (g:TcGlobals) ty = | ||
let _,tinst = destAppTy g ty | ||
match tinst with | ||
| [ty] -> ty | ||
| _ -> failwith "destListTy"; | ||
|
||
let isTypeConstructorEqualToOptional g tcOpt tc = | ||
match tcOpt with | ||
|
@@ -1439,6 +1444,8 @@ let isByrefLikeTyconRef g tcref = | |
isTypeConstructorEqualToOptional g g.system_ArgIterator_tcref tcref || | ||
isTypeConstructorEqualToOptional g g.system_RuntimeArgumentHandle_tcref tcref | ||
|
||
let isStringTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref,_) -> tyconRefEq g tcref g.system_String_tcref | _ -> false) | ||
let isListTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref,_) -> tyconRefEq g tcref g.list_tcr_canon | _ -> false) | ||
let isArrayTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref,_) -> isArrayTyconRef g tcref | _ -> false) | ||
let isArray1DTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref,_) -> tyconRefEq g tcref g.il_arr_tcr_map.[0] | _ -> false) | ||
let isUnitTy g ty = ty |> stripTyEqns g |> (function TType_app(tcref,_) -> tyconRefEq g g.unit_tcr_canon tcref | _ -> false) | ||
|
@@ -5906,6 +5913,8 @@ let mkIsInst ty e m = mkAsmExpr ([ isinst ], [ty],[e], [ ty ], m) | |
|
||
let mspec_Object_GetHashCode ilg = IL.mkILNonGenericInstanceMethSpecInTy(ilg.typ_Object,"GetHashCode",[],ilg.typ_int32) | ||
let mspec_Type_GetTypeFromHandle ilg = IL.mkILNonGenericStaticMethSpecInTy(ilg.typ_Type,"GetTypeFromHandle",[ilg.typ_RuntimeTypeHandle],ilg.typ_Type) | ||
let mspec_String_Length ilg = mkILNonGenericInstanceMethSpecInTy (ilg.typ_String, "get_Length", [], ilg.typ_int32) | ||
|
||
let fspec_Missing_Value ilg = IL.mkILFieldSpecInTy(ilg.typ_Missing.Value, "Value", ilg.typ_Missing.Value) | ||
|
||
|
||
|
@@ -6052,6 +6061,14 @@ let mkCallQuoteToLinqLambdaExpression g m ty e1 = | |
let mkLazyDelayed g m ty f = mkApps g (typedExprForIntrinsic g m g.lazy_create_info, [[ty]], [ f ], m) | ||
let mkLazyForce g m ty e = mkApps g (typedExprForIntrinsic g m g.lazy_force_info, [[ty]], [ e; mkUnit g m ], m) | ||
|
||
let mkGetString g m e1 e2 = mkApps g (typedExprForIntrinsic g m g.getstring_info, [], [e1;e2], m) | ||
let mkGetStringChar = mkGetString | ||
let mkGetStringLength g m e = | ||
let mspec = mspec_String_Length g.ilg | ||
/// ILCall(useCallvirt,isProtected,valu,newobj,valUseFlags,isProp,noTailCall,mref,actualTypeInst,actualMethInst, retTy) | ||
Expr.Op(TOp.ILCall(false,false,false,false,ValUseFlag.NormalValUse,true,false,mspec.MethodRef,[],[],[g.int32_ty]),[],[e],m) | ||
|
||
|
||
// Quotations can't contain any IL. | ||
// As a result, we aim to get rid of all IL generation in the typechecker and pattern match | ||
// compiler, or else train the quotation generator to understand the generated IL. | ||
|
@@ -7779,34 +7796,92 @@ let (|RangeInt32Step|_|) g expr = | |
when valRefEq g vf g.range_op_vref && typeEquiv g tyarg g.int_ty -> Some(startExpr, 1, finishExpr) | ||
|
||
// detect (RangeInt32 startExpr N finishExpr), the inlined/compiled form of 'n .. m' and 'n .. N .. m' | ||
| Expr.App(Expr.Val(vf,_,_),_,[],[startExpr; Int32Expr n; finishExpr],_) | ||
| Expr.App(Expr.Val(vf,_,_),_,[],[startExpr; Int32Expr n; finishExpr],_) | ||
when valRefEq g vf g.range_int32_op_vref -> Some(startExpr, n, finishExpr) | ||
|
||
| _ -> None | ||
|
||
|
||
// Detect the compiled or optimized form of a 'for <elemVar> in <startExpr> .. <finishExpr> do <bodyExpr>' expression over integers | ||
// Detect the compiled or optimized form of a 'for <elemVar> in <startExpr> .. <step> .. <finishExpr> do <bodyExpr>' expression over integers when step is positive | ||
let (|CompiledInt32ForEachExprWithKnownStep|_|) g expr = | ||
match expr with | ||
| Let (_enumerableVar, RangeInt32Step g (startExpr, step, finishExpr), _, | ||
Let (_enumeratorVar, _getEnumExpr, spBind, | ||
TryFinally (WhileLoopForCompiledForEachExpr (_guardExpr, Let (elemVar,_currentExpr,_,bodyExpr), m), _cleanupExpr))) -> | ||
let (|ExtractTypeOfExpr|_|) g expr = Some (tyOfExpr g expr) | ||
|
||
let spForLoop = match spBind with SequencePointAtBinding(spStart) -> SequencePointAtForLoop(spStart) | _ -> NoSequencePointAtForLoop | ||
type OptimizeForExpressionOptions = OptimizeIntRangesOnly | OptimizeAllForExpressions | ||
|
||
Some(spForLoop,elemVar,startExpr,step,finishExpr,bodyExpr,m) | ||
| _ -> | ||
None | ||
let DetectAndOptimizeForExpression g option expr = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The exciting stuff |
||
match expr with | ||
| Let (_, enumerableExpr, _, | ||
Let (_, _, enumeratorBind, | ||
TryFinally (WhileLoopForCompiledForEachExpr (_, Let (elemVar,_,_,bodyExpr), _), _))) -> | ||
|
||
let DetectFastIntegerForLoops g expr = | ||
match expr with | ||
| CompiledInt32ForEachExprWithKnownStep g (spForLoop,elemVar,startExpr,step,finishExpr,bodyExpr,m) | ||
// fast for loops only allow steps 1 and -1 steps at the moment | ||
when step = 1 || step = -1 -> | ||
let m = enumerableExpr.Range | ||
let mBody = bodyExpr.Range | ||
|
||
let spForLoop,mForLoop = match enumeratorBind with SequencePointAtBinding(spStart) -> SequencePointAtForLoop(spStart),spStart | _ -> NoSequencePointAtForLoop,m | ||
let spWhileLoop = match enumeratorBind with SequencePointAtBinding(spStart) -> SequencePointAtWhileLoop(spStart)| _ -> NoSequencePointAtWhileLoop | ||
|
||
match option,enumerableExpr with | ||
| _,RangeInt32Step g (startExpr, step, finishExpr) -> | ||
match step with | ||
| -1 | 1 -> | ||
mkFastForLoop g (spForLoop,m,elemVar,startExpr,(step = 1),finishExpr,bodyExpr) | ||
| _ -> expr | ||
| _ -> expr | ||
| OptimizeAllForExpressions,ExtractTypeOfExpr g ty when isStringTy g ty -> | ||
// type is string, optimize for expression as: | ||
// let $str = enumerable | ||
// for $idx in 0..(str.Length - 1) do | ||
// let elem = str.[idx] | ||
// body elem | ||
|
||
let strVar ,strExpr = mkCompGenLocal m "str" ty | ||
let idxVar ,idxExpr = mkCompGenLocal m "idx" g.int32_ty | ||
|
||
let lengthExpr = mkGetStringLength g m strExpr | ||
let charExpr = mkGetStringChar g m strExpr idxExpr | ||
|
||
let startExpr = mkZero g m | ||
let finishExpr = mkDecr g mForLoop lengthExpr | ||
let loopItemExpr = mkCoerceIfNeeded g elemVar.Type g.char_ty charExpr // for compat reasons, loop item over string is sometimes object, not char | ||
let bodyExpr = mkCompGenLet mBody elemVar loopItemExpr bodyExpr | ||
let forExpr = mkFastForLoop g (spForLoop,m,idxVar,startExpr,true,finishExpr,bodyExpr) | ||
let expr = mkCompGenLet m strVar enumerableExpr forExpr | ||
|
||
expr | ||
| OptimizeAllForExpressions,ExtractTypeOfExpr g ty when isListTy g ty -> | ||
// type is list, optimize for expression as: | ||
// let mutable $currentVar = listExpr | ||
// let mutable $nextVar = $tailOrNull | ||
// while $guardExpr do | ||
// let i = $headExpr | ||
// bodyExpr () | ||
// $current <- $next | ||
// $next <- $tailOrNull | ||
|
||
let IndexHead = 0 | ||
let IndexTail = 1 | ||
|
||
let currentVar ,currentExpr = mkMutableCompGenLocal m "current" ty | ||
let nextVar ,nextExpr = mkMutableCompGenLocal m "next" ty | ||
let elemTy = destListTy g ty | ||
|
||
let guardExpr = mkNonNullTest g m nextExpr | ||
let headOrDefaultExpr = mkUnionCaseFieldGetUnproven(currentExpr,g.cons_ucref,[elemTy],IndexHead,m) | ||
let tailOrNullExpr = mkUnionCaseFieldGetUnproven(currentExpr,g.cons_ucref,[elemTy],IndexTail,mBody) | ||
let bodyExpr = | ||
mkCompGenLet m elemVar headOrDefaultExpr | ||
(mkCompGenSequential mBody | ||
bodyExpr | ||
(mkCompGenSequential mBody | ||
(mkValSet mBody (mkLocalValRef currentVar) nextExpr) | ||
(mkValSet mBody (mkLocalValRef nextVar) tailOrNullExpr) | ||
) | ||
) | ||
let whileExpr = mkWhile g (spWhileLoop, WhileLoopForCompiledForEachExprMarker, guardExpr, bodyExpr, m) | ||
|
||
let expr = | ||
mkCompGenLet m currentVar enumerableExpr | ||
(mkCompGenLet m nextVar tailOrNullExpr whileExpr) | ||
|
||
expr | ||
| _ -> expr | ||
| _ -> expr | ||
|
||
// Used to remove Expr.Link for inner expressions in pattern matches | ||
let (|InnerExprPat|) expr = stripExpr expr | ||
let (|InnerExprPat|) expr = stripExpr expr |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
@if "%_echo%"=="" echo off | ||
|
||
call %~d0%~p0..\..\single-test-build.bat | ||
|
||
exit /b %ERRORLEVEL% | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
@if "%_echo%"=="" echo off | ||
|
||
call %~d0%~p0..\..\single-test-run.bat | ||
|
||
exit /b %ERRORLEVEL% | ||
|
||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
whitespace