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; ValueBase *SelfVal = Arr; auto *SelfBB = SelfVal->getParentBlock(); 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(); bool DoesNotDominate; StructElementAddrInst *SEI; while ((DoesNotDominate = !DT->dominates(Val->getParentBlock(), InsertBefore->getParent())) && (SEI = dyn_cast<StructElementAddrInst>(Val))) Val = SEI->getOperand(); return !DoesNotDominate; } return false; }
/// Copy the array load to the insert point. static SILValue copyArrayLoad(SILValue ArrayStructValue, SILInstruction *InsertBefore, DominanceInfo *DT) { if (DT->dominates(ArrayStructValue->getParentBlock(), InsertBefore->getParent())) return ArrayStructValue; auto *LI = cast<LoadInst>(ArrayStructValue); // Recursively move struct_element_addr. ValueBase *Val = LI->getOperand(); auto *InsertPt = InsertBefore; while (!DT->dominates(Val->getParentBlock(), InsertBefore->getParent())) { auto *Inst = cast<StructElementAddrInst>(Val); Inst->moveBefore(InsertPt); Val = Inst->getOperand(); InsertPt = Inst; } return cast<LoadInst>(LI->clone(InsertBefore)); }