|
10 | 10 | //
|
11 | 11 | //===----------------------------------------------------------------------===//
|
12 | 12 |
|
13 |
| -#include "MandatoryOptUtils.h" |
| 13 | +#define DEBUG_TYPE "raw-sil-inst-lowering" |
14 | 14 | #include "swift/SIL/SILBuilder.h"
|
15 | 15 | #include "swift/SIL/SILFunction.h"
|
16 | 16 | #include "swift/SIL/SILInstruction.h"
|
17 | 17 | #include "swift/SILOptimizer/PassManager/Passes.h"
|
18 | 18 | #include "swift/SILOptimizer/PassManager/Transforms.h"
|
| 19 | +#include "llvm/ADT/Statistic.h" |
| 20 | + |
| 21 | +STATISTIC(NumAssignRewritten, "Number of assigns rewritten"); |
19 | 22 |
|
20 | 23 | using namespace swift;
|
21 | 24 |
|
| 25 | +/// Emit the sequence that an assign instruction lowers to once we know |
| 26 | +/// if it is an initialization or an assignment. If it is an assignment, |
| 27 | +/// a live-in value can be provided to optimize out the reload. |
| 28 | +static void lowerAssignInstruction(SILBuilderWithScope &B, AssignInst *Inst) { |
| 29 | + LLVM_DEBUG(llvm::dbgs() << " *** Lowering [isInit=" |
| 30 | + << unsigned(Inst->getInitKind()) |
| 31 | + << "]: " << *Inst << "\n"); |
| 32 | + |
| 33 | + ++NumAssignRewritten; |
| 34 | + |
| 35 | + SILValue Src = Inst->getSrc(); |
| 36 | + SILLocation Loc = Inst->getLoc(); |
| 37 | + PartialInitializationKind initKind = Inst->getInitKind(); |
| 38 | + |
| 39 | + // Unknown initKind is considered unprocessed. Just lower it as |
| 40 | + // NotInitialization |
| 41 | + if (initKind == PartialInitializationKind::Unknown) { |
| 42 | + initKind = PartialInitializationKind::IsNotInitialization; |
| 43 | + } |
| 44 | + |
| 45 | + if (initKind == PartialInitializationKind::IsInitialization || |
| 46 | + Inst->getDest()->getType().isTrivial(Inst->getModule())) { |
| 47 | + |
| 48 | + // If this is an initialization, or the storage type is trivial, we |
| 49 | + // can just replace the assignment with a store. |
| 50 | + assert(initKind != PartialInitializationKind::IsReinitialization); |
| 51 | + B.createTrivialStoreOr(Loc, Src, Inst->getDest(), |
| 52 | + StoreOwnershipQualifier::Init); |
| 53 | + Inst->eraseFromParent(); |
| 54 | + return; |
| 55 | + } |
| 56 | + |
| 57 | + if (initKind == PartialInitializationKind::IsReinitialization) { |
| 58 | + // We have a case where a convenience initializer on a class |
| 59 | + // delegates to a factory initializer from a protocol extension. |
| 60 | + // Factory initializers give us a whole new instance, so the existing |
| 61 | + // instance, which has not been initialized and never will be, must be |
| 62 | + // freed using dealloc_partial_ref. |
| 63 | + SILValue Pointer = |
| 64 | + B.createLoad(Loc, Inst->getDest(), LoadOwnershipQualifier::Take); |
| 65 | + B.createStore(Loc, Src, Inst->getDest(), StoreOwnershipQualifier::Init); |
| 66 | + |
| 67 | + auto MetatypeTy = CanMetatypeType::get( |
| 68 | + Inst->getDest()->getType().getASTType(), MetatypeRepresentation::Thick); |
| 69 | + auto SILMetatypeTy = SILType::getPrimitiveObjectType(MetatypeTy); |
| 70 | + SILValue Metatype = B.createValueMetatype(Loc, SILMetatypeTy, Pointer); |
| 71 | + |
| 72 | + B.createDeallocPartialRef(Loc, Pointer, Metatype); |
| 73 | + Inst->eraseFromParent(); |
| 74 | + return; |
| 75 | + } |
| 76 | + |
| 77 | + assert(initKind == PartialInitializationKind::IsNotInitialization); |
| 78 | + // Otherwise, we need to replace the assignment with a store [assign] which |
| 79 | + // lowers to the load/store/release dance. Note that the new value is already |
| 80 | + // considered to be retained (by the semantics of the storage type), |
| 81 | + // and we're transferring that ownership count into the destination. |
| 82 | + |
| 83 | + B.createStore(Inst->getLoc(), Src, Inst->getDest(), |
| 84 | + StoreOwnershipQualifier::Assign); |
| 85 | + Inst->eraseFromParent(); |
| 86 | +} |
| 87 | + |
22 | 88 | /// lowerRawSILOperations - There are a variety of raw-sil instructions like
|
23 | 89 | /// 'assign' that are only used by this pass. Now that definite initialization
|
24 | 90 | /// checking is done, remove them.
|
|
0 commit comments