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