Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit 777d6e5

Browse files
committed
Simplify EH control flow by observing that EH scopes form a simple
hierarchy of delegation, and that EH selector values are meaningful function-wide (good thing, too, or inlining wouldn't work). 2,3d 1a hierarchy of delegation and that EH selector values have the same meaning everywhere in the function instead of being meaningful only in the context of a specific selector. This removes the need for routing edges through EH cleanups, since a cleanup simply always branches to its enclosing scope. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@137293 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 75eeeb1 commit 777d6e5

13 files changed

+540
-656
lines changed

Diff for: lib/CodeGen/CGCleanup.cpp

+63-182
Original file line numberDiff line numberDiff line change
@@ -119,16 +119,30 @@ char *EHScopeStack::allocate(size_t Size) {
119119
}
120120

121121
EHScopeStack::stable_iterator
122-
EHScopeStack::getEnclosingEHCleanup(iterator it) const {
123-
assert(it != end());
124-
do {
125-
if (isa<EHCleanupScope>(*it)) {
126-
if (cast<EHCleanupScope>(*it).isEHCleanup())
127-
return stabilize(it);
128-
return cast<EHCleanupScope>(*it).getEnclosingEHCleanup();
122+
EHScopeStack::getInnermostActiveNormalCleanup() const {
123+
for (stable_iterator si = getInnermostNormalCleanup(), se = stable_end();
124+
si != se; ) {
125+
EHCleanupScope &cleanup = cast<EHCleanupScope>(*find(si));
126+
if (cleanup.isActive()) return si;
127+
si = cleanup.getEnclosingNormalCleanup();
128+
}
129+
return stable_end();
130+
}
131+
132+
EHScopeStack::stable_iterator EHScopeStack::getInnermostActiveEHScope() const {
133+
for (stable_iterator si = getInnermostEHScope(), se = stable_end();
134+
si != se; ) {
135+
// Skip over inactive cleanups.
136+
EHCleanupScope *cleanup = dyn_cast<EHCleanupScope>(&*find(si));
137+
if (cleanup && !cleanup->isActive()) {
138+
si = cleanup->getEnclosingEHScope();
139+
continue;
129140
}
130-
++it;
131-
} while (it != end());
141+
142+
// All other scopes are always active.
143+
return si;
144+
}
145+
132146
return stable_end();
133147
}
134148

@@ -146,11 +160,11 @@ void *EHScopeStack::pushCleanup(CleanupKind Kind, size_t Size) {
146160
Size,
147161
BranchFixups.size(),
148162
InnermostNormalCleanup,
149-
InnermostEHCleanup);
163+
InnermostEHScope);
150164
if (IsNormalCleanup)
151165
InnermostNormalCleanup = stable_begin();
152166
if (IsEHCleanup)
153-
InnermostEHCleanup = stable_begin();
167+
InnermostEHScope = stable_begin();
154168

155169
return Scope->getCleanupBuffer();
156170
}
@@ -161,11 +175,9 @@ void EHScopeStack::popCleanup() {
161175
assert(isa<EHCleanupScope>(*begin()));
162176
EHCleanupScope &Cleanup = cast<EHCleanupScope>(*begin());
163177
InnermostNormalCleanup = Cleanup.getEnclosingNormalCleanup();
164-
InnermostEHCleanup = Cleanup.getEnclosingEHCleanup();
178+
InnermostEHScope = Cleanup.getEnclosingEHScope();
165179
StartOfData += Cleanup.getAllocatedSize();
166180

167-
if (empty()) NextEHDestIndex = FirstEHDestIndex;
168-
169181
// Destroy the cleanup.
170182
Cleanup.~EHCleanupScope();
171183

@@ -182,37 +194,35 @@ void EHScopeStack::popCleanup() {
182194
}
183195
}
184196

185-
EHFilterScope *EHScopeStack::pushFilter(unsigned NumFilters) {
186-
char *Buffer = allocate(EHFilterScope::getSizeForNumFilters(NumFilters));
187-
CatchDepth++;
188-
return new (Buffer) EHFilterScope(NumFilters);
197+
EHFilterScope *EHScopeStack::pushFilter(unsigned numFilters) {
198+
assert(getInnermostEHScope() == stable_end());
199+
char *buffer = allocate(EHFilterScope::getSizeForNumFilters(numFilters));
200+
EHFilterScope *filter = new (buffer) EHFilterScope(numFilters);
201+
InnermostEHScope = stable_begin();
202+
return filter;
189203
}
190204

191205
void EHScopeStack::popFilter() {
192206
assert(!empty() && "popping exception stack when not empty");
193207

194-
EHFilterScope &Filter = cast<EHFilterScope>(*begin());
195-
StartOfData += EHFilterScope::getSizeForNumFilters(Filter.getNumFilters());
196-
197-
if (empty()) NextEHDestIndex = FirstEHDestIndex;
208+
EHFilterScope &filter = cast<EHFilterScope>(*begin());
209+
StartOfData += EHFilterScope::getSizeForNumFilters(filter.getNumFilters());
198210

199-
assert(CatchDepth > 0 && "mismatched filter push/pop");
200-
CatchDepth--;
211+
InnermostEHScope = filter.getEnclosingEHScope();
201212
}
202213

203-
EHCatchScope *EHScopeStack::pushCatch(unsigned NumHandlers) {
204-
char *Buffer = allocate(EHCatchScope::getSizeForNumHandlers(NumHandlers));
205-
CatchDepth++;
206-
EHCatchScope *Scope = new (Buffer) EHCatchScope(NumHandlers);
207-
for (unsigned I = 0; I != NumHandlers; ++I)
208-
Scope->getHandlers()[I].Index = getNextEHDestIndex();
209-
return Scope;
214+
EHCatchScope *EHScopeStack::pushCatch(unsigned numHandlers) {
215+
char *buffer = allocate(EHCatchScope::getSizeForNumHandlers(numHandlers));
216+
EHCatchScope *scope =
217+
new (buffer) EHCatchScope(numHandlers, InnermostEHScope);
218+
InnermostEHScope = stable_begin();
219+
return scope;
210220
}
211221

212222
void EHScopeStack::pushTerminate() {
213223
char *Buffer = allocate(EHTerminateScope::getSize());
214-
CatchDepth++;
215-
new (Buffer) EHTerminateScope(getNextEHDestIndex());
224+
new (Buffer) EHTerminateScope(InnermostEHScope);
225+
InnermostEHScope = stable_begin();
216226
}
217227

218228
/// Remove any 'null' fixups on the stack. However, we can't pop more
@@ -384,17 +394,6 @@ static llvm::BasicBlock *CreateNormalEntry(CodeGenFunction &CGF,
384394
return Entry;
385395
}
386396

387-
static llvm::BasicBlock *CreateEHEntry(CodeGenFunction &CGF,
388-
EHCleanupScope &Scope) {
389-
assert(Scope.isEHCleanup());
390-
llvm::BasicBlock *Entry = Scope.getEHBlock();
391-
if (!Entry) {
392-
Entry = CGF.createBasicBlock("eh.cleanup");
393-
Scope.setEHBlock(Entry);
394-
}
395-
return Entry;
396-
}
397-
398397
/// Attempts to reduce a cleanup's entry block to a fallthrough. This
399398
/// is basically llvm::MergeBlockIntoPredecessor, except
400399
/// simplified/optimized for the tighter constraints on cleanup blocks.
@@ -544,7 +543,10 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
544543

545544
// Check whether we need an EH cleanup. This is only true if we've
546545
// generated a lazy EH cleanup block.
547-
bool RequiresEHCleanup = Scope.hasEHBranches();
546+
llvm::BasicBlock *EHEntry = Scope.getCachedEHDispatchBlock();
547+
assert(Scope.hasEHBranches() == (EHEntry != 0));
548+
bool RequiresEHCleanup = (EHEntry != 0);
549+
EHScopeStack::stable_iterator EHParent = Scope.getEnclosingEHScope();
548550

549551
// Check the three conditions which might require a normal cleanup:
550552

@@ -580,12 +582,6 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
580582
RequiresNormalCleanup = true;
581583
}
582584

583-
EHScopeStack::Cleanup::Flags cleanupFlags;
584-
if (Scope.isNormalCleanup())
585-
cleanupFlags.setIsNormalCleanupKind();
586-
if (Scope.isEHCleanup())
587-
cleanupFlags.setIsEHCleanupKind();
588-
589585
// If we have a prebranched fallthrough into an inactive normal
590586
// cleanup, rewrite it so that it leads to the appropriate place.
591587
if (Scope.isNormalCleanup() && HasPrebranchedFallthrough && !IsActive) {
@@ -634,61 +630,11 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
634630
EHScopeStack::Cleanup *Fn =
635631
reinterpret_cast<EHScopeStack::Cleanup*>(CleanupBuffer.data());
636632

637-
// We want to emit the EH cleanup after the normal cleanup, but go
638-
// ahead and do the setup for the EH cleanup while the scope is still
639-
// alive.
640-
llvm::BasicBlock *EHEntry = 0;
641-
SmallVector<llvm::Instruction*, 2> EHInstsToAppend;
642-
if (RequiresEHCleanup) {
643-
EHEntry = CreateEHEntry(*this, Scope);
644-
645-
// Figure out the branch-through dest if necessary.
646-
llvm::BasicBlock *EHBranchThroughDest = 0;
647-
if (Scope.hasEHBranchThroughs()) {
648-
assert(Scope.getEnclosingEHCleanup() != EHStack.stable_end());
649-
EHScope &S = *EHStack.find(Scope.getEnclosingEHCleanup());
650-
EHBranchThroughDest = CreateEHEntry(*this, cast<EHCleanupScope>(S));
651-
}
652-
653-
// If we have exactly one branch-after and no branch-throughs, we
654-
// can dispatch it without a switch.
655-
if (!Scope.hasEHBranchThroughs() &&
656-
Scope.getNumEHBranchAfters() == 1) {
657-
assert(!EHBranchThroughDest);
658-
659-
// TODO: remove the spurious eh.cleanup.dest stores if this edge
660-
// never went through any switches.
661-
llvm::BasicBlock *BranchAfterDest = Scope.getEHBranchAfterBlock(0);
662-
EHInstsToAppend.push_back(llvm::BranchInst::Create(BranchAfterDest));
663-
664-
// Otherwise, if we have any branch-afters, we need a switch.
665-
} else if (Scope.getNumEHBranchAfters()) {
666-
// The default of the switch belongs to the branch-throughs if
667-
// they exist.
668-
llvm::BasicBlock *Default =
669-
(EHBranchThroughDest ? EHBranchThroughDest : getUnreachableBlock());
670-
671-
const unsigned SwitchCapacity = Scope.getNumEHBranchAfters();
672-
673-
llvm::LoadInst *Load =
674-
new llvm::LoadInst(getEHCleanupDestSlot(), "cleanup.dest");
675-
llvm::SwitchInst *Switch =
676-
llvm::SwitchInst::Create(Load, Default, SwitchCapacity);
677-
678-
EHInstsToAppend.push_back(Load);
679-
EHInstsToAppend.push_back(Switch);
680-
681-
for (unsigned I = 0, E = Scope.getNumEHBranchAfters(); I != E; ++I)
682-
Switch->addCase(Scope.getEHBranchAfterIndex(I),
683-
Scope.getEHBranchAfterBlock(I));
684-
685-
// Otherwise, we have only branch-throughs; jump to the next EH
686-
// cleanup.
687-
} else {
688-
assert(EHBranchThroughDest);
689-
EHInstsToAppend.push_back(llvm::BranchInst::Create(EHBranchThroughDest));
690-
}
691-
}
633+
EHScopeStack::Cleanup::Flags cleanupFlags;
634+
if (Scope.isNormalCleanup())
635+
cleanupFlags.setIsNormalCleanupKind();
636+
if (Scope.isEHCleanup())
637+
cleanupFlags.setIsEHCleanupKind();
692638

693639
if (!RequiresNormalCleanup) {
694640
destroyOptimisticNormalEntry(*this, Scope);
@@ -890,10 +836,7 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
890836
cleanupFlags.setIsForEHCleanup();
891837
EmitCleanup(*this, Fn, cleanupFlags, EHActiveFlag);
892838

893-
// Append the prepared cleanup prologue from above.
894-
llvm::BasicBlock *EHExit = Builder.GetInsertBlock();
895-
for (unsigned I = 0, E = EHInstsToAppend.size(); I != E; ++I)
896-
EHExit->getInstList().push_back(EHInstsToAppend[I]);
839+
Builder.CreateBr(getEHDispatchBlock(EHParent));
897840

898841
Builder.restoreIP(SavedIP);
899842

@@ -1005,64 +948,6 @@ void CodeGenFunction::EmitBranchThroughCleanup(JumpDest Dest) {
1005948
Builder.ClearInsertionPoint();
1006949
}
1007950

1008-
void CodeGenFunction::EmitBranchThroughEHCleanup(UnwindDest Dest) {
1009-
// We should never get invalid scope depths for an UnwindDest; that
1010-
// implies that the destination wasn't set up correctly.
1011-
assert(Dest.getScopeDepth().isValid() && "invalid scope depth on EH dest?");
1012-
1013-
if (!HaveInsertPoint())
1014-
return;
1015-
1016-
// Create the branch.
1017-
llvm::BranchInst *BI = Builder.CreateBr(Dest.getBlock());
1018-
1019-
// Calculate the innermost active cleanup.
1020-
EHScopeStack::stable_iterator
1021-
InnermostCleanup = EHStack.getInnermostActiveEHCleanup();
1022-
1023-
// If the destination is in the same EH cleanup scope as us, we
1024-
// don't need to thread through anything.
1025-
if (InnermostCleanup.encloses(Dest.getScopeDepth())) {
1026-
Builder.ClearInsertionPoint();
1027-
return;
1028-
}
1029-
assert(InnermostCleanup != EHStack.stable_end());
1030-
1031-
// Store the index at the start.
1032-
llvm::ConstantInt *Index = Builder.getInt32(Dest.getDestIndex());
1033-
new llvm::StoreInst(Index, getEHCleanupDestSlot(), BI);
1034-
1035-
// Adjust BI to point to the first cleanup block.
1036-
{
1037-
EHCleanupScope &Scope =
1038-
cast<EHCleanupScope>(*EHStack.find(InnermostCleanup));
1039-
BI->setSuccessor(0, CreateEHEntry(*this, Scope));
1040-
}
1041-
1042-
// Add this destination to all the scopes involved.
1043-
for (EHScopeStack::stable_iterator
1044-
I = InnermostCleanup, E = Dest.getScopeDepth(); ; ) {
1045-
assert(E.strictlyEncloses(I));
1046-
EHCleanupScope &Scope = cast<EHCleanupScope>(*EHStack.find(I));
1047-
assert(Scope.isEHCleanup());
1048-
I = Scope.getEnclosingEHCleanup();
1049-
1050-
// If this is the last cleanup we're propagating through, add this
1051-
// as a branch-after.
1052-
if (I == E) {
1053-
Scope.addEHBranchAfter(Index, Dest.getBlock());
1054-
break;
1055-
}
1056-
1057-
// Otherwise, add it as a branch-through. If this isn't new
1058-
// information, all the rest of the work has been done before.
1059-
if (!Scope.addEHBranchThrough(Dest.getBlock()))
1060-
break;
1061-
}
1062-
1063-
Builder.ClearInsertionPoint();
1064-
}
1065-
1066951
static bool IsUsedAsNormalCleanup(EHScopeStack &EHStack,
1067952
EHScopeStack::stable_iterator C) {
1068953
// If we needed a normal block for any reason, that counts.
@@ -1083,18 +968,21 @@ static bool IsUsedAsNormalCleanup(EHScopeStack &EHStack,
1083968
}
1084969

1085970
static bool IsUsedAsEHCleanup(EHScopeStack &EHStack,
1086-
EHScopeStack::stable_iterator C) {
971+
EHScopeStack::stable_iterator cleanup) {
1087972
// If we needed an EH block for any reason, that counts.
1088-
if (cast<EHCleanupScope>(*EHStack.find(C)).getEHBlock())
973+
if (EHStack.find(cleanup)->hasEHBranches())
1089974
return true;
1090975

1091976
// Check whether any enclosed cleanups were needed.
1092977
for (EHScopeStack::stable_iterator
1093-
I = EHStack.getInnermostEHCleanup(); I != C; ) {
1094-
assert(C.strictlyEncloses(I));
1095-
EHCleanupScope &S = cast<EHCleanupScope>(*EHStack.find(I));
1096-
if (S.getEHBlock()) return true;
1097-
I = S.getEnclosingEHCleanup();
978+
i = EHStack.getInnermostEHScope(); i != cleanup; ) {
979+
assert(cleanup.strictlyEncloses(i));
980+
981+
EHScope &scope = *EHStack.find(i);
982+
if (scope.hasEHBranches())
983+
return true;
984+
985+
i = scope.getEnclosingEHScope();
1098986
}
1099987

1100988
return false;
@@ -1189,10 +1077,3 @@ llvm::Value *CodeGenFunction::getNormalCleanupDestSlot() {
11891077
CreateTempAlloca(Builder.getInt32Ty(), "cleanup.dest.slot");
11901078
return NormalCleanupDest;
11911079
}
1192-
1193-
llvm::Value *CodeGenFunction::getEHCleanupDestSlot() {
1194-
if (!EHCleanupDest)
1195-
EHCleanupDest =
1196-
CreateTempAlloca(Builder.getInt32Ty(), "eh.cleanup.dest.slot");
1197-
return EHCleanupDest;
1198-
}

0 commit comments

Comments
 (0)