Move the point at which FastISel taps into the SelectionDAGISel

process up to a higher level. This allows FastISel to leverage
more of SelectionDAGISel's infastructure, such as updating Machine
PHI nodes.

Also, implement transitioning from SDISel back to FastISel in
the middle of a block, so it's now possible to go back and
forth. This allows FastISel to hand individual CallInsts and other
complicated things off to SDISel to handle, while handling the rest
of the block itself.

To help support this, reorganize the SelectionDAG class so that it
is allocated once and reused throughout a function, instead of
being completely reallocated for each block.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@55219 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Dan Gohman 2008-08-23 02:25:05 +00:00
parent 6679906d97
commit f350b277f3
14 changed files with 366 additions and 332 deletions

View File

@ -36,13 +36,6 @@ class MachineFunction;
class MachineConstantPoolValue;
class FunctionLoweringInfo;
/// NodeAllocatorType - The AllocatorType for allocating SDNodes. We use
/// pool allocation with recycling.
///
typedef RecyclingAllocator<BumpPtrAllocator, SDNode, sizeof(LargestSDNode),
AlignOf<MostAlignedSDNode>::Alignment>
NodeAllocatorType;
template<> class ilist_traits<SDNode> : public ilist_default_traits<SDNode> {
mutable SDNode Sentinel;
public:
@ -77,21 +70,31 @@ class SelectionDAG {
FunctionLoweringInfo &FLI;
MachineModuleInfo *MMI;
/// Root - The root of the entire DAG. EntryNode - The starting token.
SDValue Root, EntryNode;
/// EntryNode - The starting token.
SDNode EntryNode;
/// Root - The root of the entire DAG.
SDValue Root;
/// AllNodes - A linked list of nodes in the current DAG.
ilist<SDNode> AllNodes;
/// NodeAllocator - Pool allocation for nodes. The allocator isn't
/// allocated inside this class because we want to reuse a single
/// recycler across multiple SelectionDAG runs.
NodeAllocatorType &NodeAllocator;
/// NodeAllocatorType - The AllocatorType for allocating SDNodes. We use
/// pool allocation with recycling.
typedef RecyclingAllocator<BumpPtrAllocator, SDNode, sizeof(LargestSDNode),
AlignOf<MostAlignedSDNode>::Alignment>
NodeAllocatorType;
/// NodeAllocator - Pool allocation for nodes.
NodeAllocatorType NodeAllocator;
/// CSEMap - This structure is used to memoize nodes, automatically performing
/// CSE with existing nodes with a duplicate is requested.
FoldingSet<SDNode> CSEMap;
/// OperandAllocator - Pool allocation for machine-opcode SDNode operands.
BumpPtrAllocator OperandAllocator;
/// Allocator - Pool allocation for misc. objects that are created once per
/// SelectionDAG.
BumpPtrAllocator Allocator;
@ -101,10 +104,14 @@ class SelectionDAG {
public:
SelectionDAG(TargetLowering &tli, MachineFunction &mf,
FunctionLoweringInfo &fli, MachineModuleInfo *mmi,
NodeAllocatorType &nodeallocator);
FunctionLoweringInfo &fli, MachineModuleInfo *mmi);
~SelectionDAG();
/// reset - Clear state and free memory necessary to make this
/// SelectionDAG ready to process a new block.
///
void reset();
MachineFunction &getMachineFunction() const { return MF; }
const TargetMachine &getTarget() const;
TargetLowering &getTargetLoweringInfo() const { return TLI; }
@ -152,7 +159,9 @@ public:
/// getEntryNode - Return the token chain corresponding to the entry of the
/// function.
const SDValue &getEntryNode() const { return EntryNode; }
SDValue getEntryNode() const {
return SDValue(const_cast<SDNode *>(&EntryNode), 0);
}
/// setRoot - Set the current root tag of the SelectionDAG.
///
@ -721,6 +730,8 @@ private:
void DeleteNodeNotInCSEMaps(SDNode *N);
unsigned getMVTAlignment(MVT MemoryVT) const;
void allnodes_clear();
// List of non-single value types.
std::vector<SDVTList> VTList;

View File

@ -15,6 +15,7 @@
#ifndef LLVM_CODEGEN_SELECTIONDAG_ISEL_H
#define LLVM_CODEGEN_SELECTIONDAG_ISEL_H
#include "llvm/BasicBlock.h"
#include "llvm/Pass.h"
#include "llvm/Constant.h"
#include "llvm/CodeGen/SelectionDAG.h"
@ -58,7 +59,7 @@ public:
unsigned MakeReg(MVT VT);
virtual void EmitFunctionEntryCode(Function &Fn, MachineFunction &MF) {}
virtual void InstructionSelect(SelectionDAG &SD) = 0;
virtual void InstructionSelect() = 0;
virtual void InstructionSelectPostProcessing() {}
void SelectRootInit() {
@ -72,8 +73,7 @@ public:
/// OutOps vector.
virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
char ConstraintCode,
std::vector<SDValue> &OutOps,
SelectionDAG &DAG) {
std::vector<SDValue> &OutOps) {
return true;
}
@ -168,8 +168,7 @@ protected:
/// SelectInlineAsmMemoryOperands - Calls to this are automatically generated
/// by tblgen. Others should not call it.
void SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops,
SelectionDAG &DAG);
void SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops);
// Calls to these predicates are generated by tblgen.
bool CheckAndMask(SDValue LHS, ConstantSDNode *RHS,
@ -180,26 +179,28 @@ protected:
private:
void SelectAllBasicBlocks(Function &Fn, MachineFunction &MF,
FunctionLoweringInfo &FuncInfo);
void SelectBasicBlock(BasicBlock *BB, MachineFunction &MF,
FunctionLoweringInfo &FuncInfo,
std::vector<std::pair<MachineInstr*, unsigned> > &PHINodesToUpdate,
NodeAllocatorType &NodeAllocator);
void FinishBasicBlock(BasicBlock *BB, MachineFunction &MF,
FunctionLoweringInfo &FuncInfo,
std::vector<std::pair<MachineInstr*, unsigned> > &PHINodesToUpdate,
NodeAllocatorType &NodeAllocator);
void FinishBasicBlock(FunctionLoweringInfo &FuncInfo,
std::vector<std::pair<MachineInstr*, unsigned> > &PHINodesToUpdate);
void BuildSelectionDAG(SelectionDAG &DAG, BasicBlock *LLVMBB,
void SelectBasicBlock(BasicBlock *LLVMBB,
BasicBlock::iterator Begin,
BasicBlock::iterator End,
bool DoArgs,
std::vector<std::pair<MachineInstr*, unsigned> > &PHINodesToUpdate,
FunctionLoweringInfo &FuncInfo);
void CodeGenAndEmitDAG(SelectionDAG &DAG);
FunctionLoweringInfo &FuncInfo);
void CodeGenAndEmitDAG();
void LowerArguments(BasicBlock *BB, SelectionDAGLowering &SDL);
void ComputeLiveOutVRegInfo(SelectionDAG &DAG);
void ComputeLiveOutVRegInfo();
void HandlePHINodesInSuccessorBlocks(BasicBlock *LLVMBB,
FunctionLoweringInfo &FuncInfo,
std::vector<std::pair<MachineInstr*, unsigned> > &PHINodesToUpdate,
SelectionDAGLowering &SDL);
/// Pick a safe ordering for instructions for each target node in the
/// graph.
ScheduleDAG *Schedule(SelectionDAG &DAG);
ScheduleDAG *Schedule();
/// SwitchCases - Vector of CaseBlock structures used to communicate
/// SwitchInst code generation information.

View File

@ -547,11 +547,8 @@ void SelectionDAG::DeleteNodeNotInCSEMaps(SDNode *N) {
// Drop all of the operands and decrement used nodes use counts.
for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I)
I->getVal()->removeUser(std::distance(N->op_begin(), I), N);
if (N->OperandsNeedDelete) {
if (N->OperandsNeedDelete)
delete[] N->OperandList;
}
N->OperandList = 0;
N->NumOperands = 0;
AllNodes.remove(N);
}
@ -563,6 +560,9 @@ void SelectionDAG::DeleteNodeNotInCSEMaps(SDNode *N) {
void SelectionDAG::RemoveNodeFromCSEMaps(SDNode *N) {
bool Erased = false;
switch (N->getOpcode()) {
case ISD::EntryToken:
assert(0 && "EntryToken should not be in CSEMaps!");
return;
case ISD::HANDLENODE: return; // noop.
case ISD::CONDCODE:
assert(CondCodeNodes[cast<CondCodeSDNode>(N)->get()] &&
@ -764,24 +764,44 @@ unsigned SelectionDAG::getMVTAlignment(MVT VT) const {
}
SelectionDAG::SelectionDAG(TargetLowering &tli, MachineFunction &mf,
FunctionLoweringInfo &fli, MachineModuleInfo *mmi,
NodeAllocatorType &nodeallocator)
: TLI(tli), MF(mf), FLI(fli), MMI(mmi), NodeAllocator(nodeallocator) {
EntryNode = Root = getNode(ISD::EntryToken, MVT::Other);
FunctionLoweringInfo &fli, MachineModuleInfo *mmi)
: TLI(tli), MF(mf), FLI(fli), MMI(mmi),
EntryNode(ISD::EntryToken, getVTList(MVT::Other)),
Root(getEntryNode()) {
AllNodes.push_back(&EntryNode);
}
SelectionDAG::~SelectionDAG() {
allnodes_clear();
}
void SelectionDAG::allnodes_clear() {
while (!AllNodes.empty()) {
SDNode *N = AllNodes.remove(AllNodes.begin());
N->SetNextInBucket(0);
if (N->OperandsNeedDelete) {
if (N->OperandsNeedDelete)
delete [] N->OperandList;
}
N->OperandList = 0;
N->NumOperands = 0;
}
}
void SelectionDAG::reset() {
allnodes_clear();
OperandAllocator.Reset();
CSEMap.clear();
ExtendedValueTypeNodes.clear();
ExternalSymbols.clear();
TargetExternalSymbols.clear();
std::fill(CondCodeNodes.begin(), CondCodeNodes.end(),
static_cast<CondCodeSDNode*>(0));
std::fill(ValueTypeNodes.begin(), ValueTypeNodes.end(),
static_cast<SDNode*>(0));
EntryNode.Uses = 0;
AllNodes.push_back(&EntryNode);
Root = getEntryNode();
}
SDValue SelectionDAG::getZeroExtendInReg(SDValue Op, MVT VT) {
if (Op.getValueType() == VT) return Op;
APInt Imm = APInt::getLowBitsSet(Op.getValueSizeInBits(),
@ -3988,9 +4008,9 @@ SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc,
delete[] N->OperandList;
if (N->isMachineOpcode()) {
// We're creating a final node that will live unmorphed for the
// remainder of this SelectionDAG's duration, so we can allocate the
// operands directly out of the pool with no recycling metadata.
N->OperandList = Allocator.Allocate<SDUse>(NumOps);
// remainder of the current SelectionDAG iteration, so we can allocate
// the operands directly out of a pool with no recycling metadata.
N->OperandList = OperandAllocator.Allocate<SDUse>(NumOps);
N->OperandsNeedDelete = false;
} else {
N->OperandList = new SDUse[NumOps];

View File

@ -394,6 +394,11 @@ static bool isUsedOutsideOfDefiningBlock(Instruction *I) {
/// entry block, return true. This includes arguments used by switches, since
/// the switch may expand into multiple basic blocks.
static bool isOnlyUsedInEntryBlock(Argument *A) {
// With FastISel active, we may be splitting blocks, so force creation
// of virtual registers for all non-dead arguments.
if (EnableFastISel)
return A->use_empty();
BasicBlock *Entry = A->getParent()->begin();
for (Value::use_iterator UI = A->use_begin(), E = A->use_end(); UI != E; ++UI)
if (cast<Instruction>(*UI)->getParent() != Entry || isa<SwitchInst>(*UI))
@ -5094,119 +5099,18 @@ static void CheckDAGForTailCallsAndFixThem(SelectionDAG &DAG,
}
}
void SelectionDAGISel::BuildSelectionDAG(SelectionDAG &DAG, BasicBlock *LLVMBB,
std::vector<std::pair<MachineInstr*, unsigned> > &PHINodesToUpdate,
FunctionLoweringInfo &FuncInfo) {
SelectionDAGLowering SDL(DAG, TLI, *AA, FuncInfo, GFI);
BB = FuncInfo.MBBMap[LLVMBB];
// Before doing SelectionDAG ISel, see if FastISel has been requested.
// FastISel doesn't currently support entry blocks, because that
// requires special handling for arguments. And it doesn't support EH
// landing pads, which also require special handling.
// For now, also exclude blocks with terminators that aren't
// unconditional branches.
BasicBlock::iterator Begin = LLVMBB->begin();
if (EnableFastISel &&
LLVMBB != &LLVMBB->getParent()->getEntryBlock() &&
!BB->isLandingPad() &&
isa<BranchInst>(LLVMBB->getTerminator()) &&
cast<BranchInst>(LLVMBB->getTerminator())->isUnconditional()) {
if (FastISel *F = TLI.createFastISel(FuncInfo.MF)) {
Begin = F->SelectInstructions(Begin, LLVMBB->end(),
FuncInfo.ValueMap, FuncInfo.MBBMap, BB);
// Clean up the FastISel object. TODO: Reorganize what data is
// stored in the FastISel class itself and what is merely passed
// to the SelectInstructions method, and then move the creation
// and deletion of the FastISel object up so that it is only
// done once per MachineFunction.
delete F;
if (Begin == LLVMBB->end())
// The "fast" selector selected the entire block, so we're done.
return;
if (!DisableFastISelAbort) {
// The "fast" selector couldn't handle something and bailed.
// For the purpose of debugging, just abort.
#ifndef NDEBUG
Begin->dump();
#endif
assert(0 && "FastISel didn't select the entire block");
abort();
}
}
}
// Lower any arguments needed in this block if this is the entry block.
if (LLVMBB == &LLVMBB->getParent()->getEntryBlock())
LowerArguments(LLVMBB, SDL);
SDL.setCurrentBasicBlock(BB);
MachineModuleInfo *MMI = DAG.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);
DAG.setRoot(DAG.getLabel(ISD::EH_LABEL, DAG.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 (isSelector(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, E = --LLVMBB->end();
I != E; ++I)
SDL.visit(*I);
// Ensure that all instructions which are used outside of their defining
// blocks are available as virtual registers. Invoke is handled elsewhere.
for (BasicBlock::iterator I = Begin, E = LLVMBB->end(); I != E;++I)
if (!I->use_empty() && !isa<PHINode>(I) && !isa<InvokeInst>(I)) {
DenseMap<const Value*, unsigned>::iterator VMI =FuncInfo.ValueMap.find(I);
if (VMI != FuncInfo.ValueMap.end())
SDL.CopyValueToVirtualRegister(I, VMI->second);
}
// Handle PHI nodes in successor blocks. Emit code into the SelectionDAG to
// ensure constants are generated 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.
//
/// Handle PHI nodes in successor blocks. Emit code into the SelectionDAG to
/// ensure constants are generated 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.
///
void
SelectionDAGISel::HandlePHINodesInSuccessorBlocks(BasicBlock *LLVMBB,
FunctionLoweringInfo &FuncInfo,
std::vector<std::pair<MachineInstr*, unsigned> > &PHINodesToUpdate,
SelectionDAGLowering &SDL) {
TerminatorInst *TI = LLVMBB->getTerminator();
// Emit constants only once even if used by multiple PHI nodes.
@ -5287,22 +5191,101 @@ void SelectionDAGISel::BuildSelectionDAG(SelectionDAG &DAG, BasicBlock *LLVMBB,
JTCases = SDL.JTCases;
BitTestCases.clear();
BitTestCases = SDL.BitTestCases;
}
void SelectionDAGISel::SelectBasicBlock(BasicBlock *LLVMBB,
BasicBlock::iterator Begin,
BasicBlock::iterator End,
bool DoArgs,
std::vector<std::pair<MachineInstr*, unsigned> > &PHINodesToUpdate,
FunctionLoweringInfo &FuncInfo) {
SelectionDAGLowering SDL(*CurDAG, TLI, *AA, FuncInfo, GFI);
// Lower any arguments needed in this block if this is the entry block.
if (DoArgs)
LowerArguments(LLVMBB, SDL);
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 (isSelector(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))
SDL.visit(*I);
// Ensure that all instructions which are used outside of their defining
// blocks are available as virtual registers. Invoke is handled elsewhere.
for (BasicBlock::iterator I = Begin; I != End; ++I)
if (!I->use_empty() && !isa<PHINode>(I) && !isa<InvokeInst>(I)) {
DenseMap<const Value*, unsigned>::iterator VMI =FuncInfo.ValueMap.find(I);
if (VMI != FuncInfo.ValueMap.end())
SDL.CopyValueToVirtualRegister(I, VMI->second);
}
// Handle PHI nodes in successor blocks.
if (Begin != End && End == LLVMBB->end())
HandlePHINodesInSuccessorBlocks(LLVMBB, FuncInfo, PHINodesToUpdate, SDL);
// Make sure the root of the DAG is up-to-date.
DAG.setRoot(SDL.getControlRoot());
CurDAG->setRoot(SDL.getControlRoot());
// Check whether calls in this block are real tail calls. Fix up CALL nodes
// with correct tailcall attribute so that the target can rely on the tailcall
// attribute indicating whether the call is really eligible for tail call
// optimization.
CheckDAGForTailCallsAndFixThem(DAG, TLI);
CheckDAGForTailCallsAndFixThem(*CurDAG, TLI);
// Final step, emit the lowered DAG as machine code.
CodeGenAndEmitDAG();
CurDAG->reset();
}
void SelectionDAGISel::ComputeLiveOutVRegInfo(SelectionDAG &DAG) {
void SelectionDAGISel::ComputeLiveOutVRegInfo() {
SmallPtrSet<SDNode*, 128> VisitedNodes;
SmallVector<SDNode*, 128> Worklist;
Worklist.push_back(DAG.getRoot().Val);
Worklist.push_back(CurDAG->getRoot().Val);
APInt Mask;
APInt KnownZero;
@ -5335,14 +5318,14 @@ void SelectionDAGISel::ComputeLiveOutVRegInfo(SelectionDAG &DAG) {
if (!SrcVT.isInteger() || SrcVT.isVector())
continue;
unsigned NumSignBits = DAG.ComputeNumSignBits(Src);
unsigned NumSignBits = CurDAG->ComputeNumSignBits(Src);
Mask = APInt::getAllOnesValue(SrcVT.getSizeInBits());
DAG.ComputeMaskedBits(Src, Mask, KnownZero, KnownOne);
CurDAG->ComputeMaskedBits(Src, Mask, KnownZero, KnownOne);
// Only install this information if it tells us something.
if (NumSignBits != 1 || KnownZero != 0 || KnownOne != 0) {
DestReg -= TargetRegisterInfo::FirstVirtualRegister;
FunctionLoweringInfo &FLI = DAG.getFunctionLoweringInfo();
FunctionLoweringInfo &FLI = CurDAG->getFunctionLoweringInfo();
if (DestReg >= FLI.LiveOutRegInfo.size())
FLI.LiveOutRegInfo.resize(DestReg+1);
FunctionLoweringInfo::LiveOutInfo &LOI = FLI.LiveOutRegInfo[DestReg];
@ -5353,102 +5336,102 @@ void SelectionDAGISel::ComputeLiveOutVRegInfo(SelectionDAG &DAG) {
}
}
void SelectionDAGISel::CodeGenAndEmitDAG(SelectionDAG &DAG) {
void SelectionDAGISel::CodeGenAndEmitDAG() {
std::string GroupName;
if (TimePassesIsEnabled)
GroupName = "Instruction Selection and Scheduling";
std::string BlockName;
if (ViewDAGCombine1 || ViewLegalizeTypesDAGs || ViewLegalizeDAGs ||
ViewDAGCombine2 || ViewISelDAGs || ViewSchedDAGs || ViewSUnitDAGs)
BlockName = DAG.getMachineFunction().getFunction()->getName() + ':' +
BlockName = CurDAG->getMachineFunction().getFunction()->getName() + ':' +
BB->getBasicBlock()->getName();
DOUT << "Initial selection DAG:\n";
DEBUG(DAG.dump());
DEBUG(CurDAG->dump());
if (ViewDAGCombine1) DAG.viewGraph("dag-combine1 input for " + BlockName);
if (ViewDAGCombine1) CurDAG->viewGraph("dag-combine1 input for " + BlockName);
// Run the DAG combiner in pre-legalize mode.
if (TimePassesIsEnabled) {
NamedRegionTimer T("DAG Combining 1", GroupName);
DAG.Combine(false, *AA, Fast);
CurDAG->Combine(false, *AA, Fast);
} else {
DAG.Combine(false, *AA, Fast);
CurDAG->Combine(false, *AA, Fast);
}
DOUT << "Optimized lowered selection DAG:\n";
DEBUG(DAG.dump());
DEBUG(CurDAG->dump());
// Second step, hack on the DAG until it only uses operations and types that
// the target supports.
if (EnableLegalizeTypes) {// Enable this some day.
if (ViewLegalizeTypesDAGs) DAG.viewGraph("legalize-types input for " +
BlockName);
if (ViewLegalizeTypesDAGs) CurDAG->viewGraph("legalize-types input for " +
BlockName);
if (TimePassesIsEnabled) {
NamedRegionTimer T("Type Legalization", GroupName);
DAG.LegalizeTypes();
CurDAG->LegalizeTypes();
} else {
DAG.LegalizeTypes();
CurDAG->LegalizeTypes();
}
DOUT << "Type-legalized selection DAG:\n";
DEBUG(DAG.dump());
DEBUG(CurDAG->dump());
// TODO: enable a dag combine pass here.
}
if (ViewLegalizeDAGs) DAG.viewGraph("legalize input for " + BlockName);
if (ViewLegalizeDAGs) CurDAG->viewGraph("legalize input for " + BlockName);
if (TimePassesIsEnabled) {
NamedRegionTimer T("DAG Legalization", GroupName);
DAG.Legalize();
CurDAG->Legalize();
} else {
DAG.Legalize();
CurDAG->Legalize();
}
DOUT << "Legalized selection DAG:\n";
DEBUG(DAG.dump());
DEBUG(CurDAG->dump());
if (ViewDAGCombine2) DAG.viewGraph("dag-combine2 input for " + BlockName);
if (ViewDAGCombine2) CurDAG->viewGraph("dag-combine2 input for " + BlockName);
// Run the DAG combiner in post-legalize mode.
if (TimePassesIsEnabled) {
NamedRegionTimer T("DAG Combining 2", GroupName);
DAG.Combine(true, *AA, Fast);
CurDAG->Combine(true, *AA, Fast);
} else {
DAG.Combine(true, *AA, Fast);
CurDAG->Combine(true, *AA, Fast);
}
DOUT << "Optimized legalized selection DAG:\n";
DEBUG(DAG.dump());
DEBUG(CurDAG->dump());
if (ViewISelDAGs) DAG.viewGraph("isel input for " + BlockName);
if (ViewISelDAGs) CurDAG->viewGraph("isel input for " + BlockName);
if (!Fast && EnableValueProp)
ComputeLiveOutVRegInfo(DAG);
ComputeLiveOutVRegInfo();
// Third, instruction select all of the operations to machine code, adding the
// code to the MachineBasicBlock.
if (TimePassesIsEnabled) {
NamedRegionTimer T("Instruction Selection", GroupName);
InstructionSelect(DAG);
InstructionSelect();
} else {
InstructionSelect(DAG);
InstructionSelect();
}
DOUT << "Selected selection DAG:\n";
DEBUG(DAG.dump());
DEBUG(CurDAG->dump());
if (ViewSchedDAGs) DAG.viewGraph("scheduler input for " + BlockName);
if (ViewSchedDAGs) CurDAG->viewGraph("scheduler input for " + BlockName);
// Schedule machine code.
ScheduleDAG *Scheduler;
if (TimePassesIsEnabled) {
NamedRegionTimer T("Instruction Scheduling", GroupName);
Scheduler = Schedule(DAG);
Scheduler = Schedule();
} else {
Scheduler = Schedule(DAG);
Scheduler = Schedule();
}
if (ViewSUnitDAGs) Scheduler->viewGraph();
@ -5470,57 +5453,94 @@ void SelectionDAGISel::CodeGenAndEmitDAG(SelectionDAG &DAG) {
delete Scheduler;
}
// Perform target specific isel post processing.
if (TimePassesIsEnabled) {
NamedRegionTimer T("Instruction Selection Post Processing", GroupName);
InstructionSelectPostProcessing();
} else {
InstructionSelectPostProcessing();
}
DOUT << "Selected machine code:\n";
DEBUG(BB->dump());
}
void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, MachineFunction &MF,
FunctionLoweringInfo &FuncInfo) {
// Define NodeAllocator here so that memory allocation is reused for
// Define the SelectionDAG here so that memory allocation is reused for
// each basic block.
NodeAllocatorType NodeAllocator;
SelectionDAG DAG(TLI, MF, FuncInfo,
getAnalysisToUpdate<MachineModuleInfo>());
CurDAG = &DAG;
std::vector<std::pair<MachineInstr*, unsigned> > PHINodesToUpdate;
for (Function::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) {
BasicBlock *LLVMBB = &*I;
BB = FuncInfo.MBBMap[LLVMBB];
BasicBlock::iterator Begin = LLVMBB->begin();
BasicBlock::iterator End = LLVMBB->end();
bool DoArgs = LLVMBB == &Fn.getEntryBlock();
// 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)) {
while (Begin != End) {
Begin = F->SelectInstructions(Begin, End, FuncInfo.ValueMap,
FuncInfo.MBBMap, BB);
if (Begin == End)
// The "fast" selector selected the entire block, so we're done.
break;
// 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);
}
SelectBasicBlock(LLVMBB, Begin, next(Begin), DoArgs,
PHINodesToUpdate, FuncInfo);
++Begin;
DoArgs = false;
continue;
}
if (!DisableFastISelAbort &&
// For now, don't abort on non-conditional-branch terminators.
(!isa<TerminatorInst>(Begin) ||
(isa<BranchInst>(Begin) &&
cast<BranchInst>(Begin)->isUnconditional()))) {
// The "fast" selector couldn't handle something and bailed.
// For the purpose of debugging, just abort.
#ifndef NDEBUG
Begin->dump();
#endif
assert(0 && "FastISel didn't select the entire block");
}
break;
}
delete F;
}
}
if (Begin != End || DoArgs)
SelectBasicBlock(LLVMBB, Begin, End, DoArgs, PHINodesToUpdate, FuncInfo);
FinishBasicBlock(FuncInfo, PHINodesToUpdate);
PHINodesToUpdate.clear();
SelectBasicBlock(LLVMBB, MF, FuncInfo, PHINodesToUpdate, NodeAllocator);
FinishBasicBlock(LLVMBB, MF, FuncInfo, PHINodesToUpdate, NodeAllocator);
}
CurDAG = 0;
}
void
SelectionDAGISel::SelectBasicBlock(BasicBlock *LLVMBB, MachineFunction &MF,
FunctionLoweringInfo &FuncInfo,
std::vector<std::pair<MachineInstr*, unsigned> > &PHINodesToUpdate,
NodeAllocatorType &NodeAllocator) {
SelectionDAG DAG(TLI, MF, FuncInfo,
getAnalysisToUpdate<MachineModuleInfo>(),
NodeAllocator);
CurDAG = &DAG;
SelectionDAGISel::FinishBasicBlock(FunctionLoweringInfo &FuncInfo,
std::vector<std::pair<MachineInstr*, unsigned> > &PHINodesToUpdate) {
// Perform target specific isel post processing.
InstructionSelectPostProcessing();
// First step, lower LLVM code to some DAG. This DAG may use operations and
// types that are not supported by the target.
BuildSelectionDAG(DAG, LLVMBB, PHINodesToUpdate, FuncInfo);
DOUT << "Target-post-processed machine code:\n";
DEBUG(BB->dump());
// Second step, emit the lowered DAG as machine code.
CodeGenAndEmitDAG(DAG);
}
void
SelectionDAGISel::FinishBasicBlock(BasicBlock *LLVMBB, MachineFunction &MF,
FunctionLoweringInfo &FuncInfo,
std::vector<std::pair<MachineInstr*, unsigned> > &PHINodesToUpdate,
NodeAllocatorType &NodeAllocator) {
DOUT << "Total amount of phi nodes to update: "
<< PHINodesToUpdate.size() << "\n";
DEBUG(for (unsigned i = 0, e = PHINodesToUpdate.size(); i != e; ++i)
@ -5544,26 +5564,19 @@ SelectionDAGISel::FinishBasicBlock(BasicBlock *LLVMBB, MachineFunction &MF,
for (unsigned i = 0, e = BitTestCases.size(); i != e; ++i) {
// Lower header first, if it wasn't already lowered
if (!BitTestCases[i].Emitted) {
SelectionDAG HSDAG(TLI, MF, FuncInfo,
getAnalysisToUpdate<MachineModuleInfo>(),
NodeAllocator);
CurDAG = &HSDAG;
SelectionDAGLowering HSDL(HSDAG, TLI, *AA, FuncInfo, GFI);
SelectionDAGLowering HSDL(*CurDAG, TLI, *AA, FuncInfo, GFI);
// Set the current basic block to the mbb we wish to insert the code into
BB = BitTestCases[i].Parent;
HSDL.setCurrentBasicBlock(BB);
// Emit the code
HSDL.visitBitTestHeader(BitTestCases[i]);
HSDAG.setRoot(HSDL.getRoot());
CodeGenAndEmitDAG(HSDAG);
CurDAG->setRoot(HSDL.getRoot());
CodeGenAndEmitDAG();
CurDAG->reset();
}
for (unsigned j = 0, ej = BitTestCases[i].Cases.size(); j != ej; ++j) {
SelectionDAG BSDAG(TLI, MF, FuncInfo,
getAnalysisToUpdate<MachineModuleInfo>(),
NodeAllocator);
CurDAG = &BSDAG;
SelectionDAGLowering BSDL(BSDAG, TLI, *AA, FuncInfo, GFI);
SelectionDAGLowering BSDL(*CurDAG, TLI, *AA, FuncInfo, GFI);
// Set the current basic block to the mbb we wish to insert the code into
BB = BitTestCases[i].Cases[j].ThisBB;
BSDL.setCurrentBasicBlock(BB);
@ -5578,8 +5591,9 @@ SelectionDAGISel::FinishBasicBlock(BasicBlock *LLVMBB, MachineFunction &MF,
BitTestCases[i].Cases[j]);
BSDAG.setRoot(BSDL.getRoot());
CodeGenAndEmitDAG(BSDAG);
CurDAG->setRoot(BSDL.getRoot());
CodeGenAndEmitDAG();
CurDAG->reset();
}
// Update PHI Nodes
@ -5618,32 +5632,26 @@ SelectionDAGISel::FinishBasicBlock(BasicBlock *LLVMBB, MachineFunction &MF,
for (unsigned i = 0, e = JTCases.size(); i != e; ++i) {
// Lower header first, if it wasn't already lowered
if (!JTCases[i].first.Emitted) {
SelectionDAG HSDAG(TLI, MF, FuncInfo,
getAnalysisToUpdate<MachineModuleInfo>(),
NodeAllocator);
CurDAG = &HSDAG;
SelectionDAGLowering HSDL(HSDAG, TLI, *AA, FuncInfo, GFI);
SelectionDAGLowering HSDL(*CurDAG, TLI, *AA, FuncInfo, GFI);
// Set the current basic block to the mbb we wish to insert the code into
BB = JTCases[i].first.HeaderBB;
HSDL.setCurrentBasicBlock(BB);
// Emit the code
HSDL.visitJumpTableHeader(JTCases[i].second, JTCases[i].first);
HSDAG.setRoot(HSDL.getRoot());
CodeGenAndEmitDAG(HSDAG);
CurDAG->setRoot(HSDL.getRoot());
CodeGenAndEmitDAG();
CurDAG->reset();
}
SelectionDAG JSDAG(TLI, MF, FuncInfo,
getAnalysisToUpdate<MachineModuleInfo>(),
NodeAllocator);
CurDAG = &JSDAG;
SelectionDAGLowering JSDL(JSDAG, TLI, *AA, FuncInfo, GFI);
SelectionDAGLowering JSDL(*CurDAG, TLI, *AA, FuncInfo, GFI);
// Set the current basic block to the mbb we wish to insert the code into
BB = JTCases[i].second.MBB;
JSDL.setCurrentBasicBlock(BB);
// Emit the code
JSDL.visitJumpTable(JTCases[i].second);
JSDAG.setRoot(JSDL.getRoot());
CodeGenAndEmitDAG(JSDAG);
CurDAG->setRoot(JSDL.getRoot());
CodeGenAndEmitDAG();
CurDAG->reset();
// Update PHI Nodes
for (unsigned pi = 0, pe = PHINodesToUpdate.size(); pi != pe; ++pi) {
@ -5682,11 +5690,7 @@ SelectionDAGISel::FinishBasicBlock(BasicBlock *LLVMBB, MachineFunction &MF,
// If we generated any switch lowering information, build and codegen any
// additional DAGs necessary.
for (unsigned i = 0, e = SwitchCases.size(); i != e; ++i) {
SelectionDAG SDAG(TLI, MF, FuncInfo,
getAnalysisToUpdate<MachineModuleInfo>(),
NodeAllocator);
CurDAG = &SDAG;
SelectionDAGLowering SDL(SDAG, TLI, *AA, FuncInfo, GFI);
SelectionDAGLowering SDL(*CurDAG, TLI, *AA, FuncInfo, GFI);
// Set the current basic block to the mbb we wish to insert the code into
BB = SwitchCases[i].ThisBB;
@ -5694,8 +5698,9 @@ SelectionDAGISel::FinishBasicBlock(BasicBlock *LLVMBB, MachineFunction &MF,
// Emit the code
SDL.visitSwitchCase(SwitchCases[i]);
SDAG.setRoot(SDL.getRoot());
CodeGenAndEmitDAG(SDAG);
CurDAG->setRoot(SDL.getRoot());
CodeGenAndEmitDAG();
CurDAG->reset();
// Handle any PHI nodes in successors of this chunk, as if we were coming
// from the original BB before switch expansion. Note that PHI nodes can
@ -5732,7 +5737,7 @@ SelectionDAGISel::FinishBasicBlock(BasicBlock *LLVMBB, MachineFunction &MF,
/// Schedule - Pick a safe ordering for instructions for each
/// target node in the graph.
///
ScheduleDAG *SelectionDAGISel::Schedule(SelectionDAG &DAG) {
ScheduleDAG *SelectionDAGISel::Schedule() {
RegisterScheduler::FunctionPassCtor Ctor = RegisterScheduler::getDefault();
if (!Ctor) {
@ -5740,7 +5745,7 @@ ScheduleDAG *SelectionDAGISel::Schedule(SelectionDAG &DAG) {
RegisterScheduler::setDefault(Ctor);
}
ScheduleDAG *Scheduler = Ctor(this, &DAG, BB, Fast);
ScheduleDAG *Scheduler = Ctor(this, CurDAG, BB, Fast);
Scheduler->Run();
return Scheduler;
@ -5823,7 +5828,7 @@ bool SelectionDAGISel::CheckOrMask(SDValue LHS, ConstantSDNode *RHS,
/// SelectInlineAsmMemoryOperands - Calls to this are automatically generated
/// by tblgen. Others should not call it.
void SelectionDAGISel::
SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops, SelectionDAG &DAG) {
SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops) {
std::vector<SDValue> InOps;
std::swap(InOps, Ops);
@ -5844,15 +5849,15 @@ SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops, SelectionDAG &DAG) {
assert((Flags >> 3) == 1 && "Memory operand with multiple values?");
// Otherwise, this is a memory operand. Ask the target to select it.
std::vector<SDValue> SelOps;
if (SelectInlineAsmMemoryOperand(InOps[i+1], 'm', SelOps, DAG)) {
if (SelectInlineAsmMemoryOperand(InOps[i+1], 'm', SelOps)) {
cerr << "Could not match memory address. Inline asm failure!\n";
exit(1);
}
// Add this to the output node.
MVT IntPtrTy = DAG.getTargetLoweringInfo().getPointerTy();
Ops.push_back(DAG.getTargetConstant(4/*MEM*/ | (SelOps.size() << 3),
IntPtrTy));
MVT IntPtrTy = CurDAG->getTargetLoweringInfo().getPointerTy();
Ops.push_back(CurDAG->getTargetConstant(4/*MEM*/ | (SelOps.size() << 3),
IntPtrTy));
Ops.insert(Ops.end(), SelOps.begin(), SelOps.end());
i += 2;
}

View File

@ -54,7 +54,7 @@ public:
}
SDNode *Select(SDValue Op);
virtual void InstructionSelect(SelectionDAG &DAG);
virtual void InstructionSelect();
bool SelectAddrMode2(SDValue Op, SDValue N, SDValue &Base,
SDValue &Offset, SDValue &Opc);
bool SelectAddrMode2Offset(SDValue Op, SDValue N,
@ -91,11 +91,11 @@ public:
};
}
void ARMDAGToDAGISel::InstructionSelect(SelectionDAG &DAG) {
void ARMDAGToDAGISel::InstructionSelect() {
DEBUG(BB->dump());
SelectRoot();
DAG.RemoveDeadNodes();
CurDAG->RemoveDeadNodes();
}
bool ARMDAGToDAGISel::SelectAddrMode2(SDValue Op, SDValue N,

View File

@ -163,7 +163,7 @@ namespace {
/// InstructionSelect - This callback is invoked by
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
virtual void InstructionSelect(SelectionDAG &DAG);
virtual void InstructionSelect();
virtual const char *getPassName() const {
return "Alpha DAG->DAG Pattern Instruction Selection";
@ -173,8 +173,7 @@ namespace {
/// inline asm expressions.
virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
char ConstraintCode,
std::vector<SDValue> &OutOps,
SelectionDAG &DAG) {
std::vector<SDValue> &OutOps) {
SDValue Op0;
switch (ConstraintCode) {
default: return true;
@ -232,12 +231,12 @@ SDValue AlphaDAGToDAGISel::getGlobalRetAddr() {
/// InstructionSelect - This callback is invoked by
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
void AlphaDAGToDAGISel::InstructionSelect(SelectionDAG &DAG) {
void AlphaDAGToDAGISel::InstructionSelect() {
DEBUG(BB->dump());
// Select target instructions for the DAG.
SelectRoot();
DAG.RemoveDeadNodes();
CurDAG->RemoveDeadNodes();
}
// Select - Convert the specified operand from a target-independent to a

View File

@ -285,8 +285,7 @@ public:
/// inline asm expressions.
virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
char ConstraintCode,
std::vector<SDValue> &OutOps,
SelectionDAG &DAG) {
std::vector<SDValue> &OutOps) {
SDValue Op0, Op1;
switch (ConstraintCode) {
default: return true;
@ -319,7 +318,7 @@ public:
/// InstructionSelect - This callback is invoked by
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
virtual void InstructionSelect(SelectionDAG &DAG);
virtual void InstructionSelect();
virtual const char *getPassName() const {
return "Cell SPU DAG->DAG Pattern Instruction Selection";
@ -342,13 +341,13 @@ public:
/// InstructionSelect - This callback is invoked by
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
void
SPUDAGToDAGISel::InstructionSelect(SelectionDAG &DAG)
SPUDAGToDAGISel::InstructionSelect()
{
DEBUG(BB->dump());
// Select target instructions for the DAG.
SelectRoot();
DAG.RemoveDeadNodes();
CurDAG->RemoveDeadNodes();
}
/*!

View File

@ -80,7 +80,7 @@ namespace {
/// InstructionSelect - This callback is invoked by
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
virtual void InstructionSelect(SelectionDAG &DAG);
virtual void InstructionSelect();
virtual const char *getPassName() const {
return "IA64 (Itanium) DAG->DAG Instruction Selector";
@ -96,12 +96,12 @@ private:
/// InstructionSelect - This callback is invoked by
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
void IA64DAGToDAGISel::InstructionSelect(SelectionDAG &DAG) {
void IA64DAGToDAGISel::InstructionSelect() {
DEBUG(BB->dump());
// Select target instructions for the DAG.
SelectRoot();
DAG.RemoveDeadNodes();
CurDAG->RemoveDeadNodes();
}
SDNode *IA64DAGToDAGISel::SelectDIV(SDValue Op) {

View File

@ -66,7 +66,7 @@ public:
TM(tm), MipsLowering(*TM.getTargetLowering()),
Subtarget(tm.getSubtarget<MipsSubtarget>()) {}
virtual void InstructionSelect(SelectionDAG &SD);
virtual void InstructionSelect();
// Pass Name
virtual const char *getPassName() const {
@ -103,7 +103,7 @@ private:
/// InstructionSelect - This callback is invoked by
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
void MipsDAGToDAGISel::
InstructionSelect(SelectionDAG &SD)
InstructionSelect()
{
DEBUG(BB->dump());
// Codegen the basic block.
@ -119,7 +119,7 @@ InstructionSelect(SelectionDAG &SD)
DOUT << "===== Instruction selection ends:\n";
#endif
SD.RemoveDeadNodes();
CurDAG->RemoveDeadNodes();
}
/// getGlobalBaseReg - Output the instructions required to put the

View File

@ -60,7 +60,7 @@ public:
SelectionDAGISel(PIC16Lowering),
TM(tm), PIC16Lowering(*TM.getTargetLowering()) {}
virtual void InstructionSelect(SelectionDAG &SD);
virtual void InstructionSelect();
// Pass Name
virtual const char *getPassName() const {
@ -98,7 +98,7 @@ private:
/// InstructionSelect - This callback is invoked by
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
void PIC16DAGToDAGISel::InstructionSelect(SelectionDAG &SD)
void PIC16DAGToDAGISel::InstructionSelect()
{
DEBUG(BB->dump());
// Codegen the basic block.
@ -113,7 +113,7 @@ void PIC16DAGToDAGISel::InstructionSelect(SelectionDAG &SD)
DOUT << "===== Instruction selection ends:\n";
SD.RemoveDeadNodes();
CurDAG->RemoveDeadNodes();
}

View File

@ -144,8 +144,7 @@ namespace {
/// inline asm expressions.
virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
char ConstraintCode,
std::vector<SDValue> &OutOps,
SelectionDAG &DAG) {
std::vector<SDValue> &OutOps) {
SDValue Op0, Op1;
switch (ConstraintCode) {
default: return true;
@ -175,7 +174,7 @@ namespace {
/// InstructionSelect - This callback is invoked by
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
virtual void InstructionSelect(SelectionDAG &DAG);
virtual void InstructionSelect();
void InsertVRSaveCode(Function &Fn);
@ -203,12 +202,12 @@ private:
/// InstructionSelect - This callback is invoked by
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
void PPCDAGToDAGISel::InstructionSelect(SelectionDAG &DAG) {
void PPCDAGToDAGISel::InstructionSelect() {
DEBUG(BB->dump());
// Select target instructions for the DAG.
SelectRoot();
DAG.RemoveDeadNodes();
CurDAG->RemoveDeadNodes();
}
/// InsertVRSaveCode - Once the entire function has been instruction selected,

View File

@ -49,7 +49,7 @@ public:
/// InstructionSelect - This callback is invoked by
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
virtual void InstructionSelect(SelectionDAG &DAG);
virtual void InstructionSelect();
virtual const char *getPassName() const {
return "SPARC DAG->DAG Pattern Instruction Selection";
@ -62,12 +62,12 @@ public:
/// InstructionSelect - This callback is invoked by
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
void SparcDAGToDAGISel::InstructionSelect(SelectionDAG &DAG) {
void SparcDAGToDAGISel::InstructionSelect() {
DEBUG(BB->dump());
// Select target instructions for the DAG.
SelectRoot();
DAG.RemoveDeadNodes();
CurDAG->RemoveDeadNodes();
}
bool SparcDAGToDAGISel::SelectADDRri(SDValue Op, SDValue Addr,

View File

@ -147,7 +147,7 @@ namespace {
/// InstructionSelect - This callback is invoked by
/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
virtual void InstructionSelect(SelectionDAG &DAG);
virtual void InstructionSelect();
/// InstructionSelectPostProcessing - Post processing of selected and
/// scheduled basic blocks.
@ -178,15 +178,14 @@ namespace {
bool TryFoldLoad(SDValue P, SDValue N,
SDValue &Base, SDValue &Scale,
SDValue &Index, SDValue &Disp);
void PreprocessForRMW(SelectionDAG &DAG);
void PreprocessForFPConvert(SelectionDAG &DAG);
void PreprocessForRMW();
void PreprocessForFPConvert();
/// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
/// inline asm expressions.
virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
char ConstraintCode,
std::vector<SDValue> &OutOps,
SelectionDAG &DAG);
std::vector<SDValue> &OutOps);
void EmitSpecialCodeForMain(MachineBasicBlock *BB, MachineFrameInfo *MFI);
@ -372,7 +371,7 @@ bool X86DAGToDAGISel::CanBeFoldedBy(SDNode *N, SDNode *U, SDNode *Root) const {
/// MoveBelowTokenFactor - Replace TokenFactor operand with load's chain operand
/// and move load below the TokenFactor. Replace store's chain operand with
/// load's chain result.
static void MoveBelowTokenFactor(SelectionDAG &DAG, SDValue Load,
static void MoveBelowTokenFactor(SelectionDAG *CurDAG, SDValue Load,
SDValue Store, SDValue TF) {
std::vector<SDValue> Ops;
for (unsigned i = 0, e = TF.Val->getNumOperands(); i != e; ++i)
@ -380,10 +379,10 @@ static void MoveBelowTokenFactor(SelectionDAG &DAG, SDValue Load,
Ops.push_back(Load.Val->getOperand(0));
else
Ops.push_back(TF.Val->getOperand(i));
DAG.UpdateNodeOperands(TF, &Ops[0], Ops.size());
DAG.UpdateNodeOperands(Load, TF, Load.getOperand(1), Load.getOperand(2));
DAG.UpdateNodeOperands(Store, Load.getValue(1), Store.getOperand(1),
Store.getOperand(2), Store.getOperand(3));
CurDAG->UpdateNodeOperands(TF, &Ops[0], Ops.size());
CurDAG->UpdateNodeOperands(Load, TF, Load.getOperand(1), Load.getOperand(2));
CurDAG->UpdateNodeOperands(Store, Load.getValue(1), Store.getOperand(1),
Store.getOperand(2), Store.getOperand(3));
}
/// isRMWLoad - Return true if N is a load that's part of RMW sub-DAG.
@ -452,9 +451,9 @@ static bool isRMWLoad(SDValue N, SDValue Chain, SDValue Address,
/// \ /
/// \ /
/// [Store]
void X86DAGToDAGISel::PreprocessForRMW(SelectionDAG &DAG) {
for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(),
E = DAG.allnodes_end(); I != E; ++I) {
void X86DAGToDAGISel::PreprocessForRMW() {
for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(),
E = CurDAG->allnodes_end(); I != E; ++I) {
if (!ISD::isNON_TRUNCStore(I))
continue;
SDValue Chain = I->getOperand(0);
@ -504,7 +503,7 @@ void X86DAGToDAGISel::PreprocessForRMW(SelectionDAG &DAG) {
}
if (RModW) {
MoveBelowTokenFactor(DAG, Load, SDValue(I, 0), Chain);
MoveBelowTokenFactor(CurDAG, Load, SDValue(I, 0), Chain);
++NumLoadMoved;
}
}
@ -519,9 +518,9 @@ void X86DAGToDAGISel::PreprocessForRMW(SelectionDAG &DAG) {
/// hack on these between the call expansion and the node legalization. As such
/// this pass basically does "really late" legalization of these inline with the
/// X86 isel pass.
void X86DAGToDAGISel::PreprocessForFPConvert(SelectionDAG &DAG) {
for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(),
E = DAG.allnodes_end(); I != E; ) {
void X86DAGToDAGISel::PreprocessForFPConvert() {
for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(),
E = CurDAG->allnodes_end(); I != E; ) {
SDNode *N = I++; // Preincrement iterator to avoid invalidation issues.
if (N->getOpcode() != ISD::FP_ROUND && N->getOpcode() != ISD::FP_EXTEND)
continue;
@ -553,39 +552,40 @@ void X86DAGToDAGISel::PreprocessForFPConvert(SelectionDAG &DAG) {
else
MemVT = SrcIsSSE ? SrcVT : DstVT;
SDValue MemTmp = DAG.CreateStackTemporary(MemVT);
SDValue MemTmp = CurDAG->CreateStackTemporary(MemVT);
// FIXME: optimize the case where the src/dest is a load or store?
SDValue Store = DAG.getTruncStore(DAG.getEntryNode(), N->getOperand(0),
MemTmp, NULL, 0, MemVT);
SDValue Result = DAG.getExtLoad(ISD::EXTLOAD, DstVT, Store, MemTmp,
NULL, 0, MemVT);
SDValue Store = CurDAG->getTruncStore(CurDAG->getEntryNode(),
N->getOperand(0),
MemTmp, NULL, 0, MemVT);
SDValue Result = CurDAG->getExtLoad(ISD::EXTLOAD, DstVT, Store, MemTmp,
NULL, 0, MemVT);
// We're about to replace all uses of the FP_ROUND/FP_EXTEND with the
// extload we created. This will cause general havok on the dag because
// anything below the conversion could be folded into other existing nodes.
// To avoid invalidating 'I', back it up to the convert node.
--I;
DAG.ReplaceAllUsesOfValueWith(SDValue(N, 0), Result);
CurDAG->ReplaceAllUsesOfValueWith(SDValue(N, 0), Result);
// Now that we did that, the node is dead. Increment the iterator to the
// next node to process, then delete N.
++I;
DAG.DeleteNode(N);
CurDAG->DeleteNode(N);
}
}
/// InstructionSelectBasicBlock - This callback is invoked by SelectionDAGISel
/// when it has created a SelectionDAG for us to codegen.
void X86DAGToDAGISel::InstructionSelect(SelectionDAG &DAG) {
void X86DAGToDAGISel::InstructionSelect() {
CurBB = BB; // BB can change as result of isel.
DEBUG(BB->dump());
if (!Fast)
PreprocessForRMW(DAG);
PreprocessForRMW();
// FIXME: This should only happen when not -fast.
PreprocessForFPConvert(DAG);
PreprocessForFPConvert();
// Codegen the basic block.
#ifndef NDEBUG
@ -597,7 +597,7 @@ void X86DAGToDAGISel::InstructionSelect(SelectionDAG &DAG) {
DOUT << "===== Instruction selection ends:\n";
#endif
DAG.RemoveDeadNodes();
CurDAG->RemoveDeadNodes();
}
void X86DAGToDAGISel::InstructionSelectPostProcessing() {
@ -1599,7 +1599,7 @@ SDNode *X86DAGToDAGISel::Select(SDValue N) {
bool X86DAGToDAGISel::
SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
std::vector<SDValue> &OutOps, SelectionDAG &DAG){
std::vector<SDValue> &OutOps) {
SDValue Op0, Op1, Op2, Op3;
switch (ConstraintCode) {
case 'o': // offsetable ??

View File

@ -1864,7 +1864,7 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
// Emit boilerplate.
OS << "SDNode *Select_INLINEASM(SDValue N) {\n"
<< " std::vector<SDValue> Ops(N.Val->op_begin(), N.Val->op_end());\n"
<< " SelectInlineAsmMemoryOperands(Ops, *CurDAG);\n\n"
<< " SelectInlineAsmMemoryOperands(Ops);\n\n"
<< " // Ensure that the asm operands are themselves selected.\n"
<< " for (unsigned j = 0, e = Ops.size(); j != e; ++j)\n"