本文整理汇总了C++中BranchInst::getArgs方法的典型用法代码示例。如果您正苦于以下问题:C++ BranchInst::getArgs方法的具体用法?C++ BranchInst::getArgs怎么用?C++ BranchInst::getArgs使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类BranchInst
的用法示例。
在下文中一共展示了BranchInst::getArgs方法的4个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: 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();
}
示例2: assert
std::pair<Optional<SILValue>, SILLocation>
SILGenFunction::emitEpilogBB(SILLocation TopLevel) {
assert(ReturnDest.getBlock() && "no epilog bb prepared?!");
SILBasicBlock *epilogBB = ReturnDest.getBlock();
SILLocation ImplicitReturnFromTopLevel =
ImplicitReturnLocation::getImplicitReturnLoc(TopLevel);
SILValue returnValue;
Optional<SILLocation> returnLoc = None;
// If the current BB isn't terminated, and we require a return, then we
// are not allowed to fall off the end of the function and can't reach here.
if (NeedsReturn && B.hasValidInsertionPoint())
B.createUnreachable(ImplicitReturnFromTopLevel);
if (epilogBB->pred_empty()) {
bool hadArg = !epilogBB->bbarg_empty();
// If the epilog was not branched to at all, kill the BB and
// just emit the epilog into the current BB.
while (!epilogBB->empty())
epilogBB->back().eraseFromParent();
eraseBasicBlock(epilogBB);
// If the current bb is terminated then the epilog is just unreachable.
if (!B.hasValidInsertionPoint())
return { None, TopLevel };
// We emit the epilog at the current insertion point.
assert(!hadArg && "NeedsReturn is false but epilog had argument?!");
(void)hadArg;
returnLoc = ImplicitReturnFromTopLevel;
} else if (std::next(epilogBB->pred_begin()) == epilogBB->pred_end()
&& !B.hasValidInsertionPoint()) {
// If the epilog has a single predecessor and there's no current insertion
// point to fall through from, then we can weld the epilog to that
// predecessor BB.
bool needsArg = false;
if (!epilogBB->bbarg_empty()) {
assert(epilogBB->bbarg_size() == 1 && "epilog should take 0 or 1 args");
needsArg = true;
}
// Steal the branch argument as the return value if present.
SILBasicBlock *pred = *epilogBB->pred_begin();
BranchInst *predBranch = cast<BranchInst>(pred->getTerminator());
assert(predBranch->getArgs().size() == (needsArg ? 1 : 0) &&
"epilog predecessor arguments does not match block params");
if (needsArg) {
returnValue = predBranch->getArgs()[0];
// RAUW the old BB argument (if any) with the new value.
SILValue(*epilogBB->bbarg_begin(),0).replaceAllUsesWith(returnValue);
}
// If we are optimizing, we should use the return location from the single,
// previously processed, return statement if any.
if (predBranch->getLoc().is<ReturnLocation>()) {
returnLoc = predBranch->getLoc();
} else {
returnLoc = ImplicitReturnFromTopLevel;
}
// Kill the branch to the now-dead epilog BB.
pred->erase(predBranch);
// Move any instructions from the EpilogBB to the end of the 'pred' block.
pred->spliceAtEnd(epilogBB);
// Finally we can erase the epilog BB.
eraseBasicBlock(epilogBB);
// Emit the epilog into its former predecessor.
B.setInsertionPoint(pred);
} else {
// Move the epilog block to the end of the ordinary section.
auto endOfOrdinarySection =
(StartOfPostmatter ? SILFunction::iterator(StartOfPostmatter) : F.end());
B.moveBlockTo(epilogBB, endOfOrdinarySection);
// Emit the epilog into the epilog bb. Its argument is the return value.
if (!epilogBB->bbarg_empty()) {
assert(epilogBB->bbarg_size() == 1 && "epilog should take 0 or 1 args");
returnValue = epilogBB->bbarg_begin()[0];
}
// If we are falling through from the current block, the return is implicit.
B.emitBlock(epilogBB, ImplicitReturnFromTopLevel);
}
// Emit top-level cleanups into the epilog block.
assert(!Cleanups.hasAnyActiveCleanups(getCleanupsDepth(),
ReturnDest.getDepth()) &&
"emitting epilog in wrong scope");
auto cleanupLoc = CleanupLocation::get(TopLevel);
Cleanups.emitCleanupsForReturn(cleanupLoc);
// If the return location is known to be that of an already
// processed return, use it. (This will get triggered when the
// epilog logic is simplified.)
//.........这里部分代码省略.........
示例3: assert
std::pair<Optional<SILValue>, SILLocation>
SILGenFunction::emitEpilogBB(SILLocation TopLevel) {
assert(ReturnDest.getBlock() && "no epilog bb prepared?!");
SILBasicBlock *epilogBB = ReturnDest.getBlock();
SILLocation ImplicitReturnFromTopLevel =
ImplicitReturnLocation::getImplicitReturnLoc(TopLevel);
SmallVector<SILValue, 4> directResults;
Optional<SILLocation> returnLoc = None;
// If the current BB isn't terminated, and we require a return, then we
// are not allowed to fall off the end of the function and can't reach here.
if (NeedsReturn && B.hasValidInsertionPoint())
B.createUnreachable(ImplicitReturnFromTopLevel);
if (epilogBB->pred_empty()) {
// If the epilog was not branched to at all, kill the BB and
// just emit the epilog into the current BB.
while (!epilogBB->empty())
epilogBB->back().eraseFromParent();
eraseBasicBlock(epilogBB);
// If the current bb is terminated then the epilog is just unreachable.
if (!B.hasValidInsertionPoint())
return { None, TopLevel };
// We emit the epilog at the current insertion point.
returnLoc = ImplicitReturnFromTopLevel;
} else if (std::next(epilogBB->pred_begin()) == epilogBB->pred_end()
&& !B.hasValidInsertionPoint()) {
// If the epilog has a single predecessor and there's no current insertion
// point to fall through from, then we can weld the epilog to that
// predecessor BB.
// Steal the branch argument as the return value if present.
SILBasicBlock *pred = *epilogBB->pred_begin();
BranchInst *predBranch = cast<BranchInst>(pred->getTerminator());
assert(predBranch->getArgs().size() == epilogBB->bbarg_size() &&
"epilog predecessor arguments does not match block params");
for (auto index : indices(predBranch->getArgs())) {
SILValue result = predBranch->getArgs()[index];
directResults.push_back(result);
epilogBB->getBBArg(index)->replaceAllUsesWith(result);
}
// If we are optimizing, we should use the return location from the single,
// previously processed, return statement if any.
if (predBranch->getLoc().is<ReturnLocation>()) {
returnLoc = predBranch->getLoc();
} else {
returnLoc = ImplicitReturnFromTopLevel;
}
// Kill the branch to the now-dead epilog BB.
pred->erase(predBranch);
// Move any instructions from the EpilogBB to the end of the 'pred' block.
pred->spliceAtEnd(epilogBB);
// Finally we can erase the epilog BB.
eraseBasicBlock(epilogBB);
// Emit the epilog into its former predecessor.
B.setInsertionPoint(pred);
} else {
// Move the epilog block to the end of the ordinary section.
auto endOfOrdinarySection = StartOfPostmatter;
B.moveBlockTo(epilogBB, endOfOrdinarySection);
// Emit the epilog into the epilog bb. Its arguments are the
// direct results.
directResults.append(epilogBB->bbarg_begin(), epilogBB->bbarg_end());
// If we are falling through from the current block, the return is implicit.
B.emitBlock(epilogBB, ImplicitReturnFromTopLevel);
}
// Emit top-level cleanups into the epilog block.
assert(!Cleanups.hasAnyActiveCleanups(getCleanupsDepth(),
ReturnDest.getDepth()) &&
"emitting epilog in wrong scope");
auto cleanupLoc = CleanupLocation::get(TopLevel);
Cleanups.emitCleanupsForReturn(cleanupLoc);
// If the return location is known to be that of an already
// processed return, use it. (This will get triggered when the
// epilog logic is simplified.)
//
// Otherwise make the ret instruction part of the cleanups.
if (!returnLoc) returnLoc = cleanupLoc;
// Build the return value. We don't do this if there are no direct
// results; this can happen for void functions, but also happens when
// prepareEpilog was asked to not add result arguments to the epilog
// block.
SILValue returnValue;
if (!directResults.empty()) {
assert(directResults.size()
//.........这里部分代码省略.........
示例4: while
static Optional<SILLocation>
prepareForEpilogBlockEmission(SILGenFunction &SGF, SILLocation topLevel,
SILBasicBlock *epilogBB,
SmallVectorImpl<SILValue> &directResults) {
SILLocation implicitReturnFromTopLevel =
ImplicitReturnLocation::getImplicitReturnLoc(topLevel);
// If the current BB we are inserting into isn't terminated, and we require a
// return, then we
// are not allowed to fall off the end of the function and can't reach here.
if (SGF.NeedsReturn && SGF.B.hasValidInsertionPoint())
SGF.B.createUnreachable(implicitReturnFromTopLevel);
if (epilogBB->pred_empty()) {
// If the epilog was not branched to at all, kill the BB and
// just emit the epilog into the current BB.
while (!epilogBB->empty())
epilogBB->back().eraseFromParent();
SGF.eraseBasicBlock(epilogBB);
// If the current bb is terminated then the epilog is just unreachable.
if (!SGF.B.hasValidInsertionPoint())
return None;
// We emit the epilog at the current insertion point.
return implicitReturnFromTopLevel;
}
if (std::next(epilogBB->pred_begin()) == epilogBB->pred_end() &&
!SGF.B.hasValidInsertionPoint()) {
// If the epilog has a single predecessor and there's no current insertion
// point to fall through from, then we can weld the epilog to that
// predecessor BB.
// Steal the branch argument as the return value if present.
SILBasicBlock *pred = *epilogBB->pred_begin();
BranchInst *predBranch = cast<BranchInst>(pred->getTerminator());
assert(predBranch->getArgs().size() == epilogBB->args_size() &&
"epilog predecessor arguments does not match block params");
for (auto index : indices(predBranch->getArgs())) {
SILValue result = predBranch->getArgs()[index];
directResults.push_back(result);
epilogBB->getArgument(index)->replaceAllUsesWith(result);
}
Optional<SILLocation> returnLoc;
// If we are optimizing, we should use the return location from the single,
// previously processed, return statement if any.
if (predBranch->getLoc().is<ReturnLocation>()) {
returnLoc = predBranch->getLoc();
} else {
returnLoc = implicitReturnFromTopLevel;
}
// Kill the branch to the now-dead epilog BB.
pred->erase(predBranch);
// Move any instructions from the EpilogBB to the end of the 'pred' block.
pred->spliceAtEnd(epilogBB);
// Finally we can erase the epilog BB.
SGF.eraseBasicBlock(epilogBB);
// Emit the epilog into its former predecessor.
SGF.B.setInsertionPoint(pred);
return returnLoc;
}
// Move the epilog block to the end of the ordinary section.
auto endOfOrdinarySection = SGF.StartOfPostmatter;
SGF.B.moveBlockTo(epilogBB, endOfOrdinarySection);
// Emit the epilog into the epilog bb. Its arguments are the
// direct results.
directResults.append(epilogBB->args_begin(), epilogBB->args_end());
// If we are falling through from the current block, the return is implicit.
SGF.B.emitBlock(epilogBB, implicitReturnFromTopLevel);
// If the return location is known to be that of an already
// processed return, use it. (This will get triggered when the
// epilog logic is simplified.)
//
// Otherwise make the ret instruction part of the cleanups.
auto cleanupLoc = CleanupLocation::get(topLevel);
return cleanupLoc;
}