aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/X86/X86WinEHState.cpp
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2016-02-18 21:13:35 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2016-02-18 21:13:35 +0000
commita822c880a90b6f393664848ea7b28bcd2110e9ab (patch)
treedb65528de09fe4debf6c52757cdf84b53ddfd890 /llvm/lib/Target/X86/X86WinEHState.cpp
parent0fc35d0a42057ab416737b38a9f836d6c99aac4c (diff)
downloadllvm-a822c880a90b6f393664848ea7b28bcd2110e9ab.zip
llvm-a822c880a90b6f393664848ea7b28bcd2110e9ab.tar.gz
llvm-a822c880a90b6f393664848ea7b28bcd2110e9ab.tar.bz2
[WinEH] Hoist state stores from successors
If we know that all of our successors want to be in the exact same state, it makes sense to hoist the state transition into their common predecessor. Differential Revision: http://reviews.llvm.org/D17391 llvm-svn: 261262
Diffstat (limited to 'llvm/lib/Target/X86/X86WinEHState.cpp')
-rw-r--r--llvm/lib/Target/X86/X86WinEHState.cpp55
1 files changed, 54 insertions, 1 deletions
diff --git a/llvm/lib/Target/X86/X86WinEHState.cpp b/llvm/lib/Target/X86/X86WinEHState.cpp
index ee2fb6d..b4edb88 100644
--- a/llvm/lib/Target/X86/X86WinEHState.cpp
+++ b/llvm/lib/Target/X86/X86WinEHState.cpp
@@ -433,7 +433,7 @@ static int getStateForCallSite(DenseMap<BasicBlock *, ColorVector> &BlockColors,
}
// Calculate the intersection of all the FinalStates for a BasicBlock's
-// predecessor.
+// predecessors.
static int getPredState(DenseMap<BasicBlock *, int> &FinalStates, Function &F,
int ParentBaseState, BasicBlock *BB) {
// The entry block has no predecessors but we know that the prologue always
@@ -473,6 +473,42 @@ static int getPredState(DenseMap<BasicBlock *, int> &FinalStates, Function &F,
return CommonState;
}
+// Calculate the intersection of all the InitialStates for a BasicBlock's
+// successors.
+static int getSuccState(DenseMap<BasicBlock *, int> &InitialStates, Function &F,
+ int ParentBaseState, BasicBlock *BB) {
+ // This block rejoins normal control flow,
+ // conservatively report this basic block as overdefined.
+ if (isa<CatchReturnInst>(BB->getTerminator()))
+ return OverdefinedState;
+
+ int CommonState = OverdefinedState;
+ for (BasicBlock *SuccBB : successors(BB)) {
+ // We didn't manage to get a state for one of these predecessors,
+ // conservatively report this basic block as overdefined.
+ auto SuccStartState = InitialStates.find(SuccBB);
+ if (SuccStartState == InitialStates.end())
+ return OverdefinedState;
+
+ // This is an EH Pad, conservatively report this basic block as overdefined.
+ if (SuccBB->isEHPad())
+ return OverdefinedState;
+
+ int SuccState = SuccStartState->second;
+ assert(SuccState != OverdefinedState &&
+ "overdefined BBs shouldn't be in FinalStates");
+ if (CommonState == OverdefinedState)
+ CommonState = SuccState;
+
+ // At least two successors have different InitialStates,
+ // conservatively report this basic block as overdefined.
+ if (CommonState != SuccState)
+ return OverdefinedState;
+ }
+
+ return CommonState;
+}
+
static bool isStateStoreNeeded(EHPersonality Personality, CallSite CS) {
if (!CS)
return false;
@@ -559,6 +595,17 @@ void WinEHStatePass::addStateStores(Function &F, WinEHFuncInfo &FuncInfo) {
Worklist.push_back(SuccBB);
}
+ // Try to hoist stores from successors.
+ for (BasicBlock *BB : RPOT) {
+ int SuccState = getSuccState(InitialStates, F, ParentBaseState, BB);
+ if (SuccState == OverdefinedState)
+ continue;
+
+ // Update our FinalState to reflect the common InitialState of our
+ // successors.
+ FinalStates.insert({BB, SuccState});
+ }
+
// Finally, insert state stores before call-sites which transition us to a new
// state.
for (BasicBlock *BB : RPOT) {
@@ -581,6 +628,12 @@ void WinEHStatePass::addStateStores(Function &F, WinEHFuncInfo &FuncInfo) {
insertStateNumberStore(&I, State);
PrevState = State;
}
+
+ // We might have hoisted a state store into this block, emit it now.
+ auto EndState = FinalStates.find(BB);
+ if (EndState != FinalStates.end())
+ if (EndState->second != PrevState)
+ insertStateNumberStore(BB->getTerminator(), EndState->second);
}
}