Index: lib/CodeGen/WinEHPrepare.cpp =================================================================== --- lib/CodeGen/WinEHPrepare.cpp +++ lib/CodeGen/WinEHPrepare.cpp @@ -925,6 +925,26 @@ return CloningDirector::CloneInstruction; } + if (auto *Compare = dyn_cast(Inst)) { + // Look for compare instructions that use selector values that were not + // defined in the current block. A series of related catch dispatch blocks + // will share a loaded selector value, but after the first dispatch block + // we will have started outlining after the value is loaded. We can + // spot this case by looking at the compare operands. + for (auto &U : Compare->operands()) { + // Ignore any operands we've already mapped. + if (VMap.count(U.get())) + continue; + if (auto *Load = dyn_cast(U.get())) { + if (LPadMap.mapIfSelectorLoad(Load)) + VMap[Load] = ConstantInt::get(SelectorIDType, 1); + break; + } + } + // Whether we mapped a selector load above or not, the compare gets cloned. + return CloningDirector::CloneInstruction; + } + // Nested landing pads will be cloned as stubs, with just the // landingpad instruction and an unreachable instruction. When // all landingpads have been outlined, we'll replace this with the @@ -1461,12 +1481,19 @@ continue; if (Inst == Compare || Inst == Branch) continue; - if (!Inst->hasOneUse() || (Inst->user_back() != Compare)) - return createCleanupHandler(CleanupHandlerMap, BB); + // Loads of selector values may be used by multiple blocks, but if the + // loaded value is used in this block, it should be used by the + // compare instruction. + if (auto *Load = dyn_cast(Inst)) { + for (auto *U : Load->users()) { + if (cast(U)->getParent() == BB && U != Compare) + return createCleanupHandler(CleanupHandlerMap, BB); + } + continue; + } if (match(Inst, m_Intrinsic())) continue; - if (!isa(Inst)) - return createCleanupHandler(CleanupHandlerMap, BB); + return createCleanupHandler(CleanupHandlerMap, BB); } // The selector dispatch block should always terminate our search. assert(BB == EndBB);