Skip to content

Optimize in FCS#3784

Merged
KevinRansom merged 37 commits into
dotnet:masterfrom
forki:optimizeinfcs
Feb 17, 2018
Merged

Optimize in FCS#3784
KevinRansom merged 37 commits into
dotnet:masterfrom
forki:optimizeinfcs

Conversation

@forki

@forki forki commented Oct 20, 2017

Copy link
Copy Markdown
Contributor

@forki

forki commented Oct 20, 2017

Copy link
Copy Markdown
Contributor Author

what's that outFile?

@forki forki changed the title Optimize in FCS [WIP] Optimize in FCS Oct 20, 2017
@forki

forki commented Oct 20, 2017

Copy link
Copy Markdown
Contributor Author

/cc @kjnilsson probably also interesting for fez

@kjnilsson

Copy link
Copy Markdown

Looks fantastic.

@dsyme

dsyme commented Oct 25, 2017

Copy link
Copy Markdown
Contributor

@forki Impressive. I took a very quick glance and it look totally feasible. I thought this would need much more work.

@forki

forki commented Oct 25, 2017

Copy link
Copy Markdown
Contributor Author

@dsyme what we need is to flag the optimizer for creating ilasm statements. These are hard to translate back in fable

@forki forki closed this Oct 25, 2017
@forki forki reopened this Oct 25, 2017
@forki forki closed this Oct 26, 2017
@forki forki reopened this Oct 26, 2017
@ncave

ncave commented Nov 26, 2017

Copy link
Copy Markdown
Contributor

@forki IMO we just need to add the missing ILAsm conversions in Exprs.fs.
I added a few here as a test, let me know if you want me to submit them to your PR.
Here is a test REPL so you can try them live: https://ncave.github.io/fable-repl-test

@forki

forki commented Nov 26, 2017 via email

Copy link
Copy Markdown
Contributor Author

@ncave

ncave commented Nov 26, 2017

Copy link
Copy Markdown
Contributor

@forki See PR#37.

@alfonsogarciacaro

Copy link
Copy Markdown
Contributor

So is this already working? Will it be merged? Or can we make a custom build for Fable? I used the Fable.FCS package in the past for that, we could reuse it now 😄

@ncave

ncave commented Nov 29, 2017

Copy link
Copy Markdown
Contributor

@alfonsogarciacaro All good questions idk the answer to. But you can definitely go ahead with a custom build if you want to try it. It's unfortunate that there are no FCS build artefacts for netstandard.

@ncave

ncave commented Nov 29, 2017

Copy link
Copy Markdown
Contributor

@alfonsogarciacaro Just FYI if you are custom building the FCS for netstandard, you may have to fix the embedded resource name in the .fsproj a little bit like that:

    <EmbeddedResource Include="$(FSharpSourcesRoot)/fsharp/FSStrings.resx">
      <Link>FSStrings.resx</Link>
      <LogicalName>fsstrings.resources</LogicalName>
    </EmbeddedResource>

@ncave

ncave commented Nov 29, 2017

Copy link
Copy Markdown
Contributor

@alfonsogarciacaro There are still a few more ILAsm that need to be properly translated before it can pass all Fable tests, (e.g. I_box, I_call).

@alfonsogarciacaro

Copy link
Copy Markdown
Contributor

@ncave Thanks a lot for the info! Hmm, I don't remember doing anything in particular last time I did a custom build, but it was FCS repo (which I'm much more familiarized with) not this one. Would it be possible to create a branch with these changes on your FCS fork?

@forki

forki commented Nov 29, 2017 via email

Copy link
Copy Markdown
Contributor Author

@alfonsogarciacaro

Copy link
Copy Markdown
Contributor

Sounds like a plan! Awesome, thank you @forki 👏 🎉

@ncave

ncave commented Nov 29, 2017

Copy link
Copy Markdown
Contributor

@alfonsogarciacaro

Would it be possible to create a branch with these changes on your FCS fork?

Not a problem, but let me add the missing ILAsm translations first.

@dsyme dsyme left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This looks a very promising FCS feature. I don't see any outright errors - but we need to add testing.

  1. Please find all the places where test assembly contents and also apply optimizations

  2. Please check if we have a test that gets the assembly contents for FSharp.Core - I did do that manually but I don't think it's automated - ideally we would add this test and also get the optimized TAST for FSHarp.Core - that is an excellent stress test

Comment thread src/fsharp/vs/service.fs Outdated

member info.AssemblyContents = FSharpAssemblyContents(info.TypedImplementionFiles)

member info.OptimizedAssemblyContents =

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please change to GetOptimizedAssemblyContents() since it involves potentially very long computation (e.g. we don't want it triggering in the debugger when looking at one of these objects)

Comment thread src/fsharp/vs/service.fs Outdated

member info.OptimizedAssemblyContents =
let tcGlobals, thisCcu, tcImports, mimpls = info.TypedImplementionFiles
let outfile = null

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What is outfile used for and can we pass in a correct (or at least non-null) value here?

@dsyme dsyme left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Request adding tests etc. per comment above

@ncave

ncave commented Feb 2, 2018

Copy link
Copy Markdown
Contributor

@dsyme Thanks for the review, here are the changes since:

  • fixed checked ops
  • fixed checked conv
  • fixed typeof
  • fixed string hash
  • fixed dual conv
  • added more tests

@dsyme dsyme left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One last set of additions please - can you also expand/multiply out your tests to include instantiations of the basic operators at the full matrix of primitive types? byte, sbyte, ..., UInt64, double, single, decimal, ... We may as well pin the whole lot down now and get everything under test?

@dsyme dsyme left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I spotted a few cases where the tree being returned was inaccurate

This is extremely close to being done - I looked through everything else and it looked good.

Comment thread tests/service/ExprTests.fs Outdated
"let testSByteToSByteOperator(e1) = Operators.ToSByte<Microsoft.FSharp.Core.sbyte> (e1) @ (42,45--42,53)";
"let testSByteToInt16Operator(e1) = Operators.ToInt16<Microsoft.FSharp.Core.sbyte> (e1) @ (43,45--43,53)";
"let testSByteToUInt16Operator(e1) = Operators.ToUInt16<Microsoft.FSharp.Core.sbyte> (e1) @ (44,45--44,54)";
"let testSByteToIntOperator(e1) = e1 @ (45,45--45,51)";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm a little concerned about this - it looks like the code being returned wouldn't pass type checking. This will be because it's a no-op conversion

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

There are quite a lot of cases of this. See comment further above in ConvExprPrim for the root cause

Comment thread src/fsharp/symbols/Exprs.fs Outdated

| TOp.ILAsm([ AI_ceq ], _), _, [arg1;arg2] ->
| TOp.ILAsm([ ], _), _, [arg] ->
ConvExprPrim cenv env arg

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This case is used for no-op conversions like sbyte --> int32.

I think in this case you strictly speaking need to insert an appropriately-typed conversion operator in the F# expression based on the type of arg and the type of expr

BTW ConvExprPrim is getting kind of huge and maybe should be chopped into ConvExprPrim and ConvOpExprPrim

Comment thread tests/service/ExprTests.fs Outdated
"let testByteToUInt64Checked(e1) = Checked.ToUInt64<Microsoft.FSharp.Core.byte> (e1) @ (37,43--37,60)";
"let testByteToIntPtrChecked(e1) = Checked.ToIntPtr<Microsoft.FSharp.Core.byte> (e1) @ (38,43--38,63)";
"let testByteToUIntPtrChecked(e1) = Checked.ToUIntPtr<Microsoft.FSharp.Core.byte> (e1) @ (39,43--39,64)";
"let testByteToByteOperator(e1) = O

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

    let testInt64ToCharOperator(e1) = Operators.ToUInt16<Microsoft.FSharp.Core.int64> (e1)

This looks wrong. I think the IL instruction sequence is ambiguous and needs to be disamiguated by the type of expr in ConvExprPrim

Comment thread tests/service/ExprTests.fs Outdated
"let testByteToUInt64Checked(e1) = Checked.ToUInt64<Microsoft.FSharp.Core.byte> (e1) @ (37,43--37,60)";
"let testByteToIntPtrChecked(e1) = Checked.ToIntPtr<Microsoft.FSharp.Core.byte> (e1) @ (38,43--38,63)";
"let testByteToUIntPtrChecked(e1) = Checked.ToUIntPtr<Microsoft.FSharp.Core.byte> (e1) @ (39,43--39,64)";
"let testByteToByteOperator(e1) = O

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Here's another char one where we've ended up with ToUInt16 (see comment below)

Comment thread tests/service/ExprTests.fs Outdated
"let testByteToUInt64Checked(e1) = Checked.ToUInt64<Microsoft.FSharp.Core.byte> (e1) @ (37,43--37,60)";
"let testByteToIntPtrChecked(e1) = Checked.ToIntPtr<Microsoft.FSharp.Core.byte> (e1) @ (38,43--38,63)";
"let testByteToUIntPtrChecked(e1) = Checked.ToUIntPtr<Microsoft.FSharp.Core.byte> (e1) @ (39,43--39,64)";
"let testByteToByteOperator(e1) = O

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

another char --> UInt16 mistake (See comment below)

Comment thread tests/service/ExprTests.fs Outdated
"let testByteToUInt64Checked(e1) = Checked.ToUInt64<Microsoft.FSharp.Core.byte> (e1) @ (37,43--37,60)";
"let testByteToIntPtrChecked(e1) = Checked.ToIntPtr<Microsoft.FSharp.Core.byte> (e1) @ (38,43--38,63)";
"let testByteToUIntPtrChecked(e1) = Checked.ToUIntPtr<Microsoft.FSharp.Core.byte> (e1) @ (39,43--39,64)";
"let testByteToByteOperator(e1) = O

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

another char/UInt16 mistake (See comment below)

@dsyme

dsyme commented Feb 14, 2018

Copy link
Copy Markdown
Contributor

The changes are good, thank you! Just a few warnings left I think:

  D:\j\w\debug_default---ce4d11dd\src\fsharp\symbols\Exprs.fs(276,15): error FS1182: The value 'x' is unused [D:\j\w\debug_default---ce4d11dd\src\fsharp\FSharp.Compiler.Private\FSharp.Compiler.Private.fsproj]
  D:\j\w\debug_default---ce4d11dd\src\fsharp\symbols\Exprs.fs(277,15): error FS1182: The value 'x' is unused [D:\j\w\debug_default---ce4d11dd\src\fsharp\FSharp.Compiler.Private\FSharp.Compiler.Private.fsproj]
  D:\j\w\debug_default---ce4d11dd\src\fsharp\symbols\Exprs.fs(278,15): error FS1182: The value 'x' is unused [D:\j\w\debug_default---ce4d11dd\src\fsharp\FSharp.Compiler.Private\FSharp.Compiler.Private.fsproj]
  D:\j\w\debug_default---ce4d11dd\src\fsharp\symbols\Exprs.fs(279,15): error FS1182: The value 'x' is unused [D:\j\w\debug_default---ce4d11dd\src\fsharp\FSharp.Compiler.Private\FSharp.Compiler.Private.fsproj]
  D:\j\w\debug_default---ce4d11dd\src\fsharp\symbols\Exprs.fs(280,15): error FS1182: The value 'x' is unused [D:\j\w\debug_default---ce4d11dd\src\fsharp\FSharp.Compiler.Private\FSharp.Compiler.Private.fsproj]
  D:\j\w\debug_default---ce4d11dd\src\fsharp\symbols\Exprs.fs(281,15): error FS1182: The value 'x' is unused [D:\j\w\debug_default---ce4d11dd\src\fsharp\FSharp.Compiler.Private\FSharp.Compiler.Private.fsproj]
  D:\j\w\debug_default---ce4d11dd\src\fsharp\symbols\Exprs.fs(282,15): error FS1182: The value 'x' is unused [D:\j\w\debug_default---ce4d11dd\src\fsharp\FSharp.Compiler.Private\FSharp.Compiler.Private.fsproj]
  D:\j\w\debug_default---ce4d11dd\src\fsharp\symbols\Exprs.fs(283,15): error FS1182: The value 'x' is unused [D:\j\w\debug_default---ce4d11dd\src\fsharp\FSharp.Compiler.Private\FSharp.Compiler.Private.fsproj]
  D:\j\w\debug_default---ce4d11dd\src\fsharp\symbols\Exprs.fs(284,15): error FS1182: The value 'x' is unused [D:\j\w\debug_default---ce4d11dd\src\fsharp\FSharp.Compiler.Private\FSharp.Compiler.Private.fsproj]
  D:\j\w\debug_default---ce4d11dd\src\fsharp\symbols\Exprs.fs(285,15): error FS1182: The value 'x' is unused [D:\j\w\debug_default---ce4d11dd\src\fsharp\FSharp.Compiler.Private\FSharp.Compiler.Private.fsproj]
  D:\j\w\debug_default---ce4d11dd\src\fsharp\symbols\Exprs.fs(286,15): error FS1182: The value 'x' is unused [D:\j\w\debug_default---ce4d11dd\src\fsharp\FSharp.Compiler.Private\FSharp.Compiler.Private.fsproj]
  D:\j\w\debug_default---ce4d11dd\src\fsharp\symbols\Exprs.fs(287,15): error FS1182: The value 'x' is unused [D:\j\w\debug_default---ce4d11dd\src\fsharp\FSharp.Compiler.Private\FSharp.Compiler.Private.fsproj]
  D:\j\w\debug_default---ce4d11dd\src\fsharp\symbols\Exprs.fs(288,15): error FS1182: The value 'x' is unused [D:\j\w\debug_default---ce4d11dd\src\fsharp\FSharp.Compiler.Private\FSharp.Compiler.Private.fsproj]

@dsyme dsyme left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

A few warnings to remove, but approved - great work on testing and thank you for going the extra distance to make this a robust feature of FCS

@ncave

ncave commented Feb 14, 2018

Copy link
Copy Markdown
Contributor

@dsyme Thank you for reviewing so thoroughly, the end result is always so much better for it.
And thank you @forki for coming up with this original idea and blazing the trail.

@forki

forki commented Feb 14, 2018 via email

Copy link
Copy Markdown
Contributor Author

@AviAvni

AviAvni commented Feb 14, 2018

Copy link
Copy Markdown
Contributor

@forki you can offer this as a service to some repos 😉

@KevinRansom KevinRansom merged commit 2180de4 into dotnet:master Feb 17, 2018
@forki

forki commented Feb 17, 2018

Copy link
Copy Markdown
Contributor Author

Awesome! This makes me happy

@realvictorprm

Copy link
Copy Markdown
Contributor

This is great! Thank you all for your work! 😃 Please take a cookie as thanks 🍪 !

"member M2(__) (unitVar1) = __.compiledAsInstanceMethod(()) @ (56,21--56,47)";
"member SM1(unitVar0) = Operators.op_Addition<Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int,Microsoft.FSharp.Core.int> (compiledAsStaticField,ClassWithImplicitConstructor.compiledAsGenericStaticMethod<Microsoft.FSharp.Core.int> (compiledAsStaticField)) @ (57,26--57,101)";
"member SM2(unitVar0) = ClassWithImplicitConstructor.compiledAsStaticMethod (()) @ (58,26--58,50)";
#if NO_PROJECTCRACKER // proxy for COMPILER

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@ncave Do you recall why this was needed? I don't think it's either NO_PROJECTCRACKER nor COMPILER. I'm hitting cases where this test is now failing and I'm not sure what I've done....

@ncave ncave Feb 22, 2018

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@dsyme This just means the output of FSharp.LanguageService is slightly different than FCS, and accounts for that.

These two projects reference FCS:
fcs/FSharp.Compiler.Service.Tests.netcore/FSharp.Compiler.Service.Tests.netcore.fsproj
fcs/FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj

but vsintegration/tests/unittests/VisualFSharp.UnitTests.fsproj references FSharp.LanguageService, so a symbol defined in VisualFSharp.UnitTests.fsproj is used to branch the output.

I don't know what is the error, perhaps the output is now the same? (if so, then there is no need to branch it anymore).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

FSharp.LanguageService

I think you mean FSharp.Compiler.Private being used from VisualFSharp.UnitTests.fsproj

In #4368 I'm now always seeing the output in the NO_PROJECTCRACKER branch even from the two FCS test projects. I don't particularly understand why though or what's changed. Don't worry about it for now - let's see if CI passes

T-Gro pushed a commit that referenced this pull request Jun 12, 2026
* Optimize in FCS

* Transport tcConfig

* Cleanup

* Replace more ILAsm in Exprs

* More ILAsm replacements

* update resource name

* Added some tests (#40)

* Add option to toggle unused declarations analyzer (#4074)

* Add option to toggle unused declarations analyzer

* Better name and handle registering code fixes.

This will ensure that if someone uses warnon:1182, we won't suggest
fixes if they've turned off the feature.

* Revert #1650 (and #3366) (#4173)

* Fix error logging in brace matching code (#4140)

* Remove error logger pushing code

* Update service.fs

* Fix #4200: Vsix: fix empty "New file" window for web projects (#4202)

* LOC CHECKIN | visualfsharp - master | 20180112 (#4194)

* Fixed FCS netcore tests (#4180)

* Remove ambiguous resolution error FS0332 (#4170)

* Add IsInteractive to parsing options for script load closures (#4169)

* Add IsInteractive to FSharpParsingOptions

* Add test

* Set serializable bit for all serializable types (#4211)

* Minor fix (#4195)

on string 58.

*  Symbols API: add Index to active pattern case, Name to pattern group (#4222)

* Symbols API: add Index to active pattern case, Name to pattern group

* Symbols API: add active pattern case use tests

* don't rebuild (#4230)

* Optimize in FCS

* Transport tcConfig

* Cleanup

* Replace more ILAsm in Exprs

* More ILAsm replacements

* update resource name

* Added some tests

* test conditions update

* test update

* test condition update

* test update

* review update

* added checked operators

* fixed dual conversions

* review fixes

* more targeted replacements

* adapt to latest

* added more tests

* added more tests

* review fixes

* fixed warnings
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants