unsigned ArgumentDescriptor::updateOptimizedBBArgs(SILBuilder &Builder, SILBasicBlock *BB, unsigned ArgOffset) { // If this argument is completely dead, delete this argument and return // ArgOffset. if (IsDead) { // If we have a callee release and we are dead, set the callee release's // operand to undef. We do not need it to have the argument anymore, but we // do need the instruction to be non-null. // // TODO: This should not be necessary. if (CalleeRelease) { SILType CalleeReleaseTy = CalleeRelease->getOperand(0).getType(); CalleeRelease->setOperand( 0, SILUndef::get(CalleeReleaseTy, Builder.getModule())); // TODO: Currently we cannot mark arguments as dead if they are released // in a throw block. But as soon as we can do this, we have to handle // CalleeReleaseInThrowBlock as well. assert(!CalleeReleaseInThrowBlock && "released arg in throw block cannot be dead"); } // We should be able to recursively delete all of the remaining // instructions. SILArgument *Arg = BB->getBBArg(ArgOffset); eraseUsesOfValue(Arg); BB->eraseBBArg(ArgOffset); return ArgOffset; } // If this argument is not dead and we did not perform SROA, increment the // offset and return. if (!shouldExplode()) { return ArgOffset + 1; } // Create values for the leaf types. llvm::SmallVector<SILValue, 8> LeafValues; // Create a reference to the old arg offset and increment arg offset so we can // create the new arguments. unsigned OldArgOffset = ArgOffset++; // We do this in the same order as leaf types since ProjTree expects that the // order of leaf values matches the order of leaf types. { llvm::SmallVector<SILType, 8> LeafTypes; ProjTree.getLeafTypes(LeafTypes); for (auto Ty : LeafTypes) { LeafValues.push_back(BB->insertBBArg( ArgOffset++, Ty, BB->getBBArg(OldArgOffset)->getDecl())); } } // Then go through the projection tree constructing aggregates and replacing // uses. // // TODO: What is the right location to use here? ProjTree.replaceValueUsesWithLeafUses(Builder, BB->getParent()->getLocation(), LeafValues); // Replace all uses of the original arg with undef so it does not have any // uses. SILValue OrigArg = SILValue(BB->getBBArg(OldArgOffset)); OrigArg.replaceAllUsesWith(SILUndef::get(OrigArg.getType(), BB->getModule())); // Now erase the old argument since it does not have any uses. We also // decrement ArgOffset since we have one less argument now. BB->eraseBBArg(OldArgOffset); --ArgOffset; return ArgOffset; }