Skip to content

Commit a5be2ff

Browse files
committed
[sil] Use FullApplySite instead of ApplyInst in SILInstruction::getMemoryBehavior().
We were giving special handling to ApplyInst when we were attempting to use getMemoryBehavior(). This commit changes the special handling to work on all full apply sites instead of just AI. Additionally, we look through partial applies and thin to thick functions. I also added a dumper called BasicInstructionPropertyDumper that just dumps the results of SILInstruction::get{Memory,Releasing}Behavior() for all instructions in order to verify this behavior.
1 parent b812efa commit a5be2ff

30 files changed

+236
-53
lines changed

include/swift/SIL/PatternMatch.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ struct Callee_match<SILFunction &> {
463463
if (!AI)
464464
return false;
465465

466-
return AI->getCalleeFunction() == &Fun;
466+
return AI->getReferencedFunction() == &Fun;
467467
}
468468
};
469469

include/swift/SIL/SILInstruction.h

+49-6
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,9 @@ combineMemoryBehavior(SILInstruction::MemoryBehavior B1,
294294
/// Pretty-print the MemoryBehavior.
295295
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
296296
SILInstruction::MemoryBehavior B);
297+
/// Pretty-print the ReleasingBehavior.
298+
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
299+
SILInstruction::ReleasingBehavior B);
297300
#endif
298301

299302
/// A template base class for instructions that take a single SILValue operand
@@ -680,11 +683,19 @@ class ApplyInstBase<Impl, Base, false> : public Base {
680683

681684
SILValue getCallee() const { return Operands[Callee].get(); }
682685

686+
/// Gets the referenced function by looking through partial apply,
687+
/// convert_function, and thin to thick function until we find a function_ref.
688+
///
689+
/// This is defined out of line to work around incomplete definition
690+
/// issues. It is at the bottom of the file.
691+
SILFunction *getCalleeFunction() const;
692+
683693
/// Gets the referenced function if the callee is a function_ref instruction.
684-
SILFunction *getCalleeFunction() const {
685-
if (auto *FRI = dyn_cast<FunctionRefInst>(getCallee()))
686-
return FRI->getReferencedFunction();
687-
return nullptr;
694+
SILFunction *getReferencedFunction() const {
695+
auto *FRI = dyn_cast<FunctionRefInst>(getCallee());
696+
if (!FRI)
697+
return nullptr;
698+
return FRI->getReferencedFunction();
688699
}
689700

690701
/// Get the type of the callee without the applied substitutions.
@@ -4354,12 +4365,18 @@ class ApplySite {
43544365
FOREACH_IMPL_RETURN(getCallee());
43554366
}
43564367

4357-
/// Return the referenced function if the callee is a function_ref
4358-
/// instruction.
4368+
/// Gets the referenced function by looking through partial apply,
4369+
/// convert_function, and thin to thick function until we find a function_ref.
43594370
SILFunction *getCalleeFunction() const {
43604371
FOREACH_IMPL_RETURN(getCalleeFunction());
43614372
}
43624373

4374+
/// Return the referenced function if the callee is a function_ref
4375+
/// instruction.
4376+
SILFunction *getReferencedFunction() const {
4377+
FOREACH_IMPL_RETURN(getReferencedFunction());
4378+
}
4379+
43634380
/// Return the type.
43644381
SILType getType() const {
43654382
FOREACH_IMPL_RETURN(getSubstCalleeType()->getSILResult());
@@ -4552,6 +4569,32 @@ class FullApplySite : public ApplySite {
45524569
}
45534570
};
45544571

4572+
// This is defined out of line to work around the fact that this depends on
4573+
// PartialApplyInst being defined, but PartialApplyInst is a subclass of
4574+
// ApplyInstBase, so we can not place ApplyInstBase after it.
4575+
template <class Impl, class Base>
4576+
SILFunction *ApplyInstBase<Impl, Base, false>::getCalleeFunction() const {
4577+
SILValue Callee = getCallee();
4578+
4579+
while (true) {
4580+
if (auto *FRI = dyn_cast<FunctionRefInst>(Callee)) {
4581+
return FRI->getReferencedFunction();
4582+
}
4583+
4584+
if (auto *PAI = dyn_cast<PartialApplyInst>(Callee)) {
4585+
Callee = PAI->getCallee();
4586+
continue;
4587+
}
4588+
4589+
if (auto *TTTFI = dyn_cast<ThinToThickFunctionInst>(Callee)) {
4590+
Callee = TTTFI->getCallee();
4591+
continue;
4592+
}
4593+
4594+
return nullptr;
4595+
}
4596+
}
4597+
45554598
} // end swift namespace
45564599

45574600
//===----------------------------------------------------------------------===//

include/swift/SILOptimizer/PassManager/Passes.def

+4
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ PASS(ArrayCountPropagation, "array-count-propagation",
4040
"Propagate the count of arrays")
4141
PASS(ArrayElementPropagation, "array-element-propagation",
4242
"Propagate the value of array elements")
43+
PASS(BasicInstructionPropertyDumper, "basic-instruction-property-dump",
44+
"Dump MemBehavior and ReleaseBehavior results from calling "
45+
"SILInstruction::{getMemoryBehavior,getReleasingBehavior}()"
46+
" on all instructions")
4347
PASS(BasicCalleePrinter, "basic-callee-printer",
4448
"Construct basic callee analysis and use it to print callees "
4549
"for testing purposes")

lib/SIL/Linker.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ bool SILLinkerVisitor::linkInVTable(ClassDecl *D) {
182182

183183
bool SILLinkerVisitor::visitApplyInst(ApplyInst *AI) {
184184
// Ok we have a function ref inst, grab the callee.
185-
SILFunction *Callee = AI->getCalleeFunction();
185+
SILFunction *Callee = AI->getReferencedFunction();
186186
if (!Callee)
187187
return false;
188188

@@ -199,7 +199,7 @@ bool SILLinkerVisitor::visitApplyInst(ApplyInst *AI) {
199199
}
200200

201201
bool SILLinkerVisitor::visitPartialApplyInst(PartialApplyInst *PAI) {
202-
SILFunction *Callee = PAI->getCalleeFunction();
202+
SILFunction *Callee = PAI->getReferencedFunction();
203203
if (!Callee)
204204
return false;
205205
if (!isLinkAll() && !Callee->isTransparent() &&

lib/SIL/SILInstruction.cpp

+17-3
Original file line numberDiff line numberDiff line change
@@ -702,12 +702,16 @@ SILInstruction::MemoryBehavior SILInstruction::getMemoryBehavior() const {
702702
}
703703
}
704704

705-
// Handle functions that have an effects attribute.
706-
if (auto *AI = dyn_cast<ApplyInst>(this))
707-
if (auto *F = AI->getCalleeFunction())
705+
// Handle full apply sites that have a resolveable callee function with an
706+
// effects attribute.
707+
if (isa<FullApplySite>(this)) {
708+
FullApplySite Site(const_cast<SILInstruction *>(this));
709+
if (auto *F = Site.getCalleeFunction()) {
708710
return F->getEffectsKind() == EffectsKind::ReadNone
709711
? MemoryBehavior::None
710712
: MemoryBehavior::MayHaveSideEffects;
713+
}
714+
}
711715

712716
switch (getKind()) {
713717
#define INST(CLASS, PARENT, MEMBEHAVIOR, RELEASINGBEHAVIOR) \
@@ -939,4 +943,14 @@ llvm::raw_ostream &swift::operator<<(llvm::raw_ostream &OS,
939943
return OS << "MayHaveSideEffects";
940944
}
941945
}
946+
947+
llvm::raw_ostream &swift::operator<<(llvm::raw_ostream &OS,
948+
SILInstruction::ReleasingBehavior B) {
949+
switch (B) {
950+
case SILInstruction::ReleasingBehavior::DoesNotRelease:
951+
return OS << "DoesNotRelease";
952+
case SILInstruction::ReleasingBehavior::MayRelease:
953+
return OS << "MayRelease";
954+
}
955+
}
942956
#endif

lib/SILOptimizer/ARC/RCStateTransition.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ static bool isAutoreleasePoolCall(SILInstruction *I) {
2929
if (!AI)
3030
return false;
3131

32-
auto *Fn = AI->getCalleeFunction();
32+
auto *Fn = AI->getReferencedFunction();
3333
if (!Fn)
3434
return false;
3535

lib/SILOptimizer/Analysis/ARCAnalysis.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -890,7 +890,7 @@ bool swift::getFinalReleasesForValue(SILValue V, ReleaseTracker &Tracker) {
890890
//===----------------------------------------------------------------------===//
891891

892892
static bool ignorableApplyInstInUnreachableBlock(const ApplyInst *AI) {
893-
const auto *Fn = AI->getCalleeFunction();
893+
const auto *Fn = AI->getReferencedFunction();
894894
if (!Fn)
895895
return false;
896896

lib/SILOptimizer/Analysis/ArraySemantic.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ bool swift::ArraySemanticsCall::isValidSignature() {
8585
if (!AllocBufferAI)
8686
return false;
8787

88-
auto *AllocFn = AllocBufferAI->getCalleeFunction();
88+
auto *AllocFn = AllocBufferAI->getReferencedFunction();
8989
if (!AllocFn)
9090
return false;
9191

@@ -109,7 +109,7 @@ swift::ArraySemanticsCall::ArraySemanticsCall(ValueBase *V,
109109
StringRef SemanticStr,
110110
bool MatchPartialName) {
111111
if (auto *AI = dyn_cast<ApplyInst>(V))
112-
if (auto *Fn = AI->getCalleeFunction())
112+
if (auto *Fn = AI->getReferencedFunction())
113113
if ((MatchPartialName &&
114114
Fn->hasSemanticsAttrThatStartsWith(SemanticStr)) ||
115115
(!MatchPartialName && Fn->hasSemanticsAttr(SemanticStr))) {

lib/SILOptimizer/Analysis/CFG.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ static bool isSafeNonExitTerminator(TermInst *TI) {
4040
static bool isTrapNoReturnFunction(ApplyInst *AI) {
4141
const char *fatalName =
4242
"_TFs18_fatalErrorMessageFTVs12StaticStringS_S_Su_T_";
43-
auto *Fn = AI->getCalleeFunction();
43+
auto *Fn = AI->getReferencedFunction();
4444

4545
// We use endswith here since if we specialize fatal error we will always
4646
// prepend the specialization records to fatalName.

lib/SILOptimizer/Analysis/ColdBlockInfo.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ static BranchHint getBranchHint(SILValue Cond) {
5555
auto AI = dyn_cast<ApplyInst>(Cond);
5656
if (!AI)
5757
return BranchHint::None;
58-
59-
if (auto *F = AI->getCalleeFunction()) {
58+
59+
if (auto *F = AI->getReferencedFunction()) {
6060
if (F->hasSemanticsAttrs()) {
6161
if (F->hasSemanticsAttr("branchhint")) {
6262
// A "branchint" model takes a Bool expected value as the second

lib/SILOptimizer/Analysis/EscapeAnalysis.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1171,7 +1171,7 @@ void EscapeAnalysis::analyzeInstruction(SILInstruction *I,
11711171
}
11721172
}
11731173

1174-
if (auto *Fn = FAS.getCalleeFunction()) {
1174+
if (auto *Fn = FAS.getReferencedFunction()) {
11751175
if (Fn->getName() == "swift_bufferAllocate")
11761176
// The call is a buffer allocation, e.g. for Array.
11771177
return;

lib/SILOptimizer/Analysis/SideEffectAnalysis.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ void SideEffectAnalysis::analyzeInstruction(FunctionInfo *FInfo,
288288
}
289289
}
290290

291-
if (SILFunction *SingleCallee = FAS.getCalleeFunction()) {
291+
if (SILFunction *SingleCallee = FAS.getReferencedFunction()) {
292292
// Does the function have any @effects?
293293
if (getDefinedEffects(FInfo->FE, SingleCallee))
294294
return;
@@ -467,7 +467,7 @@ void SideEffectAnalysis::getEffects(FunctionEffects &ApplyEffects, FullApplySite
467467
return;
468468
}
469469

470-
if (SILFunction *SingleCallee = FAS.getCalleeFunction()) {
470+
if (SILFunction *SingleCallee = FAS.getReferencedFunction()) {
471471
// Does the function have any @effects?
472472
if (getDefinedEffects(ApplyEffects, SingleCallee))
473473
return;

lib/SILOptimizer/IPO/CapturePromotion.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,7 @@ examineAllocBoxInst(AllocBoxInst *ABI, ReachabilityInfo &RI,
749749
// index so is not stored separately);
750750
unsigned Index = OpNo - 1 + closureType->getNumSILArguments();
751751

752-
auto *Fn = PAI->getCalleeFunction();
752+
auto *Fn = PAI->getReferencedFunction();
753753
if (!Fn || !Fn->isDefinition())
754754
return false;
755755

lib/SILOptimizer/IPO/ClosureSpecializer.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -739,7 +739,7 @@ void ClosureSpecializer::gatherCallSites(
739739

740740
// If AI does not have a function_ref definition as its callee, we can
741741
// not do anything here... so continue...
742-
SILFunction *ApplyCallee = AI.getCalleeFunction();
742+
SILFunction *ApplyCallee = AI.getReferencedFunction();
743743
if (!ApplyCallee || ApplyCallee->isExternalDeclaration())
744744
continue;
745745

lib/SILOptimizer/IPO/GlobalOpt.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ class InstructionsCloner : public SILClonerWithScopes<InstructionsCloner> {
151151

152152
/// If this is a call to a global initializer, map it.
153153
void SILGlobalOpt::collectGlobalInitCall(ApplyInst *AI) {
154-
SILFunction *F = AI->getCalleeFunction();
154+
SILFunction *F = AI->getReferencedFunction();
155155
if (!F || !F->isGlobalInit())
156156
return;
157157

@@ -347,8 +347,8 @@ static bool isAvailabilityCheck(SILBasicBlock *BB) {
347347
ApplyInst *AI = dyn_cast<ApplyInst>(CBR->getCondition());
348348
if (!AI)
349349
return false;
350-
351-
SILFunction *F = AI->getCalleeFunction();
350+
351+
SILFunction *F = AI->getReferencedFunction();
352352
if (!F || !F->hasSemanticsAttrs())
353353
return false;
354354

lib/SILOptimizer/IPO/PerformanceInliner.cpp

+8-8
Original file line numberDiff line numberDiff line change
@@ -508,16 +508,16 @@ static bool calleeIsSelfRecursive(SILFunction *Callee) {
508508
for (auto &BB : *Callee)
509509
for (auto &I : BB)
510510
if (auto Apply = FullApplySite::isa(&I))
511-
if (Apply.getCalleeFunction() == Callee)
511+
if (Apply.getReferencedFunction() == Callee)
512512
return true;
513513
return false;
514514
}
515515

516516
// Returns the callee of an apply_inst if it is basically inlineable.
517517
SILFunction *SILPerformanceInliner::getEligibleFunction(FullApplySite AI) {
518518

519-
SILFunction *Callee = AI.getCalleeFunction();
520-
519+
SILFunction *Callee = AI.getReferencedFunction();
520+
521521
if (!Callee) {
522522
return nullptr;
523523
}
@@ -663,8 +663,8 @@ bool SILPerformanceInliner::isProfitableToInline(FullApplySite AI,
663663
SILLoopAnalysis *LA,
664664
ConstantTracker &callerTracker,
665665
unsigned &NumCallerBlocks) {
666-
SILFunction *Callee = AI.getCalleeFunction();
667-
666+
SILFunction *Callee = AI.getReferencedFunction();
667+
668668
if (Callee->getInlineStrategy() == AlwaysInline)
669669
return true;
670670

@@ -832,15 +832,15 @@ void SILPerformanceInliner::collectAppliesToInline(
832832
// Calculate how many times a callee is called from this caller.
833833
llvm::DenseMap<SILFunction *, unsigned> CalleeCount;
834834
for (auto AI : InitialCandidates) {
835-
SILFunction *Callee = AI.getCalleeFunction();
835+
SILFunction *Callee = AI.getReferencedFunction();
836836
assert(Callee && "apply_inst does not have a direct callee anymore");
837837
CalleeCount[Callee]++;
838838
}
839839

840840
// Now copy each candidate callee that has a small enough number of
841841
// call sites into the final set of call sites.
842842
for (auto AI : InitialCandidates) {
843-
SILFunction *Callee = AI.getCalleeFunction();
843+
SILFunction *Callee = AI.getReferencedFunction();
844844
assert(Callee && "apply_inst does not have a direct callee anymore");
845845

846846
const unsigned CallsToCalleeThreshold = 1024;
@@ -869,7 +869,7 @@ bool SILPerformanceInliner::inlineCallsIntoFunction(SILFunction *Caller,
869869

870870
// Second step: do the actual inlining.
871871
for (auto AI : AppliesToInline) {
872-
SILFunction *Callee = AI.getCalleeFunction();
872+
SILFunction *Callee = AI.getReferencedFunction();
873873
assert(Callee && "apply_inst does not have a direct callee anymore");
874874

875875
if (!Callee->shouldOptimize()) {

lib/SILOptimizer/IPO/UsePrespecialized.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ bool UsePrespecialized::replaceByPrespecialized(SILFunction &F) {
7171
collectApplyInst(F, NewApplies);
7272

7373
for (auto &AI : NewApplies) {
74-
auto *ReferencedF = AI.getCalleeFunction();
74+
auto *ReferencedF = AI.getReferencedFunction();
7575
if (!ReferencedF)
7676
continue;
7777

lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ static bool isRelease(SILInstruction *Inst, SILValue RetainedValue,
284284
}
285285

286286
if (auto *AI = dyn_cast<ApplyInst>(Inst)) {
287-
if (auto *F = AI->getCalleeFunction()) {
287+
if (auto *F = AI->getReferencedFunction()) {
288288
auto Params = F->getLoweredFunctionType()->getParameters();
289289
auto Args = AI->getArguments();
290290
for (unsigned ArgIdx = 0, ArgEnd = Params.size(); ArgIdx != ArgEnd;

lib/SILOptimizer/Mandatory/ConstantPropagation.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -745,7 +745,7 @@ static bool isApplyOfBuiltin(SILInstruction &I, BuiltinValueKind kind) {
745745

746746
static bool isApplyOfStringConcat(SILInstruction &I) {
747747
if (auto *AI = dyn_cast<ApplyInst>(&I))
748-
if (auto *Fn = AI->getCalleeFunction())
748+
if (auto *Fn = AI->getReferencedFunction())
749749
if (Fn->hasSemanticsAttr("string.concat"))
750750
return true;
751751
return false;

lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -1032,7 +1032,7 @@ static SILInstruction *isSuperInitUse(UpcastInst *Inst) {
10321032
// super.init call as a hack to allow us to write testcases.
10331033
auto *AI = dyn_cast<ApplyInst>(inst);
10341034
if (AI && inst->getLoc().isSILFile())
1035-
if (auto *Fn = AI->getCalleeFunction())
1035+
if (auto *Fn = AI->getReferencedFunction())
10361036
if (Fn->getName() == "superinit")
10371037
return inst;
10381038
continue;
@@ -1072,7 +1072,7 @@ static bool isSelfInitUse(SILInstruction *I) {
10721072
// self.init call as a hack to allow us to write testcases.
10731073
if (I->getLoc().isSILFile()) {
10741074
if (auto *AI = dyn_cast<ApplyInst>(I))
1075-
if (auto *Fn = AI->getCalleeFunction())
1075+
if (auto *Fn = AI->getReferencedFunction())
10761076
if (Fn->getName().startswith("selfinit"))
10771077
return true;
10781078

0 commit comments

Comments
 (0)