From a822c880a90b6f393664848ea7b28bcd2110e9ab Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Thu, 18 Feb 2016 21:13:35 +0000 Subject: [PATCH] [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 --- llvm/lib/Target/X86/X86WinEHState.cpp | 55 ++++++++++++++++++++++++++++++++++- llvm/test/CodeGen/X86/win-catchpad.ll | 2 +- 2 files changed, 55 insertions(+), 2 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 &BlockColors, } // Calculate the intersection of all the FinalStates for a BasicBlock's -// predecessor. +// predecessors. static int getPredState(DenseMap &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 &FinalStates, Function &F, return CommonState; } +// Calculate the intersection of all the InitialStates for a BasicBlock's +// successors. +static int getSuccState(DenseMap &InitialStates, Function &F, + int ParentBaseState, BasicBlock *BB) { + // This block rejoins normal control flow, + // conservatively report this basic block as overdefined. + if (isa(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); } } diff --git a/llvm/test/CodeGen/X86/win-catchpad.ll b/llvm/test/CodeGen/X86/win-catchpad.ll index dc1490f..f6db515 100644 --- a/llvm/test/CodeGen/X86/win-catchpad.ll +++ b/llvm/test/CodeGen/X86/win-catchpad.ll @@ -255,8 +255,8 @@ try.cont: ; X86: pushl %ebp ; X86: subl $8, %esp ; X86: addl $12, %ebp -; X86: LBB1_[[loopbb:[0-9]+]]: # %loop ; X86: movl $1, -16(%ebp) +; X86: LBB1_[[loopbb:[0-9]+]]: # %loop ; X86: calll _getbool ; X86: testb $1, %al ; X86: jne LBB1_[[loopbb]] -- 2.7.4