Skip to content

Commit 3b48b4b

Browse files
authored
Merge pull request #7532 from atrick/silval
2 parents 46f4358 + 9548725 commit 3b48b4b

File tree

8 files changed

+265
-96
lines changed

8 files changed

+265
-96
lines changed

include/swift/SIL/DebugUtils.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@
3636
#ifndef SWIFT_SIL_DEBUGUTILS_H
3737
#define SWIFT_SIL_DEBUGUTILS_H
3838

39-
#include "swift/SIL/SILValue.h"
39+
#include "swift/SIL/SILBasicBlock.h"
40+
#include "swift/SIL/SILInstruction.h"
4041

4142
namespace swift {
4243

lib/SIL/SILInstruction.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,10 @@ bool SILInstruction::mayRelease() const {
864864
case ValueKind::ReleaseValueInst:
865865
return true;
866866

867+
case ValueKind::DestroyValueInst:
868+
assert(!SILModuleConventions(getModule()).useLoweredAddresses());
869+
return true;
870+
867871
case ValueKind::UnconditionalCheckedCastAddrInst: {
868872
// Failing casts with take_always can release.
869873
auto *Cast = cast<UnconditionalCheckedCastAddrInst>(this);

lib/SILOptimizer/Mandatory/AddressLowering.cpp

Lines changed: 45 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
//===----------------------------------------------------------------------===//
1818

1919
#define DEBUG_TYPE "address-lowering"
20+
#include "swift/SIL/DebugUtils.h"
2021
#include "swift/SIL/SILArgument.h"
2122
#include "swift/SIL/SILBuilder.h"
2223
#include "swift/SIL/SILVisitor.h"
@@ -107,11 +108,18 @@ struct AddressLoweringState {
107108
SmallVector<Operand *, 16> indirectOperands;
108109
// All call instruction's with formally indirect result conventions.
109110
SmallVector<SILInstruction *, 16> indirectResults;
111+
// All function-exiting terminators (return or throw instructions).
112+
SmallVector<TermInst *, 8> returnInsts;
110113
// Delete these instructions after performing transformations.
111114
// They must not have any remaining users.
112115
SmallSetVector<SILInstruction *, 16> instsToDelete;
113116

114117
AddressLoweringState(SILFunction *F) : F(F) {}
118+
119+
void markDeadInst(SILInstruction *inst) {
120+
assert(onlyHaveDebugUses(inst));
121+
instsToDelete.insert(inst);
122+
}
115123
};
116124
} // end anonymous namespace
117125

@@ -148,6 +156,9 @@ class OpaqueValueVisitor {
148156
/// to valueStorageMap in RPO.
149157
void OpaqueValueVisitor::mapValueStorage() {
150158
for (auto *BB : postorderInfo.getReversePostOrder()) {
159+
if (BB->getTerminator()->isFunctionExiting())
160+
pass.returnInsts.push_back(BB->getTerminator());
161+
151162
// Opaque function arguments have already been replaced.
152163
if (BB != pass.F->getEntryBlock()) {
153164
for (auto argI = BB->args_begin(), argEnd = BB->args_end();
@@ -220,11 +231,8 @@ namespace {
220231
class OpaqueStorageAllocation {
221232
AddressLoweringState &pass;
222233

223-
SILBuilder allocBuilder;
224-
225234
public:
226-
explicit OpaqueStorageAllocation(AddressLoweringState &pass)
227-
: pass(pass), allocBuilder(*pass.F) {}
235+
explicit OpaqueStorageAllocation(AddressLoweringState &pass) : pass(pass) {}
228236

229237
void allocateOpaqueStorage();
230238

@@ -265,13 +273,6 @@ void OpaqueStorageAllocation::allocateOpaqueStorage() {
265273
// Populate valueStorageMap.
266274
OpaqueValueVisitor(pass).mapValueStorage();
267275

268-
// Find an insertion point for new AllocStack instructions.
269-
SILBasicBlock::iterator insertionPoint = pass.F->begin()->begin();
270-
while (isa<AllocStackInst>(*insertionPoint))
271-
++insertionPoint;
272-
273-
allocBuilder.setInsertionPoint(insertionPoint);
274-
275276
// Create an AllocStack for every opaque value defined in the function.
276277
for (auto &valueStorageI : pass.valueStorageMap)
277278
allocateForValue(valueStorageI.first, valueStorageI.second);
@@ -289,7 +290,7 @@ void OpaqueStorageAllocation::allocateOpaqueStorage() {
289290
/// inserting a temprorary load instruction.
290291
void OpaqueStorageAllocation::replaceFunctionArgs() {
291292
// Insert temporary argument loads at the top of the function.
292-
allocBuilder.setInsertionPoint(pass.F->getEntryBlock()->begin());
293+
SILBuilder argBuilder(pass.F->getEntryBlock()->begin());
293294

294295
auto fnConv = pass.F->getConventions();
295296
unsigned argIdx = fnConv.getSILArgIndexOfFirstParam();
@@ -300,7 +301,7 @@ void OpaqueStorageAllocation::replaceFunctionArgs() {
300301
SILArgument *arg = pass.F->getArgument(argIdx);
301302
SILType addrType = arg->getType().getAddressType();
302303

303-
LoadInst *loadArg = allocBuilder.createLoad(
304+
LoadInst *loadArg = argBuilder.createLoad(
304305
RegularLocation(const_cast<ValueDecl *>(arg->getDecl())),
305306
SILUndef::get(addrType, pass.F->getModule()),
306307
LoadOwnershipQualifier::Unqualified);
@@ -374,14 +375,6 @@ static SILLocation getLocForValue(SILValue value) {
374375
return value->getFunction()->getLocation();
375376
}
376377

377-
/// Create a dealloc_stack instruction.
378-
static DeallocStackInst *
379-
createDeallocStackAfterBlock(SILBasicBlock *deallocBlock,
380-
AllocStackInst *allocInstr) {
381-
SILBuilder deallocBuilder(deallocBlock->getTerminator());
382-
return deallocBuilder.createDeallocStack(allocInstr->getLoc(), allocInstr);
383-
}
384-
385378
/// Allocate storage for a single opaque/resilient value.
386379
void OpaqueStorageAllocation::allocateForValue(SILValue value,
387380
ValueStorage &storage) {
@@ -397,26 +390,25 @@ void OpaqueStorageAllocation::allocateForValue(SILValue value,
397390
return;
398391
}
399392

393+
SILBuilder allocBuilder(pass.F->begin()->begin());
400394
AllocStackInst *allocInstr =
401395
allocBuilder.createAllocStack(getLocForValue(value), value->getType());
402396

403397
storage.storageAddress = allocInstr;
404398

405-
// TODO: insert deallocation at reasonable points.
406-
auto blockI = pass.F->findReturnBB();
407-
if (blockI != pass.F->end())
408-
createDeallocStackAfterBlock(&*blockI, allocInstr);
409-
410-
if (pass.F->findThrowBB() != pass.F->end())
411-
createDeallocStackAfterBlock(&*blockI, allocInstr);
399+
// Insert stack deallocations.
400+
for (TermInst *termInst : pass.returnInsts) {
401+
SILBuilder deallocBuilder(termInst);
402+
deallocBuilder.createDeallocStack(allocInstr->getLoc(), allocInstr);
403+
}
412404
}
413405

414406
/// Deallocate temporary call-site stack storage.
415407
static void insertStackDeallocationAtCall(AllocStackInst *allocInst,
416408
SILInstruction *applyInst) {
417409
switch (applyInst->getKind()) {
418410
case ValueKind::ApplyInst: {
419-
SILBuilder deallocBuilder(applyInst);
411+
SILBuilder deallocBuilder(&*std::next(applyInst->getIterator()));
420412
deallocBuilder.createDeallocStack(allocInst->getLoc(), allocInst);
421413
break;
422414
}
@@ -509,8 +501,8 @@ void OpaqueStorageAllocation::allocateForResults(SILInstruction *origInst) {
509501
switch (origInst->getKind()) {
510502
case ValueKind::ApplyInst:
511503
callInst = callBuilder.createApply(
512-
loc, apply.getCallee(), apply.getSubstCalleeSILType(), apply.getType(),
513-
apply.getSubstitutions(), args,
504+
loc, apply.getCallee(), apply.getSubstCalleeSILType(),
505+
loweredFnConv.getSILResultType(), apply.getSubstitutions(), args,
514506
cast<ApplyInst>(origInst)->isNonThrowing());
515507
break;
516508
case ValueKind::TryApplyInst:
@@ -528,15 +520,15 @@ void OpaqueStorageAllocation::allocateForResults(SILInstruction *origInst) {
528520
// origInst remains in the map but has no users.
529521
}
530522
origInst->replaceAllUsesWith(callInst);
531-
pass.instsToDelete.insert(origInst);
532-
// Load a concrete args, and mark the extract for deletion.
523+
pass.markDeadInst(origInst);
524+
// Load concrete args, and mark the extract for deletion.
533525
for (TupleExtractInst *extract : concreteResults) {
534526
unsigned argIdx = firstResultIdx + extract->getFieldNo();
535527
SILValue arg = args[argIdx];
536528
LoadInst *loadArg = callBuilder.createLoad(
537529
extract->getLoc(), arg, LoadOwnershipQualifier::Unqualified);
538530
extract->replaceAllUsesWith(loadArg);
539-
pass.instsToDelete.insert(extract);
531+
pass.markDeadInst(extract);
540532
}
541533
}
542534

@@ -600,16 +592,12 @@ class AddressOnlyRewriter : SILInstructionVisitor<AddressOnlyRewriter, void> {
600592
B.createCopyAddr(copyInst->getLoc(), srcAddr, destAddr, IsNotTake,
601593
IsInitialization);
602594
}
603-
604-
void visitTupleInst(TupleInst *tupleInst) {
605-
// Tuple elements have their own storage. Tuple instructions are dead.
606-
assert(!pass.valueStorageMap.getStorage(tupleInst).storageAddress);
607-
}
608-
609-
void visitTupleExtractInst(TupleExtractInst *TEI) {
610-
// Tuple element instructions don't require rewrite. They are dead.
611-
llvm_unreachable("Untested.");
612-
return;
595+
596+
void visitDestroyValueInst(DestroyValueInst *destroyInst) {
597+
SILValue src = destroyInst->getOperand();
598+
SILValue addr = pass.valueStorageMap.getStorage(src).storageAddress;
599+
B.createDestroyAddr(destroyInst->getLoc(), addr);
600+
pass.markDeadInst(destroyInst);
613601
}
614602

615603
void visitReturnInst(ReturnInst *returnInst) {
@@ -640,6 +628,17 @@ class AddressOnlyRewriter : SILInstructionVisitor<AddressOnlyRewriter, void> {
640628
auto *tupleInst = B.createTuple(returnInst->getLoc(), emptyTy, {});
641629
returnInst->setOperand(tupleInst);
642630
}
631+
632+
void visitTupleInst(TupleInst *tupleInst) {
633+
// Tuple elements have their own storage. Tuple instructions are dead.
634+
assert(!pass.valueStorageMap.getStorage(tupleInst).storageAddress);
635+
}
636+
637+
void visitTupleExtractInst(TupleExtractInst *extractInst) {
638+
// Tuple element instructions don't require rewrite. They are dead.
639+
llvm_unreachable("Untested.");
640+
return;
641+
}
643642
};
644643
} // end anonymous namespace
645644

@@ -659,6 +658,8 @@ class AddressLowering : public SILModuleTransform {
659658
} // end anonymous namespace
660659

661660
void AddressLowering::runOnFunction(SILFunction *F) {
661+
DEBUG(llvm::dbgs() << "LOWER "; F->dump());
662+
662663
AddressLoweringState pass(F);
663664

664665
// Rewrite function args and insert alloc_stack/dealloc_stack.

test/IRGen/opaque_values_irgen.sil

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ import Builtin
44

55
sil_stage canonical
66

7-
// CHECK: define hidden swiftcc void @irgen_identity(%swift.opaque* noalias nocapture sret, %swift.opaque* noalias nocapture, %swift.type* %T)
7+
// CHECK: define hidden swiftcc void @f010_irgen_identity(%swift.opaque* noalias nocapture sret, %swift.opaque* noalias nocapture, %swift.type* %T)
88
// CHECK: entry:
99
// CHECK-NOT: call
1010
// CHECK: %{{.*}} = call %swift.opaque* %initializeWithTake(%swift.opaque* %0, %swift.opaque* %1, %swift.type* %T)
1111
// CHECK-NOT: call
1212
// CHECK: ret void
13-
sil hidden @irgen_identity : $@convention(thin) <T> (@in T) -> @out T {
13+
sil hidden @f010_irgen_identity : $@convention(thin) <T> (@in T) -> @out T {
1414
bb0(%0 : $T):
1515
return %0 : $T
1616
}

0 commit comments

Comments
 (0)