SparcISelDAGToDAG.cpp revision d23405e6f04135cabcad4d9bd7aa6e4f187bed3a
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 SparcDAGToDAGISel(TargetMachine &TM) 39 : SelectionDAGISel(Lowering), Lowering(TM), 40 Subtarget(TM.getSubtarget<SparcSubtarget>()) { 41 } 42 43 SDNode *Select(SDOperand Op); 44 45 // Complex Pattern Selectors. 46 bool SelectADDRrr(SDOperand Op, SDOperand N, SDOperand &R1, SDOperand &R2); 47 bool SelectADDRri(SDOperand Op, SDOperand N, SDOperand &Base, 48 SDOperand &Offset); 49 50 /// InstructionSelectBasicBlock - This callback is invoked by 51 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. 52 virtual void InstructionSelectBasicBlock(SelectionDAG &DAG); 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/// InstructionSelectBasicBlock - This callback is invoked by 64/// SelectionDAGISel when it has created a SelectionDAG for us to codegen. 65void SparcDAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) { 66 DEBUG(BB->dump()); 67 68 // Select target instructions for the DAG. 69 DAG.setRoot(SelectRoot(DAG.getRoot())); 70 DAG.RemoveDeadNodes(); 71 72 // Emit machine code to BB. 73 ScheduleAndEmitDAG(DAG); 74} 75 76bool SparcDAGToDAGISel::SelectADDRri(SDOperand Op, SDOperand Addr, 77 SDOperand &Base, SDOperand &Offset) { 78 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 79 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 80 Offset = CurDAG->getTargetConstant(0, MVT::i32); 81 return true; 82 } 83 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 84 Addr.getOpcode() == ISD::TargetGlobalAddress) 85 return false; // direct calls. 86 87 if (Addr.getOpcode() == ISD::ADD) { 88 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) { 89 if (Predicate_simm13(CN)) { 90 if (FrameIndexSDNode *FIN = 91 dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) { 92 // Constant offset from frame ref. 93 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 94 } else { 95 Base = Addr.getOperand(0); 96 } 97 Offset = CurDAG->getTargetConstant(CN->getValue(), MVT::i32); 98 return true; 99 } 100 } 101 if (Addr.getOperand(0).getOpcode() == SPISD::Lo) { 102 Base = Addr.getOperand(1); 103 Offset = Addr.getOperand(0).getOperand(0); 104 return true; 105 } 106 if (Addr.getOperand(1).getOpcode() == SPISD::Lo) { 107 Base = Addr.getOperand(0); 108 Offset = Addr.getOperand(1).getOperand(0); 109 return true; 110 } 111 } 112 Base = Addr; 113 Offset = CurDAG->getTargetConstant(0, MVT::i32); 114 return true; 115} 116 117bool SparcDAGToDAGISel::SelectADDRrr(SDOperand Op, SDOperand Addr, 118 SDOperand &R1, SDOperand &R2) { 119 if (Addr.getOpcode() == ISD::FrameIndex) return false; 120 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 121 Addr.getOpcode() == ISD::TargetGlobalAddress) 122 return false; // direct calls. 123 124 if (Addr.getOpcode() == ISD::ADD) { 125 if (isa<ConstantSDNode>(Addr.getOperand(1)) && 126 Predicate_simm13(Addr.getOperand(1).Val)) 127 return false; // Let the reg+imm pattern catch this! 128 if (Addr.getOperand(0).getOpcode() == SPISD::Lo || 129 Addr.getOperand(1).getOpcode() == SPISD::Lo) 130 return false; // Let the reg+imm pattern catch this! 131 R1 = Addr.getOperand(0); 132 R2 = Addr.getOperand(1); 133 return true; 134 } 135 136 R1 = Addr; 137 R2 = CurDAG->getRegister(SP::G0, MVT::i32); 138 return true; 139} 140 141SDNode *SparcDAGToDAGISel::Select(SDOperand Op) { 142 SDNode *N = Op.Val; 143 if (N->getOpcode() >= ISD::BUILTIN_OP_END && 144 N->getOpcode() < SPISD::FIRST_NUMBER) 145 return NULL; // Already selected. 146 147 switch (N->getOpcode()) { 148 default: break; 149 case ISD::SDIV: 150 case ISD::UDIV: { 151 // FIXME: should use a custom expander to expose the SRA to the dag. 152 SDOperand DivLHS = N->getOperand(0); 153 SDOperand DivRHS = N->getOperand(1); 154 AddToISelQueue(DivLHS); 155 AddToISelQueue(DivRHS); 156 157 // Set the Y register to the high-part. 158 SDOperand TopPart; 159 if (N->getOpcode() == ISD::SDIV) { 160 TopPart = SDOperand(CurDAG->getTargetNode(SP::SRAri, MVT::i32, DivLHS, 161 CurDAG->getTargetConstant(31, MVT::i32)), 0); 162 } else { 163 TopPart = CurDAG->getRegister(SP::G0, MVT::i32); 164 } 165 TopPart = SDOperand(CurDAG->getTargetNode(SP::WRYrr, MVT::Flag, TopPart, 166 CurDAG->getRegister(SP::G0, MVT::i32)), 0); 167 168 // FIXME: Handle div by immediate. 169 unsigned Opcode = N->getOpcode() == ISD::SDIV ? SP::SDIVrr : SP::UDIVrr; 170 return CurDAG->SelectNodeTo(N, Opcode, MVT::i32, DivLHS, DivRHS, 171 TopPart); 172 } 173 case ISD::MULHU: 174 case ISD::MULHS: { 175 // FIXME: Handle mul by immediate. 176 SDOperand MulLHS = N->getOperand(0); 177 SDOperand MulRHS = N->getOperand(1); 178 AddToISelQueue(MulLHS); 179 AddToISelQueue(MulRHS); 180 unsigned Opcode = N->getOpcode() == ISD::MULHU ? SP::UMULrr : SP::SMULrr; 181 SDNode *Mul = CurDAG->getTargetNode(Opcode, MVT::i32, MVT::Flag, 182 MulLHS, MulRHS); 183 // The high part is in the Y register. 184 return CurDAG->SelectNodeTo(N, SP::RDY, MVT::i32, SDOperand(Mul, 1)); 185 return NULL; 186 } 187 } 188 189 return SelectCode(Op); 190} 191 192 193/// createSparcISelDag - This pass converts a legalized DAG into a 194/// SPARC-specific DAG, ready for instruction scheduling. 195/// 196FunctionPass *llvm::createSparcISelDag(TargetMachine &TM) { 197 return new SparcDAGToDAGISel(TM); 198} 199