Skip to content

Optimize dead private global variables #28324

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

Merged
merged 32 commits into from
Jan 13, 2020

Conversation

zoecarver
Copy link
Contributor

This optimization removes private global variables when the only use is an allocation and a store instruction. To make sure I didn't remove used variables, I updated SILGlobalOpt to collect instructions from all functions. Then, it bails out when trying to optimize, if it finds an instruction with a parent function that shouldn't be optimized.

Resolves SR-6597.

@zoecarver
Copy link
Contributor Author

cc @eeckstein

Copy link
Contributor

@slavapestov slavapestov left a comment

Choose a reason for hiding this comment

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

This looks great. I have some optional suggestions for further generalizations.

@zoecarver
Copy link
Contributor Author

I moved the collection of instructions / global variables into a collect method and added a reset method. After I erase instructions, I trigger reset then collect so that the data is up to date, and the subsequent passes can successfully optimize the code. If there is a way to trigger a re-run of the pass, that might be cleaner. Feel free to suggest alternatives.

I'll finish writing tests tomorrow.

@zoecarver
Copy link
Contributor Author

Any other review comments (or comments I missed)?

Copy link
Contributor

@slavapestov slavapestov left a comment

Choose a reason for hiding this comment

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

Sorry for the delay in responding to this. Thanksgiving week was a holiday for us.

addr->eraseFromParent();
}

reset();
Copy link
Contributor

Choose a reason for hiding this comment

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

I worry that calling collect() every time something changes is going to turn this pass into an O(n^2) algorithm. Is there a way to build a list of all instructions to be deleted, and then delete them at the end, and finally reset()?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Before deleting globals, I need to recollect everything in order to figure out what's now-dead. This will make it an O(n2) -- is that OK?

Copy link
Contributor

Choose a reason for hiding this comment

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

That's OK (and it answers one of my questions in the latest review) but my guess would be that it should be possible to determine in one pass both which instructions to delete, and which SIL globals become dead as a result.

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, see my comment.

@slavapestov
Copy link
Contributor

@swift-ci Please smoke test

@zoecarver
Copy link
Contributor Author

@slavapestov thanks for the review! I'll resolve your comment and look into the build failure.

@zoecarver
Copy link
Contributor Author

The build failure occurred because a) I didn't exit early in tryRemoveGlobalAddr and b) because I didn't check GlobalVarSkipProcessing.

Also, I've updated all uses of .count(key) on a map of vectors to now be [key].size() because we no longer re-collect between every "optimization," so those elements may exist as empty vectors.

@zoecarver
Copy link
Contributor Author

zoecarver commented Dec 14, 2019

@slavapestov I've addressed your comments and fixed some of the tests. While debugging one of the tests, I discovered that tryRemoveGlobalAlloc didn't check isSafeToRemove which meant that sometimes globals would be used but not allocated. I suspect that is the cause of most (if not all) of the miscompiles (which would explain why the swift program crashed and not the compiler).

I'll try to run all the tests tonight and fix the remaining failing tests.

@@ -20,6 +20,7 @@
#include "swift/SIL/SILCloner.h"
#include "swift/SIL/SILGlobalVariable.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILInstructionWorklist.h"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is no longer needed.

@slavapestov
Copy link
Contributor

@swift-ci Please test

@slavapestov
Copy link
Contributor

@swift-ci Please test source compatibility

@slavapestov
Copy link
Contributor

@swift-ci Please benchmark

@slavapestov slavapestov self-assigned this Dec 17, 2019
@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 2070821

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 2070821

@swift-ci
Copy link
Contributor

Performance: -O

Regression OLD NEW DELTA RATIO
FlattenListFlatMap 4334 4691 +8.2% 0.92x (?)

Code size: -O

Performance: -Osize

Regression OLD NEW DELTA RATIO
DataAppendDataLargeToLarge 25800 38000 +47.3% 0.68x (?)
DropWhileCountableRange 15 17 +13.3% 0.88x (?)
 
Improvement OLD NEW DELTA RATIO
DropFirstCountableRangeLazy 17 14 -17.6% 1.21x (?)

Code size: -Osize

Performance: -Onone

Regression OLD NEW DELTA RATIO
ArrayAppendGenericStructs 630 1530 +142.9% 0.41x (?)
 
Improvement OLD NEW DELTA RATIO
ObjectiveCBridgeStubToNSDateRef 2540 2080 -18.1% 1.22x (?)

Code size: -swiftlibs

How to read the data The tables contain differences in performance which are larger than 8% and differences in code size which are larger than 1%.

If you see any unexpected regressions, you should consider fixing the
regressions before you merge the PR.

Noise: Sometimes the performance results (not code size!) contain false
alarms. Unexpected regressions which are marked with '(?)' are probably noise.
If you see regressions which you cannot explain you can try to run the
benchmarks again. If regressions still show up, please consult with the
performance team (@eeckstein).

Hardware Overview
  Model Name: Mac mini
  Model Identifier: Macmini8,1
  Processor Name: Intel Core i7
  Processor Speed: 3.2 GHz
  Number of Processors: 1
  Total Number of Cores: 6
  L2 Cache (per Core): 256 KB
  L3 Cache: 12 MB
  Memory: 64 GB

@zoecarver
Copy link
Contributor Author

It looks like this patch caused a regression in static_strings.swift does that make sense or am I misdiagnosing the issue?

@theblixguy
Copy link
Collaborator

Maybe... it could be just that the test needs to be updated because the global is optimised out? The test is not supported on macOS so it was skipped.

(Also, do you mind squashing your commits? Patch has grown to nearly 30 commits).

@eeckstein
Copy link
Contributor

@zoecarver it looks like a real regression. Can you please investigate this before merging?
@theblixguy The test passes on macOS, it's not disabled.

@theblixguy
Copy link
Collaborator

Oh, CI logs said “UNSUPPORTED” so I assumed it was skipped.

@eeckstein
Copy link
Contributor

Wait, you are right. This test requires the stdlib to be built in no-assert mode. I think we are doing this only on linux. So it's in fact not running on our macOS CI bot. But it's not disabled for macOS in general.

@zoecarver
Copy link
Contributor Author

Alrighty, this will be fun to debug :) I suspect it has to do with the modified collection of globals.

@theblixguy I'll rebase after I fix the regression.

@@ -5,7 +5,7 @@
// RUN: %target-build-swift -O -module-name=test %s -o %t/a.out
// RUN: %target-run %t/a.out | %FileCheck %s -check-prefix=CHECK-OUTPUT

// REQUIRES: executable_test,swift_stdlib_no_asserts,optimized_stdlib
// REQUIRES: executable_test,swift_stdlib_no_asserts
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@eeckstein git blame showed that you were the one who added this requirement. The test passes without optimized_stdlib do you think this is an OK change?

@zoecarver
Copy link
Contributor Author

I finally was able to reproduce/fix the issue. Thanks for the patience. Could someone re-trigger the bots?

@slavapestov
Copy link
Contributor

Sorry, we were all out on vacation, again.

@swift-ci Please smoke test

@slavapestov
Copy link
Contributor

@swift-ci Please smoke test

@zoecarver
Copy link
Contributor Author

Friendly ping. Does this need any more reviewing or can it be merged?

@slavapestov slavapestov merged commit 3b9014d into swiftlang:master Jan 13, 2020
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.

5 participants