[func-sig-opts] If we already made a specialized version of a function, do not respecialize, just bail.

This patch ensures that if we already have a version of a function with
an optimized function signature, we do not turn the original function
into a thunk or change the original function to call the already created
specialized version of it. The reason for doing this is:

1. It enables us to avoid the question of whether or not the callee and
caller properly mesh. To do this safely, we would really need to analyze
the specialized version of the function to make sure that it
meshes. This could be fragile.

2. This situation should not occur often since we only run function
signature specialization once in the pipeline and we do not specialize
external functions (* see below) implying linking will not affect this
optimization.

* We do not specialize functions with external linkage since:

1. Linking in a function to the current module does not provide any more
information about the internals or the signature of the function that
was available in the original module.

2. For function signature optimization to work, we need to be able to
optimize both the caller and the callee. External functions are not
emitted into the final object file implying that any changes we make to
the caller or callee will not be apparent in the final object file. So
we will not get any optimization benefit and could potentially introduce
miscompiles.

Swift SVN r22609
This commit is contained in:
Michael Gottesman
2014-10-09 00:50:07 +00:00
parent aece1e24be
commit 993d9c54eb
2 changed files with 41 additions and 89 deletions

View File

@@ -470,32 +470,21 @@ optimizeFunctionSignature(SILFunction *F,
createNewName(*F, Arguments, NewFName);
// If we already have a specialized version of this function, do not
// respecialize. Just rewrite the body of this function as the appropriate
// thunk.
// respecialize. For now just bail.
//
// TODO: Can we find out when we don't need to remake the thunk? Doing this
// ensures that we do not need to identify if this function was converted into
// a thunk or not. This is simpler yet wasteful. The thing is I don't expect
// this to happen very often. If it becomes an issue, it should be
// refactored. The thing I am worried about are false negatives due to the
// compiler "shifting" or bugs where we remove the release from a thunk when
// we process it a second time.
SILFunction *NewF;
if ((NewF = F->getModule().lookUpFunction(NewFName))) {
// Otherwise, create the new function and transfer the current function over
// to that function.
convertFunctionToThunk(F, NewF, Arguments);
} else {
// Otherwise, move F over to NewF.
NewF = moveFunctionBodyToNewFunctionWithName(F, NewFName, Arguments);
}
// TODO: Improve this. I do not expect this to occur often so I am fine for
// now avoiding this issue. The main things I am worried about are assumptions
// that we make about the callee and caller being violated. That said, this is
// just a fear.
if (F->getModule().lookUpFunction(NewFName))
return false;
// Rewrite all apply insts calling F to call NewF. Update each call site as
// appropriate given the form of function signature optimization performed.
rewriteApplyInstToCallNewFunction(F, NewF, Arguments, CallSites);
// Otherwise, move F over to NewF.
SILFunction *NewF = moveFunctionBodyToNewFunctionWithName(F, NewFName,
Arguments);
// Remove all Callee releases that we found and made redundent via owned to
// guaranteed conversion.
// And remove all Callee releases that we found and made redundent via owned
// to guaranteed conversion.
//
// TODO: If more stuff needs to be placed here, refactor into its own method.
for (auto &A : Arguments) {
@@ -504,6 +493,10 @@ optimizeFunctionSignature(SILFunction *F,
}
}
// Rewrite all apply insts calling F to call NewF. Update each call site as
// appropriate given the form of function signature optimization performed.
rewriteApplyInstToCallNewFunction(F, NewF, Arguments, CallSites);
return true;
}