SparcISelDAGToDAG.cpp revision f5aeb1a8e4cf272c7348376d185ef8d8267653e0
1//===-- SparcISelDAGToDAG.cpp - A dag to dag inst selector for Sparc ------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file defines an instruction selector for the SPARC target. 11// 12//===----------------------------------------------------------------------===// 13 14#include "SparcISelLowering.h" 15#include "SparcTargetMachine.h" 16#include "llvm/Intrinsics.h" 17#include "llvm/CodeGen/SelectionDAGISel.h" 18#include "llvm/Support/Compiler.h" 19#include "llvm/Support/Debug.h" 20using namespace llvm; 21 22//===----------------------------------------------------------------------===// 23// Instruction Selector Implementation 24//===----------------------------------------------------------------------===// 25 26//===--------------------------------------------------------------------===// 27/// SparcDAGToDAGISel - SPARC specific code to select SPARC machine 28/// instructions for SelectionDAG operations. 29/// 30namespace { 31class SparcDAGToDAGISel : public SelectionDAGISel { 32 SparcTargetLowering Lowering; 33 34 /// Subtarget - Keep a pointer to the Sparc Subtarget around so that we can 35 /// make the right decision when generating code for different targets. 36 const SparcSubtarget &Subtarget; 37public: 38 explicit SparcDAGToDAGISel(TargetMachine &TM) 39 : SelectionDAGISel(Lowering), Lowering(TM), 40 Subtarget(TM.getSubtarget<SparcSubtarget>()) { 41 } 42 43 SDNode *Select(SDValue Op); 44 45 // Complex Pattern Selectors. 46 bool SelectADDRrr(SDValue Op, SDValue N, SDValue &R1, SDValue &R2); 47 bool SelectADDRri(SDValue Op, SDValue N, SDValue &Base, 48 SDValue &Offset); 49 50 /// InstructionSelect - This callback is invoked by 51 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. 52 virtual void InstructionSelect(); 53 54 virtual const char *getPassName() const { 55 return "SPARC DAG->DAG Pattern Instruction Selection"; 56 } 57 58 // Include the pieces autogenerated from the target description. 59#include "SparcGenDAGISel.inc" 60}; 61} // end anonymous namespace 62 63/// InstructionSelect - This callback is invoked by 64/// SelectionDAGISel when it has created a SelectionDAG for us to codegen. 65void SparcDAGToDAGISel::InstructionSelect() { 66 DEBUG(BB->dump()); 67 68 // Select target instructions for the DAG. 69 SelectRoot(); 70 CurDAG->RemoveDeadNodes(); 71} 72 73bool SparcDAGToDAGISel::SelectADDRri(SDValue Op, SDValue Addr, 74 SDValue &Base, SDValue &Offset) { 75 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 76 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 77 Offset = CurDAG->getTargetConstant(0, MVT::i32); 78 return true; 79 } 80 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 81 Addr.getOpcode() == ISD::TargetGlobalAddress) 82 return false; // direct calls. 83 84 if (Addr.getOpcode() == ISD::ADD) { 85 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) { 86 if (Predicate_simm13(CN)) { 87 if (FrameIndexSDNode *FIN = 88 dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) { 89 // Constant offset from frame ref. 90 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 91 } else { 92 Base = Addr.getOperand(0); 93 } 94 Offset = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32); 95 return true; 96 } 97 } 98 if (Addr.getOperand(0).getOpcode() == SPISD::Lo) { 99 Base = Addr.getOperand(1); 100 Offset = Addr.getOperand(0).getOperand(0); 101 return true; 102 } 103 if (Addr.getOperand(1).getOpcode() == SPISD::Lo) { 104 Base = Addr.getOperand(0); 105 Offset = Addr.getOperand(1).getOperand(0); 106 return true; 107 } 108 } 109 Base = Addr; 110 Offset = CurDAG->getTargetConstant(0, MVT::i32); 111 return true; 112} 113 114bool SparcDAGToDAGISel::SelectADDRrr(SDValue Op, SDValue Addr, 115 SDValue &R1, SDValue &R2) { 116 if (Addr.getOpcode() == ISD::FrameIndex) return false; 117 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 118 Addr.getOpcode() == ISD::TargetGlobalAddress) 119 return false; // direct calls. 120 121 if (Addr.getOpcode() == ISD::ADD) { 122 if (isa<ConstantSDNode>(Addr.getOperand(1)) && 123 Predicate_simm13(Addr.getOperand(1).getNode())) 124 return false; // Let the reg+imm pattern catch this! 125 if (Addr.getOperand(0).getOpcode() == SPISD::Lo || 126 Addr.getOperand(1).getOpcode() == SPISD::Lo) 127 return false; // Let the reg+imm pattern catch this! 128 R1 = Addr.getOperand(0); 129 R2 = Addr.getOperand(1); 130 return true; 131 } 132 133 R1 = Addr; 134 R2 = CurDAG->getRegister(SP::G0, MVT::i32); 135 return true; 136} 137 138SDNode *SparcDAGToDAGISel::Select(SDValue Op) { 139 SDNode *N = Op.getNode(); 140 if (N->isMachineOpcode()) 141 return NULL; // Already selected. 142 143 switch (N->getOpcode()) { 144 default: break; 145 case ISD::SDIV: 146 case ISD::UDIV: { 147 // FIXME: should use a custom expander to expose the SRA to the dag. 148 SDValue DivLHS = N->getOperand(0); 149 SDValue DivRHS = N->getOperand(1); 150 AddToISelQueue(DivLHS); 151 AddToISelQueue(DivRHS); 152 153 // Set the Y register to the high-part. 154 SDValue TopPart; 155 if (N->getOpcode() == ISD::SDIV) { 156 TopPart = SDValue(CurDAG->getTargetNode(SP::SRAri, MVT::i32, DivLHS, 157 CurDAG->getTargetConstant(31, MVT::i32)), 0); 158 } else { 159 TopPart = CurDAG->getRegister(SP::G0, MVT::i32); 160 } 161 TopPart = SDValue(CurDAG->getTargetNode(SP::WRYrr, MVT::Flag, TopPart, 162 CurDAG->getRegister(SP::G0, MVT::i32)), 0); 163 164 // FIXME: Handle div by immediate. 165 unsigned Opcode = N->getOpcode() == ISD::SDIV ? SP::SDIVrr : SP::UDIVrr; 166 return CurDAG->SelectNodeTo(N, Opcode, MVT::i32, DivLHS, DivRHS, 167 TopPart); 168 } 169 case ISD::MULHU: 170 case ISD::MULHS: { 171 // FIXME: Handle mul by immediate. 172 SDValue MulLHS = N->getOperand(0); 173 SDValue MulRHS = N->getOperand(1); 174 AddToISelQueue(MulLHS); 175 AddToISelQueue(MulRHS); 176 unsigned Opcode = N->getOpcode() == ISD::MULHU ? SP::UMULrr : SP::SMULrr; 177 SDNode *Mul = CurDAG->getTargetNode(Opcode, MVT::i32, MVT::Flag, 178 MulLHS, MulRHS); 179 // The high part is in the Y register. 180 return CurDAG->SelectNodeTo(N, SP::RDY, MVT::i32, SDValue(Mul, 1)); 181 return NULL; 182 } 183 } 184 185 return SelectCode(Op); 186} 187 188 189/// createSparcISelDag - This pass converts a legalized DAG into a 190/// SPARC-specific DAG, ready for instruction scheduling. 191/// 192FunctionPass *llvm::createSparcISelDag(TargetMachine &TM) { 193 return new SparcDAGToDAGISel(TM); 194} 195