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" |
Wesley Peck | a70f28c | 2010-02-23 19:15:24 +0000 | [diff] [blame] | 16 | #include "MBlazeMachineFunction.h" |
| 17 | #include "MBlazeRegisterInfo.h" |
| 18 | #include "MBlazeSubtarget.h" |
| 19 | #include "MBlazeTargetMachine.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" |
| 35 | using 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 | //===----------------------------------------------------------------------===// |
| 45 | namespace { |
| 46 | |
| 47 | class 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 | |
| 56 | public: |
| 57 | explicit MBlazeDAGToDAGISel(MBlazeTargetMachine &tm) : |
| 58 | SelectionDAGISel(tm), |
| 59 | TM(tm), Subtarget(tm.getSubtarget<MBlazeSubtarget>()) {} |
| 60 | |
Wesley Peck | a70f28c | 2010-02-23 19:15:24 +0000 | [diff] [blame] | 61 | // Pass Name |
| 62 | virtual const char *getPassName() const { |
| 63 | return "MBlaze DAG->DAG Pattern Instruction Selection"; |
| 64 | } |
| 65 | private: |
| 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 | |
Wesley Peck | a70f28c | 2010-02-23 19:15:24 +0000 | [diff] [blame] | 84 | // Address Selection |
Chris Lattner | 52a261b | 2010-09-21 20:31:19 +0000 | [diff] [blame] | 85 | bool SelectAddrRegReg(SDValue N, SDValue &Base, SDValue &Index); |
| 86 | bool SelectAddrRegImm(SDValue N, SDValue &Disp, SDValue &Base); |
Wesley Peck | a70f28c | 2010-02-23 19:15:24 +0000 | [diff] [blame] | 87 | |
| 88 | // getI32Imm - Return a target constant with the specified value, of type i32. |
| 89 | inline SDValue getI32Imm(unsigned Imm) { |
| 90 | return CurDAG->getTargetConstant(Imm, MVT::i32); |
| 91 | } |
Wesley Peck | a70f28c | 2010-02-23 19:15:24 +0000 | [diff] [blame] | 92 | }; |
| 93 | |
| 94 | } |
| 95 | |
| 96 | /// isIntS32Immediate - This method tests to see if the node is either a 32-bit |
| 97 | /// or 64-bit immediate, and if the value can be accurately represented as a |
| 98 | /// sign extension from a 32-bit value. If so, this returns true and the |
| 99 | /// immediate. |
| 100 | static bool isIntS32Immediate(SDNode *N, int32_t &Imm) { |
| 101 | unsigned Opc = N->getOpcode(); |
| 102 | if (Opc != ISD::Constant) |
| 103 | return false; |
| 104 | |
| 105 | Imm = (int32_t)cast<ConstantSDNode>(N)->getZExtValue(); |
| 106 | if (N->getValueType(0) == MVT::i32) |
| 107 | return Imm == (int32_t)cast<ConstantSDNode>(N)->getZExtValue(); |
| 108 | else |
| 109 | return Imm == (int64_t)cast<ConstantSDNode>(N)->getZExtValue(); |
| 110 | } |
| 111 | |
| 112 | static bool isIntS32Immediate(SDValue Op, int32_t &Imm) { |
| 113 | return isIntS32Immediate(Op.getNode(), Imm); |
| 114 | } |
| 115 | |
Wesley Peck | a70f28c | 2010-02-23 19:15:24 +0000 | [diff] [blame] | 116 | |
| 117 | /// SelectAddressRegReg - Given the specified addressed, check to see if it |
| 118 | /// can be represented as an indexed [r+r] operation. Returns false if it |
| 119 | /// can be more efficiently represented with [r+imm]. |
| 120 | bool MBlazeDAGToDAGISel:: |
Chris Lattner | 52a261b | 2010-09-21 20:31:19 +0000 | [diff] [blame] | 121 | SelectAddrRegReg(SDValue N, SDValue &Base, SDValue &Index) { |
Wesley Peck | a70f28c | 2010-02-23 19:15:24 +0000 | [diff] [blame] | 122 | if (N.getOpcode() == ISD::FrameIndex) return false; |
| 123 | if (N.getOpcode() == ISD::TargetExternalSymbol || |
| 124 | N.getOpcode() == ISD::TargetGlobalAddress) |
| 125 | return false; // direct calls. |
| 126 | |
Wesley Peck | a70f28c | 2010-02-23 19:15:24 +0000 | [diff] [blame] | 127 | int32_t imm = 0; |
| 128 | if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) { |
| 129 | if (isIntS32Immediate(N.getOperand(1), imm)) |
| 130 | return false; // r+i |
| 131 | |
Wesley Peck | c2bf2bb | 2010-03-06 23:23:12 +0000 | [diff] [blame] | 132 | if (N.getOperand(0).getOpcode() == ISD::TargetJumpTable || |
| 133 | N.getOperand(1).getOpcode() == ISD::TargetJumpTable) |
| 134 | return false; // jump tables. |
| 135 | |
Wesley Peck | 41400da | 2010-11-12 23:30:17 +0000 | [diff] [blame] | 136 | Base = N.getOperand(0); |
| 137 | Index = N.getOperand(1); |
Wesley Peck | a70f28c | 2010-02-23 19:15:24 +0000 | [diff] [blame] | 138 | return true; |
| 139 | } |
| 140 | |
| 141 | return false; |
| 142 | } |
| 143 | |
| 144 | /// Returns true if the address N can be represented by a base register plus |
| 145 | /// a signed 32-bit displacement [r+imm], and if it is not better |
| 146 | /// represented as reg+reg. |
| 147 | bool MBlazeDAGToDAGISel:: |
Wesley Peck | 41400da | 2010-11-12 23:30:17 +0000 | [diff] [blame] | 148 | SelectAddrRegImm(SDValue N, SDValue &Base, SDValue &Disp) { |
Wesley Peck | a70f28c | 2010-02-23 19:15:24 +0000 | [diff] [blame] | 149 | // If this can be more profitably realized as r+r, fail. |
Wesley Peck | 41400da | 2010-11-12 23:30:17 +0000 | [diff] [blame] | 150 | if (SelectAddrRegReg(N, Base, Disp)) |
Wesley Peck | a70f28c | 2010-02-23 19:15:24 +0000 | [diff] [blame] | 151 | return false; |
| 152 | |
| 153 | if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) { |
| 154 | int32_t imm = 0; |
| 155 | if (isIntS32Immediate(N.getOperand(1), imm)) { |
| 156 | Disp = CurDAG->getTargetConstant(imm, MVT::i32); |
| 157 | if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N.getOperand(0))) { |
| 158 | Base = CurDAG->getTargetFrameIndex(FI->getIndex(), N.getValueType()); |
| 159 | } else { |
| 160 | Base = N.getOperand(0); |
| 161 | } |
Wesley Peck | a70f28c | 2010-02-23 19:15:24 +0000 | [diff] [blame] | 162 | return true; // [r+i] |
| 163 | } |
| 164 | } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N)) { |
| 165 | // Loading from a constant address. |
| 166 | uint32_t Imm = CN->getZExtValue(); |
| 167 | Disp = CurDAG->getTargetConstant(Imm, CN->getValueType(0)); |
| 168 | Base = CurDAG->getRegister(MBlaze::R0, CN->getValueType(0)); |
Wesley Peck | a70f28c | 2010-02-23 19:15:24 +0000 | [diff] [blame] | 169 | return true; |
| 170 | } |
| 171 | |
| 172 | Disp = CurDAG->getTargetConstant(0, TM.getTargetLowering()->getPointerTy()); |
| 173 | if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N)) |
| 174 | Base = CurDAG->getTargetFrameIndex(FI->getIndex(), N.getValueType()); |
| 175 | else |
| 176 | Base = N; |
| 177 | return true; // [r+0] |
| 178 | } |
| 179 | |
| 180 | /// getGlobalBaseReg - Output the instructions required to put the |
| 181 | /// GOT address into a register. |
| 182 | SDNode *MBlazeDAGToDAGISel::getGlobalBaseReg() { |
| 183 | unsigned GlobalBaseReg = getInstrInfo()->getGlobalBaseReg(MF); |
| 184 | return CurDAG->getRegister(GlobalBaseReg, TLI.getPointerTy()).getNode(); |
| 185 | } |
| 186 | |
Wesley Peck | a70f28c | 2010-02-23 19:15:24 +0000 | [diff] [blame] | 187 | /// Select instructions not customized! Used for |
| 188 | /// expanded, promoted and normal instructions |
| 189 | SDNode* MBlazeDAGToDAGISel::Select(SDNode *Node) { |
| 190 | unsigned Opcode = Node->getOpcode(); |
| 191 | DebugLoc dl = Node->getDebugLoc(); |
| 192 | |
Wesley Peck | a70f28c | 2010-02-23 19:15:24 +0000 | [diff] [blame] | 193 | // If we have a custom node, we already have selected! |
Wesley Peck | 0a67d92 | 2010-11-08 19:40:01 +0000 | [diff] [blame] | 194 | if (Node->isMachineOpcode()) |
Wesley Peck | a70f28c | 2010-02-23 19:15:24 +0000 | [diff] [blame] | 195 | return NULL; |
Wesley Peck | a70f28c | 2010-02-23 19:15:24 +0000 | [diff] [blame] | 196 | |
| 197 | /// |
| 198 | // Instruction Selection not handled by the auto-generated |
| 199 | // tablegen selection should be handled here. |
| 200 | /// |
Wesley Peck | 0a67d92 | 2010-11-08 19:40:01 +0000 | [diff] [blame] | 201 | switch (Opcode) { |
Wesley Peck | a70f28c | 2010-02-23 19:15:24 +0000 | [diff] [blame] | 202 | default: break; |
| 203 | |
| 204 | // Get target GOT address. |
| 205 | case ISD::GLOBAL_OFFSET_TABLE: |
| 206 | return getGlobalBaseReg(); |
| 207 | |
| 208 | case ISD::FrameIndex: { |
| 209 | SDValue imm = CurDAG->getTargetConstant(0, MVT::i32); |
| 210 | int FI = dyn_cast<FrameIndexSDNode>(Node)->getIndex(); |
| 211 | EVT VT = Node->getValueType(0); |
| 212 | SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT); |
Wesley Peck | a7c7b9d | 2010-12-12 22:02:31 +0000 | [diff] [blame] | 213 | unsigned Opc = MBlaze::ADDIK; |
Wesley Peck | a70f28c | 2010-02-23 19:15:24 +0000 | [diff] [blame] | 214 | if (Node->hasOneUse()) |
| 215 | return CurDAG->SelectNodeTo(Node, Opc, VT, TFI, imm); |
| 216 | return CurDAG->getMachineNode(Opc, dl, VT, TFI, imm); |
| 217 | } |
| 218 | |
| 219 | |
| 220 | /// Handle direct and indirect calls when using PIC. On PIC, when |
| 221 | /// GOT is smaller than about 64k (small code) the GA target is |
| 222 | /// loaded with only one instruction. Otherwise GA's target must |
| 223 | /// be loaded with 3 instructions. |
| 224 | case MBlazeISD::JmpLink: { |
| 225 | if (TM.getRelocationModel() == Reloc::PIC_) { |
| 226 | SDValue Chain = Node->getOperand(0); |
| 227 | SDValue Callee = Node->getOperand(1); |
| 228 | SDValue R20Reg = CurDAG->getRegister(MBlaze::R20, MVT::i32); |
| 229 | SDValue InFlag(0, 0); |
| 230 | |
Wesley Peck | 0a67d92 | 2010-11-08 19:40:01 +0000 | [diff] [blame] | 231 | if ((isa<GlobalAddressSDNode>(Callee)) || |
| 232 | (isa<ExternalSymbolSDNode>(Callee))) |
Wesley Peck | a70f28c | 2010-02-23 19:15:24 +0000 | [diff] [blame] | 233 | { |
| 234 | /// Direct call for global addresses and external symbols |
| 235 | SDValue GPReg = CurDAG->getRegister(MBlaze::R15, MVT::i32); |
| 236 | |
| 237 | // Use load to get GOT target |
| 238 | SDValue Ops[] = { Callee, GPReg, Chain }; |
| 239 | SDValue Load = SDValue(CurDAG->getMachineNode(MBlaze::LW, dl, |
| 240 | MVT::i32, MVT::Other, Ops, 3), 0); |
| 241 | Chain = Load.getValue(1); |
| 242 | |
| 243 | // Call target must be on T9 |
| 244 | Chain = CurDAG->getCopyToReg(Chain, dl, R20Reg, Load, InFlag); |
| 245 | } else |
| 246 | /// Indirect call |
| 247 | Chain = CurDAG->getCopyToReg(Chain, dl, R20Reg, Callee, InFlag); |
| 248 | |
| 249 | // Emit Jump and Link Register |
| 250 | SDNode *ResNode = CurDAG->getMachineNode(MBlaze::BRLID, dl, MVT::Other, |
Chris Lattner | f1b4eaf | 2010-12-21 02:38:05 +0000 | [diff] [blame] | 251 | MVT::Glue, R20Reg, Chain); |
Wesley Peck | a70f28c | 2010-02-23 19:15:24 +0000 | [diff] [blame] | 252 | Chain = SDValue(ResNode, 0); |
| 253 | InFlag = SDValue(ResNode, 1); |
| 254 | ReplaceUses(SDValue(Node, 0), Chain); |
| 255 | ReplaceUses(SDValue(Node, 1), InFlag); |
| 256 | return ResNode; |
| 257 | } |
| 258 | } |
| 259 | } |
| 260 | |
| 261 | // Select the default instruction |
| 262 | SDNode *ResNode = SelectCode(Node); |
| 263 | |
Chris Lattner | 7c306da | 2010-03-02 06:34:30 +0000 | [diff] [blame] | 264 | DEBUG(errs() << "=> "); |
Wesley Peck | a70f28c | 2010-02-23 19:15:24 +0000 | [diff] [blame] | 265 | if (ResNode == NULL || ResNode == Node) |
| 266 | DEBUG(Node->dump(CurDAG)); |
| 267 | else |
| 268 | DEBUG(ResNode->dump(CurDAG)); |
| 269 | DEBUG(errs() << "\n"); |
Wesley Peck | a70f28c | 2010-02-23 19:15:24 +0000 | [diff] [blame] | 270 | return ResNode; |
| 271 | } |
| 272 | |
| 273 | /// createMBlazeISelDag - This pass converts a legalized DAG into a |
| 274 | /// MBlaze-specific DAG, ready for instruction scheduling. |
| 275 | FunctionPass *llvm::createMBlazeISelDag(MBlazeTargetMachine &TM) { |
| 276 | return new MBlazeDAGToDAGISel(TM); |
| 277 | } |