[WinEH] Hoist state stores from successors
authorDavid Majnemer <david.majnemer@gmail.com>
Thu, 18 Feb 2016 21:13:35 +0000 (21:13 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Thu, 18 Feb 2016 21:13:35 +0000 (21:13 +0000)
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
llvm/test/CodeGen/X86/win-catchpad.ll

index ee2fb6d..b4edb88 100644 (file)
@@ -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);
   }
 }
 
index dc1490f..f6db515 100644 (file)
@@ -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]]