Skip to content
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

Fix error in optimization of for loops over strings and lists #742

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages.config
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="dnx-coreclr-win-x86" version="1.0.0-beta7" />
<package id="Microsoft.DotNet.BuildTools" version="1.0.25-prerelease-00085" />
<package id="Microsoft.DotNet.BuildTools" version="1.0.16-prerelease" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this intended?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes and no. It's unrelated to the fix, but I think it's needed as the compiler won't build from scratch without it. Seems the old package is no longer available on nuget. It's in a seperate commit.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps submit this as a separate PR

<package id="FsCheck" version="2.0.3" />
<package id="NUnit" version="3.0.0" targetFramework="net45" />
<package id="NUnit.Console" version="3.0.0" targetFramework="net45" />
Expand Down
42 changes: 29 additions & 13 deletions src/fsharp/TastOps.fs
Original file line number Diff line number Diff line change
Expand Up @@ -7725,6 +7725,17 @@ let (|TryFinally|_|) expr =
| Expr.Op (TOp.TryFinally _,[_resty],[Expr.Lambda(_,_,_,[_],e1,_,_); Expr.Lambda(_,_,_,[_],e2,_,_)],_) -> Some(e1,e2)
| _ -> None

let (|GetEnumeratorCall|_|) expr =
match expr with
| Expr.Op (TOp.ILCall( _, _, _, _, _, _, _, iLMethodRef, _, _, _),_,[Expr.Val(_) as enumerableExpr],_) ->
if iLMethodRef.Name = "GetEnumerator" then Some(enumerableExpr)
else None
// not sure why in the list case there's a second operation embeded in the first, but there is ...
| Expr.Op (TOp.ILCall( _, _, _, _, _, _, _, iLMethodRef, _, _, _),_,[Expr.Op(_, _, [Expr.Val(_) as enumerableExpr], _) ],_) ->
if iLMethodRef.Name = "GetEnumerator" then Some(enumerableExpr)
else None
| _ -> None

// detect ONLY the while loops that result from compiling 'for ... in ... do ...'
let (|WhileLoopForCompiledForEachExpr|_|) expr =
match expr with
Expand Down Expand Up @@ -7752,25 +7763,20 @@ let (|ExtractTypeOfExpr|_|) g expr = Some (tyOfExpr g expr)

type OptimizeForExpressionOptions = OptimizeIntRangesOnly | OptimizeAllForExpressions

let DetectAndOptimizeForExpression g option expr =
let DetectAndOptimizeForExpression (g: TcGlobals) (option: OptimizeForExpressionOptions) (expr: Expr) =
match expr with
| Let (_, enumerableExpr, _,
Let (_, _, enumeratorBind,
TryFinally (WhileLoopForCompiledForEachExpr (_, Let (elemVar,_,_,bodyExpr), _), _))) ->

| Let (_, GetEnumeratorCall(enumerableExpr), enumeratorBind,
TryFinally (WhileLoopForCompiledForEachExpr (_, Let (elemVar,_,_,bodyExpr), _), _)) ->

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
| OptimizeAllForExpressions,ExtractTypeOfExpr g ty when isStringTy g ty ->
match option, enumerableExpr with
| 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
Expand All @@ -7791,7 +7797,8 @@ let DetectAndOptimizeForExpression g option expr =
let expr = mkCompGenLet m strVar enumerableExpr forExpr

expr
| OptimizeAllForExpressions,ExtractTypeOfExpr g ty when isListTy g ty ->

| OptimizeAllForExpressions, ExtractTypeOfExpr g ty when isListTy g ty ->
// type is list, optimize for expression as:
// let mutable $currentVar = listExpr
// let mutable $nextVar = $tailOrNull
Expand Down Expand Up @@ -7827,7 +7834,16 @@ let DetectAndOptimizeForExpression g option expr =
(mkCompGenLet m nextVar tailOrNullExpr whileExpr)

expr

| _ -> expr
| Let (_, RangeInt32Step g (startExpr, step, finishExpr), enumeratorBind,
TryFinally (WhileLoopForCompiledForEachExpr (_, Let (elemVar,_,_,bodyExpr), _), _)) ->
let m = startExpr.Range
let spForLoop = match enumeratorBind with SequencePointAtBinding(spStart) -> SequencePointAtForLoop(spStart) | _ -> NoSequencePointAtForLoop
match step with
| -1 | 1 ->
mkFastForLoop g (spForLoop,m,elemVar,startExpr,(step = 1),finishExpr,bodyExpr)
| _ -> expr
| _ -> expr

// Used to remove Expr.Link for inner expressions in pattern matches
Expand Down
2 changes: 1 addition & 1 deletion tests/RunTests.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ IF NOT DEFINED GACUTILEXE64 IF EXIST "%WINSDKNETFXTOOLS%x64\gacutil.exe" set GAC
set FSC=%FSCBINPATH%\fsc.exe
set PATH=%FSCBINPATH%;%PATH%

set FSCVPREVBINPATH=%X86_PROGRAMFILES%\Microsoft SDKs\F#\3.1\Framework\v4.0
set FSCVPREVBINPATH=%X86_PROGRAMFILES%\Microsoft SDKs\F#\4.0\Framework\v4.0
set FSCVPREV=%FSCVPREVBINPATH%\fsc.exe

REM == VS-installed paths to FSharp.Core.dll
Expand Down