From 192537c4f3530c781521b90990f64086267817ed Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Wed, 15 Apr 2015 18:48:15 +0000 Subject: [PATCH] [WinEH] Try to make the MachineFunction CFG more accurate This avoids emitting code for unreachable landingpad blocks that contain calls to llvm.eh.actions and indirectbr. It's also a first step towards unifying the SEH and WinEH lowering codepaths. I'm keeping the old fan-in lowering of SEH around until the preparation version works well enough that we can switch over without breaking existing users. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@235037 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/AsmPrinter/Win64Exception.cpp | 10 +- lib/CodeGen/MachineModuleInfo.cpp | 7 +- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 105 +++++++++++------- test/CodeGen/WinEH/cppeh-prepared-catch.ll | 6 + 4 files changed, 82 insertions(+), 46 deletions(-) diff --git a/lib/CodeGen/AsmPrinter/Win64Exception.cpp b/lib/CodeGen/AsmPrinter/Win64Exception.cpp index 0d422d83e2d..f89d36455f4 100644 --- a/lib/CodeGen/AsmPrinter/Win64Exception.cpp +++ b/lib/CodeGen/AsmPrinter/Win64Exception.cpp @@ -108,8 +108,13 @@ void Win64Exception::endFunction(const MachineFunction *MF) { if (!shouldEmitPersonality && !shouldEmitMoves) return; - // Map all labels and get rid of any dead landing pads. - MMI->TidyLandingPads(); + EHPersonality Per = MMI->getPersonalityType(); + + // Get rid of any dead landing pads if we're not using a Windows EH scheme. In + // Windows EH schemes, the landing pad is not actually reachable. It only + // exists so that we can emit the right table data. + if (!isMSVCEHPersonality(Per)) + MMI->TidyLandingPads(); if (shouldEmitPersonality) { Asm->OutStreamer.PushSection(); @@ -119,7 +124,6 @@ void Win64Exception::endFunction(const MachineFunction *MF) { // Emit the tables appropriate to the personality function in use. If we // don't recognize the personality, assume it uses an Itanium-style LSDA. - EHPersonality Per = MMI->getPersonalityType(); if (Per == EHPersonality::MSVC_Win64SEH) emitCSpecificHandlerTable(); else if (Per == EHPersonality::MSVC_CXX) diff --git a/lib/CodeGen/MachineModuleInfo.cpp b/lib/CodeGen/MachineModuleInfo.cpp index d5491213293..e8bd1f8e6d9 100644 --- a/lib/CodeGen/MachineModuleInfo.cpp +++ b/lib/CodeGen/MachineModuleInfo.cpp @@ -570,10 +570,13 @@ const Function *MachineModuleInfo::getPersonality() const { } EHPersonality MachineModuleInfo::getPersonalityType() { - if (PersonalityTypeCache == EHPersonality::Unknown) - PersonalityTypeCache = classifyEHPersonality(getPersonality()); + if (PersonalityTypeCache == EHPersonality::Unknown) { + if (const Function *F = getPersonality()) + PersonalityTypeCache = classifyEHPersonality(F); + } return PersonalityTypeCache; } + /// getPersonalityIndex - Return unique index for current personality /// function. NULL/first personality function should always get zero index. unsigned MachineModuleInfo::getPersonalityIndex() const { diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 4ff0b9fefcb..1e116dddafa 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -933,53 +933,74 @@ void SelectionDAGISel::PrepareEHLandingPad() { const LandingPadInst *LPadInst = LLVMBB->getLandingPadInst(); MF->getMMI().addPersonality( MBB, cast(LPadInst->getPersonalityFn()->stripPointerCasts())); - if (MF->getMMI().getPersonalityType() == EHPersonality::MSVC_Win64SEH) { - // Make virtual registers and a series of labels that fill in values for the - // clauses. - auto &RI = MF->getRegInfo(); - FuncInfo->ExceptionSelectorVirtReg = RI.createVirtualRegister(PtrRC); + EHPersonality Personality = MF->getMMI().getPersonalityType(); - // Get all invoke BBs that will unwind into the clause BBs. + if (isMSVCEHPersonality(Personality)) { + SmallVector ClauseBBs; + const IntrinsicInst *Actions = + dyn_cast(LLVMBB->getFirstInsertionPt()); + // Get all invoke BBs that unwind to this landingpad. SmallVector InvokeBBs(MBB->pred_begin(), MBB->pred_end()); + if (Actions && Actions->getIntrinsicID() == Intrinsic::eh_actions) { + // If this is a call to llvm.eh.actions followed by indirectbr, then we've + // run WinEHPrepare, and we should remove this block from the machine CFG. + // Mark the targets of the indirectbr as landingpads instead. + for (const BasicBlock *LLVMSucc : successors(LLVMBB)) { + MachineBasicBlock *ClauseBB = FuncInfo->MBBMap[LLVMSucc]; + // Add the edge from the invoke to the clause. + for (MachineBasicBlock *InvokeBB : InvokeBBs) + InvokeBB->addSuccessor(ClauseBB); + } + } else { + // Otherwise, we haven't done the preparation, and we need to invent some + // clause basic blocks that branch into the landingpad. + // FIXME: Remove this code once SEH preparation works. - // Emit separate machine basic blocks with separate labels for each clause - // before the main landing pad block. - MachineInstrBuilder SelectorPHI = BuildMI( - *MBB, MBB->begin(), SDB->getCurDebugLoc(), TII->get(TargetOpcode::PHI), - FuncInfo->ExceptionSelectorVirtReg); - for (unsigned I = 0, E = LPadInst->getNumClauses(); I != E; ++I) { - // Skip filter clauses, we can't implement them yet. - if (LPadInst->isFilter(I)) - continue; + // Make virtual registers and a series of labels that fill in values for + // the clauses. + auto &RI = MF->getRegInfo(); + FuncInfo->ExceptionSelectorVirtReg = RI.createVirtualRegister(PtrRC); - MachineBasicBlock *ClauseBB = MF->CreateMachineBasicBlock(LLVMBB); - MF->insert(MBB, ClauseBB); + // Emit separate machine basic blocks with separate labels for each clause + // before the main landing pad block. + MachineInstrBuilder SelectorPHI = BuildMI( + *MBB, MBB->begin(), SDB->getCurDebugLoc(), + TII->get(TargetOpcode::PHI), FuncInfo->ExceptionSelectorVirtReg); + for (unsigned I = 0, E = LPadInst->getNumClauses(); I != E; ++I) { + // Skip filter clauses, we can't implement them. + if (LPadInst->isFilter(I)) + continue; - // Add the edge from the invoke to the clause. - for (MachineBasicBlock *InvokeBB : InvokeBBs) - InvokeBB->addSuccessor(ClauseBB); + MachineBasicBlock *ClauseBB = MF->CreateMachineBasicBlock(LLVMBB); + MF->insert(MBB, ClauseBB); - // Mark the clause as a landing pad or MI passes will delete it. - ClauseBB->setIsLandingPad(); + // Add the edge from the invoke to the clause. + for (MachineBasicBlock *InvokeBB : InvokeBBs) + InvokeBB->addSuccessor(ClauseBB); - GlobalValue *ClauseGV = ExtractTypeInfo(LPadInst->getClause(I)); + // Mark the clause as a landing pad or MI passes will delete it. + ClauseBB->setIsLandingPad(); - // Start the BB with a label. - MCSymbol *ClauseLabel = MF->getMMI().addClauseForLandingPad(MBB); - BuildMI(*ClauseBB, ClauseBB->begin(), SDB->getCurDebugLoc(), II) - .addSym(ClauseLabel); + GlobalValue *ClauseGV = ExtractTypeInfo(LPadInst->getClause(I)); - // Construct a simple BB that defines a register with the typeid constant. - FuncInfo->MBB = ClauseBB; - FuncInfo->InsertPt = ClauseBB->end(); - unsigned VReg = SDB->visitLandingPadClauseBB(ClauseGV, MBB); - CurDAG->setRoot(SDB->getRoot()); - SDB->clear(); - CodeGenAndEmitDAG(); + // Start the BB with a label. + MCSymbol *ClauseLabel = MF->getMMI().addClauseForLandingPad(MBB); + BuildMI(*ClauseBB, ClauseBB->begin(), SDB->getCurDebugLoc(), II) + .addSym(ClauseLabel); - // Add the typeid virtual register to the phi in the main landing pad. - SelectorPHI.addReg(VReg).addMBB(ClauseBB); + // Construct a simple BB that defines a register with the typeid + // constant. + FuncInfo->MBB = ClauseBB; + FuncInfo->InsertPt = ClauseBB->end(); + unsigned VReg = SDB->visitLandingPadClauseBB(ClauseGV, MBB); + CurDAG->setRoot(SDB->getRoot()); + SDB->clear(); + CodeGenAndEmitDAG(); + + // Add the typeid virtual register to the phi in the main landing pad. + SelectorPHI.addReg(VReg).addMBB(ClauseBB); + } } // Remove the edge from the invoke to the lpad. @@ -990,12 +1011,14 @@ void SelectionDAGISel::PrepareEHLandingPad() { // pad block. FuncInfo->MBB = MBB; FuncInfo->InsertPt = MBB->end(); + + // Transfer EH state number assigned to the IR block to the MBB. + if (Personality == EHPersonality::MSVC_CXX) { + WinEHFuncInfo &FI = MF->getMMI().getWinEHFuncInfo(MF->getFunction()); + MF->getMMI().addWinEHState(MBB, FI.LandingPadStateMap[LPadInst]); + } return; } - if (MF->getMMI().getPersonalityType() == EHPersonality::MSVC_CXX) { - WinEHFuncInfo &FuncInfo = MF->getMMI().getWinEHFuncInfo(MF->getFunction()); - MF->getMMI().addWinEHState(MBB, FuncInfo.LandingPadStateMap[LPadInst]); - } // Mark exception register as live in. if (unsigned Reg = TLI->getExceptionPointerRegister()) @@ -1173,7 +1196,7 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) { // Setup an EH landing-pad block. FuncInfo->ExceptionPointerVirtReg = 0; FuncInfo->ExceptionSelectorVirtReg = 0; - if (FuncInfo->MBB->isLandingPad()) + if (LLVMBB->isLandingPad()) PrepareEHLandingPad(); // Before doing SelectionDAG ISel, see if FastISel has been requested. diff --git a/test/CodeGen/WinEH/cppeh-prepared-catch.ll b/test/CodeGen/WinEH/cppeh-prepared-catch.ll index 7c53085edc5..0adbb8e8296 100644 --- a/test/CodeGen/WinEH/cppeh-prepared-catch.ll +++ b/test/CodeGen/WinEH/cppeh-prepared-catch.ll @@ -50,6 +50,8 @@ lpad1: ; preds = %entry } ; CHECK-LABEL: "?f@@YAXXZ.catch": +; No code should be generated for the indirectbr. +; CHECK-NOT: jmpq * ; CHECK: .seh_handlerdata ; CHECK: .long ("$cppxdata$?f@@YAXXZ")@IMGREL @@ -72,6 +74,8 @@ lpad: ; preds = %entry } ; CHECK-LABEL: "?f@@YAXXZ.catch1": +; No code should be generated for the indirectbr. +; CHECK-NOT: jmpq * ; CHECK: ".L?f@@YAXXZ.catch1$parent_frame_offset" = 16 ; CHECK: movq %rdx, 16(%rsp) ; CHECK: .seh_handlerdata @@ -112,6 +116,8 @@ try.cont8: ; preds = %lpad2, %try.cont } ; CHECK-LABEL: "?f@@YAXXZ": +; No code should be generated for the indirectbr. +; CHECK-NOT: jmpq * ; CHECK: .seh_handlerdata ; CHECK-NEXT: .long ("$cppxdata$?f@@YAXXZ")@IMGREL ; CHECK-NEXT:"$cppxdata$?f@@YAXXZ":