From dd5b58ad7be78be90390074f0df138778af5c895 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 14 Oct 2008 23:54:11 +0000 Subject: [PATCH] FastISel support for exception-handling constructs. - Move the EH landing-pad code and adjust it so that it works with FastISel as well as with SDISel. - Add FastISel support for @llvm.eh.exception and @llvm.eh.selector. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@57539 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/FastISel.h | 11 ++- include/llvm/CodeGen/SelectionDAGISel.h | 4 +- include/llvm/Target/TargetLowering.h | 7 +- lib/CodeGen/SelectionDAG/FastISel.cpp | 70 ++++++++++++- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 97 ++++++++++--------- lib/Target/X86/X86FastISel.cpp | 24 ++++- lib/Target/X86/X86ISelLowering.cpp | 13 ++- lib/Target/X86/X86ISelLowering.h | 12 ++- 8 files changed, 178 insertions(+), 60 deletions(-) diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index 8bf8827481c..71db9b58023 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/include/llvm/CodeGen/FastISel.h @@ -16,12 +16,14 @@ #include "llvm/BasicBlock.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/CodeGen/SelectionDAGNodes.h" namespace llvm { class AllocaInst; class ConstantFP; +class Instruction; class MachineBasicBlock; class MachineConstantPool; class MachineFunction; @@ -44,6 +46,9 @@ protected: DenseMap &ValueMap; DenseMap &MBBMap; DenseMap &StaticAllocaMap; +#ifndef NDEBUG + SmallSet &CatchInfoLost; +#endif MachineFunction &MF; MachineModuleInfo *MMI; MachineRegisterInfo &MRI; @@ -108,7 +113,11 @@ protected: MachineModuleInfo *mmi, DenseMap &vm, DenseMap &bm, - DenseMap &am); + DenseMap &am +#ifndef NDEBUG + , SmallSet &cil +#endif + ); /// FastEmit_r - This method is called by target-independent code /// to request that an instruction with the given type and opcode diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h index b091fc2ff97..d3e785b5fe7 100644 --- a/include/llvm/CodeGen/SelectionDAGISel.h +++ b/include/llvm/CodeGen/SelectionDAGISel.h @@ -30,6 +30,7 @@ namespace llvm { class MachineInstr; class MachineModuleInfo; class TargetLowering; + class TargetInstrInfo; class FunctionLoweringInfo; class HazardRecognizer; class GCFunctionInfo; @@ -107,7 +108,8 @@ protected: private: void SelectAllBasicBlocks(Function &Fn, MachineFunction &MF, - MachineModuleInfo *MMI); + MachineModuleInfo *MMI, + const TargetInstrInfo &TII); void FinishBasicBlock(); void SelectBasicBlock(BasicBlock *LLVMBB, diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index de45553c1a6..c9ea40125f5 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -28,6 +28,7 @@ #include "llvm/CodeGen/RuntimeLibcalls.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/STLExtras.h" #include #include @@ -1124,7 +1125,11 @@ public: MachineModuleInfo *, DenseMap &, DenseMap &, - DenseMap &) { + DenseMap & +#ifndef NDEBUG + , SmallSet &CatchInfoLost +#endif + ) { return 0; } diff --git a/lib/CodeGen/SelectionDAG/FastISel.cpp b/lib/CodeGen/SelectionDAG/FastISel.cpp index b12665b237a..404d613ac88 100644 --- a/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -51,6 +51,7 @@ #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetMachine.h" +#include "SelectionDAGBuild.h" using namespace llvm; unsigned FastISel::getRegForValue(Value *V) { @@ -379,6 +380,66 @@ bool FastISel::SelectCall(User *I) { } return true; } + case Intrinsic::eh_exception: { + MVT VT = TLI.getValueType(I->getType()); + switch (TLI.getOperationAction(ISD::EXCEPTIONADDR, VT)) { + default: break; + case TargetLowering::Expand: { + if (!MBB->isLandingPad()) { + // FIXME: Mark exception register as live in. Hack for PR1508. + unsigned Reg = TLI.getExceptionAddressRegister(); + if (Reg) MBB->addLiveIn(Reg); + } + unsigned Reg = TLI.getExceptionAddressRegister(); + const TargetRegisterClass *RC = TLI.getRegClassFor(VT); + unsigned ResultReg = createResultReg(RC); + bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg, + Reg, RC, RC); + assert(InsertedCopy && "Can't copy address registers!"); + UpdateValueMap(I, ResultReg); + return true; + } + } + break; + } + case Intrinsic::eh_selector_i32: + case Intrinsic::eh_selector_i64: { + MVT VT = TLI.getValueType(I->getType()); + switch (TLI.getOperationAction(ISD::EHSELECTION, VT)) { + default: break; + case TargetLowering::Expand: { + MVT VT = (IID == Intrinsic::eh_selector_i32 ? + MVT::i32 : MVT::i64); + + if (MMI) { + if (MBB->isLandingPad()) + AddCatchInfo(*cast(I), MMI, MBB); + else { +#ifndef NDEBUG + CatchInfoLost.insert(cast(I)); +#endif + // FIXME: Mark exception selector register as live in. Hack for PR1508. + unsigned Reg = TLI.getExceptionSelectorRegister(); + if (Reg) MBB->addLiveIn(Reg); + } + + unsigned Reg = TLI.getExceptionSelectorRegister(); + const TargetRegisterClass *RC = TLI.getRegClassFor(VT); + unsigned ResultReg = createResultReg(RC); + bool InsertedCopy = TII.copyRegToReg(*MBB, MBB->end(), ResultReg, + Reg, RC, RC); + assert(InsertedCopy && "Can't copy address registers!"); + UpdateValueMap(I, ResultReg); + } else { + unsigned ResultReg = + getRegForValue(Constant::getNullValue(I->getType())); + UpdateValueMap(I, ResultReg); + } + return true; + } + } + break; + } } return false; } @@ -607,11 +668,18 @@ FastISel::FastISel(MachineFunction &mf, MachineModuleInfo *mmi, DenseMap &vm, DenseMap &bm, - DenseMap &am) + DenseMap &am +#ifndef NDEBUG + , SmallSet &cil +#endif + ) : MBB(0), ValueMap(vm), MBBMap(bm), StaticAllocaMap(am), +#ifndef NDEBUG + CatchInfoLost(cil), +#endif MF(mf), MMI(mmi), MRI(MF.getRegInfo()), diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 6e9b2885a8f..fb5619cc49c 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -314,7 +314,7 @@ bool SelectionDAGISel::runOnFunction(Function &Fn) { // Mark landing pad. FuncInfo->MBBMap[Invoke->getSuccessor(1)]->setIsLandingPad(); - SelectAllBasicBlocks(Fn, MF, MMI); + SelectAllBasicBlocks(Fn, MF, MMI, TII); // If the first basic block in the function has live ins that need to be // copied into vregs, emit the copies into the top of the block before @@ -452,48 +452,6 @@ void SelectionDAGISel::SelectBasicBlock(BasicBlock *LLVMBB, BasicBlock::iterator End) { SDL->setCurrentBasicBlock(BB); - MachineModuleInfo *MMI = CurDAG->getMachineModuleInfo(); - - if (MMI && BB->isLandingPad()) { - // Add a label to mark the beginning of the landing pad. Deletion of the - // landing pad can thus be detected via the MachineModuleInfo. - unsigned LabelID = MMI->addLandingPad(BB); - CurDAG->setRoot(CurDAG->getLabel(ISD::EH_LABEL, - CurDAG->getEntryNode(), LabelID)); - - // Mark exception register as live in. - unsigned Reg = TLI.getExceptionAddressRegister(); - if (Reg) BB->addLiveIn(Reg); - - // Mark exception selector register as live in. - Reg = TLI.getExceptionSelectorRegister(); - if (Reg) BB->addLiveIn(Reg); - - // FIXME: Hack around an exception handling flaw (PR1508): the personality - // function and list of typeids logically belong to the invoke (or, if you - // like, the basic block containing the invoke), and need to be associated - // with it in the dwarf exception handling tables. Currently however the - // information is provided by an intrinsic (eh.selector) that can be moved - // to unexpected places by the optimizers: if the unwind edge is critical, - // then breaking it can result in the intrinsics being in the successor of - // the landing pad, not the landing pad itself. This results in exceptions - // not being caught because no typeids are associated with the invoke. - // This may not be the only way things can go wrong, but it is the only way - // we try to work around for the moment. - BranchInst *Br = dyn_cast(LLVMBB->getTerminator()); - - if (Br && Br->isUnconditional()) { // Critical edge? - BasicBlock::iterator I, E; - for (I = LLVMBB->begin(), E = --LLVMBB->end(); I != E; ++I) - if (isa(I)) - break; - - if (I == E) - // No catch info found - try to extract some from the successor. - copyCatchInfo(Br->getSuccessor(0), LLVMBB, MMI, *FuncInfo); - } - } - // Lower all of the non-terminator instructions. for (BasicBlock::iterator I = Begin; I != End; ++I) if (!isa(I)) @@ -708,14 +666,19 @@ void SelectionDAGISel::CodeGenAndEmitDAG() { } void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, MachineFunction &MF, - MachineModuleInfo *MMI) { + MachineModuleInfo *MMI, + const TargetInstrInfo &TII) { // Initialize the Fast-ISel state, if needed. FastISel *FastIS = 0; if (EnableFastISel) FastIS = TLI.createFastISel(*FuncInfo->MF, MMI, FuncInfo->ValueMap, FuncInfo->MBBMap, - FuncInfo->StaticAllocaMap); + FuncInfo->StaticAllocaMap +#ifndef NDEBUG + , FuncInfo->CatchInfoLost +#endif + ); // Iterate over all basic blocks in the function. for (Function::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) { @@ -746,9 +709,49 @@ void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, MachineFunction &MF, } } + if (MMI && BB->isLandingPad()) { + // Add a label to mark the beginning of the landing pad. Deletion of the + // landing pad can thus be detected via the MachineModuleInfo. + unsigned LabelID = MMI->addLandingPad(BB); + + const TargetInstrDesc &II = TII.get(TargetInstrInfo::EH_LABEL); + BuildMI(BB, II).addImm(LabelID); + + // Mark exception register as live in. + unsigned Reg = TLI.getExceptionAddressRegister(); + if (Reg) BB->addLiveIn(Reg); + + // Mark exception selector register as live in. + Reg = TLI.getExceptionSelectorRegister(); + if (Reg) BB->addLiveIn(Reg); + + // FIXME: Hack around an exception handling flaw (PR1508): the personality + // function and list of typeids logically belong to the invoke (or, if you + // like, the basic block containing the invoke), and need to be associated + // with it in the dwarf exception handling tables. Currently however the + // information is provided by an intrinsic (eh.selector) that can be moved + // to unexpected places by the optimizers: if the unwind edge is critical, + // then breaking it can result in the intrinsics being in the successor of + // the landing pad, not the landing pad itself. This results in exceptions + // not being caught because no typeids are associated with the invoke. + // This may not be the only way things can go wrong, but it is the only way + // we try to work around for the moment. + BranchInst *Br = dyn_cast(LLVMBB->getTerminator()); + + if (Br && Br->isUnconditional()) { // Critical edge? + BasicBlock::iterator I, E; + for (I = LLVMBB->begin(), E = --LLVMBB->end(); I != E; ++I) + if (isa(I)) + break; + + if (I == E) + // No catch info found - try to extract some from the successor. + copyCatchInfo(Br->getSuccessor(0), LLVMBB, MMI, *FuncInfo); + } + } + // Before doing SelectionDAG ISel, see if FastISel has been requested. - // FastISel doesn't support EH landing pads, which require special handling. - if (FastIS && !SuppressFastISel && !BB->isLandingPad()) { + if (FastIS && !SuppressFastISel) { // Emit code for any incoming arguments. This must happen before // beginning FastISel on the entry block. if (LLVMBB == &Fn.getEntryBlock()) { diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp index 2ce78eccef0..d734db56c8a 100644 --- a/lib/Target/X86/X86FastISel.cpp +++ b/lib/Target/X86/X86FastISel.cpp @@ -52,8 +52,16 @@ public: MachineModuleInfo *mmi, DenseMap &vm, DenseMap &bm, - DenseMap &am) - : FastISel(mf, mmi, vm, bm, am) { + DenseMap &am +#ifndef NDEBUG + , SmallSet &cil +#endif + ) + : FastISel(mf, mmi, vm, bm, am +#ifndef NDEBUG + , cil +#endif + ) { Subtarget = &TM.getSubtarget(); StackPtr = Subtarget->is64Bit() ? X86::RSP : X86::ESP; X86ScalarSSEf64 = Subtarget->hasSSE2(); @@ -1391,7 +1399,15 @@ namespace llvm { MachineModuleInfo *mmi, DenseMap &vm, DenseMap &bm, - DenseMap &am) { - return new X86FastISel(mf, mmi, vm, bm, am); + DenseMap &am +#ifndef NDEBUG + , SmallSet &cil +#endif + ) { + return new X86FastISel(mf, mmi, vm, bm, am +#ifndef NDEBUG + , cil +#endif + ); } } diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 19b94dfe095..1841de2dc87 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -1884,9 +1884,16 @@ X86TargetLowering::createFastISel(MachineFunction &mf, DenseMap &vm, DenseMap &bm, - DenseMap &am) { - - return X86::createFastISel(mf, mmo, vm, bm, am); + DenseMap &am +#ifndef NDEBUG + , SmallSet &cil +#endif + ) { + return X86::createFastISel(mf, mmo, vm, bm, am +#ifndef NDEBUG + , cil +#endif + ); } diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index 56223d5eebd..b3d165432ff 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -493,7 +493,11 @@ namespace llvm { MachineModuleInfo *mmi, DenseMap &, DenseMap &, - DenseMap &); + DenseMap & +#ifndef NDEBUG + , SmallSet & +#endif + ); private: /// Subtarget - Keep a pointer to the X86Subtarget around so that we can @@ -638,7 +642,11 @@ namespace llvm { MachineModuleInfo *mmi, DenseMap &, DenseMap &, - DenseMap &); + DenseMap & +#ifndef NDEBUG + , SmallSet & +#endif + ); } }