Index: lib/Target/X86/X86WinEHState.cpp =================================================================== --- lib/Target/X86/X86WinEHState.cpp +++ lib/Target/X86/X86WinEHState.cpp @@ -433,7 +433,7 @@ } // 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 @@ 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 @@ 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 @@ 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); } } Index: test/CodeGen/X86/win-catchpad.ll =================================================================== --- test/CodeGen/X86/win-catchpad.ll +++ test/CodeGen/X86/win-catchpad.ll @@ -255,8 +255,8 @@ ; 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]]