1//===-- MipsISelDAGToDAG.cpp - A dag to dag inst selector for Mips --------===// 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 MIPS target. 11// 12//===----------------------------------------------------------------------===// 13 14#define DEBUG_TYPE "mips-isel" 15#include "Mips.h" 16#include "MipsMachineFunction.h" 17#include "MipsRegisterInfo.h" 18#include "MipsSubtarget.h" 19#include "MipsTargetMachine.h" 20#include "llvm/GlobalValue.h" 21#include "llvm/Instructions.h" 22#include "llvm/Intrinsics.h" 23#include "llvm/Support/CFG.h" 24#include "llvm/Type.h" 25#include "llvm/CodeGen/MachineConstantPool.h" 26#include "llvm/CodeGen/MachineFunction.h" 27#include "llvm/CodeGen/MachineFrameInfo.h" 28#include "llvm/CodeGen/MachineInstrBuilder.h" 29#include "llvm/CodeGen/MachineRegisterInfo.h" 30#include "llvm/CodeGen/SelectionDAGISel.h" 31#include "llvm/Target/TargetMachine.h" 32#include "llvm/Support/Debug.h" 33#include "llvm/Support/ErrorHandling.h" 34#include "llvm/Support/raw_ostream.h" 35using namespace llvm; 36 37//===----------------------------------------------------------------------===// 38// Instruction Selector Implementation 39//===----------------------------------------------------------------------===// 40 41//===----------------------------------------------------------------------===// 42// MipsDAGToDAGISel - MIPS specific code to select MIPS machine 43// instructions for SelectionDAG operations. 44//===----------------------------------------------------------------------===// 45namespace { 46 47class MipsDAGToDAGISel : public SelectionDAGISel { 48 49 /// TM - Keep a reference to MipsTargetMachine. 50 MipsTargetMachine &TM; 51 52 /// Subtarget - Keep a pointer to the MipsSubtarget around so that we can 53 /// make the right decision when generating code for different targets. 54 const MipsSubtarget &Subtarget; 55 56public: 57 explicit MipsDAGToDAGISel(MipsTargetMachine &tm) : 58 SelectionDAGISel(tm), 59 TM(tm), Subtarget(tm.getSubtarget<MipsSubtarget>()) {} 60 61 // Pass Name 62 virtual const char *getPassName() const { 63 return "MIPS DAG->DAG Pattern Instruction Selection"; 64 } 65 66 67private: 68 // Include the pieces autogenerated from the target description. 69 #include "MipsGenDAGISel.inc" 70 71 /// getTargetMachine - Return a reference to the TargetMachine, casted 72 /// to the target-specific type. 73 const MipsTargetMachine &getTargetMachine() { 74 return static_cast<const MipsTargetMachine &>(TM); 75 } 76 77 /// getInstrInfo - Return a reference to the TargetInstrInfo, casted 78 /// to the target-specific type. 79 const MipsInstrInfo *getInstrInfo() { 80 return getTargetMachine().getInstrInfo(); 81 } 82 83 SDNode *getGlobalBaseReg(); 84 SDNode *Select(SDNode *N); 85 86 // Complex Pattern. 87 bool SelectAddr(SDValue N, SDValue &Base, SDValue &Offset); 88 89 // getI32Imm - Return a target constant with the specified 90 // value, of type i32. 91 inline SDValue getI32Imm(unsigned Imm) { 92 return CurDAG->getTargetConstant(Imm, MVT::i32); 93 } 94 95 virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, 96 char ConstraintCode, 97 std::vector<SDValue> &OutOps); 98}; 99 100} 101 102 103/// getGlobalBaseReg - Output the instructions required to put the 104/// GOT address into a register. 105SDNode *MipsDAGToDAGISel::getGlobalBaseReg() { 106 unsigned GlobalBaseReg = getInstrInfo()->getGlobalBaseReg(MF); 107 return CurDAG->getRegister(GlobalBaseReg, TLI.getPointerTy()).getNode(); 108} 109 110/// ComplexPattern used on MipsInstrInfo 111/// Used on Mips Load/Store instructions 112bool MipsDAGToDAGISel:: 113SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) { 114 EVT ValTy = Addr.getValueType(); 115 unsigned GPReg = ValTy == MVT::i32 ? Mips::GP : Mips::GP_64; 116 117 // if Address is FI, get the TargetFrameIndex. 118 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 119 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); 120 Offset = CurDAG->getTargetConstant(0, ValTy); 121 return true; 122 } 123 124 // on PIC code Load GA 125 if (TM.getRelocationModel() == Reloc::PIC_) { 126 if (Addr.getOpcode() == MipsISD::WrapperPIC) { 127 Base = CurDAG->getRegister(GPReg, ValTy); 128 Offset = Addr.getOperand(0); 129 return true; 130 } 131 } else { 132 if ((Addr.getOpcode() == ISD::TargetExternalSymbol || 133 Addr.getOpcode() == ISD::TargetGlobalAddress)) 134 return false; 135 else if (Addr.getOpcode() == ISD::TargetGlobalTLSAddress) { 136 Base = CurDAG->getRegister(GPReg, ValTy); 137 Offset = Addr; 138 return true; 139 } 140 } 141 142 // Addresses of the form FI+const or FI|const 143 if (CurDAG->isBaseWithConstantOffset(Addr)) { 144 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)); 145 if (isInt<16>(CN->getSExtValue())) { 146 147 // If the first operand is a FI, get the TargetFI Node 148 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode> 149 (Addr.getOperand(0))) 150 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); 151 else 152 Base = Addr.getOperand(0); 153 154 Offset = CurDAG->getTargetConstant(CN->getZExtValue(), ValTy); 155 return true; 156 } 157 } 158 159 // Operand is a result from an ADD. 160 if (Addr.getOpcode() == ISD::ADD) { 161 // When loading from constant pools, load the lower address part in 162 // the instruction itself. Example, instead of: 163 // lui $2, %hi($CPI1_0) 164 // addiu $2, $2, %lo($CPI1_0) 165 // lwc1 $f0, 0($2) 166 // Generate: 167 // lui $2, %hi($CPI1_0) 168 // lwc1 $f0, %lo($CPI1_0)($2) 169 if ((Addr.getOperand(0).getOpcode() == MipsISD::Hi || 170 Addr.getOperand(0).getOpcode() == ISD::LOAD) && 171 Addr.getOperand(1).getOpcode() == MipsISD::Lo) { 172 SDValue LoVal = Addr.getOperand(1); 173 if (isa<ConstantPoolSDNode>(LoVal.getOperand(0)) || 174 isa<GlobalAddressSDNode>(LoVal.getOperand(0))) { 175 Base = Addr.getOperand(0); 176 Offset = LoVal.getOperand(0); 177 return true; 178 } 179 } 180 } 181 182 Base = Addr; 183 Offset = CurDAG->getTargetConstant(0, ValTy); 184 return true; 185} 186 187/// Select instructions not customized! Used for 188/// expanded, promoted and normal instructions 189SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { 190 unsigned Opcode = Node->getOpcode(); 191 DebugLoc dl = Node->getDebugLoc(); 192 193 // Dump information about the Node being selected 194 DEBUG(errs() << "Selecting: "; Node->dump(CurDAG); errs() << "\n"); 195 196 // If we have a custom node, we already have selected! 197 if (Node->isMachineOpcode()) { 198 DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n"); 199 return NULL; 200 } 201 202 /// 203 // Instruction Selection not handled by the auto-generated 204 // tablegen selection should be handled here. 205 /// 206 switch(Opcode) { 207 default: break; 208 209 case ISD::SUBE: 210 case ISD::ADDE: { 211 SDValue InFlag = Node->getOperand(2), CmpLHS; 212 unsigned Opc = InFlag.getOpcode(); (void)Opc; 213 assert(((Opc == ISD::ADDC || Opc == ISD::ADDE) || 214 (Opc == ISD::SUBC || Opc == ISD::SUBE)) && 215 "(ADD|SUB)E flag operand must come from (ADD|SUB)C/E insn"); 216 217 unsigned MOp; 218 if (Opcode == ISD::ADDE) { 219 CmpLHS = InFlag.getValue(0); 220 MOp = Mips::ADDu; 221 } else { 222 CmpLHS = InFlag.getOperand(0); 223 MOp = Mips::SUBu; 224 } 225 226 SDValue Ops[] = { CmpLHS, InFlag.getOperand(1) }; 227 228 SDValue LHS = Node->getOperand(0); 229 SDValue RHS = Node->getOperand(1); 230 231 EVT VT = LHS.getValueType(); 232 SDNode *Carry = CurDAG->getMachineNode(Mips::SLTu, dl, VT, Ops, 2); 233 SDNode *AddCarry = CurDAG->getMachineNode(Mips::ADDu, dl, VT, 234 SDValue(Carry,0), RHS); 235 236 return CurDAG->SelectNodeTo(Node, MOp, VT, MVT::Glue, 237 LHS, SDValue(AddCarry,0)); 238 } 239 240 /// Mul with two results 241 case ISD::SMUL_LOHI: 242 case ISD::UMUL_LOHI: { 243 assert(Node->getValueType(0) != MVT::i64 && 244 "64-bit multiplication with two results not handled."); 245 SDValue Op1 = Node->getOperand(0); 246 SDValue Op2 = Node->getOperand(1); 247 248 unsigned Op; 249 Op = (Opcode == ISD::UMUL_LOHI ? Mips::MULTu : Mips::MULT); 250 251 SDNode *Mul = CurDAG->getMachineNode(Op, dl, MVT::Glue, Op1, Op2); 252 253 SDValue InFlag = SDValue(Mul, 0); 254 SDNode *Lo = CurDAG->getMachineNode(Mips::MFLO, dl, MVT::i32, 255 MVT::Glue, InFlag); 256 InFlag = SDValue(Lo,1); 257 SDNode *Hi = CurDAG->getMachineNode(Mips::MFHI, dl, MVT::i32, InFlag); 258 259 if (!SDValue(Node, 0).use_empty()) 260 ReplaceUses(SDValue(Node, 0), SDValue(Lo,0)); 261 262 if (!SDValue(Node, 1).use_empty()) 263 ReplaceUses(SDValue(Node, 1), SDValue(Hi,0)); 264 265 return NULL; 266 } 267 268 /// Special Muls 269 case ISD::MUL: 270 // Mips32 has a 32-bit three operand mul instruction. 271 if (Subtarget.hasMips32() && Node->getValueType(0) == MVT::i32) 272 break; 273 case ISD::MULHS: 274 case ISD::MULHU: { 275 assert((Opcode == ISD::MUL || Node->getValueType(0) != MVT::i64) && 276 "64-bit MULH* not handled."); 277 EVT Ty = Node->getValueType(0); 278 SDValue MulOp1 = Node->getOperand(0); 279 SDValue MulOp2 = Node->getOperand(1); 280 281 unsigned MulOp = (Opcode == ISD::MULHU ? 282 Mips::MULTu : 283 (Ty == MVT::i32 ? Mips::MULT : Mips::DMULT)); 284 SDNode *MulNode = CurDAG->getMachineNode(MulOp, dl, 285 MVT::Glue, MulOp1, MulOp2); 286 287 SDValue InFlag = SDValue(MulNode, 0); 288 289 if (Opcode == ISD::MUL) { 290 unsigned Opc = (Ty == MVT::i32 ? Mips::MFLO : Mips::MFLO64); 291 return CurDAG->getMachineNode(Opc, dl, Ty, InFlag); 292 } 293 else 294 return CurDAG->getMachineNode(Mips::MFHI, dl, MVT::i32, InFlag); 295 } 296 297 // Get target GOT address. 298 case ISD::GLOBAL_OFFSET_TABLE: 299 return getGlobalBaseReg(); 300 301 case ISD::ConstantFP: { 302 ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(Node); 303 if (Node->getValueType(0) == MVT::f64 && CN->isExactlyValue(+0.0)) { 304 SDValue Zero = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl, 305 Mips::ZERO, MVT::i32); 306 return CurDAG->getMachineNode(Mips::BuildPairF64, dl, MVT::f64, Zero, 307 Zero); 308 } 309 break; 310 } 311 312 case MipsISD::ThreadPointer: { 313 unsigned SrcReg = Mips::HWR29; 314 unsigned DestReg = Mips::V1; 315 SDNode *Rdhwr = CurDAG->getMachineNode(Mips::RDHWR, Node->getDebugLoc(), 316 Node->getValueType(0), CurDAG->getRegister(SrcReg, MVT::i32)); 317 SDValue Chain = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, DestReg, 318 SDValue(Rdhwr, 0)); 319 SDValue ResNode = CurDAG->getCopyFromReg(Chain, dl, DestReg, MVT::i32); 320 ReplaceUses(SDValue(Node, 0), ResNode); 321 return ResNode.getNode(); 322 } 323 } 324 325 // Select the default instruction 326 SDNode *ResNode = SelectCode(Node); 327 328 DEBUG(errs() << "=> "); 329 if (ResNode == NULL || ResNode == Node) 330 DEBUG(Node->dump(CurDAG)); 331 else 332 DEBUG(ResNode->dump(CurDAG)); 333 DEBUG(errs() << "\n"); 334 return ResNode; 335} 336 337bool MipsDAGToDAGISel:: 338SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, 339 std::vector<SDValue> &OutOps) { 340 assert(ConstraintCode == 'm' && "unexpected asm memory constraint"); 341 OutOps.push_back(Op); 342 return false; 343} 344 345/// createMipsISelDag - This pass converts a legalized DAG into a 346/// MIPS-specific DAG, ready for instruction scheduling. 347FunctionPass *llvm::createMipsISelDag(MipsTargetMachine &TM) { 348 return new MipsDAGToDAGISel(TM); 349} 350