Initial support for inline asm memory operand constraints.
[oota-llvm.git] / lib / Target / Mips / MipsISelDAGToDAG.cpp
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"
35 using 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 //===----------------------------------------------------------------------===//
45 namespace {
46
47 class 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
56 public:
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
67 private:
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   SDNode *SelectLoadFp64(SDNode *N);
90   SDNode *SelectStoreFp64(SDNode *N);
91
92   // getI32Imm - Return a target constant with the specified
93   // value, of type i32.
94   inline SDValue getI32Imm(unsigned Imm) {
95     return CurDAG->getTargetConstant(Imm, MVT::i32);
96   }
97
98   virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
99                                             char ConstraintCode,
100                                             std::vector<SDValue> &OutOps);
101 };
102
103 }
104
105
106 /// getGlobalBaseReg - Output the instructions required to put the
107 /// GOT address into a register.
108 SDNode *MipsDAGToDAGISel::getGlobalBaseReg() {
109   unsigned GlobalBaseReg = getInstrInfo()->getGlobalBaseReg(MF);
110   return CurDAG->getRegister(GlobalBaseReg, TLI.getPointerTy()).getNode();
111 }
112
113 /// ComplexPattern used on MipsInstrInfo
114 /// Used on Mips Load/Store instructions
115 bool MipsDAGToDAGISel::
116 SelectAddr(SDValue Addr, SDValue &Offset, SDValue &Base) {
117   // if Address is FI, get the TargetFrameIndex.
118   if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
119     Base   = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
120     Offset = CurDAG->getTargetConstant(0, MVT::i32);
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(Mips::GP, MVT::i32);
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(Mips::GP, MVT::i32);
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(), MVT::i32);
151       else
152         Base = Addr.getOperand(0);
153
154       Offset = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32);
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 (dyn_cast<ConstantPoolSDNode>(LoVal.getOperand(0))) {
174         Base = Addr.getOperand(0);
175         Offset = LoVal.getOperand(0);
176         return true;
177       }
178     }
179   }
180
181   Base   = Addr;
182   Offset = CurDAG->getTargetConstant(0, MVT::i32);
183   return true;
184 }
185
186 SDNode *MipsDAGToDAGISel::SelectLoadFp64(SDNode *N) {
187   MVT::SimpleValueType NVT =
188     N->getValueType(0).getSimpleVT().SimpleTy;
189
190   if (!Subtarget.isMips1() || NVT != MVT::f64)
191     return NULL;
192
193   LoadSDNode *LN = cast<LoadSDNode>(N);
194   if (LN->getExtensionType() != ISD::NON_EXTLOAD ||
195       LN->getAddressingMode() != ISD::UNINDEXED)
196     return NULL;
197
198   SDValue Chain = N->getOperand(0);
199   SDValue N1 = N->getOperand(1);
200   SDValue Offset0, Offset1, Base;
201
202   if (!SelectAddr(N1, Offset0, Base) ||
203       N1.getValueType() != MVT::i32)
204     return NULL;
205
206   MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1);
207   MemRefs0[0] = cast<MemSDNode>(N)->getMemOperand();
208   DebugLoc dl = N->getDebugLoc();
209
210   // The second load should start after for 4 bytes.
211   if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Offset0))
212     Offset1 = CurDAG->getTargetConstant(C->getSExtValue()+4, MVT::i32);
213   else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Offset0))
214     Offset1 = CurDAG->getTargetConstantPool(CP->getConstVal(),
215                                             MVT::i32,
216                                             CP->getAlignment(),
217                                             CP->getOffset()+4,
218                                             CP->getTargetFlags());
219   else
220     return NULL;
221
222   // Choose the offsets depending on the endianess
223   if (TM.getTargetData()->isBigEndian())
224     std::swap(Offset0, Offset1);
225
226   // Instead of:
227   //    ldc $f0, X($3)
228   // Generate:
229   //    lwc $f0, X($3)
230   //    lwc $f1, X+4($3)
231   SDNode *LD0 = CurDAG->getMachineNode(Mips::LWC1, dl, MVT::f32,
232                                     MVT::Other, Offset0, Base, Chain);
233   SDValue Undef = SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
234                                                  dl, NVT), 0);
235   SDValue I0 = CurDAG->getTargetInsertSubreg(Mips::sub_fpeven, dl,
236                             MVT::f64, Undef, SDValue(LD0, 0));
237
238   SDNode *LD1 = CurDAG->getMachineNode(Mips::LWC1, dl, MVT::f32,
239                           MVT::Other, Offset1, Base, SDValue(LD0, 1));
240   SDValue I1 = CurDAG->getTargetInsertSubreg(Mips::sub_fpodd, dl,
241                             MVT::f64, I0, SDValue(LD1, 0));
242
243   ReplaceUses(SDValue(N, 0), I1);
244   ReplaceUses(SDValue(N, 1), Chain);
245   cast<MachineSDNode>(LD0)->setMemRefs(MemRefs0, MemRefs0 + 1);
246   cast<MachineSDNode>(LD1)->setMemRefs(MemRefs0, MemRefs0 + 1);
247   return I1.getNode();
248 }
249
250 SDNode *MipsDAGToDAGISel::SelectStoreFp64(SDNode *N) {
251
252   if (!Subtarget.isMips1() ||
253       N->getOperand(1).getValueType() != MVT::f64)
254     return NULL;
255
256   SDValue Chain = N->getOperand(0);
257
258   StoreSDNode *SN = cast<StoreSDNode>(N);
259   if (SN->isTruncatingStore() || SN->getAddressingMode() != ISD::UNINDEXED)
260     return NULL;
261
262   SDValue N1 = N->getOperand(1);
263   SDValue N2 = N->getOperand(2);
264   SDValue Offset0, Offset1, Base;
265
266   if (!SelectAddr(N2, Offset0, Base) ||
267       N1.getValueType() != MVT::f64 ||
268       N2.getValueType() != MVT::i32)
269     return NULL;
270
271   MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1);
272   MemRefs0[0] = cast<MemSDNode>(N)->getMemOperand();
273   DebugLoc dl = N->getDebugLoc();
274
275   // Get the even and odd part from the f64 register
276   SDValue FPOdd = CurDAG->getTargetExtractSubreg(Mips::sub_fpodd,
277                                                  dl, MVT::f32, N1);
278   SDValue FPEven = CurDAG->getTargetExtractSubreg(Mips::sub_fpeven,
279                                                  dl, MVT::f32, N1);
280
281   // The second store should start after for 4 bytes.
282   if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Offset0))
283     Offset1 = CurDAG->getTargetConstant(C->getSExtValue()+4, MVT::i32);
284   else
285     return NULL;
286
287   // Choose the offsets depending on the endianess
288   if (TM.getTargetData()->isBigEndian())
289     std::swap(Offset0, Offset1);
290
291   // Instead of:
292   //    sdc $f0, X($3)
293   // Generate:
294   //    swc $f0, X($3)
295   //    swc $f1, X+4($3)
296   SDValue Ops0[] = { FPEven, Offset0, Base, Chain };
297   Chain = SDValue(CurDAG->getMachineNode(Mips::SWC1, dl,
298                                        MVT::Other, Ops0, 4), 0);
299   cast<MachineSDNode>(Chain.getNode())->setMemRefs(MemRefs0, MemRefs0 + 1);
300
301   SDValue Ops1[] = { FPOdd, Offset1, Base, Chain };
302   Chain = SDValue(CurDAG->getMachineNode(Mips::SWC1, dl,
303                                        MVT::Other, Ops1, 4), 0);
304   cast<MachineSDNode>(Chain.getNode())->setMemRefs(MemRefs0, MemRefs0 + 1);
305
306   ReplaceUses(SDValue(N, 0), Chain);
307   return Chain.getNode();
308 }
309
310 /// Select instructions not customized! Used for
311 /// expanded, promoted and normal instructions
312 SDNode* MipsDAGToDAGISel::Select(SDNode *Node) {
313   unsigned Opcode = Node->getOpcode();
314   DebugLoc dl = Node->getDebugLoc();
315
316   // Dump information about the Node being selected
317   DEBUG(errs() << "Selecting: "; Node->dump(CurDAG); errs() << "\n");
318
319   // If we have a custom node, we already have selected!
320   if (Node->isMachineOpcode()) {
321     DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n");
322     return NULL;
323   }
324
325   ///
326   // Instruction Selection not handled by the auto-generated
327   // tablegen selection should be handled here.
328   ///
329   switch(Opcode) {
330     default: break;
331
332     case ISD::SUBE:
333     case ISD::ADDE: {
334       SDValue InFlag = Node->getOperand(2), CmpLHS;
335       unsigned Opc = InFlag.getOpcode(); (void)Opc;
336       assert(((Opc == ISD::ADDC || Opc == ISD::ADDE) ||
337               (Opc == ISD::SUBC || Opc == ISD::SUBE)) &&
338              "(ADD|SUB)E flag operand must come from (ADD|SUB)C/E insn");
339
340       unsigned MOp;
341       if (Opcode == ISD::ADDE) {
342         CmpLHS = InFlag.getValue(0);
343         MOp = Mips::ADDu;
344       } else {
345         CmpLHS = InFlag.getOperand(0);
346         MOp = Mips::SUBu;
347       }
348
349       SDValue Ops[] = { CmpLHS, InFlag.getOperand(1) };
350
351       SDValue LHS = Node->getOperand(0);
352       SDValue RHS = Node->getOperand(1);
353
354       EVT VT = LHS.getValueType();
355       SDNode *Carry = CurDAG->getMachineNode(Mips::SLTu, dl, VT, Ops, 2);
356       SDNode *AddCarry = CurDAG->getMachineNode(Mips::ADDu, dl, VT,
357                                                 SDValue(Carry,0), RHS);
358
359       return CurDAG->SelectNodeTo(Node, MOp, VT, MVT::Glue,
360                                   LHS, SDValue(AddCarry,0));
361     }
362
363     /// Mul with two results
364     case ISD::SMUL_LOHI:
365     case ISD::UMUL_LOHI: {
366       SDValue Op1 = Node->getOperand(0);
367       SDValue Op2 = Node->getOperand(1);
368
369       unsigned Op;
370       Op = (Opcode == ISD::UMUL_LOHI ? Mips::MULTu : Mips::MULT);
371
372       SDNode *Mul = CurDAG->getMachineNode(Op, dl, MVT::Glue, Op1, Op2);
373
374       SDValue InFlag = SDValue(Mul, 0);
375       SDNode *Lo = CurDAG->getMachineNode(Mips::MFLO, dl, MVT::i32,
376                                           MVT::Glue, InFlag);
377       InFlag = SDValue(Lo,1);
378       SDNode *Hi = CurDAG->getMachineNode(Mips::MFHI, dl, MVT::i32, InFlag);
379
380       if (!SDValue(Node, 0).use_empty())
381         ReplaceUses(SDValue(Node, 0), SDValue(Lo,0));
382
383       if (!SDValue(Node, 1).use_empty())
384         ReplaceUses(SDValue(Node, 1), SDValue(Hi,0));
385
386       return NULL;
387     }
388
389     /// Special Muls
390     case ISD::MUL:
391       if (Subtarget.isMips32())
392         break;
393     case ISD::MULHS:
394     case ISD::MULHU: {
395       SDValue MulOp1 = Node->getOperand(0);
396       SDValue MulOp2 = Node->getOperand(1);
397
398       unsigned MulOp  = (Opcode == ISD::MULHU ? Mips::MULTu : Mips::MULT);
399       SDNode *MulNode = CurDAG->getMachineNode(MulOp, dl,
400                                                MVT::Glue, MulOp1, MulOp2);
401
402       SDValue InFlag = SDValue(MulNode, 0);
403
404       if (Opcode == ISD::MUL)
405         return CurDAG->getMachineNode(Mips::MFLO, dl, MVT::i32, InFlag);
406       else
407         return CurDAG->getMachineNode(Mips::MFHI, dl, MVT::i32, InFlag);
408     }
409
410     // Get target GOT address.
411     case ISD::GLOBAL_OFFSET_TABLE:
412       return getGlobalBaseReg();
413
414     case ISD::ConstantFP: {
415       ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(Node);
416       if (Node->getValueType(0) == MVT::f64 && CN->isExactlyValue(+0.0)) {
417         SDValue Zero = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl,
418                                         Mips::ZERO, MVT::i32);
419         SDValue Undef = SDValue(
420           CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, MVT::f64), 0);
421         SDNode *MTC = CurDAG->getMachineNode(Mips::MTC1, dl, MVT::f32, Zero);
422         SDValue I0 = CurDAG->getTargetInsertSubreg(Mips::sub_fpeven, dl,
423                             MVT::f64, Undef, SDValue(MTC, 0));
424         SDValue I1 = CurDAG->getTargetInsertSubreg(Mips::sub_fpodd, dl,
425                             MVT::f64, I0, SDValue(MTC, 0));
426         ReplaceUses(SDValue(Node, 0), I1);
427         return I1.getNode();
428       }
429       break;
430     }
431
432     case ISD::LOAD:
433       if (SDNode *ResNode = SelectLoadFp64(Node))
434         return ResNode;
435       // Other cases are autogenerated.
436       break;
437
438     case ISD::STORE:
439       if (SDNode *ResNode = SelectStoreFp64(Node))
440         return ResNode;
441       // Other cases are autogenerated.
442       break;
443
444     case MipsISD::ThreadPointer: {
445       unsigned SrcReg = Mips::HWR29;
446       unsigned DestReg = Mips::V1;
447       SDNode *Rdhwr = CurDAG->getMachineNode(Mips::RDHWR, Node->getDebugLoc(),
448           Node->getValueType(0), CurDAG->getRegister(SrcReg, MVT::i32));
449       SDValue Chain = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, DestReg,
450           SDValue(Rdhwr, 0));
451       SDValue ResNode = CurDAG->getCopyFromReg(Chain, dl, DestReg, MVT::i32);
452       ReplaceUses(SDValue(Node, 0), ResNode);
453       return ResNode.getNode();
454     }
455   }
456
457   // Select the default instruction
458   SDNode *ResNode = SelectCode(Node);
459
460   DEBUG(errs() << "=> ");
461   if (ResNode == NULL || ResNode == Node)
462     DEBUG(Node->dump(CurDAG));
463   else
464     DEBUG(ResNode->dump(CurDAG));
465   DEBUG(errs() << "\n");
466   return ResNode;
467 }
468
469 bool MipsDAGToDAGISel::
470 SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
471                              std::vector<SDValue> &OutOps) {
472   assert(ConstraintCode == 'm' && "unexpected asm memory constraint");
473   OutOps.push_back(Op);
474   return false;
475 }
476
477 /// createMipsISelDag - This pass converts a legalized DAG into a
478 /// MIPS-specific DAG, ready for instruction scheduling.
479 FunctionPass *llvm::createMipsISelDag(MipsTargetMachine &TM) {
480   return new MipsDAGToDAGISel(TM);
481 }