MBlazeISelDAGToDAG.cpp revision 208954
1311310Sdim//===-- MBlazeISelDAGToDAG.cpp - A dag to dag inst selector for MBlaze ----===// 2311310Sdim// 3311310Sdim// The LLVM Compiler Infrastructure 4311310Sdim// 5311310Sdim// This file is distributed under the University of Illinois Open Source 6360660Sdim// License. See LICENSE.TXT for details. 7344213Sdim// 8344213Sdim//===----------------------------------------------------------------------===// 9344213Sdim// 10344213Sdim// This file defines an instruction selector for the MBlaze target. 11344213Sdim// 12344213Sdim//===----------------------------------------------------------------------===// 13344213Sdim 14344213Sdim#define DEBUG_TYPE "mblaze-isel" 15344213Sdim#include "MBlaze.h" 16344213Sdim#include "MBlazeMachineFunction.h" 17311310Sdim#include "MBlazeRegisterInfo.h" 18311310Sdim#include "MBlazeSubtarget.h" 19311310Sdim#include "MBlazeTargetMachine.h" 20311310Sdim#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// MBlazeDAGToDAGISel - MBlaze specific code to select MBlaze machine 43// instructions for SelectionDAG operations. 44//===----------------------------------------------------------------------===// 45namespace { 46 47class MBlazeDAGToDAGISel : public SelectionDAGISel { 48 49 /// TM - Keep a reference to MBlazeTargetMachine. 50 MBlazeTargetMachine &TM; 51 52 /// Subtarget - Keep a pointer to the MBlazeSubtarget around so that we can 53 /// make the right decision when generating code for different targets. 54 const MBlazeSubtarget &Subtarget; 55 56public: 57 explicit MBlazeDAGToDAGISel(MBlazeTargetMachine &tm) : 58 SelectionDAGISel(tm), 59 TM(tm), Subtarget(tm.getSubtarget<MBlazeSubtarget>()) {} 60 61 // Pass Name 62 virtual const char *getPassName() const { 63 return "MBlaze DAG->DAG Pattern Instruction Selection"; 64 } 65private: 66 // Include the pieces autogenerated from the target description. 67 #include "MBlazeGenDAGISel.inc" 68 69 /// getTargetMachine - Return a reference to the TargetMachine, casted 70 /// to the target-specific type. 71 const MBlazeTargetMachine &getTargetMachine() { 72 return static_cast<const MBlazeTargetMachine &>(TM); 73 } 74 75 /// getInstrInfo - Return a reference to the TargetInstrInfo, casted 76 /// to the target-specific type. 77 const MBlazeInstrInfo *getInstrInfo() { 78 return getTargetMachine().getInstrInfo(); 79 } 80 81 SDNode *getGlobalBaseReg(); 82 SDNode *Select(SDNode *N); 83 84 // Complex Pattern. 85 bool SelectAddr(SDNode *Op, SDValue N, 86 SDValue &Base, SDValue &Offset); 87 88 // Address Selection 89 bool SelectAddrRegReg(SDNode *Op, SDValue N, SDValue &Base, SDValue &Index); 90 bool SelectAddrRegImm(SDNode *Op, SDValue N, SDValue &Disp, SDValue &Base); 91 92 // getI32Imm - Return a target constant with the specified value, of type i32. 93 inline SDValue getI32Imm(unsigned Imm) { 94 return CurDAG->getTargetConstant(Imm, MVT::i32); 95 } 96}; 97 98} 99 100/// isIntS32Immediate - This method tests to see if the node is either a 32-bit 101/// or 64-bit immediate, and if the value can be accurately represented as a 102/// sign extension from a 32-bit value. If so, this returns true and the 103/// immediate. 104static bool isIntS32Immediate(SDNode *N, int32_t &Imm) { 105 unsigned Opc = N->getOpcode(); 106 if (Opc != ISD::Constant) 107 return false; 108 109 Imm = (int32_t)cast<ConstantSDNode>(N)->getZExtValue(); 110 if (N->getValueType(0) == MVT::i32) 111 return Imm == (int32_t)cast<ConstantSDNode>(N)->getZExtValue(); 112 else 113 return Imm == (int64_t)cast<ConstantSDNode>(N)->getZExtValue(); 114} 115 116static bool isIntS32Immediate(SDValue Op, int32_t &Imm) { 117 return isIntS32Immediate(Op.getNode(), Imm); 118} 119 120 121/// SelectAddressRegReg - Given the specified addressed, check to see if it 122/// can be represented as an indexed [r+r] operation. Returns false if it 123/// can be more efficiently represented with [r+imm]. 124bool MBlazeDAGToDAGISel:: 125SelectAddrRegReg(SDNode *Op, SDValue N, SDValue &Base, SDValue &Index) { 126 if (N.getOpcode() == ISD::FrameIndex) return false; 127 if (N.getOpcode() == ISD::TargetExternalSymbol || 128 N.getOpcode() == ISD::TargetGlobalAddress) 129 return false; // direct calls. 130 131 int32_t imm = 0; 132 if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) { 133 if (isIntS32Immediate(N.getOperand(1), imm)) 134 return false; // r+i 135 136 if (N.getOperand(0).getOpcode() == ISD::TargetJumpTable || 137 N.getOperand(1).getOpcode() == ISD::TargetJumpTable) 138 return false; // jump tables. 139 140 Base = N.getOperand(1); 141 Index = N.getOperand(0); 142 return true; 143 } 144 145 return false; 146} 147 148/// Returns true if the address N can be represented by a base register plus 149/// a signed 32-bit displacement [r+imm], and if it is not better 150/// represented as reg+reg. 151bool MBlazeDAGToDAGISel:: 152SelectAddrRegImm(SDNode *Op, SDValue N, SDValue &Disp, SDValue &Base) { 153 // If this can be more profitably realized as r+r, fail. 154 if (SelectAddrRegReg(Op, N, Disp, Base)) 155 return false; 156 157 if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) { 158 int32_t imm = 0; 159 if (isIntS32Immediate(N.getOperand(1), imm)) { 160 Disp = CurDAG->getTargetConstant(imm, MVT::i32); 161 if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N.getOperand(0))) { 162 Base = CurDAG->getTargetFrameIndex(FI->getIndex(), N.getValueType()); 163 } else { 164 Base = N.getOperand(0); 165 } 166 DEBUG( errs() << "WESLEY: Using Operand Immediate\n" ); 167 return true; // [r+i] 168 } 169 } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N)) { 170 // Loading from a constant address. 171 uint32_t Imm = CN->getZExtValue(); 172 Disp = CurDAG->getTargetConstant(Imm, CN->getValueType(0)); 173 Base = CurDAG->getRegister(MBlaze::R0, CN->getValueType(0)); 174 DEBUG( errs() << "WESLEY: Using Constant Node\n" ); 175 return true; 176 } 177 178 Disp = CurDAG->getTargetConstant(0, TM.getTargetLowering()->getPointerTy()); 179 if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N)) 180 Base = CurDAG->getTargetFrameIndex(FI->getIndex(), N.getValueType()); 181 else 182 Base = N; 183 return true; // [r+0] 184} 185 186/// getGlobalBaseReg - Output the instructions required to put the 187/// GOT address into a register. 188SDNode *MBlazeDAGToDAGISel::getGlobalBaseReg() { 189 unsigned GlobalBaseReg = getInstrInfo()->getGlobalBaseReg(MF); 190 return CurDAG->getRegister(GlobalBaseReg, TLI.getPointerTy()).getNode(); 191} 192 193/// ComplexPattern used on MBlazeInstrInfo 194/// Used on MBlaze Load/Store instructions 195bool MBlazeDAGToDAGISel:: 196SelectAddr(SDNode *Op, SDValue Addr, SDValue &Offset, SDValue &Base) { 197 // if Address is FI, get the TargetFrameIndex. 198 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 199 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 200 Offset = CurDAG->getTargetConstant(0, MVT::i32); 201 return true; 202 } 203 204 // on PIC code Load GA 205 if (TM.getRelocationModel() == Reloc::PIC_) { 206 if ((Addr.getOpcode() == ISD::TargetGlobalAddress) || 207 (Addr.getOpcode() == ISD::TargetConstantPool) || 208 (Addr.getOpcode() == ISD::TargetJumpTable)){ 209 Base = CurDAG->getRegister(MBlaze::R15, MVT::i32); 210 Offset = Addr; 211 return true; 212 } 213 } else { 214 if ((Addr.getOpcode() == ISD::TargetExternalSymbol || 215 Addr.getOpcode() == ISD::TargetGlobalAddress)) 216 return false; 217 } 218 219 // Operand is a result from an ADD. 220 if (Addr.getOpcode() == ISD::ADD) { 221 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) { 222 if (Predicate_immSExt16(CN)) { 223 224 // If the first operand is a FI, get the TargetFI Node 225 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode> 226 (Addr.getOperand(0))) { 227 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 228 } else { 229 Base = Addr.getOperand(0); 230 } 231 232 Offset = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32); 233 return true; 234 } 235 } 236 } 237 238 Base = Addr; 239 Offset = CurDAG->getTargetConstant(0, MVT::i32); 240 return true; 241} 242 243/// Select instructions not customized! Used for 244/// expanded, promoted and normal instructions 245SDNode* MBlazeDAGToDAGISel::Select(SDNode *Node) { 246 unsigned Opcode = Node->getOpcode(); 247 DebugLoc dl = Node->getDebugLoc(); 248 249 // Dump information about the Node being selected 250 DEBUG(errs() << "Selecting: "; Node->dump(CurDAG); errs() << "\n"); 251 252 // If we have a custom node, we already have selected! 253 if (Node->isMachineOpcode()) { 254 DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n"); 255 return NULL; 256 } 257 258 /// 259 // Instruction Selection not handled by the auto-generated 260 // tablegen selection should be handled here. 261 /// 262 switch(Opcode) { 263 default: break; 264 265 // Get target GOT address. 266 case ISD::GLOBAL_OFFSET_TABLE: 267 return getGlobalBaseReg(); 268 269 case ISD::FrameIndex: { 270 SDValue imm = CurDAG->getTargetConstant(0, MVT::i32); 271 int FI = dyn_cast<FrameIndexSDNode>(Node)->getIndex(); 272 EVT VT = Node->getValueType(0); 273 SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT); 274 unsigned Opc = MBlaze::ADDI; 275 if (Node->hasOneUse()) 276 return CurDAG->SelectNodeTo(Node, Opc, VT, TFI, imm); 277 return CurDAG->getMachineNode(Opc, dl, VT, TFI, imm); 278 } 279 280 281 /// Handle direct and indirect calls when using PIC. On PIC, when 282 /// GOT is smaller than about 64k (small code) the GA target is 283 /// loaded with only one instruction. Otherwise GA's target must 284 /// be loaded with 3 instructions. 285 case MBlazeISD::JmpLink: { 286 if (TM.getRelocationModel() == Reloc::PIC_) { 287 SDValue Chain = Node->getOperand(0); 288 SDValue Callee = Node->getOperand(1); 289 SDValue R20Reg = CurDAG->getRegister(MBlaze::R20, MVT::i32); 290 SDValue InFlag(0, 0); 291 292 if ( (isa<GlobalAddressSDNode>(Callee)) || 293 (isa<ExternalSymbolSDNode>(Callee)) ) 294 { 295 /// Direct call for global addresses and external symbols 296 SDValue GPReg = CurDAG->getRegister(MBlaze::R15, MVT::i32); 297 298 // Use load to get GOT target 299 SDValue Ops[] = { Callee, GPReg, Chain }; 300 SDValue Load = SDValue(CurDAG->getMachineNode(MBlaze::LW, dl, 301 MVT::i32, MVT::Other, Ops, 3), 0); 302 Chain = Load.getValue(1); 303 304 // Call target must be on T9 305 Chain = CurDAG->getCopyToReg(Chain, dl, R20Reg, Load, InFlag); 306 } else 307 /// Indirect call 308 Chain = CurDAG->getCopyToReg(Chain, dl, R20Reg, Callee, InFlag); 309 310 // Emit Jump and Link Register 311 SDNode *ResNode = CurDAG->getMachineNode(MBlaze::BRLID, dl, MVT::Other, 312 MVT::Flag, R20Reg, Chain); 313 Chain = SDValue(ResNode, 0); 314 InFlag = SDValue(ResNode, 1); 315 ReplaceUses(SDValue(Node, 0), Chain); 316 ReplaceUses(SDValue(Node, 1), InFlag); 317 return ResNode; 318 } 319 } 320 } 321 322 // Select the default instruction 323 SDNode *ResNode = SelectCode(Node); 324 325 DEBUG(errs() << "=> "); 326 if (ResNode == NULL || ResNode == Node) 327 DEBUG(Node->dump(CurDAG)); 328 else 329 DEBUG(ResNode->dump(CurDAG)); 330 DEBUG(errs() << "\n"); 331 return ResNode; 332} 333 334/// createMBlazeISelDag - This pass converts a legalized DAG into a 335/// MBlaze-specific DAG, ready for instruction scheduling. 336FunctionPass *llvm::createMBlazeISelDag(MBlazeTargetMachine &TM) { 337 return new MBlazeDAGToDAGISel(TM); 338} 339