summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Target/X86/X86WinEHState.cpp55
-rw-r--r--llvm/test/CodeGen/X86/win-catchpad.ll2
2 files changed, 55 insertions, 2 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);
}
}
diff --git a/llvm/test/CodeGen/X86/win-catchpad.ll b/llvm/test/CodeGen/X86/win-catchpad.ll
index dc1490fadda..f6db515cbad 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]]
OpenPOWER on IntegriCloud