Create HandlePHINodesInSuccessorBlocksFast, a version of

HandlePHINodesInSuccessorBlocks that works FastISel-style. This
allows PHI nodes to be updated correctly while using FastISel.

This also involves some code reorganization; ValueMap and
MBBMap are now members of the FastISel class, so they needn't
be passed around explicitly anymore. Also, SelectInstructions
is changed to SelectInstruction, and only does one instruction
at a time.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@55746 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Dan Gohman 2008-09-03 23:12:08 +00:00
parent 7bbb4339f9
commit 3df24e667f
9 changed files with 296 additions and 251 deletions

View File

@ -36,6 +36,8 @@ class TargetRegisterClass;
class FastISel {
protected:
MachineBasicBlock *MBB;
DenseMap<const Value *, unsigned> &ValueMap;
DenseMap<const BasicBlock *, MachineBasicBlock *> &MBBMap;
MachineFunction &MF;
MachineRegisterInfo &MRI;
const TargetMachine &TM;
@ -44,17 +46,18 @@ protected:
const TargetLowering &TLI;
public:
/// SelectInstructions - Do "fast" instruction selection over the
/// LLVM IR instructions in the range [Begin, N) where N is either
/// End or the first unsupported instruction. Return N.
/// ValueMap is filled in with a mapping of LLVM IR Values to
/// virtual register numbers. MBB is a block to which to append
/// the generated MachineInstrs.
BasicBlock::iterator
SelectInstructions(BasicBlock::iterator Begin, BasicBlock::iterator End,
DenseMap<const Value *, unsigned> &ValueMap,
DenseMap<const BasicBlock *, MachineBasicBlock *> &MBBMap,
MachineBasicBlock *MBB);
/// setCurrentBlock - Set the current block, to which generated
/// machine instructions will be appended.
///
void setCurrentBlock(MachineBasicBlock *mbb) {
MBB = mbb;
}
/// SelectInstruction - Do "fast" instruction selection for the given
/// LLVM IR instruction, and append generated machine instructions to
/// the current block. Return true if selection was successful.
///
bool SelectInstruction(Instruction *I);
/// TargetSelectInstruction - This method is called by target-independent
/// code when the normal FastISel process fails to select an instruction.
@ -62,15 +65,18 @@ public:
/// fit into FastISel's framework. It returns true if it was successful.
///
virtual bool
TargetSelectInstruction(Instruction *I,
DenseMap<const Value *, unsigned> &ValueMap,
DenseMap<const BasicBlock *, MachineBasicBlock *> &MBBMap,
MachineBasicBlock *MBB) = 0;
TargetSelectInstruction(Instruction *I) = 0;
/// getRegForValue - Create a virtual register and arrange for it to
/// be assigned the value for the given LLVM value.
unsigned getRegForValue(Value *V);
virtual ~FastISel();
protected:
explicit FastISel(MachineFunction &mf);
FastISel(MachineFunction &mf,
DenseMap<const Value *, unsigned> &vm,
DenseMap<const BasicBlock *, MachineBasicBlock *> &bm);
/// FastEmit_r - This method is called by target-independent code
/// to request that an instruction with the given type and opcode
@ -208,26 +214,18 @@ protected:
/// from a specified index of a superregister.
unsigned FastEmitInst_extractsubreg(unsigned Op0, uint32_t Idx);
unsigned getRegForValue(Value *V,
DenseMap<const Value*, unsigned> &ValueMap);
void UpdateValueMap(Instruction* I, unsigned Reg,
DenseMap<const Value*, unsigned> &ValueMap);
void UpdateValueMap(Instruction* I, unsigned Reg);
unsigned createResultReg(const TargetRegisterClass *RC);
private:
bool SelectBinaryOp(Instruction *I, ISD::NodeType ISDOpcode,
DenseMap<const Value*, unsigned> &ValueMap);
bool SelectBinaryOp(Instruction *I, ISD::NodeType ISDOpcode);
bool SelectGetElementPtr(Instruction *I,
DenseMap<const Value*, unsigned> &ValueMap);
bool SelectGetElementPtr(Instruction *I);
bool SelectBitCast(Instruction *I,
DenseMap<const Value*, unsigned> &ValueMap);
bool SelectBitCast(Instruction *I);
bool SelectCast(Instruction *I, ISD::NodeType Opcode,
DenseMap<const Value*, unsigned> &ValueMap);
bool SelectCast(Instruction *I, ISD::NodeType Opcode);
};
}

View File

@ -21,6 +21,7 @@
#include "llvm/CodeGen/SelectionDAG.h"
namespace llvm {
class FastISel;
class SelectionDAGLowering;
class SDValue;
class MachineRegisterInfo;
@ -118,6 +119,8 @@ private:
void HandlePHINodesInSuccessorBlocks(BasicBlock *LLVMBB);
bool HandlePHINodesInSuccessorBlocksFast(BasicBlock *LLVMBB, FastISel *F);
/// Pick a safe ordering for instructions for each target node in the
/// graph.
ScheduleDAG *Schedule();

View File

@ -27,6 +27,7 @@
#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/CodeGen/RuntimeLibcalls.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include <map>
#include <vector>
@ -1116,7 +1117,12 @@ public:
/// createFastISel - This method returns a target specific FastISel object,
/// or null if the target does not support "fast" ISel.
virtual FastISel *createFastISel(MachineFunction &) { return 0; }
virtual FastISel *
createFastISel(MachineFunction &,
DenseMap<const Value *, unsigned> &,
DenseMap<const BasicBlock *, MachineBasicBlock *> &) {
return 0;
}
//===--------------------------------------------------------------------===//
// Inline Asm Support hooks

View File

@ -25,8 +25,7 @@ using namespace llvm;
// tracking what uses they dominate. Non-constants, however, already
// have the SSA def-doms-use requirement enforced, so we can cache their
// computations.
unsigned FastISel::getRegForValue(Value *V,
DenseMap<const Value*, unsigned> &ValueMap) {
unsigned FastISel::getRegForValue(Value *V) {
if (ValueMap.count(V))
return ValueMap[V];
@ -78,8 +77,7 @@ unsigned FastISel::getRegForValue(Value *V,
/// NOTE: This is only necessary because we might select a block that uses
/// a value before we select the block that defines the value. It might be
/// possible to fix this by selecting blocks in reverse postorder.
void FastISel::UpdateValueMap(Instruction* I, unsigned Reg,
DenseMap<const Value*, unsigned> &ValueMap) {
void FastISel::UpdateValueMap(Instruction* I, unsigned Reg) {
if (!ValueMap.count(I))
ValueMap[I] = Reg;
else
@ -90,8 +88,7 @@ void FastISel::UpdateValueMap(Instruction* I, unsigned Reg,
/// SelectBinaryOp - Select and emit code for a binary operator instruction,
/// which has an opcode which directly corresponds to the given ISD opcode.
///
bool FastISel::SelectBinaryOp(Instruction *I, ISD::NodeType ISDOpcode,
DenseMap<const Value*, unsigned> &ValueMap) {
bool FastISel::SelectBinaryOp(Instruction *I, ISD::NodeType ISDOpcode) {
MVT VT = MVT::getMVT(I->getType(), /*HandleUnknown=*/true);
if (VT == MVT::Other || !VT.isSimple())
// Unhandled type. Halt "fast" selection and bail.
@ -103,7 +100,7 @@ bool FastISel::SelectBinaryOp(Instruction *I, ISD::NodeType ISDOpcode,
if (!TLI.isTypeLegal(VT))
return false;
unsigned Op0 = getRegForValue(I->getOperand(0), ValueMap);
unsigned Op0 = getRegForValue(I->getOperand(0));
if (Op0 == 0)
// Unhandled operand. Halt "fast" selection and bail.
return false;
@ -114,7 +111,7 @@ bool FastISel::SelectBinaryOp(Instruction *I, ISD::NodeType ISDOpcode,
ISDOpcode, Op0, CI->getZExtValue());
if (ResultReg != 0) {
// We successfully emitted code for the given LLVM Instruction.
UpdateValueMap(I, ResultReg, ValueMap);
UpdateValueMap(I, ResultReg);
return true;
}
}
@ -125,12 +122,12 @@ bool FastISel::SelectBinaryOp(Instruction *I, ISD::NodeType ISDOpcode,
ISDOpcode, Op0, CF);
if (ResultReg != 0) {
// We successfully emitted code for the given LLVM Instruction.
UpdateValueMap(I, ResultReg, ValueMap);
UpdateValueMap(I, ResultReg);
return true;
}
}
unsigned Op1 = getRegForValue(I->getOperand(1), ValueMap);
unsigned Op1 = getRegForValue(I->getOperand(1));
if (Op1 == 0)
// Unhandled operand. Halt "fast" selection and bail.
return false;
@ -144,13 +141,12 @@ bool FastISel::SelectBinaryOp(Instruction *I, ISD::NodeType ISDOpcode,
return false;
// We successfully emitted code for the given LLVM Instruction.
UpdateValueMap(I, ResultReg, ValueMap);
UpdateValueMap(I, ResultReg);
return true;
}
bool FastISel::SelectGetElementPtr(Instruction *I,
DenseMap<const Value*, unsigned> &ValueMap) {
unsigned N = getRegForValue(I->getOperand(0), ValueMap);
bool FastISel::SelectGetElementPtr(Instruction *I) {
unsigned N = getRegForValue(I->getOperand(0));
if (N == 0)
// Unhandled operand. Halt "fast" selection and bail.
return false;
@ -190,7 +186,7 @@ bool FastISel::SelectGetElementPtr(Instruction *I,
// N = N + Idx * ElementSize;
uint64_t ElementSize = TD.getABITypeSize(Ty);
unsigned IdxN = getRegForValue(Idx, ValueMap);
unsigned IdxN = getRegForValue(Idx);
if (IdxN == 0)
// Unhandled operand. Halt "fast" selection and bail.
return false;
@ -220,12 +216,11 @@ bool FastISel::SelectGetElementPtr(Instruction *I,
}
// We successfully emitted code for the given LLVM Instruction.
UpdateValueMap(I, N, ValueMap);
UpdateValueMap(I, N);
return true;
}
bool FastISel::SelectCast(Instruction *I, ISD::NodeType Opcode,
DenseMap<const Value*, unsigned> &ValueMap) {
bool FastISel::SelectCast(Instruction *I, ISD::NodeType Opcode) {
MVT SrcVT = TLI.getValueType(I->getOperand(0)->getType());
MVT DstVT = TLI.getValueType(I->getType());
@ -235,7 +230,7 @@ bool FastISel::SelectCast(Instruction *I, ISD::NodeType Opcode,
// Unhandled type. Halt "fast" selection and bail.
return false;
unsigned InputReg = getRegForValue(I->getOperand(0), ValueMap);
unsigned InputReg = getRegForValue(I->getOperand(0));
if (!InputReg)
// Unhandled operand. Halt "fast" selection and bail.
return false;
@ -247,18 +242,17 @@ bool FastISel::SelectCast(Instruction *I, ISD::NodeType Opcode,
if (!ResultReg)
return false;
UpdateValueMap(I, ResultReg, ValueMap);
UpdateValueMap(I, ResultReg);
return true;
}
bool FastISel::SelectBitCast(Instruction *I,
DenseMap<const Value*, unsigned> &ValueMap) {
bool FastISel::SelectBitCast(Instruction *I) {
// If the bitcast doesn't change the type, just use the operand value.
if (I->getType() == I->getOperand(0)->getType()) {
unsigned Reg = getRegForValue(I->getOperand(0), ValueMap);
unsigned Reg = getRegForValue(I->getOperand(0));
if (Reg == 0)
return false;
UpdateValueMap(I, Reg, ValueMap);
UpdateValueMap(I, Reg);
return true;
}
@ -272,7 +266,7 @@ bool FastISel::SelectBitCast(Instruction *I,
// Unhandled type. Halt "fast" selection and bail.
return false;
unsigned Op0 = getRegForValue(I->getOperand(0), ValueMap);
unsigned Op0 = getRegForValue(I->getOperand(0));
if (Op0 == 0)
// Unhandled operand. Halt "fast" selection and bail.
return false;
@ -298,143 +292,124 @@ bool FastISel::SelectBitCast(Instruction *I,
if (!ResultReg)
return false;
UpdateValueMap(I, ResultReg, ValueMap);
UpdateValueMap(I, ResultReg);
return true;
}
BasicBlock::iterator
FastISel::SelectInstructions(BasicBlock::iterator Begin,
BasicBlock::iterator End,
DenseMap<const Value*, unsigned> &ValueMap,
DenseMap<const BasicBlock*,
MachineBasicBlock *> &MBBMap,
MachineBasicBlock *mbb) {
MBB = mbb;
BasicBlock::iterator I = Begin;
bool
FastISel::SelectInstruction(Instruction *I) {
switch (I->getOpcode()) {
case Instruction::Add: {
ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FADD : ISD::ADD;
return SelectBinaryOp(I, Opc);
}
case Instruction::Sub: {
ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FSUB : ISD::SUB;
return SelectBinaryOp(I, Opc);
}
case Instruction::Mul: {
ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FMUL : ISD::MUL;
return SelectBinaryOp(I, Opc);
}
case Instruction::SDiv:
return SelectBinaryOp(I, ISD::SDIV);
case Instruction::UDiv:
return SelectBinaryOp(I, ISD::UDIV);
case Instruction::FDiv:
return SelectBinaryOp(I, ISD::FDIV);
case Instruction::SRem:
return SelectBinaryOp(I, ISD::SREM);
case Instruction::URem:
return SelectBinaryOp(I, ISD::UREM);
case Instruction::FRem:
return SelectBinaryOp(I, ISD::FREM);
case Instruction::Shl:
return SelectBinaryOp(I, ISD::SHL);
case Instruction::LShr:
return SelectBinaryOp(I, ISD::SRL);
case Instruction::AShr:
return SelectBinaryOp(I, ISD::SRA);
case Instruction::And:
return SelectBinaryOp(I, ISD::AND);
case Instruction::Or:
return SelectBinaryOp(I, ISD::OR);
case Instruction::Xor:
return SelectBinaryOp(I, ISD::XOR);
for (; I != End; ++I) {
switch (I->getOpcode()) {
case Instruction::Add: {
ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FADD : ISD::ADD;
if (!SelectBinaryOp(I, Opc, ValueMap)) return I; break;
}
case Instruction::Sub: {
ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FSUB : ISD::SUB;
if (!SelectBinaryOp(I, Opc, ValueMap)) return I; break;
}
case Instruction::Mul: {
ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FMUL : ISD::MUL;
if (!SelectBinaryOp(I, Opc, ValueMap)) return I; break;
}
case Instruction::SDiv:
if (!SelectBinaryOp(I, ISD::SDIV, ValueMap)) return I; break;
case Instruction::UDiv:
if (!SelectBinaryOp(I, ISD::UDIV, ValueMap)) return I; break;
case Instruction::FDiv:
if (!SelectBinaryOp(I, ISD::FDIV, ValueMap)) return I; break;
case Instruction::SRem:
if (!SelectBinaryOp(I, ISD::SREM, ValueMap)) return I; break;
case Instruction::URem:
if (!SelectBinaryOp(I, ISD::UREM, ValueMap)) return I; break;
case Instruction::FRem:
if (!SelectBinaryOp(I, ISD::FREM, ValueMap)) return I; break;
case Instruction::Shl:
if (!SelectBinaryOp(I, ISD::SHL, ValueMap)) return I; break;
case Instruction::LShr:
if (!SelectBinaryOp(I, ISD::SRL, ValueMap)) return I; break;
case Instruction::AShr:
if (!SelectBinaryOp(I, ISD::SRA, ValueMap)) return I; break;
case Instruction::And:
if (!SelectBinaryOp(I, ISD::AND, ValueMap)) return I; break;
case Instruction::Or:
if (!SelectBinaryOp(I, ISD::OR, ValueMap)) return I; break;
case Instruction::Xor:
if (!SelectBinaryOp(I, ISD::XOR, ValueMap)) return I; break;
case Instruction::GetElementPtr:
return SelectGetElementPtr(I);
case Instruction::GetElementPtr:
if (!SelectGetElementPtr(I, ValueMap)) return I;
break;
case Instruction::Br: {
BranchInst *BI = cast<BranchInst>(I);
case Instruction::Br: {
BranchInst *BI = cast<BranchInst>(I);
if (BI->isUnconditional()) {
MachineFunction::iterator NextMBB =
next(MachineFunction::iterator(MBB));
BasicBlock *LLVMSucc = BI->getSuccessor(0);
MachineBasicBlock *MSucc = MBBMap[LLVMSucc];
if (BI->isUnconditional()) {
MachineFunction::iterator NextMBB =
next(MachineFunction::iterator(MBB));
BasicBlock *LLVMSucc = BI->getSuccessor(0);
MachineBasicBlock *MSucc = MBBMap[LLVMSucc];
if (NextMBB != MF.end() && MSucc == NextMBB) {
// The unconditional fall-through case, which needs no instructions.
} else {
// The unconditional branch case.
TII.InsertBranch(*MBB, MSucc, NULL, SmallVector<MachineOperand, 0>());
}
MBB->addSuccessor(MSucc);
break;
}
// Conditional branches are not handed yet.
// Halt "fast" selection and bail.
return I;
}
case Instruction::PHI:
// PHI nodes are already emitted.
break;
case Instruction::BitCast:
if (!SelectBitCast(I, ValueMap)) return I; break;
case Instruction::FPToSI:
if (!SelectCast(I, ISD::FP_TO_SINT, ValueMap)) return I;
break;
case Instruction::ZExt:
if (!SelectCast(I, ISD::ZERO_EXTEND, ValueMap)) return I;
break;
case Instruction::SExt:
if (!SelectCast(I, ISD::SIGN_EXTEND, ValueMap)) return I;
break;
case Instruction::Trunc:
if (!SelectCast(I, ISD::TRUNCATE, ValueMap)) return I;
break;
case Instruction::SIToFP:
if (!SelectCast(I, ISD::SINT_TO_FP, ValueMap)) return I;
break;
case Instruction::IntToPtr: // Deliberate fall-through.
case Instruction::PtrToInt: {
MVT SrcVT = TLI.getValueType(I->getOperand(0)->getType());
MVT DstVT = TLI.getValueType(I->getType());
if (SrcVT.getSimpleVT() == DstVT.getSimpleVT()) {
if (ValueMap[I->getOperand(0)]) {
UpdateValueMap(I, ValueMap[I->getOperand(0)], ValueMap);
break;
} else
// Unhandled operand
return I;
} else if (DstVT.bitsGT(SrcVT)) {
if (!SelectCast(I, ISD::ZERO_EXTEND, ValueMap)) return I;
break;
if (NextMBB != MF.end() && MSucc == NextMBB) {
// The unconditional fall-through case, which needs no instructions.
} else {
// TODO: Handle SrcVT > DstVT, where truncation is needed.
return I;
// The unconditional branch case.
TII.InsertBranch(*MBB, MSucc, NULL, SmallVector<MachineOperand, 0>());
}
MBB->addSuccessor(MSucc);
return true;
}
default:
// Unhandled instruction. Halt "fast" selection and bail.
return I;
}
// Conditional branches are not handed yet.
// Halt "fast" selection and bail.
return false;
}
return I;
case Instruction::PHI:
// PHI nodes are already emitted.
return true;
case Instruction::BitCast:
return SelectBitCast(I);
case Instruction::FPToSI:
return SelectCast(I, ISD::FP_TO_SINT);
case Instruction::ZExt:
return SelectCast(I, ISD::ZERO_EXTEND);
case Instruction::SExt:
return SelectCast(I, ISD::SIGN_EXTEND);
case Instruction::Trunc:
return SelectCast(I, ISD::TRUNCATE);
case Instruction::SIToFP:
return SelectCast(I, ISD::SINT_TO_FP);
case Instruction::IntToPtr: // Deliberate fall-through.
case Instruction::PtrToInt: {
MVT SrcVT = TLI.getValueType(I->getOperand(0)->getType());
MVT DstVT = TLI.getValueType(I->getType());
if (DstVT.bitsGT(SrcVT))
return SelectCast(I, ISD::ZERO_EXTEND);
if (DstVT.bitsLT(SrcVT))
return SelectCast(I, ISD::TRUNCATE);
unsigned Reg = getRegForValue(I->getOperand(0));
if (Reg == 0) return false;
UpdateValueMap(I, Reg);
return true;
}
default:
// Unhandled instruction. Halt "fast" selection and bail.
return false;
}
}
FastISel::FastISel(MachineFunction &mf)
: MF(mf),
MRI(mf.getRegInfo()),
TM(mf.getTarget()),
FastISel::FastISel(MachineFunction &mf,
DenseMap<const Value *, unsigned> &vm,
DenseMap<const BasicBlock *, MachineBasicBlock *> &bm)
: MBB(0),
ValueMap(vm),
MBBMap(bm),
MF(mf),
MRI(MF.getRegInfo()),
TM(MF.getTarget()),
TD(*TM.getTargetData()),
TII(*TM.getInstrInfo()),
TLI(*TM.getTargetLowering()) {

View File

@ -4757,9 +4757,64 @@ SelectionDAGISel::HandlePHINodesInSuccessorBlocks(BasicBlock *LLVMBB) {
}
}
SDL->ConstantsOut.clear();
// Lower the terminator after the copies are emitted.
SDL->visit(*LLVMBB->getTerminator());
}
/// This is the Fast-ISel version of HandlePHINodesInSuccessorBlocks. It only
/// supports legal types, and it emits MachineInstrs directly instead of
/// creating SelectionDAG nodes.
///
bool
SelectionDAGISel::HandlePHINodesInSuccessorBlocksFast(BasicBlock *LLVMBB,
FastISel *F) {
TerminatorInst *TI = LLVMBB->getTerminator();
SmallPtrSet<MachineBasicBlock *, 4> SuccsHandled;
unsigned OrigNumPHINodesToUpdate = SDL->PHINodesToUpdate.size();
// Check successor nodes' PHI nodes that expect a constant to be available
// from this block.
for (unsigned succ = 0, e = TI->getNumSuccessors(); succ != e; ++succ) {
BasicBlock *SuccBB = TI->getSuccessor(succ);
if (!isa<PHINode>(SuccBB->begin())) continue;
MachineBasicBlock *SuccMBB = FuncInfo->MBBMap[SuccBB];
// If this terminator has multiple identical successors (common for
// switches), only handle each succ once.
if (!SuccsHandled.insert(SuccMBB)) continue;
MachineBasicBlock::iterator MBBI = SuccMBB->begin();
PHINode *PN;
// At this point we know that there is a 1-1 correspondence between LLVM PHI
// nodes and Machine PHI nodes, but the incoming operands have not been
// emitted yet.
for (BasicBlock::iterator I = SuccBB->begin();
(PN = dyn_cast<PHINode>(I)); ++I) {
// Ignore dead phi's.
if (PN->use_empty()) continue;
// Only handle legal types. Two interesting things to note here. First,
// by bailing out early, we may leave behind some dead instructions,
// since SelectionDAG's HandlePHINodesInSuccessorBlocks will insert its
// own moves. Second, this check is necessary becuase FastISel doesn't
// use CreateRegForValue to create registers, so it always creates
// exactly one register for each non-void instruction.
MVT VT = TLI.getValueType(PN->getType(), /*AllowUnknown=*/true);
if (VT == MVT::Other || !TLI.isTypeLegal(VT)) {
SDL->PHINodesToUpdate.resize(OrigNumPHINodesToUpdate);
return false;
}
Value *PHIOp = PN->getIncomingValueForBlock(LLVMBB);
unsigned Reg = F->getRegForValue(PHIOp);
if (Reg == 0) {
SDL->PHINodesToUpdate.resize(OrigNumPHINodesToUpdate);
return false;
}
SDL->PHINodesToUpdate.push_back(std::make_pair(MBBI++, Reg));
}
}
return true;
}

View File

@ -408,8 +408,12 @@ void SelectionDAGISel::SelectBasicBlock(BasicBlock *LLVMBB,
}
// Handle PHI nodes in successor blocks.
if (End == LLVMBB->end())
if (End == LLVMBB->end()) {
HandlePHINodesInSuccessorBlocks(LLVMBB);
// Lower the terminator after the copies are emitted.
SDL->visit(*LLVMBB->getTerminator());
}
// Make sure the root of the DAG is up-to-date.
CurDAG->setRoot(SDL->getControlRoot());
@ -606,8 +610,9 @@ void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, MachineFunction &MF) {
BasicBlock *LLVMBB = &*I;
BB = FuncInfo->MBBMap[LLVMBB];
BasicBlock::iterator Begin = LLVMBB->begin();
BasicBlock::iterator End = LLVMBB->end();
BasicBlock::iterator const Begin = LLVMBB->begin();
BasicBlock::iterator const End = LLVMBB->end();
BasicBlock::iterator I = Begin;
// Lower any arguments needed in this block if this is the entry block.
if (LLVMBB == &Fn.getEntryBlock())
@ -616,7 +621,8 @@ void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, MachineFunction &MF) {
// Before doing SelectionDAG ISel, see if FastISel has been requested.
// FastISel doesn't support EH landing pads, which require special handling.
if (EnableFastISel && !BB->isLandingPad()) {
if (FastISel *F = TLI.createFastISel(*FuncInfo->MF)) {
if (FastISel *F = TLI.createFastISel(*FuncInfo->MF, FuncInfo->ValueMap,
FuncInfo->MBBMap)) {
// Emit code for any incoming arguments. This must happen before
// beginning FastISel on the entry block.
if (LLVMBB == &Fn.getEntryBlock()) {
@ -624,45 +630,51 @@ void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, MachineFunction &MF) {
CodeGenAndEmitDAG();
SDL->clear();
}
F->setCurrentBlock(BB);
// Do FastISel on as many instructions as possible.
while (Begin != End) {
Begin = F->SelectInstructions(Begin, End, FuncInfo->ValueMap,
FuncInfo->MBBMap, BB);
// If the "fast" selector selected the entire block, we're done.
if (Begin == End)
break;
// Next, try calling the target to attempt to handle the instruction.
if (F->TargetSelectInstruction(Begin, FuncInfo->ValueMap,
FuncInfo->MBBMap, BB)) {
++Begin;
continue;
}
// Handle certain instructions as single-LLVM-Instruction blocks.
if (isa<CallInst>(Begin) || isa<LoadInst>(Begin) ||
isa<StoreInst>(Begin)) {
if (Begin->getType() != Type::VoidTy) {
unsigned &R = FuncInfo->ValueMap[Begin];
if (!R)
R = FuncInfo->CreateRegForValue(Begin);
for (; I != End; ++I) {
// Just before the terminator instruction, insert instructions to
// feed PHI nodes in successor blocks.
if (isa<TerminatorInst>(I))
if (!HandlePHINodesInSuccessorBlocksFast(LLVMBB, F)) {
if (DisableFastISelAbort)
break;
#ifndef NDEBUG
I->dump();
#endif
assert(0 && "FastISel didn't handle a PHI in a successor");
}
SelectBasicBlock(LLVMBB, Begin, next(Begin));
++Begin;
// First try normal tablegen-generated "fast" selection.
if (F->SelectInstruction(I))
continue;
// Next, try calling the target to attempt to handle the instruction.
if (F->TargetSelectInstruction(I))
continue;
// Then handle certain instructions as single-LLVM-Instruction blocks.
if (isa<CallInst>(I) || isa<LoadInst>(I) ||
isa<StoreInst>(I)) {
if (I->getType() != Type::VoidTy) {
unsigned &R = FuncInfo->ValueMap[I];
if (!R)
R = FuncInfo->CreateRegForValue(I);
}
SelectBasicBlock(LLVMBB, I, next(I));
continue;
}
if (!DisableFastISelAbort &&
// For now, don't abort on non-conditional-branch terminators.
(!isa<TerminatorInst>(Begin) ||
(isa<BranchInst>(Begin) &&
cast<BranchInst>(Begin)->isUnconditional()))) {
(!isa<TerminatorInst>(I) ||
(isa<BranchInst>(I) &&
cast<BranchInst>(I)->isUnconditional()))) {
// The "fast" selector couldn't handle something and bailed.
// For the purpose of debugging, just abort.
#ifndef NDEBUG
Begin->dump();
I->dump();
#endif
assert(0 && "FastISel didn't select the entire block");
}
@ -674,12 +686,9 @@ void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, MachineFunction &MF) {
// Run SelectionDAG instruction selection on the remainder of the block
// not handled by FastISel. If FastISel is not run, this is the entire
// block. If FastISel is run and happens to handle all of the
// LLVM Instructions in the block, [Begin,End) will be an empty range,
// but we still need to run this so that
// HandlePHINodesInSuccessorBlocks is called and any resulting code
// is emitted.
SelectBasicBlock(LLVMBB, Begin, End);
// block.
if (I != End)
SelectBasicBlock(LLVMBB, I, End);
FinishBasicBlock();
}

View File

@ -30,34 +30,27 @@ class X86FastISel : public FastISel {
const X86Subtarget *Subtarget;
public:
explicit X86FastISel(MachineFunction &mf) : FastISel(mf) {
explicit X86FastISel(MachineFunction &mf,
DenseMap<const Value *, unsigned> &vm,
DenseMap<const BasicBlock *, MachineBasicBlock *> &bm)
: FastISel(mf, vm, bm) {
Subtarget = &TM.getSubtarget<X86Subtarget>();
}
virtual bool
TargetSelectInstruction(Instruction *I,
DenseMap<const Value *, unsigned> &ValueMap,
DenseMap<const BasicBlock *, MachineBasicBlock *> &MBBMap,
MachineBasicBlock *MBB);
virtual bool TargetSelectInstruction(Instruction *I);
#include "X86GenFastISel.inc"
private:
bool X86SelectConstAddr(Value *V,
DenseMap<const Value *, unsigned> &ValueMap,
MachineBasicBlock *MBB, unsigned &Op0);
bool X86SelectConstAddr(Value *V, unsigned &Op0);
bool X86SelectLoad(Instruction *I,
DenseMap<const Value *, unsigned> &ValueMap,
MachineBasicBlock *MBB);
bool X86SelectLoad(Instruction *I);
};
/// X86SelectConstAddr - Select and emit code to materialize constant address.
///
bool X86FastISel::X86SelectConstAddr(Value *V,
DenseMap<const Value *, unsigned> &ValueMap,
MachineBasicBlock *MBB,
unsigned &Op0) {
unsigned &Op0) {
// FIXME: Only GlobalAddress for now.
GlobalValue *GV = dyn_cast<GlobalValue>(V);
if (!GV)
@ -84,9 +77,7 @@ bool X86FastISel::X86SelectConstAddr(Value *V,
/// X86SelectLoad - Select and emit code to implement load instructions.
///
bool X86FastISel::X86SelectLoad(Instruction *I,
DenseMap<const Value *, unsigned> &ValueMap,
MachineBasicBlock *MBB) {
bool X86FastISel::X86SelectLoad(Instruction *I) {
MVT VT = MVT::getMVT(I->getType(), /*HandleUnknown=*/true);
if (VT == MVT::Other || !VT.isSimple())
// Unhandled type. Halt "fast" selection and bail.
@ -102,10 +93,10 @@ bool X86FastISel::X86SelectLoad(Instruction *I,
return false;
Value *V = I->getOperand(0);
unsigned Op0 = getRegForValue(V, ValueMap);
unsigned Op0 = getRegForValue(V);
if (Op0 == 0) {
// Handle constant load address.
if (!isa<Constant>(V) || !X86SelectConstAddr(V, ValueMap, MBB, Op0))
if (!isa<Constant>(V) || !X86SelectConstAddr(V, Op0))
// Unhandled operand. Halt "fast" selection and bail.
return false;
}
@ -164,27 +155,26 @@ bool X86FastISel::X86SelectLoad(Instruction *I,
else
AM.GV = cast<GlobalValue>(V);
addFullAddress(BuildMI(MBB, TII.get(Opc), ResultReg), AM);
UpdateValueMap(I, ResultReg, ValueMap);
UpdateValueMap(I, ResultReg);
return true;
}
bool
X86FastISel::TargetSelectInstruction(Instruction *I,
DenseMap<const Value *, unsigned> &ValueMap,
DenseMap<const BasicBlock *, MachineBasicBlock *> &MBBMap,
MachineBasicBlock *MBB) {
X86FastISel::TargetSelectInstruction(Instruction *I) {
switch (I->getOpcode()) {
default: break;
case Instruction::Load:
return X86SelectLoad(I, ValueMap, MBB);
return X86SelectLoad(I);
}
return false;
}
namespace llvm {
llvm::FastISel *X86::createFastISel(MachineFunction &mf) {
return new X86FastISel(mf);
llvm::FastISel *X86::createFastISel(MachineFunction &mf,
DenseMap<const Value *, unsigned> &vm,
DenseMap<const BasicBlock *, MachineBasicBlock *> &bm) {
return new X86FastISel(mf, vm, bm);
}
}

View File

@ -1879,8 +1879,12 @@ bool X86TargetLowering::IsEligibleForTailCallOptimization(SDValue Call,
return false;
}
FastISel *X86TargetLowering::createFastISel(MachineFunction &mf) {
return X86::createFastISel(mf);
FastISel *
X86TargetLowering::createFastISel(MachineFunction &mf,
DenseMap<const Value *, unsigned> &vm,
DenseMap<const BasicBlock *,
MachineBasicBlock *> &bm) {
return X86::createFastISel(mf, vm, bm);
}

View File

@ -470,7 +470,10 @@ namespace llvm {
/// createFastISel - This method returns a target specific FastISel object,
/// or null if the target does not support "fast" ISel.
virtual FastISel *createFastISel(MachineFunction &mf);
virtual FastISel *
createFastISel(MachineFunction &mf,
DenseMap<const Value *, unsigned> &,
DenseMap<const BasicBlock *, MachineBasicBlock *> &);
private:
/// Subtarget - Keep a pointer to the X86Subtarget around so that we can
@ -598,7 +601,9 @@ namespace llvm {
};
namespace X86 {
FastISel *createFastISel(MachineFunction &mf);
FastISel *createFastISel(MachineFunction &mf,
DenseMap<const Value *, unsigned> &,
DenseMap<const BasicBlock *, MachineBasicBlock *> &);
}
}