diff --git a/bolt/lib/Core/BinaryFunction.cpp b/bolt/lib/Core/BinaryFunction.cpp
--- a/bolt/lib/Core/BinaryFunction.cpp
+++ b/bolt/lib/Core/BinaryFunction.cpp
@@ -1884,8 +1884,12 @@
       if (!EHInfo || !EHInfo->first)
         continue;
 
-      BinaryBasicBlock *LPBlock = getBasicBlockForLabel(EHInfo->first);
-      if (!BBLandingPads.count(LPBlock)) {
+      // If LPFunc has no CFG, LPBlock does not exist
+      // Solution: rerun recomputeLandingPads after buildCFG for all functions
+      const MCSymbol *LPLabel = EHInfo->first;
+      BinaryFunction *LPFunc = BC.getFunctionForSymbol(LPLabel);
+      BinaryBasicBlock *LPBlock = LPFunc->getBasicBlockForLabel(LPLabel);
+      if (LPBlock != nullptr && !BBLandingPads.count(LPBlock)) {
         BBLandingPads.insert(LPBlock);
         BB->LandingPads.emplace_back(LPBlock);
         LPBlock->Throwers.emplace_back(BB);
diff --git a/bolt/lib/Core/Exceptions.cpp b/bolt/lib/Core/Exceptions.cpp
--- a/bolt/lib/Core/Exceptions.cpp
+++ b/bolt/lib/Core/Exceptions.cpp
@@ -177,12 +177,11 @@
 
     uint64_t LPOffset = LPStart + LandingPad;
     uint64_t LPAddress = Address + LPOffset;
+    BinaryFunction *Fragment = BC.getBinaryFunctionContainingAddress(LPAddress);
 
     // Verify if landing pad code is located outside current function
     // Support landing pad to builtin_unreachable
     if (LPAddress < Address || LPAddress > Address + getSize()) {
-      BinaryFunction *Fragment =
-          BC.getBinaryFunctionContainingAddress(LPAddress);
       assert(Fragment != nullptr &&
              "BOLT-ERROR: cannot find landing pad fragment");
       BC.addInterproceduralReference(this, Fragment->getAddress());
@@ -196,37 +195,51 @@
              "functions");
       setHasIndirectTargetToSplitFragment(true);
       BC.addFragmentsToSkip(this);
-      return;
     }
 
-    if (opts::PrintExceptions) {
-      outs() << "Call Site: [0x" << Twine::utohexstr(RangeBase + Start)
-             << ", 0x" << Twine::utohexstr(RangeBase + Start + Length)
-             << "); landing pad: 0x" << Twine::utohexstr(LPOffset)
-             << "; action entry: 0x" << Twine::utohexstr(ActionEntry) << "\n";
-      outs() << "  current offset is " << (CallSitePtr - CallSiteTableStart)
-             << '\n';
-    }
+    // Special case, consider builtin_unreachable as part of this function
+    if (LPAddress == Address + getSize())
+      Fragment = this;
 
     // Create a handler entry if necessary.
-    MCSymbol *LPSymbol = nullptr;
-    if (LPOffset) {
-      if (!getInstructionAtOffset(LPOffset)) {
+    MCSymbol *LPLabel = nullptr;
+
+    // Assumption: landing pad cannot target current fragment entry
+    // Note: split landing pad can target other fragment entry
+    if (LPAddress != Address) {
+      uint64_t FragmentOffset = LPAddress - Fragment->getAddress();
+      if (!Fragment->getInstructionAtOffset(FragmentOffset)) {
         if (opts::Verbosity >= 1)
           errs() << "BOLT-WARNING: landing pad " << Twine::utohexstr(LPOffset)
-                 << " not pointing to an instruction in function " << *this
+                 << " not pointing to an instruction in function " << *Fragment
                  << " - ignoring.\n";
       } else {
-        auto Label = Labels.find(LPOffset);
-        if (Label != Labels.end()) {
-          LPSymbol = Label->second;
-        } else {
-          LPSymbol = BC.Ctx->createNamedTempSymbol("LP");
-          Labels[LPOffset] = LPSymbol;
-        }
+        // Create or fetch landing pad label
+        // For landing pad in same function, create a local label
+        // For landing pad in a sibling fragment, register as a secondary entry
+        auto Label = Fragment->Labels.find(FragmentOffset);
+        LPLabel = (Label != Fragment->Labels.end())
+                      ? Label->second
+                      : ((Fragment != this)
+                             ? Fragment->addEntryPointAtOffset(FragmentOffset)
+                             : BC.Ctx->createNamedTempSymbol("LP"));
+        // Support recomputeLandingPad to identify split landing pad
+        BC.setSymbolToFunctionMap(LPLabel, Fragment);
+        Labels[LPOffset] = LPLabel;
       }
     }
 
+    if (opts::PrintExceptions) {
+      outs() << "Call Site: [0x" << Twine::utohexstr(RangeBase + Start)
+             << ", 0x" << Twine::utohexstr(RangeBase + Start + Length)
+             << "); landing pad: 0x" << Twine::utohexstr(LPOffset)
+             << "; action entry: 0x" << Twine::utohexstr(ActionEntry) << "\n";
+      outs() << "  current offset is " << (CallSitePtr - CallSiteTableStart)
+             << '\n';
+      if (LPLabel != nullptr)
+        outs() << "  landing pad label: " << LPLabel->getName() << "\n";
+    }
+
     // Mark all call instructions in the range.
     auto II = Instructions.find(Start);
     auto IE = Instructions.end();
@@ -240,7 +253,7 @@
         // Add extra operands to a call instruction making it an invoke from
         // now on.
         BC.MIB->addEHInfo(Instruction,
-                          MCPlus::MCLandingPad(LPSymbol, ActionEntry));
+                          MCPlus::MCLandingPad(LPLabel, ActionEntry));
       }
       ++II;
     } while (II != IE && II->first < Start + Length);
diff --git a/bolt/lib/Passes/SplitFunctions.cpp b/bolt/lib/Passes/SplitFunctions.cpp
--- a/bolt/lib/Passes/SplitFunctions.cpp
+++ b/bolt/lib/Passes/SplitFunctions.cpp
@@ -333,8 +333,11 @@
       if (!EHInfo || !EHInfo->first)
         continue;
 
+      // In case of split landing pad, LPFunc != BF
       const MCSymbol *LPLabel = EHInfo->first;
-      BinaryBasicBlock *LPBlock = BF.getBasicBlockForLabel(LPLabel);
+      BinaryFunction *LPFunc =
+          BF.getBinaryContext().getFunctionForSymbol(LPLabel);
+      BinaryBasicBlock *LPBlock = LPFunc->getBasicBlockForLabel(LPLabel);
       if (BB->isCold() == LPBlock->isCold())
         continue;
 
@@ -346,13 +349,14 @@
         // Create a trampoline basic block in the same fragment as the thrower.
         // Note: there's no need to insert the jump instruction, it will be
         // added by fixBranches().
-        BinaryBasicBlock *TrampolineBB = BF.addBasicBlock();
+        BinaryBasicBlock *TrampolineBB = LPFunc->addBasicBlock();
         TrampolineBB->setIsCold(BB->isCold());
         TrampolineBB->setExecutionCount(LPBlock->getExecutionCount());
         TrampolineBB->addSuccessor(LPBlock, TrampolineBB->getExecutionCount());
         TrampolineBB->setCFIState(LPBlock->getCFIState());
         TrampolineLabel = TrampolineBB->getLabel();
         LPTrampolines.insert(std::make_pair(LPLabel, TrampolineLabel));
+        BF.getBinaryContext().setSymbolToFunctionMap(TrampolineLabel, LPFunc);
       }
 
       // Substitute the landing pad with the trampoline.
diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp
--- a/bolt/lib/Rewrite/RewriteInstance.cpp
+++ b/bolt/lib/Rewrite/RewriteInstance.cpp
@@ -2922,9 +2922,10 @@
     if (!shouldDisassemble(Function))
       continue;
 
-    if (!Function.isSimple()) {
-      assert((!BC->HasRelocations || Function.getSize() == 0 ||
-              Function.hasIndirectTargetToSplitFragment()) &&
+    // Process non-simple cases due to split jump table or split landing pad
+    // Ignore all other non-simple cases
+    if (!Function.isSimple() && !Function.hasIndirectTargetToSplitFragment()) {
+      assert((!BC->HasRelocations || Function.getSize() == 0) &&
              "unexpected non-simple function in relocation mode");
       continue;
     }
@@ -2978,6 +2979,18 @@
       /*ForceSequential*/ opts::SequentialDisassembly || opts::PrintAll);
 
   BC->postProcessSymbolTable();
+
+  // recomputeLandingPads is invoked during buildCFG for every function.
+  // For split landing pad, it is possible that the target function does
+  // not yet have CFG, so recomputeLandingPads would fail to capture
+  // cross-function targets.
+  //
+  // Solution:
+  // (a) Safely ignore split landing pad during buildCFG
+  // (b) Rerun recomputeLandingPads after all functions have CFG
+  for (BinaryFunction *Function : BC->getAllBinaryFunctions())
+    if (Function->getState() == BinaryFunction::State::CFG)
+      Function->recomputeLandingPads();
 }
 
 void RewriteInstance::postProcessFunctions() {
diff --git a/bolt/test/X86/split-landing-pad.s b/bolt/test/X86/split-landing-pad.s
--- a/bolt/test/X86/split-landing-pad.s
+++ b/bolt/test/X86/split-landing-pad.s
@@ -25,10 +25,13 @@
 # REQUIRES: system-linux
 # RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s -o %t.o
 # RUN: %clang++ %cxxflags %t.o -o %t.exe -Wl,-q
-# RUN: llvm-bolt -v=3 %t.exe -o %t.out 2>&1 | FileCheck %s
+# RUN: llvm-bolt -v=3 %t.exe -o %t.out -print-exceptions 2>&1 | FileCheck %s
 
-# CHECK: BOLT-WARNING: Ignoring foo
-# CHECK: BOLT-WARNING: Ignoring foo.cold.1
+# CHECK: BOLT-INFO: marking [[FOO_COLD:.+]] as a fragment of [[FOO:.+]]
+# CHECK: landing pad label: [[TMP2:.+]]
+# CHECK: landing pad label: [[TMP5:.+]]
+# CHECK: BOLT-WARNING: Ignoring [[FOO]]
+# CHECK: BOLT-WARNING: Ignoring [[FOO_COLD]]
 # CHECK: BOLT-WARNING: skipped 2 functions due to cold fragments
 
 	.text