static void replaceLoad(LoadInst *LI, SILValue val, AllocStackInst *ASI) { ProjectionPath projections(val->getType()); SILValue op = LI->getOperand(); while (op != ASI) { assert(isa<StructElementAddrInst>(op) || isa<TupleElementAddrInst>(op)); SILInstruction *Inst = cast<SILInstruction>(op); projections.push_back(Projection(Inst)); op = Inst->getOperand(0); } SILBuilder builder(LI); for (auto iter = projections.rbegin(); iter != projections.rend(); ++iter) { const Projection &projection = *iter; val = projection.createObjectProjection(builder, LI->getLoc(), val).get(); } op = LI->getOperand(); LI->replaceAllUsesWith(val); LI->eraseFromParent(); while (op != ASI && op->use_empty()) { assert(isa<StructElementAddrInst>(op) || isa<TupleElementAddrInst>(op)); SILInstruction *Inst = cast<SILInstruction>(op); SILValue next = Inst->getOperand(0); Inst->eraseFromParent(); op = next; } }
static bool constantFoldStringConcatenation(ApplyInst *AI, llvm::SetVector<SILInstruction *> &WorkList) { SILBuilder B(AI); // Try to apply the string literal concatenation optimization. auto *Concatenated = tryToConcatenateStrings(AI, B); // Bail if string literal concatenation could not be performed. if (!Concatenated) return false; // Replace all uses of the old instruction by a new instruction. AI->replaceAllUsesWith(Concatenated); auto RemoveCallback = [&](SILInstruction *DeadI) { WorkList.remove(DeadI); }; // Remove operands that are not used anymore. // Even if they are apply_inst, it is safe to // do so, because they can only be applies // of functions annotated as string.utf16 // or string.utf16. for (auto &Op : AI->getAllOperands()) { SILValue Val = Op.get(); Op.drop(); if (Val->use_empty()) { auto *DeadI = dyn_cast<SILInstruction>(Val); recursivelyDeleteTriviallyDeadInstructions(DeadI, /*force*/ true, RemoveCallback); WorkList.remove(DeadI); } } // Schedule users of the new instruction for constant folding. // We only need to schedule the string.concat invocations. for (auto AIUse : Concatenated->getUses()) { if (isApplyOfStringConcat(*AIUse->getUser())) { WorkList.insert(AIUse->getUser()); } } // Delete the old apply instruction. recursivelyDeleteTriviallyDeadInstructions(AI, /*force*/ true, RemoveCallback); return true; }
void MemoryToRegisters::removeSingleBlockAllocation(AllocStackInst *ASI) { DEBUG(llvm::dbgs() << "*** Promoting in-block: " << *ASI); SILBasicBlock *BB = ASI->getParent(); // The default value of the AllocStack is NULL because we don't have // uninitialized variables in Swift. SILValue RunningVal = SILValue(); // For all instructions in the block. for (auto BBI = BB->begin(), E = BB->end(); BBI != E;) { SILInstruction *Inst = &*BBI; ++BBI; // Remove instructions that we are loading from. Replace the loaded value // with our running value. if (isLoadFromStack(Inst, ASI)) { if (!RunningVal) { assert(ASI->getElementType().isVoid() && "Expected initialization of non-void type!"); RunningVal = SILUndef::get(ASI->getElementType(), ASI->getModule()); } replaceLoad(cast<LoadInst>(Inst), RunningVal, ASI); NumInstRemoved++; continue; } // Remove stores and record the value that we are saving as the running // value. if (auto *SI = dyn_cast<StoreInst>(Inst)) { if (SI->getDest() == ASI) { RunningVal = SI->getSrc(); Inst->eraseFromParent(); NumInstRemoved++; continue; } } // Replace debug_value_addr with debug_value of the promoted value. if (auto *DVAI = dyn_cast<DebugValueAddrInst>(Inst)) { if (DVAI->getOperand() == ASI) { if (RunningVal) { promoteDebugValueAddr(DVAI, RunningVal, B); } else { // Drop debug_value_addr of uninitialized void values. assert(ASI->getElementType().isVoid() && "Expected initialization of non-void type!"); DVAI->eraseFromParent(); } } continue; } // Replace destroys with a release of the value. if (auto *DAI = dyn_cast<DestroyAddrInst>(Inst)) { if (DAI->getOperand() == ASI) { replaceDestroy(DAI, RunningVal); } continue; } // Remove deallocation. if (auto *DSI = dyn_cast<DeallocStackInst>(Inst)) { if (DSI->getOperand() == ASI) { Inst->eraseFromParent(); NumInstRemoved++; // No need to continue scanning after deallocation. break; } } SILValue InstVal = Inst; // Remove dead address instructions that may be uses of the allocation. while (InstVal->use_empty() && (isa<StructElementAddrInst>(InstVal) || isa<TupleElementAddrInst>(InstVal))) { SILInstruction *I = cast<SILInstruction>(InstVal); InstVal = I->getOperand(0); I->eraseFromParent(); NumInstRemoved++; } } }