Skip to content

Commit f3569c7

Browse files
gottesmmnvzqz
authored andcommitted
[inlining] Teach the SILCloner (and thus Mandatory Inlining) how to specialize polymorphic builtins as it inlines.
The reason why I am doing this is that today, the builtin concrete type specialization happens in DiagnosticConstantPropagation. This is not because of any super reason, it is just a peephole optimizer where we do stuff sort of like this (and emit diagnostics). So since we are emitting diagnostics, it makes sense to just plugin there. Sadly, this is actually /after/ predictable memory access optimizations. This means that if (without any loss of generality) we transform a generic_add to an add_Vec4xInt32 and load/store before/after the args/results of the builtin, we get unnecessary temporaries. In contrast, by teaching the SILCloner how to specialize polymorphic builtins, the specialization occurs in Mandatory Inlining, before both Predictable Memory Access Operations and DiagnosticConstantPropagation. This means that we will have a chance to eliminate any temporary stack slots improving -Onone codegen.
1 parent d003bf4 commit f3569c7

File tree

1 file changed

+66
-7
lines changed

1 file changed

+66
-7
lines changed

include/swift/SIL/SILCloner.h

Lines changed: 66 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@
1818
#define SWIFT_SIL_SILCLONER_H
1919

2020
#include "swift/AST/ProtocolConformance.h"
21-
#include "swift/SIL/SILOpenedArchetypesTracker.h"
21+
#include "swift/SIL/InstructionUtils.h"
2222
#include "swift/SIL/SILBuilder.h"
2323
#include "swift/SIL/SILDebugScope.h"
24+
#include "swift/SIL/SILOpenedArchetypesTracker.h"
2425
#include "swift/SIL/SILVisitor.h"
2526

2627
namespace swift {
@@ -866,13 +867,71 @@ SILCloner<ImplClass>::visitAllocValueBufferInst(AllocValueBufferInst *Inst) {
866867
template<typename ImplClass>
867868
void
868869
SILCloner<ImplClass>::visitBuiltinInst(BuiltinInst *Inst) {
869-
auto Args = getOpValueArray<8>(Inst->getArguments());
870+
auto RawArgsStorage = getOpValueArray<8>(Inst->getArguments());
870871
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
871-
recordClonedInstruction(
872-
Inst, getBuilder().createBuiltin(
873-
getOpLocation(Inst->getLoc()), Inst->getName(),
874-
getOpType(Inst->getType()),
875-
getOpSubstitutionMap(Inst->getSubstitutions()), Args));
872+
873+
// First check if we have a polymorphic builtin that has indirect
874+
// parameters. If we do not, just clone the builtin and return.
875+
//
876+
// NOTE: We cannot use the *PBSOI::init that takes a
877+
// BuiltinInst. This is b/c our BuiltinInst is going to be generic
878+
// and thus we will not try to specialize. Instead we have to infer
879+
// the types that the builtin in *Op* land would have.
880+
//
881+
// *PBSOI == PolymorphicBuiltinSpecializedOverloadInfo.
882+
auto Kind = Inst->getBuiltinKind();
883+
PolymorphicBuiltinSpecializedOverloadInfo Info;
884+
SmallVector<SILType, 8> RawOperandTypes;
885+
transform(RawArgsStorage, std::back_inserter(RawOperandTypes),
886+
[](SILValue v) -> SILType { return v->getType(); });
887+
SILType RawResultType = getOpType(Inst->getType());
888+
if (!Kind.hasValue() ||
889+
!Info.init(Inst->getModule(), *Kind, RawOperandTypes, RawResultType)) {
890+
return recordClonedInstruction(
891+
Inst,
892+
getBuilder().createBuiltin(
893+
getOpLocation(Inst->getLoc()), Inst->getName(), RawResultType,
894+
getOpSubstitutionMap(Inst->getSubstitutions()), RawArgsStorage));
895+
}
896+
897+
// Otherwise, see if we can instead of inserting the polymorphic builtin,
898+
// dispatch it to the relevant static builtin as we go. This will ensure that
899+
// we specialize the generic calls to these polymorphic builtins before
900+
// predictable memory access optimizations so we form SSA around this value at
901+
// -Onone.
902+
ArrayRef<SILValue> RawArgs(RawArgsStorage);
903+
SILValue Result;
904+
SILType ResultType = RawResultType;
905+
if (Info.hasOutParam) {
906+
Result = RawArgs.front();
907+
ResultType = Result->getType().getObjectType();
908+
RawArgs = RawArgs.drop_front();
909+
}
910+
911+
SmallVector<SILValue, 8> PromotedArgs;
912+
for (SILValue v : RawArgs) {
913+
if (v->getType().isAddress()) {
914+
PromotedArgs.push_back(getBuilder().emitLoadValueOperation(
915+
getOpLocation(Inst->getLoc()), v, LoadOwnershipQualifier::Take));
916+
continue;
917+
}
918+
PromotedArgs.push_back(v);
919+
}
920+
921+
// If we specialize, our type no longer has any substitutions.
922+
BuiltinInst *NewInst = getBuilder().createBuiltin(
923+
getOpLocation(Inst->getLoc()), Info.staticOverloadIdentifier, ResultType,
924+
{}, // If we specialize, the function no longer has any substitutions.
925+
PromotedArgs);
926+
927+
if (Result) {
928+
assert(Result->getType().isAddress());
929+
getBuilder().emitStoreValueOperation(getOpLocation(Inst->getLoc()),
930+
NewInst->getResult(0), Result,
931+
StoreOwnershipQualifier::Init);
932+
}
933+
934+
recordClonedInstruction(Inst, NewInst);
876935
}
877936

878937
template<typename ImplClass>

0 commit comments

Comments
 (0)