Initial checkin of SelectionDAG implementation. This is still rough and

unfinished

llvm-svn: 7717
This commit is contained in:
Chris Lattner 2003-08-11 14:57:33 +00:00
parent 963e822148
commit 600d308853
3 changed files with 332 additions and 0 deletions

View File

@ -0,0 +1,222 @@
//===-- DAGBuilder.cpp - Turn an LLVM BasicBlock into a DAG for selection -===//
//
// This file turns an LLVM BasicBlock into a target independent SelectionDAG in
// preparation for target specific optimizations and instruction selection.
//
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/Support/InstVisitor.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Type.h"
#include "llvm/Constants.h"
struct SelectionDAGBuilder : public InstVisitor<SelectionDAGBuilder> {
// DAG - the current dag we are building.
SelectionDAG &DAG;
// BB - The current machine basic block we are working on.
MachineBasicBlock *BB;
// CurRoot - The root built for the current basic block.
SelectionDAGNode *CurRoot;
SelectionDAGBuilder(SelectionDAG &dag) : DAG(dag), BB(0), CurRoot(0) {}
void visitBB(BasicBlock &bb);
// Visitation methods for instructions: Create the appropriate DAG nodes for
// the instruction.
void visitAdd(BinaryOperator &BO);
void visitSub(BinaryOperator &BO);
void visitMul(BinaryOperator &BO);
void visitRet(ReturnInst &RI);
void visitAnd(BinaryOperator &BO);
void visitOr (BinaryOperator &BO);
void visitXor(BinaryOperator &BO);
void visitInstruction(Instruction &I) {
std::cerr << "Instruction Selection cannot select: " << I;
abort();
}
private:
SelectionDAGNode *getNodeFor(Value *V);
SelectionDAGNode *getNodeFor(Value &V) { return getNodeFor(&V); }
SelectionDAGNode *addSeqNode(SelectionDAGNode *N);
};
/// addSeqNode - The same as addNode, but the node is also included in the
/// sequence nodes for this block. This method should be called for any
/// instructions which have a specified sequence they must be evaluated in.
///
SelectionDAGNode *SelectionDAGBuilder::addSeqNode(SelectionDAGNode *N) {
DAG.addNode(N); // First, add the node to the selection DAG
if (!CurRoot)
CurRoot = N;
else {
// Create and add a new chain node for the existing root and this node...
CurRoot = DAG.addNode(new SelectionDAGNode(ISD::ChainNode, MVT::isVoid,
BB, CurRoot, N));
}
return N;
}
/// getNodeFor - This method returns the SelectionDAGNode for the specified LLVM
/// value, creating a node as necessary.
///
SelectionDAGNode *SelectionDAGBuilder::getNodeFor(Value *V) {
// If we already have the entry, return it.
SelectionDAGNode*& Entry = DAG.ValueMap[V];
if (Entry) return Entry;
// Otherwise, we need to create a node to return now... start by figuring out
// which type the node will be...
MVT::ValueType ValueType = DAG.getValueType(V->getType());
if (Instruction *I = dyn_cast<Instruction>(V))
// Instructions will be filled in later. For now, just create and return a
// dummy node.
return Entry = new SelectionDAGNode(ISD::ProtoNode, ValueType);
if (Constant *C = dyn_cast<Constant>(V)) {
if (ConstantBool *CB = dyn_cast<ConstantBool>(C)) {
Entry = new SelectionDAGNode(ISD::Constant, ValueType);
Entry->addValue(new ReducedValue_Constant_i1(CB->getValue()));
} else if (ConstantInt *CI = dyn_cast<ConstantInt>(C)) {
Entry = new SelectionDAGNode(ISD::Constant, ValueType);
switch (ValueType) {
case MVT::i8:
Entry->addValue(new ReducedValue_Constant_i8(CI->getRawValue()));
break;
case MVT::i16:
Entry->addValue(new ReducedValue_Constant_i16(CI->getRawValue()));
break;
case MVT::i32:
Entry->addValue(new ReducedValue_Constant_i32(CI->getRawValue()));
break;
case MVT::i64:
Entry->addValue(new ReducedValue_Constant_i64(CI->getRawValue()));
break;
default:
assert(0 && "Invalid ValueType for an integer constant!");
}
} else if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
Entry = new SelectionDAGNode(ISD::Constant, ValueType);
if (ValueType == MVT::f32)
Entry->addValue(new ReducedValue_Constant_f32(CFP->getValue()));
else
Entry->addValue(new ReducedValue_Constant_f64(CFP->getValue()));
}
if (Entry) return Entry;
}
std::cerr << "Unhandled LLVM value in DAG Builder!: " << *V << "\n";
abort();
return 0;
}
// visitBB - This method is used to visit a basic block in the program. It
// manages the CurRoot instance variable so that all of the visit(Instruction)
// methods can be written to assume that there is only one basic block being
// constructed.
//
void SelectionDAGBuilder::visitBB(BasicBlock &bb) {
BB = DAG.BlockMap[&bb]; // Update BB instance var
// Save the current global DAG...
SelectionDAGNode *OldRoot = CurRoot;
CurRoot = 0;
visit(bb.begin(), bb.end()); // Visit all of the instructions...
if (OldRoot) {
if (!CurRoot)
CurRoot = OldRoot; // This block had no root of its own..
else {
// The previous basic block AND this basic block had roots, insert a
// block chain node now...
CurRoot = DAG.addNode(new SelectionDAGNode(ISD::BlockChainNode,
MVT::isVoid,
BB, OldRoot, CurRoot));
}
}
}
//===----------------------------------------------------------------------===//
// ...Visitation Methods...
//===----------------------------------------------------------------------===//
void SelectionDAGBuilder::visitAdd(BinaryOperator &BO) {
getNodeFor(BO)->setNode(ISD::Plus, BB, getNodeFor(BO.getOperand(0)),
getNodeFor(BO.getOperand(1)));
}
void SelectionDAGBuilder::visitSub(BinaryOperator &BO) {
getNodeFor(BO)->setNode(ISD::Minus, BB, getNodeFor(BO.getOperand(0)),
getNodeFor(BO.getOperand(1)));
}
void SelectionDAGBuilder::visitMul(BinaryOperator &BO) {
getNodeFor(BO)->setNode(ISD::Times, BB, getNodeFor(BO.getOperand(0)),
getNodeFor(BO.getOperand(1)));
}
void SelectionDAGBuilder::visitAnd(BinaryOperator &BO) {
getNodeFor(BO)->setNode(ISD::And, BB, getNodeFor(BO.getOperand(0)),
getNodeFor(BO.getOperand(1)));
}
void SelectionDAGBuilder::visitOr(BinaryOperator &BO) {
getNodeFor(BO)->setNode(ISD::Or, BB, getNodeFor(BO.getOperand(0)),
getNodeFor(BO.getOperand(1)));
}
void SelectionDAGBuilder::visitXor(BinaryOperator &BO) {
getNodeFor(BO)->setNode(ISD::Xor, BB, getNodeFor(BO.getOperand(0)),
getNodeFor(BO.getOperand(1)));
}
void SelectionDAGBuilder::visitRet(ReturnInst &RI) {
if (RI.getNumOperands()) { // Value return
addSeqNode(new SelectionDAGNode(ISD::Ret, MVT::isVoid, BB,
getNodeFor(RI.getOperand(0))));
} else { // Void return
addSeqNode(new SelectionDAGNode(ISD::RetVoid, MVT::isVoid, BB));
}
}
// SelectionDAG constructor - Just use the SeelectionDAGBuilder to do all of the
// dirty work...
SelectionDAG::SelectionDAG(MachineFunction &f, const TargetMachine &tm,
SelectionDAGTargetBuilder &SDTB)
: F(f), TM(tm) {
switch (TM.getTargetData().getPointerSize()) {
default: assert(0 && "Unknown pointer size!"); abort();
case 8: PointerType = MVT::i8; break;
case 16: PointerType = MVT::i16; break;
case 32: PointerType = MVT::i32; break;
case 64: PointerType = MVT::i64; break;
}
// Create all of the machine basic blocks for the function... building the
// BlockMap. This map is used for PHI node conversion.
const Function &Fn = *F.getFunction();
for (Function::const_iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
F.getBasicBlockList().push_back(BlockMap[I] = new MachineBasicBlock(I));
SDTB.expandArguments(*this, f);
SelectionDAGBuilder SDB(*this);
for (Function::const_iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
SDB.visitBB(const_cast<BasicBlock&>(*I));
Root = SDB.CurRoot;
}

View File

@ -0,0 +1,5 @@
LEVEL = ../../..
PARALLEL_DIRS =
LIBRARYNAME = selection
include $(LEVEL)/Makefile.common

View File

@ -0,0 +1,105 @@
//===-- SelectionDAG.cpp - Implement the SelectionDAG* classes ------------===//
//
// This file implements the SelectionDAG* classes, which are used to perform
// DAG-based instruction selection in a target-specific manner.
//
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/Type.h"
SelectionDAG::~SelectionDAG() {
for (unsigned i = 0, e = AllNodes.size(); i != e; ++i)
delete AllNodes[i];
}
/// dump - Print out the current Selection DAG...
void SelectionDAG::dump() const {
Root->dump(); // Print from the root...
}
/// getValueType - Return the ValueType for the specified LLVM type. This
/// method works on all scalar LLVM types.
///
MVT::ValueType SelectionDAG::getValueType(const Type *Ty) const {
switch (Ty->getPrimitiveID()) {
case Type::VoidTyID: assert(0 && "Void type object in getValueType!");
default: assert(0 && "Unknown type in DAGBuilder!\n");
case Type::BoolTyID: return MVT::i1;
case Type::SByteTyID:
case Type::UByteTyID: return MVT::i8;
case Type::ShortTyID:
case Type::UShortTyID: return MVT::i16;
case Type::IntTyID:
case Type::UIntTyID: return MVT::i32;
case Type::LongTyID:
case Type::ULongTyID: return MVT::i64;
case Type::FloatTyID: return MVT::f32;
case Type::DoubleTyID: return MVT::f64;
case Type::PointerTyID: return PointerType;
}
}
void SelectionDAGNode::dump() const {
// Print out the DAG in post-order
std::map<const SelectionDAGNode*, unsigned> NodeIDs;
unsigned ID = 0;
printit(0, ID, NodeIDs);
}
void SelectionDAGNode::printit(unsigned Offset, unsigned &LastID,
std::map<const SelectionDAGNode*,
unsigned> &NodeIDs) const {
if (!NodeIDs.count(this)) {
// Emit all of the uses first...
for (unsigned i = 0, e = Uses.size(); i != e; ++i)
Uses[i]->printit(Offset+1, LastID, NodeIDs);
NodeIDs[this] = LastID++;
std::cerr << std::string(Offset, ' ') << "#" << LastID-1 << " ";
} else {
// Node has already been emitted...
std::cerr << std::string(Offset, ' ') << "#" << NodeIDs[this] << " ";
}
switch (ValueType) {
case MVT::isVoid: std::cerr << "V:"; break;
case MVT::i1: std::cerr << "i1:"; break;
case MVT::i8: std::cerr << "i8:"; break;
case MVT::i16: std::cerr << "i16:"; break;
case MVT::i32: std::cerr << "i32:"; break;
case MVT::i64: std::cerr << "i64:"; break;
case MVT::f32: std::cerr << "f32:"; break;
case MVT::f64: std::cerr << "f64:"; break;
default: assert(0 && "Invalid node ValueType!");
}
switch (NodeType) {
case ISD::ChainNode: std::cerr << "ChainNode"; break;
case ISD::BlockChainNode: std::cerr << "BlockChainNode"; break;
case ISD::ProtoNode: std::cerr << "ProtoNode"; break;
case ISD::Constant: std::cerr << "Constant"; break;
case ISD::FrameIndex: std::cerr << "FrameIndex"; break;
case ISD::Plus: std::cerr << "Plus"; break;
case ISD::Minus: std::cerr << "Minus"; break;
case ISD::Times: std::cerr << "Times"; break;
case ISD::SDiv: std::cerr << "SDiv"; break;
case ISD::UDiv: std::cerr << "UDiv"; break;
case ISD::SRem: std::cerr << "SRem"; break;
case ISD::URem: std::cerr << "URem"; break;
case ISD::And: std::cerr << "And"; break;
case ISD::Or: std::cerr << "Or"; break;
case ISD::Xor: std::cerr << "Xor"; break;
case ISD::Br: std::cerr << "Br"; break;
case ISD::Switch: std::cerr << "Switch"; break;
case ISD::Ret: std::cerr << "Ret"; break;
case ISD::RetVoid: std::cerr << "RetVoid"; break;
case ISD::Load: std::cerr << "Load"; break;
case ISD::Store: std::cerr << "Store"; break;
case ISD::PHI: std::cerr << "PHI"; break;
case ISD::Call: std::cerr << "Call"; break;
}
std::cerr << "\n";
}