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