Move HandlePHINodesInSuccessorBlocks functions out of SelectionDAGISel

and into SelectionDAGBuilder and FastISel.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@102123 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Dan Gohman 2010-04-22 20:46:50 +00:00
parent f720a4edb0
commit f81eca0ab9
10 changed files with 113 additions and 96 deletions

View File

@ -28,6 +28,7 @@ class Instruction;
class MachineBasicBlock;
class MachineConstantPool;
class MachineFunction;
class MachineInstr;
class MachineFrameInfo;
class MachineRegisterInfo;
class TargetData;
@ -46,6 +47,7 @@ protected:
DenseMap<const Value *, unsigned> &ValueMap;
DenseMap<const BasicBlock *, MachineBasicBlock *> &MBBMap;
DenseMap<const AllocaInst *, int> &StaticAllocaMap;
std::vector<std::pair<MachineInstr*, unsigned> > &PHINodesToUpdate;
#ifndef NDEBUG
SmallSet<const Instruction *, 8> &CatchInfoLost;
#endif
@ -105,13 +107,22 @@ public:
/// index value.
unsigned getRegForGEPIndex(const Value *V);
/// HandlePHINodesInSuccessorBlocks - Handle PHI nodes in successor blocks.
/// Emit code to ensure constants are copied into registers when needed.
/// Remember the virtual registers that need to be added to the Machine PHI
/// nodes as input. We cannot just directly add them, because expansion
/// might result in multiple MBB's for one BB. As such, the start of the
/// BB might correspond to a different MBB than the end.
bool HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB);
virtual ~FastISel();
protected:
FastISel(MachineFunction &mf,
DenseMap<const Value *, unsigned> &vm,
DenseMap<const BasicBlock *, MachineBasicBlock *> &bm,
DenseMap<const AllocaInst *, int> &am
DenseMap<const AllocaInst *, int> &am,
std::vector<std::pair<MachineInstr*, unsigned> > &PHINodesToUpdate
#ifndef NDEBUG
, SmallSet<const Instruction *, 8> &cil
#endif

View File

@ -295,11 +295,6 @@ private:
void ShrinkDemandedOps();
void ComputeLiveOutVRegInfo();
void HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB);
bool HandlePHINodesInSuccessorBlocksFast(const BasicBlock *LLVMBB,
FastISel *F);
/// Create the scheduler. If a specific scheduler was specified
/// via the SchedulerRegistry, use it, otherwise select the
/// one preferred by the target.

View File

@ -1302,7 +1302,8 @@ public:
createFastISel(MachineFunction &,
DenseMap<const Value *, unsigned> &,
DenseMap<const BasicBlock *, MachineBasicBlock *> &,
DenseMap<const AllocaInst *, int> &
DenseMap<const AllocaInst *, int> &,
std::vector<std::pair<MachineInstr*, unsigned> > &
#ifndef NDEBUG
, SmallSet<const Instruction *, 8> &CatchInfoLost
#endif

View File

@ -744,7 +744,8 @@ FastISel::SelectOperator(const User *I, unsigned Opcode) {
FastISel::FastISel(MachineFunction &mf,
DenseMap<const Value *, unsigned> &vm,
DenseMap<const BasicBlock *, MachineBasicBlock *> &bm,
DenseMap<const AllocaInst *, int> &am
DenseMap<const AllocaInst *, int> &am,
std::vector<std::pair<MachineInstr*, unsigned> > &pn
#ifndef NDEBUG
, SmallSet<const Instruction *, 8> &cil
#endif
@ -753,6 +754,7 @@ FastISel::FastISel(MachineFunction &mf,
ValueMap(vm),
MBBMap(bm),
StaticAllocaMap(am),
PHINodesToUpdate(pn),
#ifndef NDEBUG
CatchInfoLost(cil),
#endif
@ -1020,3 +1022,67 @@ unsigned FastISel::FastEmitInst_extractsubreg(MVT RetVT,
unsigned FastISel::FastEmitZExtFromI1(MVT VT, unsigned Op) {
return FastEmit_ri(VT, VT, ISD::AND, Op, 1);
}
/// HandlePHINodesInSuccessorBlocks - Handle PHI nodes in successor blocks.
/// Emit code to ensure constants are copied into registers when needed.
/// Remember the virtual registers that need to be added to the Machine PHI
/// nodes as input. We cannot just directly add them, because expansion
/// might result in multiple MBB's for one BB. As such, the start of the
/// BB might correspond to a different MBB than the end.
bool FastISel::HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB) {
const TerminatorInst *TI = LLVMBB->getTerminator();
SmallPtrSet<MachineBasicBlock *, 4> SuccsHandled;
unsigned OrigNumPHINodesToUpdate = 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) {
const BasicBlock *SuccBB = TI->getSuccessor(succ);
if (!isa<PHINode>(SuccBB->begin())) continue;
MachineBasicBlock *SuccMBB = 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();
// 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::const_iterator I = SuccBB->begin();
const PHINode *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.
EVT VT = TLI.getValueType(PN->getType(), /*AllowUnknown=*/true);
if (VT == MVT::Other || !TLI.isTypeLegal(VT)) {
// Promote MVT::i1.
if (VT == MVT::i1)
VT = TLI.getTypeToTransformTo(LLVMBB->getContext(), VT);
else {
PHINodesToUpdate.resize(OrigNumPHINodesToUpdate);
return false;
}
}
const Value *PHIOp = PN->getIncomingValueForBlock(LLVMBB);
unsigned Reg = getRegForValue(PHIOp);
if (Reg == 0) {
PHINodesToUpdate.resize(OrigNumPHINodesToUpdate);
return false;
}
PHINodesToUpdate.push_back(std::make_pair(MBBI++, Reg));
}
}
return true;
}

View File

@ -5801,7 +5801,7 @@ void SelectionDAGISel::LowerArguments(const BasicBlock *LLVMBB) {
// or one register.
ISD::ArgFlagsTy Flags;
Flags.setSRet();
EVT RegisterVT = TLI.getRegisterType(*CurDAG->getContext(), ValueVTs[0]);
EVT RegisterVT = TLI.getRegisterType(*DAG.getContext(), ValueVTs[0]);
ISD::InputArg RetArg(Flags, RegisterVT, true);
Ins.push_back(RetArg);
}
@ -5964,7 +5964,7 @@ void SelectionDAGISel::LowerArguments(const BasicBlock *LLVMBB) {
/// the end.
///
void
SelectionDAGISel::HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB) {
SelectionDAGBuilder::HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB) {
const TerminatorInst *TI = LLVMBB->getTerminator();
SmallPtrSet<MachineBasicBlock *, 4> SuccsHandled;
@ -5974,7 +5974,7 @@ SelectionDAGISel::HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB) {
for (unsigned succ = 0, e = TI->getNumSuccessors(); succ != e; ++succ) {
const BasicBlock *SuccBB = TI->getSuccessor(succ);
if (!isa<PHINode>(SuccBB->begin())) continue;
MachineBasicBlock *SuccMBB = FuncInfo->MBBMap[SuccBB];
MachineBasicBlock *SuccMBB = FuncInfo.MBBMap[SuccBB];
// If this terminator has multiple identical successors (common for
// switches), only handle each succ once.
@ -5994,20 +5994,20 @@ SelectionDAGISel::HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB) {
const Value *PHIOp = PN->getIncomingValueForBlock(LLVMBB);
if (const Constant *C = dyn_cast<Constant>(PHIOp)) {
unsigned &RegOut = SDB->ConstantsOut[C];
unsigned &RegOut = ConstantsOut[C];
if (RegOut == 0) {
RegOut = FuncInfo->CreateRegForValue(C);
SDB->CopyValueToVirtualRegister(C, RegOut);
RegOut = FuncInfo.CreateRegForValue(C);
CopyValueToVirtualRegister(C, RegOut);
}
Reg = RegOut;
} else {
Reg = FuncInfo->ValueMap[PHIOp];
Reg = FuncInfo.ValueMap[PHIOp];
if (Reg == 0) {
assert(isa<AllocaInst>(PHIOp) &&
FuncInfo->StaticAllocaMap.count(cast<AllocaInst>(PHIOp)) &&
FuncInfo.StaticAllocaMap.count(cast<AllocaInst>(PHIOp)) &&
"Didn't codegen value into a register!??");
Reg = FuncInfo->CreateRegForValue(PHIOp);
SDB->CopyValueToVirtualRegister(PHIOp, Reg);
Reg = FuncInfo.CreateRegForValue(PHIOp);
CopyValueToVirtualRegister(PHIOp, Reg);
}
}
@ -6017,76 +6017,12 @@ SelectionDAGISel::HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB) {
ComputeValueVTs(TLI, PN->getType(), ValueVTs);
for (unsigned vti = 0, vte = ValueVTs.size(); vti != vte; ++vti) {
EVT VT = ValueVTs[vti];
unsigned NumRegisters = TLI.getNumRegisters(*CurDAG->getContext(), VT);
unsigned NumRegisters = TLI.getNumRegisters(*DAG.getContext(), VT);
for (unsigned i = 0, e = NumRegisters; i != e; ++i)
FuncInfo->PHINodesToUpdate.push_back(std::make_pair(MBBI++, Reg+i));
FuncInfo.PHINodesToUpdate.push_back(std::make_pair(MBBI++, Reg+i));
Reg += NumRegisters;
}
}
}
SDB->ConstantsOut.clear();
}
/// 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(const BasicBlock *LLVMBB,
FastISel *F) {
const TerminatorInst *TI = LLVMBB->getTerminator();
SmallPtrSet<MachineBasicBlock *, 4> SuccsHandled;
unsigned OrigNumPHINodesToUpdate = FuncInfo->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) {
const 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();
// 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::const_iterator I = SuccBB->begin();
const PHINode *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.
EVT VT = TLI.getValueType(PN->getType(), /*AllowUnknown=*/true);
if (VT == MVT::Other || !TLI.isTypeLegal(VT)) {
// Promote MVT::i1.
if (VT == MVT::i1)
VT = TLI.getTypeToTransformTo(*CurDAG->getContext(), VT);
else {
FuncInfo->PHINodesToUpdate.resize(OrigNumPHINodesToUpdate);
return false;
}
}
const Value *PHIOp = PN->getIncomingValueForBlock(LLVMBB);
unsigned Reg = F->getRegForValue(PHIOp);
if (Reg == 0) {
FuncInfo->PHINodesToUpdate.resize(OrigNumPHINodesToUpdate);
return false;
}
FuncInfo->PHINodesToUpdate.push_back(std::make_pair(MBBI++, Reg));
}
}
return true;
ConstantsOut.clear();
}

View File

@ -369,6 +369,8 @@ public:
void LowerCallTo(ImmutableCallSite CS, SDValue Callee, bool IsTailCall,
MachineBasicBlock *LandingPad = NULL);
void HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB);
private:
// Terminator instructions.
void visitRet(const ReturnInst &I);

View File

@ -241,7 +241,7 @@ SelectionDAGISel::SelectBasicBlock(MachineBasicBlock *BB,
if (!SDB->HasTailCall) {
// Handle PHI nodes in successor blocks.
if (End == LLVMBB->end()) {
HandlePHINodesInSuccessorBlocks(LLVMBB);
SDB->HandlePHINodesInSuccessorBlocks(LLVMBB);
// Lower the terminator after the copies are emitted.
SDB->visit(*LLVMBB->getTerminator());
@ -711,7 +711,8 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
FastISel *FastIS = 0;
if (EnableFastISel)
FastIS = TLI.createFastISel(*MF, FuncInfo->ValueMap, FuncInfo->MBBMap,
FuncInfo->StaticAllocaMap
FuncInfo->StaticAllocaMap,
FuncInfo->PHINodesToUpdate
#ifndef NDEBUG
, FuncInfo->CatchInfoLost
#endif
@ -765,7 +766,7 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
// Just before the terminator instruction, insert instructions to
// feed PHI nodes in successor blocks.
if (isa<TerminatorInst>(BI))
if (!HandlePHINodesInSuccessorBlocksFast(LLVMBB, FastIS)) {
if (!FastIS->HandlePHINodesInSuccessorBlocks(LLVMBB)) {
++NumFastIselFailures;
if (EnableFastISelVerbose || EnableFastISelAbort) {
dbgs() << "FastISel miss: ";

View File

@ -55,12 +55,13 @@ public:
explicit X86FastISel(MachineFunction &mf,
DenseMap<const Value *, unsigned> &vm,
DenseMap<const BasicBlock *, MachineBasicBlock *> &bm,
DenseMap<const AllocaInst *, int> &am
DenseMap<const AllocaInst *, int> &am,
std::vector<std::pair<MachineInstr*, unsigned> > &pn
#ifndef NDEBUG
, SmallSet<const Instruction *, 8> &cil
#endif
)
: FastISel(mf, vm, bm, am
: FastISel(mf, vm, bm, am, pn
#ifndef NDEBUG
, cil
#endif
@ -1754,12 +1755,13 @@ namespace llvm {
llvm::FastISel *X86::createFastISel(MachineFunction &mf,
DenseMap<const Value *, unsigned> &vm,
DenseMap<const BasicBlock *, MachineBasicBlock *> &bm,
DenseMap<const AllocaInst *, int> &am
DenseMap<const AllocaInst *, int> &am,
std::vector<std::pair<MachineInstr*, unsigned> > &pn
#ifndef NDEBUG
, SmallSet<const Instruction *, 8> &cil
#endif
) {
return new X86FastISel(mf, vm, bm, am
return new X86FastISel(mf, vm, bm, am, pn
#ifndef NDEBUG
, cil
#endif

View File

@ -2419,12 +2419,13 @@ FastISel *
X86TargetLowering::createFastISel(MachineFunction &mf,
DenseMap<const Value *, unsigned> &vm,
DenseMap<const BasicBlock*, MachineBasicBlock*> &bm,
DenseMap<const AllocaInst *, int> &am
DenseMap<const AllocaInst *, int> &am,
std::vector<std::pair<MachineInstr*, unsigned> > &pn
#ifndef NDEBUG
, SmallSet<const Instruction *, 8> &cil
#endif
) const {
return X86::createFastISel(mf, vm, bm, am
return X86::createFastISel(mf, vm, bm, am, pn
#ifndef NDEBUG
, cil
#endif

View File

@ -580,7 +580,8 @@ namespace llvm {
createFastISel(MachineFunction &mf,
DenseMap<const Value *, unsigned> &,
DenseMap<const BasicBlock *, MachineBasicBlock *> &,
DenseMap<const AllocaInst *, int> &
DenseMap<const AllocaInst *, int> &,
std::vector<std::pair<MachineInstr*, unsigned> > &
#ifndef NDEBUG
, SmallSet<const Instruction *, 8> &
#endif
@ -826,7 +827,8 @@ namespace llvm {
FastISel *createFastISel(MachineFunction &mf,
DenseMap<const Value *, unsigned> &,
DenseMap<const BasicBlock *, MachineBasicBlock *> &,
DenseMap<const AllocaInst *, int> &
DenseMap<const AllocaInst *, int> &,
std::vector<std::pair<MachineInstr*, unsigned> > &
#ifndef NDEBUG
, SmallSet<const Instruction*, 8> &
#endif