static bool isLessThan(SILValue Start, SILValue End) { auto S = dyn_cast<IntegerLiteralInst>(Start.getDef()); if (!S) return false; auto E = dyn_cast<IntegerLiteralInst>(End.getDef()); if (!E) return false; return S->getValue().slt(E->getValue()); }
// Get the pair of array and index. Because we want to disambiguate between the // two types of check bounds checks merge in the type into the lower bit of one // of the addresse index. static std::pair<ValueBase *, ArrayAccessDesc> getArrayIndexPair(SILValue Array, SILValue ArrayIndex, ArrayCallKind K) { assert((K == ArrayCallKind::kCheckIndex || K == ArrayCallKind::kCheckSubscript) && "Must be a bounds check call"); return std::make_pair( Array.getDef(), ArrayAccessDesc(ArrayIndex.getDef(), K == ArrayCallKind::kCheckIndex)); }
/// Two allocations of a mutable array struct cannot reference the same /// storage after modification. So we can treat them as not aliasing for the /// purpose of bound checking. The change would only be tracked through one of /// the allocations. static bool isIdentifiedUnderlyingArrayObject(SILValue V) { // Allocations are safe. if (isa<AllocationInst>(V.getDef())) return true; // Function arguments are safe. if (auto Arg = dyn_cast<SILArgument>(V.getDef())) return Arg->isFunctionArg(); return false; }
AliasKeyTy AliasAnalysis::toAliasKey(SILValue V1, SILValue V2, SILType Type1, SILType Type2) { size_t idx1 = AliasValueBaseToIndex.getIndex(V1.getDef()); assert(idx1 != std::numeric_limits<size_t>::max() && "~0 index reserved for empty/tombstone keys"); size_t idx2 = AliasValueBaseToIndex.getIndex(V2.getDef()); assert(idx2 != std::numeric_limits<size_t>::max() && "~0 index reserved for empty/tombstone keys"); void *t1 = Type1.getOpaqueValue(); void *t2 = Type2.getOpaqueValue(); return {idx1, idx2, t1, t2}; }
/// Check if the root value for Value that comes /// along the path from DomBB is equivalent to the /// DomCondition. SILValue CheckedCastBrJumpThreading::isArgValueEquivalentToCondition( SILValue Value, SILBasicBlock *DomBB, SILValue DomValue, DominanceInfo *DT) { SmallPtrSet<ValueBase *, 16> SeenValues; DomValue = DomValue.stripClassCasts(); while (true) { Value = Value.stripClassCasts(); if (Value == DomValue) return Value; // We know how to propagate through BBArgs only. auto *V = dyn_cast<SILArgument>(Value); if (!V) return SILValue(); // Have we visited this BB already? if (!SeenValues.insert(Value.getDef()).second) return SILValue(); if (SeenValues.size() > 10) return SILValue(); SmallVector<SILValue, 4> IncomingValues; if (!V->getIncomingValues(IncomingValues) || IncomingValues.empty()) return SILValue(); ValueBase *Def = nullptr; for (auto IncomingValue : IncomingValues) { // Each incoming value should be either from a block // dominated by DomBB or it should be the value used in // condition in DomBB Value = IncomingValue.stripClassCasts(); if (Value == DomValue) continue; // Values should be the same if (!Def) Def = Value.getDef(); if (Def != Value.getDef()) return SILValue(); if (!DT->dominates(DomBB, Value.getDef()->getParentBB())) return SILValue(); // OK, this value is a potential candidate } Value = IncomingValues[0]; } }
bool swift:: mayGuaranteedUseValue(SILInstruction *User, SILValue Ptr, AliasAnalysis *AA) { // Only full apply sites can require a guaranteed lifetime. If we don't have // one, bail. if (!isa<FullApplySite>(User)) return false; FullApplySite FAS(User); // Ok, we have a full apply site. If the apply has no arguments, we don't need // to worry about any guaranteed parameters. if (!FAS.getNumArguments()) return false; // Ok, we have an apply site with arguments. Look at the function type and // iterate through the function parameters. If any of the parameters are // guaranteed, attempt to prove that the passed in parameter cannot alias // Ptr. If we fail, return true. CanSILFunctionType FType = FAS.getSubstCalleeType(); auto Params = FType->getParameters(); for (unsigned i : indices(Params)) { if (!Params[i].isGuaranteed()) continue; SILValue Op = FAS.getArgument(i); for (int i = 0, e = Ptr->getNumTypes(); i < e; i++) if (!AA->isNoAlias(Op, SILValue(Ptr.getDef(), i))) return true; } // Ok, we were able to prove that all arguments to the apply that were // guaranteed do not alias Ptr. Return false. return false; }
static SILValue stripRCIdentityPreservingInsts(SILValue V) { // First strip off RC identity preserving casts. if (isRCIdentityPreservingCast(V->getKind())) return cast<SILInstruction>(V.getDef())->getOperand(0); // Then if we have a struct_extract that is extracting a non-trivial member // from a struct with no other non-trivial members, a ref count operation on // the struct is equivalent to a ref count operation on the extracted // member. Strip off the extract. if (auto *SEI = dyn_cast<StructExtractInst>(V)) if (SEI->isFieldOnlyNonTrivialField()) return SEI->getOperand(); // If we have a struct instruction with only one non-trivial stored field, the // only reference count that can be modified is the non-trivial field. Return // the non-trivial field. if (auto *SI = dyn_cast<StructInst>(V)) if (SILValue NewValue = SI->getUniqueNonTrivialFieldValue()) return NewValue; // If we have an unchecked_enum_data, strip off the unchecked_enum_data. if (auto *UEDI = dyn_cast<UncheckedEnumDataInst>(V)) return UEDI->getOperand(); // If we have an enum instruction with a payload, strip off the enum to // expose the enum's payload. if (auto *EI = dyn_cast<EnumInst>(V)) if (EI->hasOperand()) return EI->getOperand(); // If we have a tuple_extract that is extracting the only non trivial member // of a tuple, a retain_value on the tuple is equivalent to a retain_value on // the extracted value. if (auto *TEI = dyn_cast<TupleExtractInst>(V)) if (TEI->isEltOnlyNonTrivialElt()) return TEI->getOperand(); // If we are forming a tuple and the tuple only has one element with reference // semantics, a retain_value on the tuple is equivalent to a retain value on // the tuple operand. if (auto *TI = dyn_cast<TupleInst>(V)) if (SILValue NewValue = TI->getUniqueNonTrivialElt()) return NewValue; // Any SILArgument with a single predecessor from a "phi" perspective is // dead. In such a case, the SILArgument must be rc-identical. // // This is the easy case. The difficult case is when you have an argument with // /multiple/ predecessors. // // We do not need to insert this SILArgument into the visited SILArgument set // since we will only visit it twice if we go around a back edge due to a // different SILArgument that is actually being used for its phi node like // purposes. if (auto *A = dyn_cast<SILArgument>(V)) if (SILValue Result = A->getSingleIncomingValue()) return Result; return SILValue(); }
static bool canApplyDecrementRefCount(OperandValueArrayRef Ops, SILValue Ptr, AliasAnalysis *AA) { // Ok, this apply *MAY* decrement ref counts. Now our strategy is to attempt // to use properties of the pointer, the function's arguments, and the // function itself to prove that the pointer cannot have its ref count // affected by the applied function. // TODO: Put in function property check section here when we get access to // such information. // First make sure that the underlying object of ptr is a local object which // does not escape. This prevents the apply from indirectly via the global // affecting the reference count of the pointer. if (!isNonEscapingLocalObject(getUnderlyingObject(Ptr))) return true; // Now that we know that the function can not affect the pointer indirectly, // make sure that the apply can not affect the pointer directly via the // applies arguments by proving that the pointer can not alias any of the // functions arguments. for (auto Op : Ops) { for (int i = 0, e = Ptr->getNumTypes(); i < e; i++) { if (!AA->isNoAlias(Op, SILValue(Ptr.getDef(), i))) return true; } } // Success! The apply inst can not affect the reference count of ptr! return false; }
static bool canHoistArrayArgument(ApplyInst *SemanticsCall, SILValue Arr, SILInstruction *InsertBefore, DominanceInfo *DT) { // We only know how to hoist inout, owned or guaranteed parameters. auto Convention = getSelfParameterConvention(SemanticsCall); if (Convention != ParameterConvention::Indirect_Inout && Convention != ParameterConvention::Direct_Owned && Convention != ParameterConvention::Direct_Guaranteed) return false; auto *SelfVal = Arr.getDef(); auto *SelfBB = SelfVal->getParentBB(); if (DT->dominates(SelfBB, InsertBefore->getParent())) return true; if (auto LI = dyn_cast<LoadInst>(SelfVal)) { // Are we loading a value from an address in a struct defined at a point // dominating the hoist point. auto Val = LI->getOperand().getDef(); bool DoesNotDominate; StructElementAddrInst *SEI; while ((DoesNotDominate = !DT->dominates(Val->getParentBB(), InsertBefore->getParent())) && (SEI = dyn_cast<StructElementAddrInst>(Val))) Val = SEI->getOperand().getDef(); return DoesNotDominate == false; } return false; }
SILValue SILValue::stripIndexingInsts() { SILValue V = *this; while (true) { if (!isa<IndexingInst>(V.getDef())) return V; V = cast<IndexingInst>(V)->getBase(); } }
static void mapOperands(SILInstruction *I, const llvm::DenseMap<ValueBase *, SILValue> &ValueMap) { for (auto &Opd : I->getAllOperands()) { SILValue OrigVal = Opd.get(); ValueBase *OrigDef = OrigVal.getDef(); auto Found = ValueMap.find(OrigDef); if (Found != ValueMap.end()) { SILValue MappedVal = Found->second; unsigned ResultIdx = OrigVal.getResultNumber(); // All mapped instructions have their result number set to zero. Except // for arguments that we followed along one edge to their incoming value // on that edge. if (isa<SILArgument>(OrigDef)) ResultIdx = MappedVal.getResultNumber(); Opd.set(SILValue(MappedVal.getDef(), ResultIdx)); } } }
/// Analyse one potential induction variable starting at Arg. InductionInfo *analyseIndVar(SILArgument *HeaderVal, BuiltinInst *Inc, IntegerLiteralInst *IncVal) { if (IncVal->getValue() != 1) return nullptr; // Find the start value. auto *PreheaderTerm = dyn_cast<BranchInst>(Preheader->getTerminator()); if (!PreheaderTerm) return nullptr; auto Start = PreheaderTerm->getArg(HeaderVal->getIndex()); // Find the exit condition. auto CondBr = dyn_cast<CondBranchInst>(ExitingBlk->getTerminator()); if (!CondBr) return nullptr; if (ExitBlk == CondBr->getFalseBB()) return nullptr; assert(ExitBlk == CondBr->getTrueBB() && "The loop's exiting blocks terminator must exit"); auto Cond = CondBr->getCondition(); SILValue End; // Look for a compare of induction variable + 1. // TODO: obviously we need to handle many more patterns. if (!match(Cond, m_ApplyInst(BuiltinValueKind::ICMP_EQ, m_TupleExtractInst(m_Specific(Inc), 0), m_SILValue(End))) && !match(Cond, m_ApplyInst(BuiltinValueKind::ICMP_EQ, m_SILValue(End), m_TupleExtractInst(m_Specific(Inc), 0)))) { DEBUG(llvm::dbgs() << " found no exit condition\n"); return nullptr; } // Make sure our end value is loop invariant. if (!dominates(DT, End, Preheader)) return nullptr; DEBUG(llvm::dbgs() << " found an induction variable (ICMP_EQ): " << *HeaderVal << " start: " << *Start.getDef() << " end: " << *End.getDef()); // Check whether the addition is overflow checked by a cond_fail or whether // code in the preheader's predecessor ensures that we won't overflow. bool IsRangeChecked = false; if (!isOverflowChecked(Inc)) { IsRangeChecked = isRangeChecked(Start, End, Preheader, DT); if (!IsRangeChecked) return nullptr; } return new (Allocator.Allocate()) InductionInfo( HeaderVal, Inc, Start, End, BuiltinValueKind::ICMP_EQ, IsRangeChecked); }
static SILValue getArrayStructPointer(ArrayCallKind K, SILValue Array) { assert(K != ArrayCallKind::kNone); if (K < ArrayCallKind::kMakeMutable) { auto LI = dyn_cast<LoadInst>(Array.getDef()); if (!LI) { return Array; } return LI->getOperand(); } return Array; }
/// Copy the array load to the insert point. static SILValue copyArrayLoad(SILValue ArrayStructValue, SILInstruction *InsertBefore, DominanceInfo *DT) { if (DT->dominates(ArrayStructValue.getDef()->getParentBB(), InsertBefore->getParent())) return ArrayStructValue; auto *LI = cast<LoadInst>(ArrayStructValue.getDef()); // Recursively move struct_element_addr. auto *Val = LI->getOperand().getDef(); auto *InsertPt = InsertBefore; while (!DT->dominates(Val->getParentBB(), InsertBefore->getParent())) { auto *Inst = cast<StructElementAddrInst>(Val); Inst->moveBefore(InsertPt); Val = Inst->getOperand().getDef(); InsertPt = Inst; } return SILValue(LI->clone(InsertBefore), 0); }
// Walk backwards in BB looking for the last use of a given // value, and add it to the set of release points. static bool addLastUse(SILValue V, SILBasicBlock *BB, ReleaseTracker &Tracker) { for (auto I = BB->rbegin(); I != BB->rend(); ++I) { for (auto &Op : I->getAllOperands()) if (Op.get().getDef() == V.getDef()) { Tracker.trackLastRelease(&*I); return true; } } llvm_unreachable("BB is expected to have a use of a closure"); return false; }
bool swift::mayUseValue(SILInstruction *User, SILValue Ptr, AliasAnalysis *AA) { // If Inst is an instruction that we know can never use values with reference // semantics, return true. if (canNeverUseValues(User)) return false; // If the user is a load or a store and we can prove that it does not access // the object then return true. // Notice that we need to check all of the values of the object. if (isa<StoreInst>(User)) { for (int i = 0, e = Ptr->getNumTypes(); i < e; i++) { if (AA->mayWriteToMemory(User, SILValue(Ptr.getDef(), i))) return true; } return false; } if (isa<LoadInst>(User) ) { for (int i = 0, e = Ptr->getNumTypes(); i < e; i++) { if (AA->mayReadFromMemory(User, SILValue(Ptr.getDef(), i))) return true; } return false; } // If we have a terminator instruction, see if it can use ptr. This currently // means that we first show that TI cannot indirectly use Ptr and then use // alias analysis on the arguments. if (auto *TI = dyn_cast<TermInst>(User)) return canTerminatorUseValue(TI, Ptr, AA); // TODO: If we add in alias analysis support here for apply inst, we will need // to check that the pointer does not escape. // Otherwise, assume that Inst can use Target. return true; }
/// Given an address defined by 'Def', find the object root and all direct uses, /// not including: /// - 'Def' itself /// - Transitive uses of 'Def' (listed elsewhere in DestUserInsts) /// /// If the returned root is not 'Def' itself, then 'Def' must be an address /// projection that can be trivially rematerialized with the root as its /// operand. static ValueBase * findAddressRootAndUsers(ValueBase *Def, SmallPtrSetImpl<SILInstruction*> &RootUserInsts) { if (isa<InitEnumDataAddrInst>(Def) || isa<InitExistentialAddrInst>(Def)) { SILValue InitRoot = cast<SILInstruction>(Def)->getOperand(0); for (auto *Use : InitRoot.getUses()) { auto *UserInst = Use->getUser(); if (UserInst == Def) continue; RootUserInsts.insert(UserInst); } return InitRoot.getDef(); } return Def; }
SILValue SILValue::stripValueProjections() { SILValue V = *this; while (true) { V = stripSinglePredecessorArgs(V); switch (V->getKind()) { case ValueKind::StructExtractInst: case ValueKind::TupleExtractInst: V = cast<SILInstruction>(V.getDef())->getOperand(0); continue; default: return V; } } }
SILValue SILValue::stripCasts() { SILValue V = *this; while (true) { V = stripSinglePredecessorArgs(V); auto K = V->getKind(); if (isRCIdentityPreservingCast(K) || K == ValueKind::UncheckedTrivialBitCastInst || K == ValueKind::MarkDependenceInst) { V = cast<SILInstruction>(V.getDef())->getOperand(0); continue; } return V; } }
/// Look for checks that guarantee that start is less than or equal to end. static bool isSignedLessEqual(SILValue Start, SILValue End, SILBasicBlock &BB) { // If we have an inclusive range "low...up" the loop exit count will be // "up + 1" but the overflow check is on "up". SILValue PreInclusiveEnd; if (!match( End.getDef(), m_TupleExtractInst(m_ApplyInst(BuiltinValueKind::SAddOver, m_SILValue(PreInclusiveEnd), m_One()), 0))) PreInclusiveEnd = SILValue(); bool IsPreInclusiveEndLEQ = false; bool IsPreInclusiveEndGTEnd = false; for (auto &Inst : BB) if (auto CF = dyn_cast<CondFailInst>(&Inst)) { // Try to match a cond_fail on "XOR , (SLE Start, End), 1". if (match(CF->getOperand().getDef(), m_ApplyInst(BuiltinValueKind::Xor, m_ApplyInst(BuiltinValueKind::ICMP_SLE, m_Specific(Start.getDef()), m_Specific(End.getDef())), m_One()))) return true; // Inclusive ranges will have a check on the upper value (before adding // one). if (PreInclusiveEnd) { if (match(CF->getOperand().getDef(), m_ApplyInst(BuiltinValueKind::Xor, m_ApplyInst(BuiltinValueKind::ICMP_SLE, m_Specific(Start.getDef()), m_Specific(PreInclusiveEnd.getDef())), m_One()))) IsPreInclusiveEndLEQ = true; if (match(CF->getOperand().getDef(), m_ApplyInst(BuiltinValueKind::Xor, m_ApplyInst(BuiltinValueKind::ICMP_SGT, m_Specific(End.getDef()), m_Specific(PreInclusiveEnd.getDef())), m_One()))) IsPreInclusiveEndGTEnd = true; if (IsPreInclusiveEndLEQ && IsPreInclusiveEndGTEnd) return true; } } return false; }
SILValue SILValue::stripAddressProjections() { SILValue V = *this; while (true) { V = stripSinglePredecessorArgs(V); switch (V->getKind()) { case ValueKind::StructElementAddrInst: case ValueKind::TupleElementAddrInst: case ValueKind::RefElementAddrInst: case ValueKind::UncheckedTakeEnumDataAddrInst: V = cast<SILInstruction>(V.getDef())->getOperand(0); continue; default: return V; } } }
SILValue ConstantTracker::scanProjections(SILValue addr, SmallVectorImpl<Projection> *Result) { for (;;) { if (Projection::isAddrProjection(addr)) { SILInstruction *I = cast<SILInstruction>(addr.getDef()); if (Result) { Optional<Projection> P = Projection::addressProjectionForInstruction(I); Result->push_back(P.getValue()); } addr = I->getOperand(0); continue; } if (SILValue param = getParam(addr)) { // Go to the caller. addr = param; continue; } // Return the base address = the first address which is not a projection. return addr; } }
SILInstruction *optimizeBitOp(BuiltinInst *BI, CombineFunc combine, NeutralFunc isNeutral, ZeroFunc isZero, SILBuilder &Builder, SILCombiner *C) { SILValue firstOp; APInt bits; if (!getBitOpArgs(BI, firstOp, bits)) return nullptr; // Combine all bits of consecutive bit operations, e.g. ((op & c1) & c2) & c3 SILValue op = firstOp; BuiltinInst *Prev; APInt prevBits; while ((Prev = dyn_cast<BuiltinInst>(op)) && Prev->getBuiltinInfo().ID == BI->getBuiltinInfo().ID && getBitOpArgs(Prev, op, prevBits)) { combine(bits, prevBits); } if (isNeutral(bits)) // The bit operation has no effect, e.g. x | 0 -> x return C->replaceInstUsesWith(*BI, op.getDef()); if (isZero(bits)) // The bit operation yields to a constant, e.g. x & 0 -> 0 return Builder.createIntegerLiteral(BI->getLoc(), BI->getType(), bits); if (op != firstOp) { // We combined multiple bit operations to a single one, // e.g. (x & c1) & c2 -> x & (c1 & c2) auto *newLI = Builder.createIntegerLiteral(BI->getLoc(), BI->getType(), bits); return Builder.createBuiltin(BI->getLoc(), BI->getName(), BI->getType(), BI->getSubstitutions(), { op, newLI }); } return nullptr; }
/// Like ValueIsPHI but also check if the PHI has no source /// operands, i.e., it was just added. static SILArgument *ValueIsNewPHI(SILValue Val, SILSSAUpdater *Updater) { SILArgument *PHI = ValueIsPHI(Val, Updater); if (PHI) { auto *PhiBB = PHI->getParent(); size_t PhiIdx = PHI->getIndex(); // If all predecessor edges are 'not set' this is a new phi. for (auto *PredBB : PhiBB->getPreds()) { OperandValueArrayRef Edges = getEdgeValuesForTerminator(PredBB->getTerminator(), PhiBB); assert(PhiIdx < Edges.size() && "Not enough edges!"); SILValue V = Edges[PhiIdx]; // Check for the 'not set' sentinel. if (V.getDef() != Updater->PHISentinel.get()) return nullptr; } return PHI; } return nullptr; }
/// Compute the subelement number indicated by the specified pointer (which is /// derived from the root by a series of tuple/struct element addresses) by /// treating the type as a linearized namespace with sequential elements. For /// example, given: /// /// root = alloc { a: { c: i64, d: i64 }, b: (i64, i64) } /// tmp1 = struct_element_addr root, 1 /// tmp2 = tuple_element_addr tmp1, 0 /// /// This will return a subelement number of 2. /// /// If this pointer is to within a existential projection, it returns ~0U. /// static unsigned computeSubelement(SILValue Pointer, SILInstruction *RootInst) { unsigned SubEltNumber = 0; SILModule &M = RootInst->getModule(); while (1) { // If we got to the root, we're done. if (RootInst == Pointer.getDef()) return SubEltNumber; auto *Inst = cast<SILInstruction>(Pointer); if (auto *TEAI = dyn_cast<TupleElementAddrInst>(Inst)) { SILType TT = TEAI->getOperand().getType(); // Keep track of what subelement is being referenced. for (unsigned i = 0, e = TEAI->getFieldNo(); i != e; ++i) { SubEltNumber += getNumSubElements(TT.getTupleElementType(i), M); } Pointer = TEAI->getOperand(); } else if (auto *SEAI = dyn_cast<StructElementAddrInst>(Inst)) { SILType ST = SEAI->getOperand().getType(); // Keep track of what subelement is being referenced. StructDecl *SD = SEAI->getStructDecl(); for (auto *D : SD->getStoredProperties()) { if (D == SEAI->getField()) break; SubEltNumber += getNumSubElements(ST.getFieldType(D, M), M); } Pointer = SEAI->getOperand(); } else { assert((isa<InitExistentialAddrInst>(Inst) || isa<InjectEnumAddrInst>(Inst))&& "Unknown access path instruction"); // Cannot promote loads and stores from within an existential projection. return ~0U; } } }
/// Analyse one instruction wrt. the instructions we have seen so far. void analyseInstruction(SILInstruction *Inst) { SILValue Array; ArrayCallKind K; auto BoundsEffect = mayChangeArraySize(Inst, K, Array, ReleaseSafeArrayReferences, RCIA); if (BoundsEffect == ArrayBoundsEffect::kMayChangeAny) { DEBUG(llvm::dbgs() << " no safe because kMayChangeAny " << *Inst); allArraysInMemoryAreUnsafe = true; // No need to store specific arrays in this case. UnsafeArrays.clear(); return; } assert(Array || K == ArrayCallKind::kNone && "Need to have an array for array semantic functions"); // We need to make sure that the array container is not aliased in ways // that we don't understand. if (Array && !isIdentifiedUnderlyingArrayObject(Array)) { DEBUG(llvm::dbgs() << " not safe because of not identified underlying object " << *Array.getDef() << " in " << *Inst); allArraysInMemoryAreUnsafe = true; // No need to store specific arrays in this case. UnsafeArrays.clear(); return; } if (BoundsEffect == ArrayBoundsEffect::kMayChangeArg) { UnsafeArrays.insert(Array); return; } assert(BoundsEffect == ArrayBoundsEffect::kNone); }
/// \brief Removes instructions that create the callee value if they are no /// longer necessary after inlining. static void cleanupCalleeValue(SILValue CalleeValue, ArrayRef<SILValue> CaptureArgs, ArrayRef<SILValue> FullArgs) { SmallVector<SILInstruction*, 16> InstsToDelete; for (SILValue V : FullArgs) { if (SILInstruction *I = dyn_cast<SILInstruction>(V)) if (I != CalleeValue.getDef() && isInstructionTriviallyDead(I)) InstsToDelete.push_back(I); } recursivelyDeleteTriviallyDeadInstructions(InstsToDelete, true); // Handle the case where the callee of the apply is a load instruction. if (LoadInst *LI = dyn_cast<LoadInst>(CalleeValue)) { assert(CalleeValue.getResultNumber() == 0); SILInstruction *ABI = dyn_cast<AllocBoxInst>(LI->getOperand()); assert(ABI && LI->getOperand().getResultNumber() == 1); // The load instruction must have no more uses left to erase it. if (!LI->use_empty()) return; LI->eraseFromParent(); // Look through uses of the alloc box the load is loading from to find up to // one store and up to one strong release. StoreInst *SI = nullptr; StrongReleaseInst *SRI = nullptr; for (auto UI = ABI->use_begin(), UE = ABI->use_end(); UI != UE; ++UI) { if (SI == nullptr && isa<StoreInst>(UI.getUser())) { SI = cast<StoreInst>(UI.getUser()); assert(SI->getDest() == SILValue(ABI, 1)); } else if (SRI == nullptr && isa<StrongReleaseInst>(UI.getUser())) { SRI = cast<StrongReleaseInst>(UI.getUser()); assert(SRI->getOperand() == SILValue(ABI, 0)); } else return; } // If we found a store, record its source and erase it. if (SI) { CalleeValue = SI->getSrc(); SI->eraseFromParent(); } else { CalleeValue = SILValue(); } // If we found a strong release, replace it with a strong release of the // source of the store and erase it. if (SRI) { if (CalleeValue.isValid()) SILBuilderWithScope(SRI) .emitStrongReleaseAndFold(SRI->getLoc(), CalleeValue); SRI->eraseFromParent(); } assert(ABI->use_empty()); ABI->eraseFromParent(); if (!CalleeValue.isValid()) return; } if (auto *PAI = dyn_cast<PartialApplyInst>(CalleeValue)) { assert(CalleeValue.getResultNumber() == 0); SILValue Callee = PAI->getCallee(); if (!tryDeleteDeadClosure(PAI)) return; CalleeValue = Callee; } if (auto *TTTFI = dyn_cast<ThinToThickFunctionInst>(CalleeValue)) { assert(CalleeValue.getResultNumber() == 0); SILValue Callee = TTTFI->getCallee(); if (!tryDeleteDeadClosure(TTTFI)) return; CalleeValue = Callee; } if (FunctionRefInst *FRI = dyn_cast<FunctionRefInst>(CalleeValue)) { assert(CalleeValue.getResultNumber() == 0); if (!FRI->use_empty()) return; FRI->eraseFromParent(); } }
/// \brief Devirtualize an apply of a class method. /// /// \p AI is the apply to devirtualize. /// \p ClassOrMetatype is a class value or metatype value that is the /// self argument of the apply we will devirtualize. /// return the result value of the new ApplyInst if created one or null. DevirtualizationResult swift::devirtualizeClassMethod(FullApplySite AI, SILValue ClassOrMetatype) { DEBUG(llvm::dbgs() << " Trying to devirtualize : " << *AI.getInstruction()); SILModule &Mod = AI.getModule(); auto *CMI = cast<ClassMethodInst>(AI.getCallee()); auto ClassOrMetatypeType = ClassOrMetatype.getType(); auto *F = getTargetClassMethod(Mod, ClassOrMetatypeType, CMI->getMember()); CanSILFunctionType GenCalleeType = F->getLoweredFunctionType(); auto Subs = getSubstitutionsForCallee(Mod, GenCalleeType, ClassOrMetatypeType, AI); CanSILFunctionType SubstCalleeType = GenCalleeType; if (GenCalleeType->isPolymorphic()) SubstCalleeType = GenCalleeType->substGenericArgs(Mod, Mod.getSwiftModule(), Subs); SILBuilderWithScope B(AI.getInstruction()); FunctionRefInst *FRI = B.createFunctionRef(AI.getLoc(), F); // Create the argument list for the new apply, casting when needed // in order to handle covariant indirect return types and // contravariant argument types. llvm::SmallVector<SILValue, 8> NewArgs; auto Args = AI.getArguments(); auto ParamTypes = SubstCalleeType->getParameterSILTypes(); for (unsigned i = 0, e = Args.size() - 1; i != e; ++i) NewArgs.push_back(castValueToABICompatibleType(&B, AI.getLoc(), Args[i], Args[i].getType(), ParamTypes[i]).getValue()); // Add the self argument, upcasting if required because we're // calling a base class's method. auto SelfParamTy = SubstCalleeType->getSelfParameter().getSILType(); NewArgs.push_back(castValueToABICompatibleType(&B, AI.getLoc(), ClassOrMetatype, ClassOrMetatypeType, SelfParamTy).getValue()); // If we have a direct return type, make sure we use the subst callee return // type. If we have an indirect return type, AI's return type of the empty // tuple should be ok. SILType ResultTy = AI.getType(); if (!SubstCalleeType->hasIndirectResult()) { ResultTy = SubstCalleeType->getSILResult(); } SILType SubstCalleeSILType = SILType::getPrimitiveObjectType(SubstCalleeType); FullApplySite NewAI; SILBasicBlock *ResultBB = nullptr; SILBasicBlock *NormalBB = nullptr; SILValue ResultValue; bool ResultCastRequired = false; SmallVector<Operand *, 4> OriginalResultUses; if (!isa<TryApplyInst>(AI)) { NewAI = B.createApply(AI.getLoc(), FRI, SubstCalleeSILType, ResultTy, Subs, NewArgs, cast<ApplyInst>(AI)->isNonThrowing()); ResultValue = SILValue(NewAI.getInstruction(), 0); } else { auto *TAI = cast<TryApplyInst>(AI); // Create new normal and error BBs only if: // - re-using a BB would create a critical edge // - or, the result of the new apply would be of different // type than the argument of the original normal BB. if (TAI->getNormalBB()->getSinglePredecessor()) ResultBB = TAI->getNormalBB(); else { ResultBB = B.getFunction().createBasicBlock(); ResultBB->createBBArg(ResultTy); } NormalBB = TAI->getNormalBB(); SILBasicBlock *ErrorBB = nullptr; if (TAI->getErrorBB()->getSinglePredecessor()) ErrorBB = TAI->getErrorBB(); else { ErrorBB = B.getFunction().createBasicBlock(); ErrorBB->createBBArg(TAI->getErrorBB()->getBBArg(0)->getType()); } NewAI = B.createTryApply(AI.getLoc(), FRI, SubstCalleeSILType, Subs, NewArgs, ResultBB, ErrorBB); if (ErrorBB != TAI->getErrorBB()) { B.setInsertionPoint(ErrorBB); B.createBranch(TAI->getLoc(), TAI->getErrorBB(), {ErrorBB->getBBArg(0)}); } // Does the result value need to be casted? ResultCastRequired = ResultTy != NormalBB->getBBArg(0)->getType(); if (ResultBB != NormalBB) B.setInsertionPoint(ResultBB); else if (ResultCastRequired) { B.setInsertionPoint(NormalBB->begin()); // Collect all uses, before casting. for (auto *Use : NormalBB->getBBArg(0)->getUses()) { OriginalResultUses.push_back(Use); } NormalBB->getBBArg(0)->replaceAllUsesWith(SILUndef::get(AI.getType(), Mod)); NormalBB->replaceBBArg(0, ResultTy, nullptr); } // The result value is passed as a parameter to the normal block. ResultValue = ResultBB->getBBArg(0); } // Check if any casting is required for the return value. ResultValue = castValueToABICompatibleType(&B, NewAI.getLoc(), ResultValue, ResultTy, AI.getType()).getValue(); DEBUG(llvm::dbgs() << " SUCCESS: " << F->getName() << "\n"); NumClassDevirt++; if (NormalBB) { if (NormalBB != ResultBB) { // If artificial normal BB was introduced, branch // to the original normal BB. B.createBranch(NewAI.getLoc(), NormalBB, { ResultValue }); } else if (ResultCastRequired) { // Update all original uses by the new value. for(auto *Use: OriginalResultUses) { Use->set(ResultValue); } } return std::make_pair(NewAI.getInstruction(), NewAI); } // We need to return a pair of values here: // - the first one is the actual result of the devirtualized call, possibly // casted into an appropriate type. This SILValue may be a BB arg, if it // was a cast between optional types. // - the second one is the new apply site. return std::make_pair(ResultValue.getDef(), NewAI); }
/// The main AA entry point. Performs various analyses on V1, V2 in an attempt /// to disambiguate the two values. AliasResult AliasAnalysis::aliasInner(SILValue V1, SILValue V2, SILType TBAAType1, SILType TBAAType2) { #ifndef NDEBUG // If alias analysis is disabled, always return may alias. if (!shouldRunAA()) return AliasResult::MayAlias; #endif // If the two values equal, quickly return must alias. if (isSameValueOrGlobal(V1, V2)) return AliasResult::MustAlias; DEBUG(llvm::dbgs() << "ALIAS ANALYSIS:\n V1: " << *V1.getDef() << " V2: " << *V2.getDef()); // Pass in both the TBAA types so we can perform typed access TBAA and the // actual types of V1, V2 so we can perform class based TBAA. if (!typesMayAlias(TBAAType1, TBAAType2)) return AliasResult::NoAlias; #ifndef NDEBUG if (!shouldRunBasicAA()) return AliasResult::MayAlias; #endif // Strip off any casts on V1, V2. V1 = V1.stripCasts(); V2 = V2.stripCasts(); DEBUG(llvm::dbgs() << " After Cast Stripping V1:" << *V1.getDef()); DEBUG(llvm::dbgs() << " After Cast Stripping V2:" << *V2.getDef()); // Ok, we need to actually compute an Alias Analysis result for V1, V2. Begin // by finding the "base" of V1, V2 by stripping off all casts and GEPs. SILValue O1 = getUnderlyingObject(V1); SILValue O2 = getUnderlyingObject(V2); DEBUG(llvm::dbgs() << " Underlying V1:" << *O1.getDef()); DEBUG(llvm::dbgs() << " Underlying V2:" << *O2.getDef()); // If O1 and O2 do not equal, see if we can prove that they cannot be the // same object. If we can, return No Alias. if (O1 != O2 && aliasUnequalObjects(O1, O2)) return AliasResult::NoAlias; // Ok, either O1, O2 are the same or we could not prove anything based off of // their inequality. // Next: ask escape analysis. This catches cases where we compare e.g. a // non-escaping pointer with another (maybe escaping) pointer. Escape analysis // uses the connection graph to check if the pointers may point to the same // content. // Note that escape analysis must work with the original pointers and not the // underlying objects because it treats projections differently. if (!EA->canPointToSameMemory(V1, V2)) { DEBUG(llvm::dbgs() << " Found not-aliased objects based on" "escape analysis\n"); return AliasResult::NoAlias; } // Now we climb up use-def chains and attempt to do tricks based off of GEPs. // First if one instruction is a gep and the other is not, canonicalize our // inputs so that V1 always is the instruction containing the GEP. if (!NewProjection::isAddressProjection(V1) && NewProjection::isAddressProjection(V2)) { std::swap(V1, V2); std::swap(O1, O2); } // If V1 is an address projection, attempt to use information from the // aggregate type tree to disambiguate it from V2. if (NewProjection::isAddressProjection(V1)) { AliasResult Result = aliasAddressProjection(V1, V2, O1, O2); if (Result != AliasResult::MayAlias) return Result; } // We could not prove anything. Be conservative and return that V1, V2 may // alias. return AliasResult::MayAlias; }
/// Check if the value \p Value is known to be zero, non-zero or unknown. IsZeroKind swift::isZeroValue(SILValue Value) { // Inspect integer literals. if (auto *L = dyn_cast<IntegerLiteralInst>(Value.getDef())) { if (!L->getValue()) return IsZeroKind::Zero; return IsZeroKind::NotZero; } // Inspect Structs. switch (Value.getDef()->getKind()) { // Bitcast of zero is zero. case ValueKind::UncheckedTrivialBitCastInst: // Extracting from a zero class returns a zero. case ValueKind::StructExtractInst: return isZeroValue(cast<SILInstruction>(Value.getDef())->getOperand(0)); default: break; } // Inspect casts. if (auto *BI = dyn_cast<BuiltinInst>(Value.getDef())) { switch (BI->getBuiltinInfo().ID) { case BuiltinValueKind::IntToPtr: case BuiltinValueKind::PtrToInt: case BuiltinValueKind::ZExt: return isZeroValue(BI->getArguments()[0]); case BuiltinValueKind::UDiv: case BuiltinValueKind::SDiv: { if (IsZeroKind::Zero == isZeroValue(BI->getArguments()[0])) return IsZeroKind::Zero; return IsZeroKind::Unknown; } case BuiltinValueKind::Mul: case BuiltinValueKind::SMulOver: case BuiltinValueKind::UMulOver: { IsZeroKind LHS = isZeroValue(BI->getArguments()[0]); IsZeroKind RHS = isZeroValue(BI->getArguments()[1]); if (LHS == IsZeroKind::Zero || RHS == IsZeroKind::Zero) return IsZeroKind::Zero; return IsZeroKind::Unknown; } default: return IsZeroKind::Unknown; } } // Handle results of XXX_with_overflow arithmetic. if (auto *T = dyn_cast<TupleExtractInst>(Value.getDef())) { // Make sure we are extracting the number value and not // the overflow flag. if (T->getFieldNo() != 0) return IsZeroKind::Unknown; BuiltinInst *BI = dyn_cast<BuiltinInst>(T->getOperand()); if (!BI) return IsZeroKind::Unknown; return isZeroValue(BI); } //Inspect allocations and pointer literals. if (isa<StringLiteralInst>(Value.getDef()) || isa<AllocationInst>(Value.getDef()) || isa<GlobalAddrInst>(Value.getDef())) return IsZeroKind::NotZero; return IsZeroKind::Unknown; }