X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FSparc%2FSparcISelDAGToDAG.cpp;h=93710c4e0b0fecb0c5d39b303c96657b4e1b3c6b;hb=fef904d0e824a2c587f8c1063b6c4fbf47fec898;hp=64e9bcec6a181a225998bb6cc2932e32006ba7ad;hpb=f350b277f32d7d47f86c0e54f4aec4d470500618;p=oota-llvm.git diff --git a/lib/Target/Sparc/SparcISelDAGToDAG.cpp b/lib/Target/Sparc/SparcISelDAGToDAG.cpp index 64e9bcec6a1..93710c4e0b0 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/Support/Compiler.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; //===----------------------------------------------------------------------===// @@ -29,48 +30,47 @@ 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: - explicit SparcDAGToDAGISel(TargetMachine &TM) - : SelectionDAGISel(Lowering), Lowering(TM), - Subtarget(TM.getSubtarget()) { + explicit SparcDAGToDAGISel(SparcTargetMachine &tm) + : SelectionDAGISel(tm), + Subtarget(tm.getSubtarget()), + TM(tm) { } - SDNode *Select(SDValue Op); + SDNode *Select(SDNode *N); // Complex Pattern Selectors. - bool SelectADDRrr(SDValue Op, SDValue N, SDValue &R1, SDValue &R2); - bool SelectADDRri(SDValue Op, SDValue N, SDValue &Base, - SDValue &Offset); - - /// InstructionSelect - This callback is invoked by - /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. - virtual void InstructionSelect(); - + 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 -/// InstructionSelect - This callback is invoked by -/// SelectionDAGISel when it has created a SelectionDAG for us to codegen. -void SparcDAGToDAGISel::InstructionSelect() { - DEBUG(BB->dump()); - - // Select target instructions for the DAG. - SelectRoot(); - CurDAG->RemoveDeadNodes(); +SDNode* SparcDAGToDAGISel::getGlobalBaseReg() { + unsigned GlobalBaseReg = TM.getInstrInfo()->getGlobalBaseReg(MF); + return CurDAG->getRegister(GlobalBaseReg, TLI.getPointerTy()).getNode(); } -bool SparcDAGToDAGISel::SelectADDRri(SDValue Op, SDValue Addr, +bool SparcDAGToDAGISel::SelectADDRri(SDValue Addr, SDValue &Base, SDValue &Offset) { if (FrameIndexSDNode *FIN = dyn_cast(Addr)) { Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); @@ -80,18 +80,18 @@ bool SparcDAGToDAGISel::SelectADDRri(SDValue Op, SDValue Addr, if (Addr.getOpcode() == ISD::TargetExternalSymbol || Addr.getOpcode() == ISD::TargetGlobalAddress) 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); } else { Base = Addr.getOperand(0); } - Offset = CurDAG->getTargetConstant(CN->getValue(), MVT::i32); + Offset = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32); return true; } } @@ -111,17 +111,16 @@ bool SparcDAGToDAGISel::SelectADDRri(SDValue Op, SDValue Addr, return true; } -bool SparcDAGToDAGISel::SelectADDRrr(SDValue Op, SDValue Addr, - SDValue &R1, SDValue &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) 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! @@ -135,60 +134,78 @@ bool SparcDAGToDAGISel::SelectADDRrr(SDValue Op, SDValue Addr, return true; } -SDNode *SparcDAGToDAGISel::Select(SDValue Op) { - SDNode *N = Op.Val; +SDNode *SparcDAGToDAGISel::Select(SDNode *N) { + DebugLoc dl = N->getDebugLoc(); if (N->isMachineOpcode()) return NULL; // Already selected. switch (N->getOpcode()) { default: break; + case SPISD::GLOBAL_BASE_REG: + return getGlobalBaseReg(); + case ISD::SDIV: case ISD::UDIV: { // FIXME: should use a custom expander to expose the SRA to the dag. SDValue DivLHS = N->getOperand(0); SDValue DivRHS = N->getOperand(1); - AddToISelQueue(DivLHS); - AddToISelQueue(DivRHS); - + // Set the Y register to the high-part. SDValue TopPart; if (N->getOpcode() == ISD::SDIV) { - TopPart = SDValue(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 = SDValue(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. SDValue MulLHS = N->getOperand(0); SDValue MulRHS = N->getOperand(1); - AddToISelQueue(MulLHS); - AddToISelQueue(MulRHS); 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, SDValue(Mul, 1)); - return NULL; } } - - 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); }