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

[linker] Add an well known candidate inliner substep along with tests #1513

Merged
merged 3 commits into from
Jan 18, 2017

Conversation

spouliot
Copy link
Contributor

@spouliot spouliot commented Jan 16, 2017

TL&DR: This is how it should be done and tested, it's not complete
(single, simple case) nor the most interesting case ;-)

The trick is to make sure each case is covered by tests so a mono
bump won't give us a BCL that does not conform to what the linker
expect.

What's the impact ?

  1. There is the expected reduction of metadata in mscorlib. Since both
    methods don't call other API there's no indirect effect (removal).
--- before	2017-01-15 11:12:44.000000000 -0500
+++ after	2017-01-15 11:12:56.000000000 -0500
@@ -13166,9 +13166,6 @@
 System.Void System.Security.SecurityException::.ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)
 System.Void System.Security.SecurityException::.ctor(System.String)
 System.Void System.Security.SecurityException::GetObjectData(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)
-System.Boolean System.Security.SecurityManager::CheckElevatedPermissions()
-System.Security.SecurityManager
-System.Void System.Security.SecurityManager::EnsureElevatedPermissions()
 System.Security.SecurityRulesAttribute
 System.Security.SecurityRuleSet System.Security.SecurityRulesAttribute::m_ruleSet
 System.Void System.Security.SecurityRulesAttribute::.ctor(System.Security.SecurityRuleSet)
  1. There is no visible size change (even with make install does not work unless make all is already complete #1) in mscorlib.dll due to
    padding (compiler /filealign)

    mscorlib.dll 793,600 793,600 0 0.00 %

  2. there's a very small reduction of mscorlib.*.aotdata size

    mscorlib.armv7.aotdata 717,264 717,216 -48 -0.01 %
    mscorlib.arm64.aotdata 712,840 712,704 -136 -0.02 %

    AOT data *.aotdata 6,460,064 6,459,880 -184 0.00 %

  3. there's no change in executable size - normal as the AOT compiler has
    likely already doing the same optimization (before this commit)

    Executable 29,270,272 29,270,272 0 0.00 %

Full comparison: https://gist.github.com/spouliot/0464c8fa3a92b6486dfd90595d9eb718

TL&DR: This is *how* it should be done and tested, it's not complete
(single, simple case) nor the most interesting case ;-)

The trick is to make sure each case is covered by tests so a mono
_bump_ won't give us a BCL that does not conform to what the linker
expect.

What's the impact ?

1. There is the expected reduction of metadata in mscorlib. Since both
   methods don't call other API there's no indirect effect (removal).

--- before	2017-01-15 11:12:44.000000000 -0500
+++ after	2017-01-15 11:12:56.000000000 -0500
@@ -13166,9 +13166,6 @@
 System.Void System.Security.SecurityException::.ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)
 System.Void System.Security.SecurityException::.ctor(System.String)
 System.Void System.Security.SecurityException::GetObjectData(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)
-System.Boolean System.Security.SecurityManager::CheckElevatedPermissions()
-System.Security.SecurityManager
-System.Void System.Security.SecurityManager::EnsureElevatedPermissions()
 System.Security.SecurityRulesAttribute
 System.Security.SecurityRuleSet System.Security.SecurityRulesAttribute::m_ruleSet
 System.Void System.Security.SecurityRulesAttribute::.ctor(System.Security.SecurityRuleSet)

2. There is no visible size change (even with #1) in mscorlib.dll due to
   padding (compiler /filealign)

   mscorlib.dll                793,600      793,600            0       0.00 %

3. there's a *very* small reduction of mscorlib.*.aotdata size

   mscorlib.armv7.aotdata      717,264      717,216          -48      -0.01 %
   mscorlib.arm64.aotdata      712,840      712,704         -136      -0.02 %

   AOT data *.aotdata        6,460,064    6,459,880         -184       0.00 %

4. there's no change in executable size - normal as the AOT compiler has
   _likely_ already doing the same optimization (before this commit)

   Executable               29,270,272   29,270,272            0       0.00 %

Full comparison: https://gist.github.com/spouliot/0464c8fa3a92b6486dfd90595d9eb718
@monojenkins
Copy link
Collaborator

Build failure

I did not notice the xml files were duplicated across platforms.
@monojenkins
Copy link
Collaborator

Build success


/// <summary>
/// We look for candidates, without parameters, that only do `return true;`.
/// Such methods can be inlined by replacing the `call` with a `ldc.i4.1` instruction
Copy link
Member

Choose a reason for hiding this comment

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

Is this true for instance calls as well, or will replacing the call with a ldc.* leave the instance on the IL stack?

You might also have to consider tail calls (not a problem for the methods in this PR, but it might be a problem for a more general scenario).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point, the comment should have been on the NoParameterReturnOnlyConstant method (one time) on not on the here, which would be duplicated for each assembly and might differ in future cases.


/// <summary>
/// We look for candidates, without parameters and return value, that does nothing (only `ret`).
/// Such methods can be inlined by replacing the `call` with a nop` instruction.
Copy link
Member

Choose a reason for hiding this comment

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

Same comment wrt instance calls & tail calls.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

same (will move comment)

var ins = b.Instructions [0];
if (code == ins.OpCode.Code) {
var s = m.ToString ();
list.Remove (s);
Copy link
Member

Choose a reason for hiding this comment

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

This will fail if a new candidate not in the list shows up (good), but it will fail unhelpfully (you'll get a KeyNotFoundException). Maybe accumulate all the failures (so that you don't have to fix them one-by-one), and then show them at once in a single assert at the end, with a helpful assert message?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

HashSet.Remove returns bool, i.e. it does not throw. So ListMethods will show the list (not just the first instance) of the things that needs fixing.

Copy link
Member

Choose a reason for hiding this comment

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

Ah, you're right about HashSet. However ListMethods will show if a method we already inline changes (if it's not inlineable anymore), but it will not show if a method becomes inlineable (either because it's new, or its implementation changed) - but I guess that wasn't your intention.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, I added the DisplayCandidates for this https://github.com/xamarin/xamarin-macios/pull/1513/files#diff-35eb92cb55aa583082344a291c8b5c86R25 - nut so far it seems only a few of them will have an real impact (many are naturally removed from most apps).

@monojenkins
Copy link
Collaborator

Build success

@spouliot spouliot merged commit 00b1c09 into xamarin:master Jan 18, 2017
@spouliot spouliot deleted the mtouch-inliner branch January 18, 2017 02:49
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.

4 participants