mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
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. llvm-svn: 57539
This commit is contained in:
parent
e11e618cc6
commit
c070ffc493
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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()),
|
||||
|
@ -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()) {
|
||||
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user