Skip to content

[Optimize] Move dead partial apply elimination to mandatory combine #28536

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

Conversation

zoecarver
Copy link
Contributor

This patch moves the removal of dead partial applies to mandatory combine (from mandatory inlining). SourceKit doesn't run mandatory combine but, it does run mandatory inlining, so the more we can move out of mandatory inlining, the better.

refs #28484 #28394 #28396
cc @gottesmm

@zoecarver
Copy link
Contributor Author

@gottesmm friendly ping. Does the general idea of this patch look good to you?

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.

Are there any tests that exercise the old code? If not, do you mind adding one?

// Remove the stack dealloc, then the partial apply, then the function ref.
instModCallbacks.deleteInst(user->getUser());
instModCallbacks.deleteInst(i);
instModCallbacks.deleteInst(cast<FunctionRefInst>(i->getCallee()));
Copy link
Contributor

Choose a reason for hiding this comment

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

It's unlikely but possible that the function_ref has other uses, so I'm not sure it's quite safe to remove it.

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. I'll fix this.

@slavapestov
Copy link
Contributor

@swift-ci Please smoke test

@zoecarver
Copy link
Contributor Author

@slavapestov this should mostly be a NFC. So, no tests should need to change. Do you mean I should add a test that only runs mandatory inlining (to make sure the closure isn't optimized)?

instModCallbacks.deleteInst(i);
// If the only use of the function_ref is us, then remove it.
if (i->getCallee()->getSingleUse()->getUser() == i)
instModCallbacks.deleteInst(cast<FunctionRefInst>(i->getCallee()));
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think you can guarantee that the callee is always going to be a function_ref. Can you add an isa check to make sure?

@slavapestov
Copy link
Contributor

slavapestov commented Dec 17, 2019

It's up to you if you want to add a SIL test that only runs mandatory combining or not (do please fix the unconditional cast though)

@slavapestov
Copy link
Contributor

@swift-ci Please smoke test

return %5 : $Builtin.Int8
}

sil shared [transparent] @identity_closure : $@convention(thin) (Builtin.Int8) -> Builtin.Int8 {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm ignoring the fact that this function no longer gets removed because it seems inline with the update in #28484

@@ -1088,7 +1012,7 @@ bb0(%0 : $C):
// CHECK: [[F:%.*]] = function_ref @use_c
// CHECK: apply [[F]]([[ARG]])
// CHECK: strong_release [[ARG]]
// CHECK: strong_release [[ARG]]
// TODO: why is this broken?
Copy link
Contributor Author

@zoecarver zoecarver Dec 31, 2019

Choose a reason for hiding this comment

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

I need to figure out why there are too few strong_releases here. Any ideas?

// CHECK-NEXT: br [[MERGE_BB]]
//
// CHECK: [[MERGE_BB]]:
// TODO: strong_release [[ARG]]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was able to fix the other strong_release todos but I'm still looking into the cause of this one.

@zoecarver
Copy link
Contributor Author

@slavapestov I've added mandatory_inlining_and_combine.sil to test that mandatory inlining and mandatory combine each do the "right" thing.

I had to update this patch quite a bit to cover all the closure cleanup done in mandatory inlining, now it should cover all the cases that it used to.

mandatory_inlining_ownership2.sil had a lot of tests that now required both a mandatory inlining and mandatory combine pass. Instead of moving them to mandatory_inlining_and_combine.sil I added a RUN comment that runs both passes. If you'd prefer, I'm happy to move it into mandatory_inlining_and_combine.sil (no sure which is best).

@zoecarver zoecarver requested a review from slavapestov January 2, 2020 23:32
@@ -1449,7 +1449,8 @@ static bool keepArgsOfPartialApplyAlive(PartialApplyInst *pai,

ValueLifetimeAnalysis::Frontier partialApplyFrontier;
if (!vla.computeFrontier(partialApplyFrontier,
ValueLifetimeAnalysis::DontModifyCFG)) {
ValueLifetimeAnalysis::DontModifyCFG) ||
partialApplyFrontier.empty()) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

If partialApplyFrontier is empty (and we don't return), we will create an alloc_stack and copy_addr but no dealloc_stack.

@zoecarver
Copy link
Contributor Author

@slavapestov and @gottesmm friendly ping. I've made sure that all the tests will pass after this patch is applied. Some of the tests appear to have been deleted but that either reflects an increase in deleted partial_applys or they have been moved elsewhere (such as from mandatory_inlining.sil to mandatory_inlining_and_combine.sil).

I realize this is a large patch so it may take a while to review. Let me know if you have any questions.

@zoecarver
Copy link
Contributor Author

@swift-ci please test.

@zoecarver
Copy link
Contributor Author

@swift-ci please test.

Copy link
Contributor

@gottesmm gottesmm left a comment

Choose a reason for hiding this comment

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

Some quick comments. I am going to want to relook at this after you make improvements/what we talked about over chat.

@@ -1943,3 +1944,102 @@ AbstractFunctionDecl *swift::getBaseMethod(AbstractFunctionDecl *FD) {
}
return FD;
}

SILValue swift::stripCopiesAndBorrows(SILValue v) {
while (isa<CopyValueInst>(v) || isa<BeginBorrowInst>(v)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we already have a routine like this. I would look around.

@@ -201,11 +203,6 @@ bool MandatoryCombiner::doOneIteration(SILFunction &function,
);
}

for (SILInstruction *instruction : instructionsPendingDeletion) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is this removed?

}
}

if (auto *convFunc = dyn_cast<ConvertFunctionInst>(val)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This is not needed. Should happen automatically when we go back around.

}
}
} else if (auto *tttf = dyn_cast<ThinToThickFunctionInst>(src)) {
if (tryDeleteDeadClosure(tttf, instModCallbacks)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Most of the optimizations here should not be on LoadInst. You aren't removing load inst anywhere! Instead, all of these should be on the actual instructions you are removing (i.e. ThinToThick, Partial, Etc).

    * remove mand inlining changes
    * update combiner to be more like a "combiner"
    * delete trivially dead instructions
    * promote loads
    * don't delete instructions in the callback
@zoecarver
Copy link
Contributor Author

I'll make all these changes as their own (smaller, more focused) PRs.

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.

3 participants