本文整理汇总了C++中SILArgument类的典型用法代码示例。如果您正苦于以下问题:C++ SILArgument类的具体用法?C++ SILArgument怎么用?C++ SILArgument使用的例子?那么, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了SILArgument类的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: new
void EpilogueARCContext::initializeDataflow() {
for (auto &B : *F) {
// Find the exit blocks.
if (isInterestedFunctionExitingBlock(&B)) {
ExitBlocks.insert(&B);
}
// Allocate the storage.
EpilogueARCBlockStates[&B] =
new (BPA.Allocate()) EpilogueARCBlockState();
}
// Split the SILargument into local arguments to each specific basic block.
llvm::SmallVector<SILValue, 4> ToProcess;
llvm::DenseSet<SILValue> Processed;
ToProcess.push_back(Arg);
while (!ToProcess.empty()) {
SILValue CArg = ToProcess.pop_back_val();
if (!CArg)
continue;
if (Processed.find(CArg) != Processed.end())
continue;
Processed.insert(CArg);
SILArgument *A = dyn_cast<SILArgument>(CArg);
if (A && !A->isFunctionArg()) {
// Find predecessor and break the SILArgument to predecessors.
for (auto X : A->getParent()->getPreds()) {
// Try to find the predecessor edge-value.
SILValue IA = A->getIncomingValue(X);
EpilogueARCBlockStates[X]->LocalArg = IA;
// Maybe the edge value is another SILArgument.
ToProcess.push_back(IA);
}
}
}
}
示例2: getMaxLoopTripCount
/// Determine the number of iterations the loop is at most executed. The loop
/// might contain early exits so this is the maximum if no early exits are
/// taken.
static Optional<uint64_t> getMaxLoopTripCount(SILLoop *Loop,
SILBasicBlock *Preheader,
SILBasicBlock *Header,
SILBasicBlock *Latch) {
// Skip a split backedge.
SILBasicBlock *OrigLatch = Latch;
if (!Loop->isLoopExiting(Latch) && !(Latch = Latch->getSinglePredecessor()))
return None;
if (!Loop->isLoopExiting(Latch))
return None;
// Get the loop exit condition.
auto *CondBr = dyn_cast<CondBranchInst>(Latch->getTerminator());
if (!CondBr)
return None;
// Match an add 1 recurrence.
SILArgument *RecArg;
IntegerLiteralInst *End;
SILValue RecNext;
if (!match(CondBr->getCondition(),
m_BuiltinInst(BuiltinValueKind::ICMP_EQ, m_SILValue(RecNext),
m_IntegerLiteralInst(End))))
return None;
if (!match(RecNext,
m_TupleExtractInst(m_ApplyInst(BuiltinValueKind::SAddOver,
m_SILArgument(RecArg), m_One()),
0)))
return None;
if (RecArg->getParent() != Header)
return None;
auto *Start = dyn_cast_or_null<IntegerLiteralInst>(
RecArg->getIncomingValue(Preheader).getDef());
if (!Start)
return None;
if (RecNext != RecArg->getIncomingValue(OrigLatch))
return None;
auto StartVal = Start->getValue();
auto EndVal = End->getValue();
if (StartVal.sgt(EndVal))
return None;
auto Dist = EndVal - StartVal;
if (Dist.getBitWidth() > 64)
return None;
if (Dist == 0)
return None;
return Dist.getZExtValue();
}
示例3: Builder
void FunctionSignatureTransform::ArgumentExplosionFinalizeOptimizedFunction() {
SILBasicBlock *BB = &*NewF->begin();
SILBuilder Builder(BB->begin());
Builder.setCurrentDebugScope(BB->getParent()->getDebugScope());
unsigned TotalArgIndex = 0;
for (ArgumentDescriptor &AD : ArgumentDescList) {
// Simply continue if do not explode.
if (!AD.Explode) {
AIM[TotalArgIndex] = AD.Index;
TotalArgIndex ++;
continue;
}
// OK, we need to explode this argument.
unsigned ArgOffset = ++TotalArgIndex;
unsigned OldArgIndex = ArgOffset - 1;
llvm::SmallVector<SILValue, 8> LeafValues;
// 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<const ProjectionTreeNode*, 8> LeafNodes;
AD.ProjTree.getLeafNodes(LeafNodes);
for (auto *Node : LeafNodes) {
auto OwnershipKind = *AD.getTransformedOwnershipKind(Node->getType());
LeafValues.push_back(BB->insertFunctionArgument(
ArgOffset++, Node->getType(), OwnershipKind,
BB->getArgument(OldArgIndex)->getDecl()));
AIM[TotalArgIndex - 1] = AD.Index;
TotalArgIndex ++;
}
// Then go through the projection tree constructing aggregates and replacing
// uses.
AD.ProjTree.replaceValueUsesWithLeafUses(Builder, BB->getParent()->getLocation(),
LeafValues);
// We ignored debugvalue uses when we constructed the new arguments, in order
// to preserve as much information as possible, we construct a new value for
// OrigArg from the leaf values and use that in place of the OrigArg.
SILValue NewOrigArgValue = AD.ProjTree.computeExplodedArgumentValue(Builder,
BB->getParent()->getLocation(),
LeafValues);
// Replace all uses of the original arg with the new value.
SILArgument *OrigArg = BB->getArgument(OldArgIndex);
OrigArg->replaceAllUsesWith(NewOrigArgValue);
// Now erase the old argument since it does not have any uses. We also
// decrement ArgOffset since we have one less argument now.
BB->eraseArgument(OldArgIndex);
TotalArgIndex --;
}
}
示例4: getArgumentCount
void AccessSummaryAnalysis::FunctionSummary::print(raw_ostream &os,
SILFunction *fn) const {
unsigned argCount = getArgumentCount();
os << "(";
for (unsigned i = 0; i < argCount; i++) {
if (i > 0) {
os << ", ";
}
SILArgument *arg = fn->getArgument(i);
SILModule &m = fn->getModule();
os << getAccessForArgument(i).getDescription(arg->getType(), m);
}
os << ")";
}
示例5: assert
void ReleaseCodeMotionContext::computeCodeMotionGenKillSet() {
for (SILBasicBlock *BB : PO->getPostOrder()) {
auto *State = BlockStates[BB];
bool InterestBlock = false;
for (auto I = BB->rbegin(), E = BB->rend(); I != E; ++I) {
// Check whether this instruction blocks any RC root code motion.
for (unsigned i = 0; i < RCRootVault.size(); ++i) {
if (!State->BBMaxSet.test(i) || !mayBlockCodeMotion(&*I, RCRootVault[i]))
continue;
// This instruction blocks this RC root.
InterestBlock = true;
State->BBKillSet.set(i);
State->BBGenSet.reset(i);
}
// If this is an epilogue release and we are freezing epilogue release
// simply continue.
if (FreezeEpilogueReleases && ERM.isEpilogueRelease(&*I))
continue;
// If this is a release instruction, it also generates.
if (isReleaseInstruction(&*I)) {
unsigned idx = RCRootIndex[getRCRoot(&*I)];
State->BBGenSet.set(idx);
assert(State->BBKillSet.test(idx) && "Killset computed incorrectly");
State->BBKillSet.reset(idx);
InterestBlock = true;
}
}
// Handle SILArgument, SILArgument can invalidate.
for (unsigned i = 0; i < RCRootVault.size(); ++i) {
SILArgument *A = dyn_cast<SILArgument>(RCRootVault[i]);
if (!A || A->getParent() != BB)
continue;
InterestBlock = true;
State->BBKillSet.set(i);
State->BBGenSet.reset(i);
}
// Is this interesting to the last iteration of the data flow.
if (!InterestBlock)
continue;
InterestBlocks.insert(BB);
}
}
示例6: ValueIsPHI
/// 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;
}
示例7: skipValueProjections
Effects *FunctionEffects::getEffectsOn(SILValue Addr) {
SILValue BaseAddr = skipValueProjections(skipAddrProjections(Addr));
switch (BaseAddr->getKind()) {
case swift::ValueKind::SILArgument: {
// Can we associate the address to a function parameter?
SILArgument *Arg = cast<SILArgument>(BaseAddr);
if (Arg->isFunctionArg()) {
return &ParamEffects[Arg->getIndex()];
}
break;
}
case ValueKind::AllocStackInst:
case ValueKind::AllocRefInst:
case ValueKind::AllocRefDynamicInst:
case ValueKind::AllocBoxInst:
// Effects on locally allocated storage.
return &LocalEffects;
default:
break;
}
// Everything else.
return &GlobalEffects;
}
示例8: propagateBasicBlockArgs
/// \brief Propagate/remove basic block input values when all predecessors
/// supply the same arguments.
static void propagateBasicBlockArgs(SILBasicBlock &BB) {
// This functions would simplify the code as following:
//
// bb0:
// br bb2(%1 : $Builtin.Int1, %2 : $Builtin.Int1)
// bb1:
// br bb2(%1 : $Builtin.Int1, %2 : $Builtin.Int1)
// bb2(%3 : $Builtin.Int1, %4 : $Builtin.Int1):
// use(%3 : $Builtin.Int1)
// use(%4 : $Builtin.Int1)
// =>
// bb0:
// br bb2
// bb1:
// br bb2
// bb2:
// use(%1 : $Builtin.Int1)
// use(%2 : $Builtin.Int1)
// If there are no predecessors or no arguments, there is nothing to do.
if (BB.pred_empty() || BB.bbarg_empty())
return;
// Check if all the predecessors supply the same arguments to the BB.
SmallVector<SILValue, 4> Args;
bool checkArgs = false;
for (SILBasicBlock::pred_iterator PI = BB.pred_begin(), PE = BB.pred_end();
PI != PE; ++PI) {
SILBasicBlock *PredB = *PI;
// We are only simplifying cases where all predecessors are
// unconditional branch instructions.
if (!isa<BranchInst>(PredB->getTerminator()))
return;
BranchInst *BI = cast<BranchInst>(PredB->getTerminator());
unsigned Idx = 0;
assert(!BI->getArgs().empty());
for (OperandValueArrayRef::iterator AI = BI->getArgs().begin(),
AE = BI->getArgs().end();
AI != AE; ++AI, ++Idx) {
// When processing the first predecessor, record the arguments.
if (!checkArgs)
Args.push_back(*AI);
else
// On each subsequent predecessor, check the arguments.
if (Args[Idx] != *AI)
return;
}
// After the first branch is processed, the arguments vector is populated.
assert(Args.size() > 0);
checkArgs = true;
}
// If we've reached this point, the optimization is valid, so optimize.
// We know that the incoming arguments from all predecessors are the same,
// so just use them directly and remove the basic block parameters.
// Drop the arguments from the branch instructions by creating a new branch
// instruction and deleting the old one.
llvm::SmallVector<SILInstruction*, 32> ToBeDeleted;
for (SILBasicBlock::pred_iterator PI = BB.pred_begin(), PE = BB.pred_end();
PI != PE; ++PI) {
SILBasicBlock *PredB = *PI;
BranchInst *BI = cast<BranchInst>(PredB->getTerminator());
SILBuilderWithScope Bldr(PredB, BI);
Bldr.createBranch(BI->getLoc(), BI->getDestBB());
ToBeDeleted.push_back(BI);
}
// Drop the parameters from basic blocks and replace all uses with the passed
// in arguments.
unsigned Idx = 0;
for (SILBasicBlock::bbarg_iterator AI = BB.bbarg_begin(),
AE = BB.bbarg_end();
AI != AE; ++AI, ++Idx) {
// FIXME: These could be further propagatable now, we might want to move
// this to CCP and trigger another round of copy propagation.
SILArgument *Arg = *AI;
// We were able to fold, so all users should use the new folded value.
assert(Arg->getTypes().size() == 1 &&
"Currently, we only support single result instructions.");
SILValue(Arg).replaceAllUsesWith(Args[Idx]);
NumBasicBlockArgsPropagated++;
}
// Remove args from the block.
BB.dropAllBBArgs();
// The old branch instructions are no longer used, erase them.
recursivelyDeleteTriviallyDeadInstructions(ToBeDeleted, true);
NumInstructionsRemoved += ToBeDeleted.size();
}
示例9: getCloned
/// \brief Populate the body of the cloned closure, modifying instructions as
/// necessary. This is where we create the actual specialized BB Arguments.
void ClosureSpecCloner::populateCloned() {
SILFunction *Cloned = getCloned();
SILFunction *ClosureUser = CallSiteDesc.getApplyCallee();
// Create arguments for the entry block.
SILBasicBlock *ClosureUserEntryBB = &*ClosureUser->begin();
SILBasicBlock *ClonedEntryBB = Cloned->createBasicBlock();
SmallVector<SILValue, 4> entryArgs;
entryArgs.reserve(ClosureUserEntryBB->getArguments().size());
// Remove the closure argument.
SILArgument *ClosureArg = nullptr;
for (size_t i = 0, e = ClosureUserEntryBB->args_size(); i != e; ++i) {
SILArgument *Arg = ClosureUserEntryBB->getArgument(i);
if (i == CallSiteDesc.getClosureIndex()) {
ClosureArg = Arg;
entryArgs.push_back(SILValue());
continue;
}
// Otherwise, create a new argument which copies the original argument
SILValue MappedValue =
ClonedEntryBB->createFunctionArgument(Arg->getType(), Arg->getDecl());
entryArgs.push_back(MappedValue);
}
// Next we need to add in any arguments that are not captured as arguments to
// the cloned function.
//
// We do not insert the new mapped arguments into the value map since there by
// definition is nothing in the partial apply user function that references
// such arguments. After this pass is done the only thing that will reference
// the arguments is the partial apply that we will create.
SILFunction *ClosedOverFun = CallSiteDesc.getClosureCallee();
auto ClosedOverFunConv = ClosedOverFun->getConventions();
unsigned NumTotalParams = ClosedOverFunConv.getNumParameters();
unsigned NumNotCaptured = NumTotalParams - CallSiteDesc.getNumArguments();
llvm::SmallVector<SILValue, 4> NewPAIArgs;
for (auto &PInfo : ClosedOverFunConv.getParameters().slice(NumNotCaptured)) {
auto paramTy = ClosedOverFunConv.getSILType(PInfo);
SILValue MappedValue = ClonedEntryBB->createFunctionArgument(paramTy);
NewPAIArgs.push_back(MappedValue);
}
SILBuilder &Builder = getBuilder();
Builder.setInsertionPoint(ClonedEntryBB);
// Clone FRI and PAI, and replace usage of the removed closure argument
// with result of cloned PAI.
SILValue FnVal =
Builder.createFunctionRef(CallSiteDesc.getLoc(), ClosedOverFun);
auto *NewClosure = CallSiteDesc.createNewClosure(Builder, FnVal, NewPAIArgs);
// Clone a chain of ConvertFunctionInsts. This can create further
// reabstraction partial_apply instructions.
SmallVector<PartialApplyInst*, 4> NeedsRelease;
SILValue ConvertedCallee = cloneCalleeConversion(
CallSiteDesc.getClosureCallerArg(), NewClosure, Builder, NeedsRelease);
// Make sure that we actually emit the releases for reabstraction thunks. We
// have guaranteed earlier that we only allow reabstraction thunks if the
// closure was passed trivial.
assert(NeedsRelease.empty() || CallSiteDesc.isTrivialNoEscapeParameter());
entryArgs[CallSiteDesc.getClosureIndex()] = ConvertedCallee;
// Visit original BBs in depth-first preorder, starting with the
// entry block, cloning all instructions and terminators.
cloneFunctionBody(ClosureUser, ClonedEntryBB, entryArgs);
// Then insert a release in all non failure exit BBs if our partial apply was
// guaranteed. This is b/c it was passed at +0 originally and we need to
// balance the initial increment of the newly created closure(s).
bool ClosureHasRefSemantics = CallSiteDesc.closureHasRefSemanticContext();
if ((CallSiteDesc.isClosureGuaranteed() ||
CallSiteDesc.isTrivialNoEscapeParameter()) &&
(ClosureHasRefSemantics || !NeedsRelease.empty())) {
for (SILBasicBlock *BB : CallSiteDesc.getNonFailureExitBBs()) {
SILBasicBlock *OpBB = getOpBasicBlock(BB);
TermInst *TI = OpBB->getTerminator();
auto Loc = CleanupLocation::get(NewClosure->getLoc());
// If we have an exit, we place the release right before it so we know
// that it will be executed at the end of the epilogue.
if (TI->isFunctionExiting()) {
Builder.setInsertionPoint(TI);
if (ClosureHasRefSemantics)
Builder.createReleaseValue(Loc, SILValue(NewClosure),
Builder.getDefaultAtomicity());
for (auto PAI : NeedsRelease)
Builder.createReleaseValue(Loc, SILValue(PAI),
Builder.getDefaultAtomicity());
continue;
}
// We use casts where findAllNonFailureExitBBs should have made sure that
//.........这里部分代码省略.........
示例10: getCloned
/// \brief Populate the body of the cloned closure, modifying instructions as
/// necessary. This is where we create the actual specialized BB Arguments.
void ClosureSpecCloner::populateCloned() {
SILFunction *Cloned = getCloned();
SILFunction *ClosureUser = CallSiteDesc.getApplyCallee();
// Create arguments for the entry block.
SILBasicBlock *ClosureUserEntryBB = &*ClosureUser->begin();
SILBasicBlock *ClonedEntryBB = Cloned->createBasicBlock();
// Remove the closure argument.
SILArgument *ClosureArg = nullptr;
for (size_t i = 0, e = ClosureUserEntryBB->args_size(); i != e; ++i) {
SILArgument *Arg = ClosureUserEntryBB->getArgument(i);
if (i == CallSiteDesc.getClosureIndex()) {
ClosureArg = Arg;
continue;
}
// Otherwise, create a new argument which copies the original argument
SILValue MappedValue =
ClonedEntryBB->createFunctionArgument(Arg->getType(), Arg->getDecl());
ValueMap.insert(std::make_pair(Arg, MappedValue));
}
// Next we need to add in any arguments that are not captured as arguments to
// the cloned function.
//
// We do not insert the new mapped arguments into the value map since there by
// definition is nothing in the partial apply user function that references
// such arguments. After this pass is done the only thing that will reference
// the arguments is the partial apply that we will create.
SILFunction *ClosedOverFun = CallSiteDesc.getClosureCallee();
CanSILFunctionType ClosedOverFunTy = ClosedOverFun->getLoweredFunctionType();
unsigned NumTotalParams = ClosedOverFunTy->getParameters().size();
unsigned NumNotCaptured = NumTotalParams - CallSiteDesc.getNumArguments();
llvm::SmallVector<SILValue, 4> NewPAIArgs;
for (auto &PInfo : ClosedOverFunTy->getParameters().slice(NumNotCaptured)) {
SILValue MappedValue =
ClonedEntryBB->createFunctionArgument(PInfo.getSILType());
NewPAIArgs.push_back(MappedValue);
}
SILBuilder &Builder = getBuilder();
Builder.setInsertionPoint(ClonedEntryBB);
// Clone FRI and PAI, and replace usage of the removed closure argument
// with result of cloned PAI.
SILValue FnVal =
Builder.createFunctionRef(CallSiteDesc.getLoc(), ClosedOverFun);
auto *NewClosure = CallSiteDesc.createNewClosure(Builder, FnVal, NewPAIArgs);
ValueMap.insert(std::make_pair(ClosureArg, SILValue(NewClosure)));
BBMap.insert(std::make_pair(ClosureUserEntryBB, ClonedEntryBB));
// Recursively visit original BBs in depth-first preorder, starting with the
// entry block, cloning all instructions other than terminators.
visitSILBasicBlock(ClosureUserEntryBB);
// Now iterate over the BBs and fix up the terminators.
for (auto BI = BBMap.begin(), BE = BBMap.end(); BI != BE; ++BI) {
Builder.setInsertionPoint(BI->second);
visit(BI->first->getTerminator());
}
// Then insert a release in all non failure exit BBs if our partial apply was
// guaranteed. This is b/c it was passed at +0 originally and we need to
// balance the initial increment of the newly created closure.
if (CallSiteDesc.isClosureGuaranteed() &&
CallSiteDesc.closureHasRefSemanticContext()) {
for (SILBasicBlock *BB : CallSiteDesc.getNonFailureExitBBs()) {
SILBasicBlock *OpBB = BBMap[BB];
TermInst *TI = OpBB->getTerminator();
auto Loc = CleanupLocation::get(NewClosure->getLoc());
// If we have a return, we place the release right before it so we know
// that it will be executed at the end of the epilogue.
if (isa<ReturnInst>(TI)) {
Builder.setInsertionPoint(TI);
Builder.createReleaseValue(Loc, SILValue(NewClosure),
Atomicity::Atomic);
continue;
}
// We use casts where findAllNonFailureExitBBs should have made sure that
// this is true. This will ensure that the code is updated when we hit the
// cast failure in debug builds.
auto *Unreachable = cast<UnreachableInst>(TI);
auto PrevIter = std::prev(SILBasicBlock::iterator(Unreachable));
auto NoReturnApply = FullApplySite::isa(&*PrevIter);
// We insert the release value right before the no return apply so that if
// the partial apply is passed into the no-return function as an @owned
// value, we will retain the partial apply before we release it and
// potentially eliminate it.
Builder.setInsertionPoint(NoReturnApply.getInstruction());
Builder.createReleaseValue(Loc, SILValue(NewClosure), Atomicity::Atomic);
}
}
}
示例11: eraseUsesOfValue
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.
for (auto &X : CalleeRelease) {
SILType CalleeReleaseTy = X->getOperand(0)->getType();
X->setOperand(
0, SILUndef::get(CalleeReleaseTy, Builder.getModule()));
}
// 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);
// We ignored debugvalue uses when we constructed the new arguments, in order
// to preserve as much information as possible, we construct a new value for
// OrigArg from the leaf values and use that in place of the OrigArg.
SILValue NewOrigArgValue = ProjTree.computeExplodedArgumentValue(Builder,
BB->getParent()->getLocation(),
LeafValues);
// Replace all uses of the original arg with the new value.
SILArgument *OrigArg = BB->getBBArg(OldArgOffset);
OrigArg->replaceAllUsesWith(NewOrigArgValue);
// 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;
}
示例12: findMatchingRetains
void
ConsumedResultToEpilogueRetainMatcher::
findMatchingRetains(SILBasicBlock *BB) {
// Iterate over the instructions post-order and find retains associated with
// return value.
SILValue RV = SILValue();
for (auto II = BB->rbegin(), IE = BB->rend(); II != IE; ++II) {
if (ReturnInst *RI = dyn_cast<ReturnInst>(&*II)) {
RV = RI->getOperand();
break;
}
}
// Somehow, we managed not to find a return value.
if (!RV)
return;
// OK. we've found the return value, now iterate on the CFG to find all the
// post-dominating retains.
//
// The ConsumedArgToEpilogueReleaseMatcher finds the final releases
// in the following way.
//
// 1. If an instruction, which is not releaseinst nor releasevalue, that
// could decrement reference count is found. bail out.
//
// 2. If a release is found and the release that can not be mapped to any
// @owned argument. bail as this release may well be the final release of
// an @owned argument, but somehow rc-identity fails to prove that.
//
// 3. A release that is mapped to an argument which already has a release
// that overlaps with this release. This release for sure is not the final
// release.
constexpr unsigned WorkListMaxSize = 4;
llvm::DenseSet<SILBasicBlock *> RetainFrees;
llvm::SmallVector<BasicBlockRetainValue, 4> WorkList;
llvm::DenseSet<SILBasicBlock *> HandledBBs;
WorkList.push_back(std::make_pair(BB, RV));
HandledBBs.insert(BB);
while (!WorkList.empty()) {
// Too many blocks ?.
if (WorkList.size() > WorkListMaxSize) {
EpilogueRetainInsts.clear();
return;
}
// Try to find a retain %value in this basic block.
auto R = WorkList.pop_back_val();
RetainKindValue Kind = findMatchingRetainsInBasicBlock(R.first, R.second);
// We've found a retain on this path.
if (Kind.first == FindRetainKind::Found) {
EpilogueRetainInsts.push_back(Kind.second);
continue;
}
// There is a MayDecrement instruction.
if (Kind.first == FindRetainKind::Blocked) {
EpilogueRetainInsts.clear();
return;
}
// There is a self-recursion. Use the apply instruction as the retain.
if (Kind.first == FindRetainKind::Recursion) {
EpilogueRetainInsts.push_back(Kind.second);
continue;
}
// Did not find a retain in this block, try to go to its predecessors.
if (Kind.first == FindRetainKind::None) {
// We can not find a retain in a block with no predecessors.
if (R.first->getPreds().begin() == R.first->getPreds().end()) {
EpilogueRetainInsts.clear();
return;
}
// This block does not have a retain.
RetainFrees.insert(R.first);
// If this is a SILArgument of current basic block, we can split it up to
// values in the predecessors.
SILArgument *SA = dyn_cast<SILArgument>(R.second);
if (SA && SA->getParent() != R.first)
SA = nullptr;
for (auto X : R.first->getPreds()) {
if (HandledBBs.find(X) != HandledBBs.end())
continue;
// Try to use the predecessor edge-value.
if (SA && SA->getIncomingValue(X)) {
WorkList.push_back(std::make_pair(X, SA->getIncomingValue(X)));
}
else
WorkList.push_back(std::make_pair(X, R.second));
HandledBBs.insert(X);
}
}
}
//.........这里部分代码省略.........
示例13: assert
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.
SILArgument *OrigArg = 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;
}
示例14: mergeBBDataFlowStates
void ReleaseCodeMotionContext::computeCodeMotionInsertPoints() {
// The BBSetIns have converged, run last iteration and figure out insertion
// point for each RC root.
for (SILBasicBlock *BB : PO->getPostOrder()) {
// Intersect in the successor BBSetIns.
mergeBBDataFlowStates(BB);
ReleaseBlockState *S = BlockStates[BB];
// Compute insertion point generated by the edge value transition.
// If there is a transition from 1 to 0, that means we have a partial
// merge, which means the release can NOT be hoisted to the current block.
// place it at the successors.
for (unsigned i = 0; i < RCRootVault.size(); ++i) {
if (S->BBSetOut[i])
continue;
for (auto &Succ : BB->getSuccessors()) {
BlockState *SBB = BlockStates[Succ];
if (!SBB->BBSetIn[i])
continue;
InsertPoints[RCRootVault[i]].push_back(&*(*Succ).begin());
}
}
// Is this block interesting ?
if (MultiIteration && !InterestBlocks.count(BB))
continue;
// Compute insertion point generated by MayUse terminator inst.
// If terminator instruction can block the RC root. We will have no
// choice but to anchor the release instructions in the successor blocks.
for (unsigned i = 0; i < RCRootVault.size(); ++i) {
SILInstruction *Term = BB->getTerminator();
if (!S->BBSetOut[i] || !mayBlockCodeMotion(Term, RCRootVault[i]))
continue;
for (auto &Succ : BB->getSuccessors()) {
BlockState *SBB = BlockStates[Succ];
if (!SBB->BBSetIn[i])
continue;
InsertPoints[RCRootVault[i]].push_back(&*(*Succ).begin());
}
S->BBSetOut.reset(i);
}
// Compute insertion point generated within the basic block. Process
// instructions in post-order fashion.
for (auto I = std::next(BB->rbegin()), E = BB->rend(); I != E; ++I) {
for (unsigned i = 0; i < RCRootVault.size(); ++i) {
if (!S->BBSetOut[i] || !mayBlockCodeMotion(&*I, RCRootVault[i]))
continue;
auto *InsertPt = &*std::next(SILBasicBlock::iterator(&*I));
InsertPoints[RCRootVault[i]].push_back(InsertPt);
S->BBSetOut.reset(i);
}
// If we are freezing this epilogue release. Simply continue.
if (FreezeEpilogueReleases && ERM.isEpilogueRelease(&*I))
continue;
// This release generates.
if (isReleaseInstruction(&*I)) {
S->BBSetOut.set(RCRootIndex[getRCRoot(&*I)]);
}
}
// Compute insertion point generated by SILArgument. SILArgument blocks if
// it defines the released value.
for (unsigned i = 0; i < RCRootVault.size(); ++i) {
if (!S->BBSetOut[i])
continue;
SILArgument *A = dyn_cast<SILArgument>(RCRootVault[i]);
if (!A || A->getParent() != BB)
continue;
InsertPoints[RCRootVault[i]].push_back(&*BB->begin());
S->BBSetOut.reset(i);
}
// Lastly update the BBSetIn, only necessary when we are running a single
// iteration dataflow.
if (!MultiIteration) {
S->updateBBSetIn(S->BBSetOut);
}
}
}
示例15: getCloned
void GenericCloner::populateCloned() {
SILFunction *Cloned = getCloned();
// Create arguments for the entry block.
SILBasicBlock *OrigEntryBB = &*Original.begin();
SILBasicBlock *ClonedEntryBB = Cloned->createBasicBlock();
getBuilder().setInsertionPoint(ClonedEntryBB);
llvm::SmallVector<AllocStackInst *, 8> AllocStacks;
AllocStackInst *ReturnValueAddr = nullptr;
// Create the entry basic block with the function arguments.
auto I = OrigEntryBB->args_begin(), E = OrigEntryBB->args_end();
int ArgIdx = 0;
while (I != E) {
SILArgument *OrigArg = *I;
RegularLocation Loc((Decl *)OrigArg->getDecl());
AllocStackInst *ASI = nullptr;
SILType mappedType = remapType(OrigArg->getType());
if (ReInfo.isArgConverted(ArgIdx)) {
// We need an alloc_stack as a replacement for the indirect parameter.
assert(mappedType.isAddress());
mappedType = mappedType.getObjectType();
ASI = getBuilder().createAllocStack(Loc, mappedType);
ValueMap[OrigArg] = ASI;
AllocStacks.push_back(ASI);
if (ReInfo.isResultIndex(ArgIdx)) {
// This result is converted from indirect to direct. The return inst
// needs to load the value from the alloc_stack. See below.
assert(!ReturnValueAddr);
ReturnValueAddr = ASI;
} else {
// Store the new direct parameter to the alloc_stack.
auto *NewArg =
ClonedEntryBB->createArgument(mappedType, OrigArg->getDecl());
getBuilder().createStore(Loc, NewArg, ASI,
StoreOwnershipQualifier::Unqualified);
// Try to create a new debug_value from an existing debug_value_addr.
for (Operand *ArgUse : OrigArg->getUses()) {
if (auto *DVAI = dyn_cast<DebugValueAddrInst>(ArgUse->getUser())) {
getBuilder().createDebugValue(DVAI->getLoc(), NewArg,
DVAI->getVarInfo());
break;
}
}
}
} else {
auto *NewArg =
ClonedEntryBB->createArgument(mappedType, OrigArg->getDecl());
ValueMap[OrigArg] = NewArg;
}
++I;
++ArgIdx;
}
BBMap.insert(std::make_pair(OrigEntryBB, ClonedEntryBB));
// Recursively visit original BBs in depth-first preorder, starting with the
// entry block, cloning all instructions other than terminators.
visitSILBasicBlock(OrigEntryBB);
// Now iterate over the BBs and fix up the terminators.
for (auto BI = BBMap.begin(), BE = BBMap.end(); BI != BE; ++BI) {
getBuilder().setInsertionPoint(BI->second);
TermInst *OrigTermInst = BI->first->getTerminator();
if (auto *RI = dyn_cast<ReturnInst>(OrigTermInst)) {
SILValue ReturnValue;
if (ReturnValueAddr) {
// The result is converted from indirect to direct. We have to load the
// returned value from the alloc_stack.
ReturnValue =
getBuilder().createLoad(ReturnValueAddr->getLoc(), ReturnValueAddr,
LoadOwnershipQualifier::Unqualified);
}
for (AllocStackInst *ASI : reverse(AllocStacks)) {
getBuilder().createDeallocStack(ASI->getLoc(), ASI);
}
if (ReturnValue) {
getBuilder().createReturn(RI->getLoc(), ReturnValue);
continue;
}
} else if (isa<ThrowInst>(OrigTermInst)) {
for (AllocStackInst *ASI : reverse(AllocStacks)) {
getBuilder().createDeallocStack(ASI->getLoc(), ASI);
}
}
visit(BI->first->getTerminator());
}
}