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
This commit is contained in:
Dan Gohman 2008-10-14 23:54:11 +00:00
parent 76dea9547d
commit dd5b58ad7b
8 changed files with 178 additions and 60 deletions

View File

@ -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<const Value *, unsigned> &ValueMap;
DenseMap<const BasicBlock *, MachineBasicBlock *> &MBBMap;
DenseMap<const AllocaInst *, int> &StaticAllocaMap;
#ifndef NDEBUG
SmallSet<Instruction*, 8> &CatchInfoLost;
#endif
MachineFunction &MF;
MachineModuleInfo *MMI;
MachineRegisterInfo &MRI;
@ -108,7 +113,11 @@ protected:
MachineModuleInfo *mmi,
DenseMap<const Value *, unsigned> &vm,
DenseMap<const BasicBlock *, MachineBasicBlock *> &bm,
DenseMap<const AllocaInst *, int> &am);
DenseMap<const AllocaInst *, int> &am
#ifndef NDEBUG
, SmallSet<Instruction*, 8> &cil
#endif
);
/// FastEmit_r - This method is called by target-independent code
/// to request that an instruction with the given type and opcode

View File

@ -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,

View File

@ -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 <map>
#include <vector>
@ -1124,7 +1125,11 @@ public:
MachineModuleInfo *,
DenseMap<const Value *, unsigned> &,
DenseMap<const BasicBlock *, MachineBasicBlock *> &,
DenseMap<const AllocaInst *, int> &) {
DenseMap<const AllocaInst *, int> &
#ifndef NDEBUG
, SmallSet<Instruction*, 8> &CatchInfoLost
#endif
) {
return 0;
}

View File

@ -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<CallInst>(I), MMI, MBB);
else {
#ifndef NDEBUG
CatchInfoLost.insert(cast<CallInst>(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<const Value *, unsigned> &vm,
DenseMap<const BasicBlock *, MachineBasicBlock *> &bm,
DenseMap<const AllocaInst *, int> &am)
DenseMap<const AllocaInst *, int> &am
#ifndef NDEBUG
, SmallSet<Instruction*, 8> &cil
#endif
)
: MBB(0),
ValueMap(vm),
MBBMap(bm),
StaticAllocaMap(am),
#ifndef NDEBUG
CatchInfoLost(cil),
#endif
MF(mf),
MMI(mmi),
MRI(MF.getRegInfo()),

View File

@ -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<BranchInst>(LLVMBB->getTerminator());
if (Br && Br->isUnconditional()) { // Critical edge?
BasicBlock::iterator I, E;
for (I = LLVMBB->begin(), E = --LLVMBB->end(); I != E; ++I)
if (isa<EHSelectorInst>(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<TerminatorInst>(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<BranchInst>(LLVMBB->getTerminator());
if (Br && Br->isUnconditional()) { // Critical edge?
BasicBlock::iterator I, E;
for (I = LLVMBB->begin(), E = --LLVMBB->end(); I != E; ++I)
if (isa<EHSelectorInst>(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()) {

View File

@ -52,8 +52,16 @@ public:
MachineModuleInfo *mmi,
DenseMap<const Value *, unsigned> &vm,
DenseMap<const BasicBlock *, MachineBasicBlock *> &bm,
DenseMap<const AllocaInst *, int> &am)
: FastISel(mf, mmi, vm, bm, am) {
DenseMap<const AllocaInst *, int> &am
#ifndef NDEBUG
, SmallSet<Instruction*, 8> &cil
#endif
)
: FastISel(mf, mmi, vm, bm, am
#ifndef NDEBUG
, cil
#endif
) {
Subtarget = &TM.getSubtarget<X86Subtarget>();
StackPtr = Subtarget->is64Bit() ? X86::RSP : X86::ESP;
X86ScalarSSEf64 = Subtarget->hasSSE2();
@ -1391,7 +1399,15 @@ namespace llvm {
MachineModuleInfo *mmi,
DenseMap<const Value *, unsigned> &vm,
DenseMap<const BasicBlock *, MachineBasicBlock *> &bm,
DenseMap<const AllocaInst *, int> &am) {
return new X86FastISel(mf, mmi, vm, bm, am);
DenseMap<const AllocaInst *, int> &am
#ifndef NDEBUG
, SmallSet<Instruction*, 8> &cil
#endif
) {
return new X86FastISel(mf, mmi, vm, bm, am
#ifndef NDEBUG
, cil
#endif
);
}
}

View File

@ -1884,9 +1884,16 @@ X86TargetLowering::createFastISel(MachineFunction &mf,
DenseMap<const Value *, unsigned> &vm,
DenseMap<const BasicBlock *,
MachineBasicBlock *> &bm,
DenseMap<const AllocaInst *, int> &am) {
return X86::createFastISel(mf, mmo, vm, bm, am);
DenseMap<const AllocaInst *, int> &am
#ifndef NDEBUG
, SmallSet<Instruction*, 8> &cil
#endif
) {
return X86::createFastISel(mf, mmo, vm, bm, am
#ifndef NDEBUG
, cil
#endif
);
}

View File

@ -493,7 +493,11 @@ namespace llvm {
MachineModuleInfo *mmi,
DenseMap<const Value *, unsigned> &,
DenseMap<const BasicBlock *, MachineBasicBlock *> &,
DenseMap<const AllocaInst *, int> &);
DenseMap<const AllocaInst *, int> &
#ifndef NDEBUG
, SmallSet<Instruction*, 8> &
#endif
);
private:
/// Subtarget - Keep a pointer to the X86Subtarget around so that we can
@ -638,7 +642,11 @@ namespace llvm {
MachineModuleInfo *mmi,
DenseMap<const Value *, unsigned> &,
DenseMap<const BasicBlock *, MachineBasicBlock *> &,
DenseMap<const AllocaInst *, int> &);
DenseMap<const AllocaInst *, int> &
#ifndef NDEBUG
, SmallSet<Instruction*, 8> &
#endif
);
}
}