Skip to content

Commit 1ad1811

Browse files
committed
Merge remote-tracking branch 'origin/master' into master-rebranch
2 parents 0591c81 + 12b33f6 commit 1ad1811

File tree

9 files changed

+66
-172
lines changed

9 files changed

+66
-172
lines changed

lib/SILOptimizer/Mandatory/SemanticARCOpts.cpp

Lines changed: 48 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ STATISTIC(NumLoadCopyConvertedToLoadBorrow,
4444
///
4545
/// Semantically this implies that a value is never passed off as +1 to memory
4646
/// or another function implying it can be used everywhere at +0.
47-
static bool
48-
isDeadLiveRange(SILValue v, SmallVectorImpl<DestroyValueInst *> &destroys,
49-
SmallVectorImpl<SILInstruction *> &forwardingInsts) {
47+
static bool isDeadLiveRange(
48+
SILValue v, SmallVectorImpl<DestroyValueInst *> &destroys,
49+
NullablePtr<SmallVectorImpl<SILInstruction *>> forwardingInsts = nullptr) {
5050
assert(v.getOwnershipKind() == ValueOwnershipKind::Owned);
5151
SmallVector<Operand *, 32> worklist(v->use_begin(), v->use_end());
5252
while (!worklist.empty()) {
@@ -84,7 +84,8 @@ isDeadLiveRange(SILValue v, SmallVectorImpl<DestroyValueInst *> &destroys,
8484
//
8585
// NOTE: Today we do not support TermInsts for simplicity... we /could/
8686
// support it though if we need to.
87-
if (isa<TermInst>(user) || !isGuaranteedForwardingInst(user) ||
87+
if (forwardingInsts.isNull() || isa<TermInst>(user) ||
88+
!isGuaranteedForwardingInst(user) ||
8889
1 != count_if(user->getOperandValues(
8990
true /*ignore type dependent operands*/),
9091
[&](SILValue v) {
@@ -97,7 +98,7 @@ isDeadLiveRange(SILValue v, SmallVectorImpl<DestroyValueInst *> &destroys,
9798
// Ok, this is a forwarding instruction whose ownership we can flip from
9899
// owned -> guaranteed. Visit its users recursively to see if the the
99100
// users force the live range to be alive.
100-
forwardingInsts.push_back(user);
101+
forwardingInsts.get()->push_back(user);
101102
for (SILValue v : user->getResults()) {
102103
if (v.getOwnershipKind() != ValueOwnershipKind::Owned)
103104
continue;
@@ -297,49 +298,6 @@ static bool canHandleOperand(SILValue operand, SmallVectorImpl<SILValue> &out) {
297298
return all_of(out, canHandleValue);
298299
}
299300

300-
static void convertForwardingInstsFromOwnedToGuaranteed(
301-
SmallVectorImpl<SILInstruction *> &guaranteedForwardingInsts) {
302-
// Then change all of our guaranteed forwarding insts to have guaranteed
303-
// ownership kind instead of what ever they previously had (ignoring trivial
304-
// results);
305-
while (!guaranteedForwardingInsts.empty()) {
306-
auto *i = guaranteedForwardingInsts.pop_back_val();
307-
assert(i->hasResults());
308-
309-
for (SILValue result : i->getResults()) {
310-
if (auto *svi = dyn_cast<OwnershipForwardingSingleValueInst>(result)) {
311-
if (svi->getOwnershipKind() == ValueOwnershipKind::Owned) {
312-
svi->setOwnershipKind(ValueOwnershipKind::Guaranteed);
313-
}
314-
continue;
315-
}
316-
317-
if (auto *ofci = dyn_cast<OwnershipForwardingConversionInst>(result)) {
318-
if (ofci->getOwnershipKind() == ValueOwnershipKind::Owned) {
319-
ofci->setOwnershipKind(ValueOwnershipKind::Guaranteed);
320-
}
321-
continue;
322-
}
323-
324-
if (auto *sei = dyn_cast<OwnershipForwardingSelectEnumInstBase>(result)) {
325-
if (sei->getOwnershipKind() == ValueOwnershipKind::Owned) {
326-
sei->setOwnershipKind(ValueOwnershipKind::Guaranteed);
327-
}
328-
continue;
329-
}
330-
331-
if (auto *mvir = dyn_cast<MultipleValueInstructionResult>(result)) {
332-
if (mvir->getOwnershipKind() == ValueOwnershipKind::Owned) {
333-
mvir->setOwnershipKind(ValueOwnershipKind::Guaranteed);
334-
}
335-
continue;
336-
}
337-
338-
llvm_unreachable("unhandled forwarding instruction?!");
339-
}
340-
}
341-
}
342-
343301
// Eliminate a copy of a borrowed value, if:
344302
//
345303
// 1. All of the copies users do not consume the copy (and thus can accept a
@@ -387,7 +345,7 @@ bool SemanticARCOptVisitor::performGuaranteedCopyValueOptimization(CopyValueInst
387345
// value (e.x. storing into memory).
388346
SmallVector<DestroyValueInst *, 16> destroys;
389347
SmallVector<SILInstruction *, 16> guaranteedForwardingInsts;
390-
if (!isDeadLiveRange(cvi, destroys, guaranteedForwardingInsts))
348+
if (!isDeadLiveRange(cvi, destroys, &guaranteedForwardingInsts))
391349
return false;
392350

393351
// Next check if we have any destroys at all of our copy_value and an operand
@@ -494,8 +452,47 @@ bool SemanticARCOptVisitor::performGuaranteedCopyValueOptimization(CopyValueInst
494452
}
495453

496454
eraseAndRAUWSingleValueInstruction(cvi, cvi->getOperand());
497-
convertForwardingInstsFromOwnedToGuaranteed(guaranteedForwardingInsts);
498455

456+
// Then change all of our guaranteed forwarding insts to have guaranteed
457+
// ownership kind instead of what ever they previously had (ignoring trivial
458+
// results);
459+
while (!guaranteedForwardingInsts.empty()) {
460+
auto *i = guaranteedForwardingInsts.pop_back_val();
461+
462+
assert(i->hasResults());
463+
464+
for (SILValue result : i->getResults()) {
465+
if (auto *svi = dyn_cast<OwnershipForwardingSingleValueInst>(result)) {
466+
if (svi->getOwnershipKind() == ValueOwnershipKind::Owned) {
467+
svi->setOwnershipKind(ValueOwnershipKind::Guaranteed);
468+
}
469+
continue;
470+
}
471+
472+
if (auto *ofci = dyn_cast<OwnershipForwardingConversionInst>(result)) {
473+
if (ofci->getOwnershipKind() == ValueOwnershipKind::Owned) {
474+
ofci->setOwnershipKind(ValueOwnershipKind::Guaranteed);
475+
}
476+
continue;
477+
}
478+
479+
if (auto *sei = dyn_cast<OwnershipForwardingSelectEnumInstBase>(result)) {
480+
if (sei->getOwnershipKind() == ValueOwnershipKind::Owned) {
481+
sei->setOwnershipKind(ValueOwnershipKind::Guaranteed);
482+
}
483+
continue;
484+
}
485+
486+
if (auto *mvir = dyn_cast<MultipleValueInstructionResult>(result)) {
487+
if (mvir->getOwnershipKind() == ValueOwnershipKind::Owned) {
488+
mvir->setOwnershipKind(ValueOwnershipKind::Guaranteed);
489+
}
490+
continue;
491+
}
492+
493+
llvm_unreachable("unhandled forwarding instruction?!");
494+
}
495+
}
499496
++NumEliminatedInsts;
500497
return true;
501498
}
@@ -738,8 +735,7 @@ bool SemanticARCOptVisitor::visitLoadInst(LoadInst *li) {
738735
// -> load_borrow if we can put a copy_value on a cold path and thus
739736
// eliminate RR traffic on a hot path.
740737
SmallVector<DestroyValueInst *, 32> destroyValues;
741-
SmallVector<SILInstruction *, 16> guaranteedForwardingInsts;
742-
if (!isDeadLiveRange(li, destroyValues, guaranteedForwardingInsts))
738+
if (!isDeadLiveRange(li, destroyValues))
743739
return false;
744740

745741
// Then check if our address is ever written to. If it is, then we
@@ -764,8 +760,6 @@ bool SemanticARCOptVisitor::visitLoadInst(LoadInst *li) {
764760
}
765761

766762
eraseAndRAUWSingleValueInstruction(li, lbi);
767-
convertForwardingInstsFromOwnedToGuaranteed(guaranteedForwardingInsts);
768-
769763
++NumEliminatedInsts;
770764
++NumLoadCopyConvertedToLoadBorrow;
771765
return true;

test/SILOptimizer/semantic-arc-opts.sil

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -437,28 +437,6 @@ bb0(%x : @guaranteed $ClassLet):
437437
return undef : $()
438438
}
439439

440-
// CHECK-LABEL: sil [ossa] @dont_copy_let_properties_with_guaranteed_base_and_forwarding_uses :
441-
// CHECK: ref_element_addr
442-
// CHECK-NEXT: load_borrow
443-
// CHECK-NEXT: unchecked_ref_cast
444-
// CHECK-NEXT: apply
445-
// CHECK-NEXT: end_borrow
446-
// CHECK-NEXT: return
447-
// CHECK: } // end sil function 'dont_copy_let_properties_with_guaranteed_base_and_forwarding_uses'
448-
sil [ossa] @dont_copy_let_properties_with_guaranteed_base_and_forwarding_uses : $@convention(thin) (@guaranteed ClassLet) -> () {
449-
bb0(%x : @guaranteed $ClassLet):
450-
%f = function_ref @black_hole : $@convention(thin) (@guaranteed Klass) -> ()
451-
452-
%p = ref_element_addr %x : $ClassLet, #ClassLet.aLet
453-
%v = load [copy] %p : $*Klass
454-
%c = unchecked_ref_cast %v : $Klass to $Klass
455-
%b = begin_borrow %c : $Klass
456-
apply %f(%b) : $@convention(thin) (@guaranteed Klass) -> ()
457-
end_borrow %b : $Klass
458-
destroy_value %c : $Klass
459-
return undef : $()
460-
}
461-
462440
// CHECK-LABEL: sil [ossa] @dont_copy_let_properties_with_guaranteed_upcast_base
463441
// CHECK: ref_element_addr
464442
// CHECK-NEXT: load_borrow

test/api-digester/stability-stdlib-abi-with-asserts.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
// REQUIRES: swift_stdlib_asserts
33
// RUN: %empty-directory(%t.tmp)
44
// mkdir %t.tmp/module-cache && mkdir %t.tmp/dummy.sdk
5-
// RUN: %api-digester -diagnose-sdk -module Swift -o %t.tmp/changes.txt -module-cache-path %t.tmp/module-cache -sdk %t.tmp/dummy.sdk -abi -avoid-location
5+
// RUN: %api-digester -dump-sdk -module Swift -o %t.tmp/current-stdlib.json -module-cache-path %t.tmp/module-cache -sdk %t.tmp/dummy.sdk -abi -avoid-location
6+
// RUN: %api-digester -diagnose-sdk -input-paths %S/Inputs/stdlib-stable-abi.json -input-paths %t.tmp/current-stdlib.json -abi -o %t.tmp/changes.txt -v
67
// RUN: %clang -E -P -x c %S/Outputs/stability-stdlib-abi.without.asserts.swift.expected -o - > %t.tmp/stability-stdlib-abi.swift.expected
78
// RUN: %clang -E -P -x c %S/Outputs/stability-stdlib-abi.asserts.additional.swift.expected -o - >> %t.tmp/stability-stdlib-abi.swift.expected
89
// RUN: %clang -E -P -x c %t.tmp/stability-stdlib-abi.swift.expected -o - | sed '/^\s*$/d' | sort > %t.tmp/stability-stdlib-abi.swift.expected.sorted
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
// REQUIRES: OS=macosx
22
// RUN: %empty-directory(%t.tmp)
33
// mkdir %t.tmp/module-cache && mkdir %t.tmp/dummy.sdk
4-
// RUN: %api-digester -diagnose-sdk -module Swift -o %t.tmp/changes.txt -module-cache-path %t.tmp/module-cache -sdk %t.tmp/dummy.sdk -avoid-location
4+
// RUN: %api-digester -dump-sdk -module Swift -o %t.tmp/current-stdlib.json -module-cache-path %t.tmp/module-cache -sdk %t.tmp/dummy.sdk -avoid-location
5+
// RUN: %api-digester -diagnose-sdk -input-paths %S/Inputs/stdlib-stable.json -input-paths %t.tmp/current-stdlib.json -o %t.tmp/changes.txt -v
56
// RUN: %clang -E -P -x c %S/Outputs/stability-stdlib-source.swift.expected -o - | sed '/^\s*$/d' | sort > %t.tmp/stability-stdlib-source.swift.expected
67
// RUN: %clang -E -P -x c %t.tmp/changes.txt -o - | sed '/^\s*$/d' | sort > %t.tmp/changes.txt.tmp
78
// RUN: diff -u %t.tmp/stability-stdlib-source.swift.expected %t.tmp/changes.txt.tmp

tools/swift-api-digester/ModuleAnalyzerNodes.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -586,8 +586,8 @@ static StringRef getKeyContent(SDKContext &Ctx, KeyKind Kind) {
586586
SDKNode* SDKNode::constructSDKNode(SDKContext &Ctx,
587587
llvm::yaml::MappingNode *Node) {
588588
static auto GetScalarString = [&](llvm::yaml::Node *N) -> StringRef {
589-
SmallString<64> Buffer;
590-
return Ctx.buffer(cast<llvm::yaml::ScalarNode>(N)->getValue(Buffer));
589+
auto WithQuote = cast<llvm::yaml::ScalarNode>(N)->getRawValue();
590+
return WithQuote.substr(1, WithQuote.size() - 2);
591591
};
592592

593593
static auto getAsInt = [&](llvm::yaml::Node *N) -> int {
@@ -2102,6 +2102,7 @@ static parseJsonEmit(SDKContext &Ctx, StringRef FileName) {
21022102
// previously dumped.
21032103
void SwiftDeclCollector::deSerialize(StringRef Filename) {
21042104
auto Pair = parseJsonEmit(Ctx, Filename);
2105+
OwnedBuffers.push_back(std::move(Pair.first));
21052106
RootNode = std::move(Pair.second);
21062107
}
21072108

tools/swift-api-digester/ModuleAnalyzerNodes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ class SDKContext {
230230
CIs.emplace_back(new CompilerInstance());
231231
return *CIs.back();
232232
}
233+
233234
template<class YAMLNodeTy, typename ...ArgTypes>
234235
void diagnose(YAMLNodeTy node, Diag<ArgTypes...> ID,
235236
typename detail::PassArgument<ArgTypes>::type... args) {
@@ -706,6 +707,7 @@ struct TypeInitInfo {
706707

707708
class SwiftDeclCollector: public VisibleDeclConsumer {
708709
SDKContext &Ctx;
710+
std::vector<std::unique_ptr<llvm::MemoryBuffer>> OwnedBuffers;
709711
SDKNode *RootNode;
710712
llvm::SetVector<Decl*> KnownDecls;
711713
// Collected and sorted after we get all of them.

tools/swift-api-digester/swift-api-digester.cpp

Lines changed: 9 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -234,11 +234,6 @@ static llvm::cl::list<std::string>
234234
PreferInterfaceForModules("use-interface-for-module", llvm::cl::ZeroOrMore,
235235
llvm::cl::desc("Prefer loading these modules via interface"),
236236
llvm::cl::cat(Category));
237-
238-
static llvm::cl::opt<std::string>
239-
BaselineFilePath("baseline-path",
240-
llvm::cl::desc("The path to the Json file that we should use as the baseline"),
241-
llvm::cl::cat(Category));
242237
} // namespace options
243238

244239
namespace {
@@ -2534,77 +2529,6 @@ static bool hasBaselineInput() {
25342529
!options::BaselineFrameworkPaths.empty() || !options::BaselineSDK.empty();
25352530
}
25362531

2537-
enum class ComparisonInputMode: uint8_t {
2538-
BothJson,
2539-
BaselineJson,
2540-
BothLoad,
2541-
};
2542-
2543-
static ComparisonInputMode checkComparisonInputMode() {
2544-
if (options::SDKJsonPaths.size() == 2)
2545-
return ComparisonInputMode::BothJson;
2546-
else if (hasBaselineInput())
2547-
return ComparisonInputMode::BothLoad;
2548-
else
2549-
return ComparisonInputMode::BaselineJson;
2550-
}
2551-
2552-
static SDKNodeRoot *getBaselineFromJson(const char *Main, SDKContext &Ctx) {
2553-
SwiftDeclCollector Collector(Ctx);
2554-
// If the baseline path has been given, honor that.
2555-
if (!options::BaselineFilePath.empty()) {
2556-
Collector.deSerialize(options::BaselineFilePath);
2557-
return Collector.getSDKRoot();
2558-
}
2559-
CompilerInvocation Invok;
2560-
llvm::StringSet<> Modules;
2561-
// We need to call prepareForDump to parse target triple.
2562-
if (prepareForDump(Main, Invok, Modules, true))
2563-
return nullptr;
2564-
2565-
assert(Modules.size() == 1 &&
2566-
"Cannot find builtin baseline for more than one module");
2567-
// The path of the swift-api-digester executable.
2568-
std::string ExePath = llvm::sys::fs::getMainExecutable(Main,
2569-
reinterpret_cast<void *>(&anchorForGetMainExecutable));
2570-
llvm::SmallString<128> BaselinePath(ExePath);
2571-
llvm::sys::path::remove_filename(BaselinePath); // Remove /swift-api-digester
2572-
llvm::sys::path::remove_filename(BaselinePath); // Remove /bin
2573-
llvm::sys::path::append(BaselinePath, "lib", "swift", "FrameworkABIBaseline",
2574-
Modules.begin()->getKey());
2575-
// Look for ABI or API baseline
2576-
if (Ctx.checkingABI())
2577-
llvm::sys::path::append(BaselinePath, "ABI");
2578-
else
2579-
llvm::sys::path::append(BaselinePath, "API");
2580-
// Look for deployment target specific baseline files.
2581-
auto Triple = Invok.getLangOptions().Target;
2582-
if (Triple.isMacCatalystEnvironment())
2583-
llvm::sys::path::append(BaselinePath, "iosmac.json");
2584-
else if (Triple.isMacOSX())
2585-
llvm::sys::path::append(BaselinePath, "macos.json");
2586-
else if (Triple.isiOS())
2587-
llvm::sys::path::append(BaselinePath, "iphoneos.json");
2588-
else if (Triple.isTvOS())
2589-
llvm::sys::path::append(BaselinePath, "appletvos.json");
2590-
else if (Triple.isWatchOS())
2591-
llvm::sys::path::append(BaselinePath, "watchos.json");
2592-
else {
2593-
llvm::errs() << "Unsupported triple target\n";
2594-
exit(1);
2595-
}
2596-
StringRef Path = BaselinePath.str();
2597-
if (!fs::exists(Path)) {
2598-
llvm::errs() << "Baseline at " << Path << " does not exist\n";
2599-
exit(1);
2600-
}
2601-
if (options::Verbose) {
2602-
llvm::errs() << "Using baseline at " << Path << "\n";
2603-
}
2604-
Collector.deSerialize(Path);
2605-
return Collector.getSDKRoot();
2606-
}
2607-
26082532
int main(int argc, char *argv[]) {
26092533
PROGRAM_START(argc, argv);
26102534
INITIALIZE_LLVM();
@@ -2626,40 +2550,33 @@ int main(int argc, char *argv[]) {
26262550
dumpSDKContent(InitInvok, Modules, options::OutputFile, Opts);
26272551
case ActionType::MigratorGen:
26282552
case ActionType::DiagnoseSDKs: {
2629-
ComparisonInputMode Mode = checkComparisonInputMode();
2553+
bool CompareJson = options::SDKJsonPaths.size() == 2;
2554+
if (!CompareJson && !hasBaselineInput()) {
2555+
llvm::errs() << "Only two SDK versions can be compared\n";
2556+
llvm::cl::PrintHelpMessage();
2557+
return 1;
2558+
}
26302559
llvm::StringSet<> protocolWhitelist;
26312560
if (!options::ProtReqWhiteList.empty()) {
26322561
if (readFileLineByLine(options::ProtReqWhiteList, protocolWhitelist))
26332562
return 1;
26342563
}
2635-
if (options::Action == ActionType::MigratorGen) {
2636-
assert(Mode == ComparisonInputMode::BothJson && "Only BothJson mode is supported");
2564+
if (options::Action == ActionType::MigratorGen)
26372565
return generateMigrationScript(options::SDKJsonPaths[0],
26382566
options::SDKJsonPaths[1],
26392567
options::OutputFile, IgnoredUsrs, Opts);
2640-
}
2641-
switch(Mode) {
2642-
case ComparisonInputMode::BothJson: {
2568+
else if (CompareJson)
26432569
return diagnoseModuleChange(options::SDKJsonPaths[0],
26442570
options::SDKJsonPaths[1],
26452571
options::OutputFile, Opts,
26462572
std::move(protocolWhitelist));
2647-
}
2648-
case ComparisonInputMode::BaselineJson: {
2649-
SDKContext Ctx(Opts);
2650-
return diagnoseModuleChange(Ctx, getBaselineFromJson(argv[0], Ctx),
2651-
getSDKRoot(argv[0], Ctx, false),
2652-
options::OutputFile,
2653-
std::move(protocolWhitelist));
2654-
}
2655-
case ComparisonInputMode::BothLoad: {
2573+
else {
26562574
SDKContext Ctx(Opts);
26572575
return diagnoseModuleChange(Ctx, getSDKRoot(argv[0], Ctx, true),
26582576
getSDKRoot(argv[0], Ctx, false),
26592577
options::OutputFile,
26602578
std::move(protocolWhitelist));
26612579
}
2662-
}
26632580
}
26642581
case ActionType::DeserializeSDK:
26652582
case ActionType::DeserializeDiffItems: {

0 commit comments

Comments
 (0)