X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FSparc%2FSparcISelDAGToDAG.cpp;h=b012bfdb01025fde4980ff92d3a691c972ac72d2;hb=508bd630466f9625ba07a3f601435e1ff824b768;hp=3ef27dd642bf150ba90c4257d1b78aefee4685db;hpb=d23405e6f04135cabcad4d9bd7aa6e4f187bed3a;p=oota-llvm.git diff --git a/lib/Target/Sparc/SparcISelDAGToDAG.cpp b/lib/Target/Sparc/SparcISelDAGToDAG.cpp index 3ef27dd642b..b012bfdb010 100644 --- a/lib/Target/Sparc/SparcISelDAGToDAG.cpp +++ b/lib/Target/Sparc/SparcISelDAGToDAG.cpp @@ -11,12 +11,13 @@ // //===----------------------------------------------------------------------===// -#include "SparcISelLowering.h" #include "SparcTargetMachine.h" -#include "llvm/Intrinsics.h" #include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/IR/Intrinsics.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; //===----------------------------------------------------------------------===// @@ -29,72 +30,72 @@ using namespace llvm; /// namespace { class SparcDAGToDAGISel : public SelectionDAGISel { - SparcTargetLowering Lowering; - /// Subtarget - Keep a pointer to the Sparc Subtarget around so that we can /// make the right decision when generating code for different targets. const SparcSubtarget &Subtarget; + SparcTargetMachine &TM; public: - SparcDAGToDAGISel(TargetMachine &TM) - : SelectionDAGISel(Lowering), Lowering(TM), - Subtarget(TM.getSubtarget()) { + explicit SparcDAGToDAGISel(SparcTargetMachine &tm) + : SelectionDAGISel(tm), + Subtarget(tm.getSubtarget()), + TM(tm) { } - SDNode *Select(SDOperand Op); + SDNode *Select(SDNode *N); // Complex Pattern Selectors. - bool SelectADDRrr(SDOperand Op, SDOperand N, SDOperand &R1, SDOperand &R2); - bool SelectADDRri(SDOperand Op, SDOperand N, SDOperand &Base, - SDOperand &Offset); - - /// InstructionSelectBasicBlock - This callback is invoked by - /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. - virtual void InstructionSelectBasicBlock(SelectionDAG &DAG); - + bool SelectADDRrr(SDValue N, SDValue &R1, SDValue &R2); + bool SelectADDRri(SDValue N, SDValue &Base, SDValue &Offset); + + /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for + /// inline asm expressions. + virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, + char ConstraintCode, + std::vector &OutOps); + virtual const char *getPassName() const { return "SPARC DAG->DAG Pattern Instruction Selection"; - } - + } + // Include the pieces autogenerated from the target description. #include "SparcGenDAGISel.inc" + +private: + SDNode* getGlobalBaseReg(); }; } // end anonymous namespace -/// InstructionSelectBasicBlock - This callback is invoked by -/// SelectionDAGISel when it has created a SelectionDAG for us to codegen. -void SparcDAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) { - DEBUG(BB->dump()); - - // Select target instructions for the DAG. - DAG.setRoot(SelectRoot(DAG.getRoot())); - DAG.RemoveDeadNodes(); - - // Emit machine code to BB. - ScheduleAndEmitDAG(DAG); +SDNode* SparcDAGToDAGISel::getGlobalBaseReg() { + unsigned GlobalBaseReg = TM.getInstrInfo()->getGlobalBaseReg(MF); + return CurDAG->getRegister(GlobalBaseReg, + getTargetLowering()->getPointerTy()).getNode(); } -bool SparcDAGToDAGISel::SelectADDRri(SDOperand Op, SDOperand Addr, - SDOperand &Base, SDOperand &Offset) { +bool SparcDAGToDAGISel::SelectADDRri(SDValue Addr, + SDValue &Base, SDValue &Offset) { if (FrameIndexSDNode *FIN = dyn_cast(Addr)) { - Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), + getTargetLowering()->getPointerTy()); Offset = CurDAG->getTargetConstant(0, MVT::i32); return true; } if (Addr.getOpcode() == ISD::TargetExternalSymbol || - Addr.getOpcode() == ISD::TargetGlobalAddress) + Addr.getOpcode() == ISD::TargetGlobalAddress || + Addr.getOpcode() == ISD::TargetGlobalTLSAddress) return false; // direct calls. - + if (Addr.getOpcode() == ISD::ADD) { if (ConstantSDNode *CN = dyn_cast(Addr.getOperand(1))) { - if (Predicate_simm13(CN)) { - if (FrameIndexSDNode *FIN = + if (isInt<13>(CN->getSExtValue())) { + if (FrameIndexSDNode *FIN = dyn_cast(Addr.getOperand(0))) { // Constant offset from frame ref. - Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), + getTargetLowering()->getPointerTy()); } else { Base = Addr.getOperand(0); } - Offset = CurDAG->getTargetConstant(CN->getValue(), MVT::i32); + Offset = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32); return true; } } @@ -114,17 +115,17 @@ bool SparcDAGToDAGISel::SelectADDRri(SDOperand Op, SDOperand Addr, return true; } -bool SparcDAGToDAGISel::SelectADDRrr(SDOperand Op, SDOperand Addr, - SDOperand &R1, SDOperand &R2) { +bool SparcDAGToDAGISel::SelectADDRrr(SDValue Addr, SDValue &R1, SDValue &R2) { if (Addr.getOpcode() == ISD::FrameIndex) return false; if (Addr.getOpcode() == ISD::TargetExternalSymbol || - Addr.getOpcode() == ISD::TargetGlobalAddress) + Addr.getOpcode() == ISD::TargetGlobalAddress || + Addr.getOpcode() == ISD::TargetGlobalTLSAddress) return false; // direct calls. - + if (Addr.getOpcode() == ISD::ADD) { - if (isa(Addr.getOperand(1)) && - Predicate_simm13(Addr.getOperand(1).Val)) - return false; // Let the reg+imm pattern catch this! + if (ConstantSDNode *CN = dyn_cast(Addr.getOperand(1))) + if (isInt<13>(CN->getSExtValue())) + return false; // Let the reg+imm pattern catch this! if (Addr.getOperand(0).getOpcode() == SPISD::Lo || Addr.getOperand(1).getOpcode() == SPISD::Lo) return false; // Let the reg+imm pattern catch this! @@ -134,65 +135,87 @@ bool SparcDAGToDAGISel::SelectADDRrr(SDOperand Op, SDOperand Addr, } R1 = Addr; - R2 = CurDAG->getRegister(SP::G0, MVT::i32); + R2 = CurDAG->getRegister(SP::G0, getTargetLowering()->getPointerTy()); return true; } -SDNode *SparcDAGToDAGISel::Select(SDOperand Op) { - SDNode *N = Op.Val; - if (N->getOpcode() >= ISD::BUILTIN_OP_END && - N->getOpcode() < SPISD::FIRST_NUMBER) +SDNode *SparcDAGToDAGISel::Select(SDNode *N) { + SDLoc dl(N); + if (N->isMachineOpcode()) { + N->setNodeId(-1); return NULL; // Already selected. + } switch (N->getOpcode()) { default: break; + case SPISD::GLOBAL_BASE_REG: + return getGlobalBaseReg(); + case ISD::SDIV: case ISD::UDIV: { + // sdivx / udivx handle 64-bit divides. + if (N->getValueType(0) == MVT::i64) + break; // FIXME: should use a custom expander to expose the SRA to the dag. - SDOperand DivLHS = N->getOperand(0); - SDOperand DivRHS = N->getOperand(1); - AddToISelQueue(DivLHS); - AddToISelQueue(DivRHS); - + SDValue DivLHS = N->getOperand(0); + SDValue DivRHS = N->getOperand(1); + // Set the Y register to the high-part. - SDOperand TopPart; + SDValue TopPart; if (N->getOpcode() == ISD::SDIV) { - TopPart = SDOperand(CurDAG->getTargetNode(SP::SRAri, MVT::i32, DivLHS, + TopPart = SDValue(CurDAG->getMachineNode(SP::SRAri, dl, MVT::i32, DivLHS, CurDAG->getTargetConstant(31, MVT::i32)), 0); } else { TopPart = CurDAG->getRegister(SP::G0, MVT::i32); } - TopPart = SDOperand(CurDAG->getTargetNode(SP::WRYrr, MVT::Flag, TopPart, + TopPart = SDValue(CurDAG->getMachineNode(SP::WRYrr, dl, MVT::Glue, TopPart, CurDAG->getRegister(SP::G0, MVT::i32)), 0); // FIXME: Handle div by immediate. unsigned Opcode = N->getOpcode() == ISD::SDIV ? SP::SDIVrr : SP::UDIVrr; return CurDAG->SelectNodeTo(N, Opcode, MVT::i32, DivLHS, DivRHS, TopPart); - } + } case ISD::MULHU: case ISD::MULHS: { // FIXME: Handle mul by immediate. - SDOperand MulLHS = N->getOperand(0); - SDOperand MulRHS = N->getOperand(1); - AddToISelQueue(MulLHS); - AddToISelQueue(MulRHS); + SDValue MulLHS = N->getOperand(0); + SDValue MulRHS = N->getOperand(1); unsigned Opcode = N->getOpcode() == ISD::MULHU ? SP::UMULrr : SP::SMULrr; - SDNode *Mul = CurDAG->getTargetNode(Opcode, MVT::i32, MVT::Flag, - MulLHS, MulRHS); + SDNode *Mul = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::Glue, + MulLHS, MulRHS); // The high part is in the Y register. - return CurDAG->SelectNodeTo(N, SP::RDY, MVT::i32, SDOperand(Mul, 1)); - return NULL; + return CurDAG->SelectNodeTo(N, SP::RDY, MVT::i32, SDValue(Mul, 1)); } } - - return SelectCode(Op); + + return SelectCode(N); } -/// createSparcISelDag - This pass converts a legalized DAG into a +/// SelectInlineAsmMemoryOperand - Implement addressing mode selection for +/// inline asm expressions. +bool +SparcDAGToDAGISel::SelectInlineAsmMemoryOperand(const SDValue &Op, + char ConstraintCode, + std::vector &OutOps) { + SDValue Op0, Op1; + switch (ConstraintCode) { + default: return true; + case 'm': // memory + if (!SelectADDRrr(Op, Op0, Op1)) + SelectADDRri(Op, Op0, Op1); + break; + } + + OutOps.push_back(Op0); + OutOps.push_back(Op1); + return false; +} + +/// createSparcISelDag - This pass converts a legalized DAG into a /// SPARC-specific DAG, ready for instruction scheduling. /// -FunctionPass *llvm::createSparcISelDag(TargetMachine &TM) { +FunctionPass *llvm::createSparcISelDag(SparcTargetMachine &TM) { return new SparcDAGToDAGISel(TM); }