Skip to content

SIL: add a utility function to check if a terminator exits a function… #1984

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 31, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions include/swift/SIL/SILInstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -3787,6 +3787,12 @@ class TermInst : public SILInstruction {

bool isBranch() const { return !getSuccessors().empty(); }

/// Returns true if this terminator exits the function.
bool isFunctionExiting() const {
return getKind() == ValueKind::ThrowInst ||
getKind() == ValueKind::ReturnInst;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be an exhaustive switch, so we cover any new instructions we add? Should Unreachable also be considered to exit the function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be an exhaustive switch
Makes sense. I'll change it.

Should Unreachable also be considered to exit the function?
Not for the purposes where this function is used.

}

TermKind getTermKind() const { return ValueKindAsTermKind(getKind()); }
};

Expand Down
8 changes: 4 additions & 4 deletions lib/SIL/SILVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2975,11 +2975,11 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
"stack dealloc does not match most recent stack alloc");
stack.pop_back();
}
if (isa<ReturnInst>(&i) || isa<ThrowInst>(&i)) {
require(stack.empty(),
"return with stack allocs that haven't been deallocated");
}
if (auto term = dyn_cast<TermInst>(&i)) {
if (term->isFunctionExiting()) {
require(stack.empty(),
"return with stack allocs that haven't been deallocated");
}
for (auto &successor : term->getSuccessors()) {
SILBasicBlock *SuccBB = successor.getBB();
auto found = visitedBBs.find(SuccBB);
Expand Down
4 changes: 2 additions & 2 deletions lib/SILOptimizer/IPO/EagerSpecializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ llvm::cl::opt<bool> EagerSpecializeFlag(
/// for new return or error values.
static bool isTrivialReturnBlock(SILBasicBlock *RetBB) {
auto *RetInst = RetBB->getTerminator();
assert(isa<ReturnInst>(RetInst) || isa<ThrowInst>(RetInst) &&
assert(RetInst->isFunctionExiting() &&
"expected a properly terminated return or throw block");

auto RetOperand = RetInst->getOperand(0);
Expand Down Expand Up @@ -87,7 +87,7 @@ static void addReturnValueImpl(SILBasicBlock *RetBB, SILBasicBlock *NewRetBB,
SILLocation Loc = F->getLocation();

auto *RetInst = RetBB->getTerminator();
assert(isa<ReturnInst>(RetInst) || isa<ThrowInst>(RetInst) &&
assert(RetInst->isFunctionExiting() &&
"expected a properly terminated return or throw block");
assert(RetInst->getOperand(0)->getType() == NewRetVal->getType() &&
"Mismatched return type");
Expand Down
2 changes: 1 addition & 1 deletion lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1874,7 +1874,7 @@ SILValue LifetimeChecker::handleConditionalInitAssign() {
// before the return.
for (auto &BB : TheMemory.getFunction()) {
auto *Term = BB.getTerminator();
if (isa<ReturnInst>(Term) || isa<ThrowInst>(Term)) {
if (Term->isFunctionExiting()) {
B.setInsertionPoint(Term);
B.createDeallocStack(Loc, ControlVariableBox);
}
Expand Down
4 changes: 2 additions & 2 deletions lib/SILOptimizer/Mandatory/InOutDeshadowing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ class StackSlotState {
// We need to see a store back to the inout on every exit path.
for (auto &bb : *F) {
auto term = bb.getTerminator();
if (isa<ReturnInst>(term) || isa<ThrowInst>(term)) {
if (term->isFunctionExiting()) {
DEBUG(llvm::dbgs() << " need load from stack slot on exit " << &bb
<< '\n');
ExitBBs.insert(&bb);
Expand Down Expand Up @@ -224,7 +224,7 @@ static void analyzeUseOfInOut(Operand *UI, StackSlotState &state) {
if (isa<UnreachableInst>(term))
return;

if (!isa<ReturnInst>(term) && !isa<ThrowInst>(term))
if (!term->isFunctionExiting())
// Any copy from the inout outside of an exit block fails the analysis.
// We don't need full flow-sensitive analysis for SILGen-ed code.
return state.setFailed("inout is stored outside of an exit block");
Expand Down
4 changes: 2 additions & 2 deletions lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,10 +219,10 @@ bool PartialApplyCombiner::allocateTemporaries() {

/// Emit dealloc_stack for all temporaries.
void PartialApplyCombiner::deallocateTemporaries() {
// Insert dealloc_stack instructions.
// Insert dealloc_stack instructions at all function exit points.
for (SILBasicBlock &BB : *PAI->getFunction()) {
TermInst *Term = BB.getTerminator();
if (!isa<ReturnInst>(Term) && !isa<ThrowInst>(Term))
if (!Term->isFunctionExiting())
continue;

for (auto Op : Tmps) {
Expand Down
2 changes: 1 addition & 1 deletion lib/SILOptimizer/Transforms/AllocBoxToStack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -837,7 +837,7 @@ class AllocBoxToStack : public SILFunctionTransform {

for (auto &BB : *getFunction()) {
auto *Term = BB.getTerminator();
if (isa<ReturnInst>(Term) || isa<ThrowInst>(Term))
if (Term->isFunctionExiting())
Returns.push_back(Term);

for (auto &I : BB)
Expand Down