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