LLVM API Documentation
00001 //===-- SparcISelDAGToDAG.cpp - A dag to dag inst selector for Sparc ------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines an instruction selector for the SPARC target. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "SparcTargetMachine.h" 00015 #include "llvm/CodeGen/SelectionDAGISel.h" 00016 #include "llvm/IR/Intrinsics.h" 00017 #include "llvm/Support/Compiler.h" 00018 #include "llvm/Support/Debug.h" 00019 #include "llvm/Support/ErrorHandling.h" 00020 #include "llvm/Support/raw_ostream.h" 00021 using namespace llvm; 00022 00023 //===----------------------------------------------------------------------===// 00024 // Instruction Selector Implementation 00025 //===----------------------------------------------------------------------===// 00026 00027 //===--------------------------------------------------------------------===// 00028 /// SparcDAGToDAGISel - SPARC specific code to select SPARC machine 00029 /// instructions for SelectionDAG operations. 00030 /// 00031 namespace { 00032 class SparcDAGToDAGISel : public SelectionDAGISel { 00033 /// Subtarget - Keep a pointer to the Sparc Subtarget around so that we can 00034 /// make the right decision when generating code for different targets. 00035 const SparcSubtarget &Subtarget; 00036 SparcTargetMachine& TM; 00037 public: 00038 explicit SparcDAGToDAGISel(SparcTargetMachine &tm) 00039 : SelectionDAGISel(tm), 00040 Subtarget(tm.getSubtarget<SparcSubtarget>()), 00041 TM(tm) { 00042 } 00043 00044 SDNode *Select(SDNode *N); 00045 00046 // Complex Pattern Selectors. 00047 bool SelectADDRrr(SDValue N, SDValue &R1, SDValue &R2); 00048 bool SelectADDRri(SDValue N, SDValue &Base, SDValue &Offset); 00049 00050 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for 00051 /// inline asm expressions. 00052 virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, 00053 char ConstraintCode, 00054 std::vector<SDValue> &OutOps); 00055 00056 virtual const char *getPassName() const { 00057 return "SPARC DAG->DAG Pattern Instruction Selection"; 00058 } 00059 00060 // Include the pieces autogenerated from the target description. 00061 #include "SparcGenDAGISel.inc" 00062 00063 private: 00064 SDNode* getGlobalBaseReg(); 00065 }; 00066 } // end anonymous namespace 00067 00068 SDNode* SparcDAGToDAGISel::getGlobalBaseReg() { 00069 unsigned GlobalBaseReg = TM.getInstrInfo()->getGlobalBaseReg(MF); 00070 return CurDAG->getRegister(GlobalBaseReg, TLI.getPointerTy()).getNode(); 00071 } 00072 00073 bool SparcDAGToDAGISel::SelectADDRri(SDValue Addr, 00074 SDValue &Base, SDValue &Offset) { 00075 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 00076 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), TLI.getPointerTy()); 00077 Offset = CurDAG->getTargetConstant(0, MVT::i32); 00078 return true; 00079 } 00080 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 00081 Addr.getOpcode() == ISD::TargetGlobalAddress) 00082 return false; // direct calls. 00083 00084 if (Addr.getOpcode() == ISD::ADD) { 00085 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) { 00086 if (isInt<13>(CN->getSExtValue())) { 00087 if (FrameIndexSDNode *FIN = 00088 dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) { 00089 // Constant offset from frame ref. 00090 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), 00091 TLI.getPointerTy()); 00092 } else { 00093 Base = Addr.getOperand(0); 00094 } 00095 Offset = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32); 00096 return true; 00097 } 00098 } 00099 if (Addr.getOperand(0).getOpcode() == SPISD::Lo) { 00100 Base = Addr.getOperand(1); 00101 Offset = Addr.getOperand(0).getOperand(0); 00102 return true; 00103 } 00104 if (Addr.getOperand(1).getOpcode() == SPISD::Lo) { 00105 Base = Addr.getOperand(0); 00106 Offset = Addr.getOperand(1).getOperand(0); 00107 return true; 00108 } 00109 } 00110 Base = Addr; 00111 Offset = CurDAG->getTargetConstant(0, MVT::i32); 00112 return true; 00113 } 00114 00115 bool SparcDAGToDAGISel::SelectADDRrr(SDValue Addr, SDValue &R1, SDValue &R2) { 00116 if (Addr.getOpcode() == ISD::FrameIndex) return false; 00117 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 00118 Addr.getOpcode() == ISD::TargetGlobalAddress) 00119 return false; // direct calls. 00120 00121 if (Addr.getOpcode() == ISD::ADD) { 00122 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) 00123 if (isInt<13>(CN->getSExtValue())) 00124 return false; // Let the reg+imm pattern catch this! 00125 if (Addr.getOperand(0).getOpcode() == SPISD::Lo || 00126 Addr.getOperand(1).getOpcode() == SPISD::Lo) 00127 return false; // Let the reg+imm pattern catch this! 00128 R1 = Addr.getOperand(0); 00129 R2 = Addr.getOperand(1); 00130 return true; 00131 } 00132 00133 R1 = Addr; 00134 R2 = CurDAG->getRegister(SP::G0, TLI.getPointerTy()); 00135 return true; 00136 } 00137 00138 SDNode *SparcDAGToDAGISel::Select(SDNode *N) { 00139 DebugLoc dl = N->getDebugLoc(); 00140 if (N->isMachineOpcode()) 00141 return NULL; // Already selected. 00142 00143 switch (N->getOpcode()) { 00144 default: break; 00145 case SPISD::GLOBAL_BASE_REG: 00146 return getGlobalBaseReg(); 00147 00148 case ISD::SDIV: 00149 case ISD::UDIV: { 00150 // sdivx / udivx handle 64-bit divides. 00151 if (N->getValueType(0) == MVT::i64) 00152 break; 00153 // FIXME: should use a custom expander to expose the SRA to the dag. 00154 SDValue DivLHS = N->getOperand(0); 00155 SDValue DivRHS = N->getOperand(1); 00156 00157 // Set the Y register to the high-part. 00158 SDValue TopPart; 00159 if (N->getOpcode() == ISD::SDIV) { 00160 TopPart = SDValue(CurDAG->getMachineNode(SP::SRAri, dl, MVT::i32, DivLHS, 00161 CurDAG->getTargetConstant(31, MVT::i32)), 0); 00162 } else { 00163 TopPart = CurDAG->getRegister(SP::G0, MVT::i32); 00164 } 00165 TopPart = SDValue(CurDAG->getMachineNode(SP::WRYrr, dl, MVT::Glue, TopPart, 00166 CurDAG->getRegister(SP::G0, MVT::i32)), 0); 00167 00168 // FIXME: Handle div by immediate. 00169 unsigned Opcode = N->getOpcode() == ISD::SDIV ? SP::SDIVrr : SP::UDIVrr; 00170 return CurDAG->SelectNodeTo(N, Opcode, MVT::i32, DivLHS, DivRHS, 00171 TopPart); 00172 } 00173 case ISD::MULHU: 00174 case ISD::MULHS: { 00175 // FIXME: Handle mul by immediate. 00176 SDValue MulLHS = N->getOperand(0); 00177 SDValue MulRHS = N->getOperand(1); 00178 unsigned Opcode = N->getOpcode() == ISD::MULHU ? SP::UMULrr : SP::SMULrr; 00179 SDNode *Mul = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::Glue, 00180 MulLHS, MulRHS); 00181 // The high part is in the Y register. 00182 return CurDAG->SelectNodeTo(N, SP::RDY, MVT::i32, SDValue(Mul, 1)); 00183 } 00184 } 00185 00186 return SelectCode(N); 00187 } 00188 00189 00190 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for 00191 /// inline asm expressions. 00192 bool 00193 SparcDAGToDAGISel::SelectInlineAsmMemoryOperand(const SDValue &Op, 00194 char ConstraintCode, 00195 std::vector<SDValue> &OutOps) { 00196 SDValue Op0, Op1; 00197 switch (ConstraintCode) { 00198 default: return true; 00199 case 'm': // memory 00200 if (!SelectADDRrr(Op, Op0, Op1)) 00201 SelectADDRri(Op, Op0, Op1); 00202 break; 00203 } 00204 00205 OutOps.push_back(Op0); 00206 OutOps.push_back(Op1); 00207 return false; 00208 } 00209 00210 /// createSparcISelDag - This pass converts a legalized DAG into a 00211 /// SPARC-specific DAG, ready for instruction scheduling. 00212 /// 00213 FunctionPass *llvm::createSparcISelDag(SparcTargetMachine &TM) { 00214 return new SparcDAGToDAGISel(TM); 00215 }