diff options
Diffstat (limited to 'llvm/lib/Target/X86')
-rw-r--r-- | llvm/lib/Target/X86/X86WinEHState.cpp | 55 |
1 files changed, 54 insertions, 1 deletions
diff --git a/llvm/lib/Target/X86/X86WinEHState.cpp b/llvm/lib/Target/X86/X86WinEHState.cpp index ee2fb6dae9d..b4edb88d850 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); } } |