[mips] Rename functions and variables to start with proper case.
[oota-llvm.git] / lib / Target / Mips / Mips16ISelDAGToDAG.cpp
1 //===-- Mips16ISelDAGToDAG.cpp - A Dag to Dag Inst Selector for Mips16 ----===//
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 // Subclass of MipsDAGToDAGISel specialized for mips16.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #define DEBUG_TYPE "mips-isel"
15 #include "Mips16ISelDAGToDAG.h"
16 #include "Mips.h"
17 #include "MCTargetDesc/MipsBaseInfo.h"
18 #include "MipsAnalyzeImmediate.h"
19 #include "MipsMachineFunction.h"
20 #include "MipsRegisterInfo.h"
21 #include "llvm/CodeGen/MachineConstantPool.h"
22 #include "llvm/CodeGen/MachineFrameInfo.h"
23 #include "llvm/CodeGen/MachineFunction.h"
24 #include "llvm/CodeGen/MachineInstrBuilder.h"
25 #include "llvm/CodeGen/MachineRegisterInfo.h"
26 #include "llvm/CodeGen/SelectionDAGNodes.h"
27 #include "llvm/IR/GlobalValue.h"
28 #include "llvm/IR/Instructions.h"
29 #include "llvm/IR/Intrinsics.h"
30 #include "llvm/IR/Type.h"
31 #include "llvm/Support/CFG.h"
32 #include "llvm/Support/Debug.h"
33 #include "llvm/Support/ErrorHandling.h"
34 #include "llvm/Support/raw_ostream.h"
35 #include "llvm/Target/TargetMachine.h"
36 using namespace llvm;
37
38 /// Select multiply instructions.
39 std::pair<SDNode*, SDNode*>
40 Mips16DAGToDAGISel::selectMULT(SDNode *N, unsigned Opc, DebugLoc DL, EVT Ty,
41                                bool HasLo, bool HasHi) {
42   SDNode *Lo = 0, *Hi = 0;
43   SDNode *Mul = CurDAG->getMachineNode(Opc, DL, MVT::Glue, N->getOperand(0),
44                                        N->getOperand(1));
45   SDValue InFlag = SDValue(Mul, 0);
46
47   if (HasLo) {
48     unsigned Opcode = Mips::Mflo16;
49     Lo = CurDAG->getMachineNode(Opcode, DL, Ty, MVT::Glue, InFlag);
50     InFlag = SDValue(Lo, 1);
51   }
52   if (HasHi) {
53     unsigned Opcode = Mips::Mfhi16;
54     Hi = CurDAG->getMachineNode(Opcode, DL, Ty, InFlag);
55   }
56   return std::make_pair(Lo, Hi);
57 }
58
59 void Mips16DAGToDAGISel::initGlobalBaseReg(MachineFunction &MF) {
60   MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
61
62   if (!MipsFI->globalBaseRegSet())
63     return;
64
65   MachineBasicBlock &MBB = MF.front();
66   MachineBasicBlock::iterator I = MBB.begin();
67   MachineRegisterInfo &RegInfo = MF.getRegInfo();
68   const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
69   DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc();
70   unsigned V0, V1, V2, GlobalBaseReg = MipsFI->getGlobalBaseReg();
71   const TargetRegisterClass *RC =
72     (const TargetRegisterClass*)&Mips::CPU16RegsRegClass;
73
74   V0 = RegInfo.createVirtualRegister(RC);
75   V1 = RegInfo.createVirtualRegister(RC);
76   V2 = RegInfo.createVirtualRegister(RC);
77
78   BuildMI(MBB, I, DL, TII.get(Mips::LiRxImmX16), V0)
79     .addExternalSymbol("_gp_disp", MipsII::MO_ABS_HI);
80   BuildMI(MBB, I, DL, TII.get(Mips::AddiuRxPcImmX16), V1)
81     .addExternalSymbol("_gp_disp", MipsII::MO_ABS_LO);
82   BuildMI(MBB, I, DL, TII.get(Mips::SllX16), V2).addReg(V0).addImm(16);
83   BuildMI(MBB, I, DL, TII.get(Mips::AdduRxRyRz16), GlobalBaseReg)
84     .addReg(V1).addReg(V2);
85 }
86
87 // Insert instructions to initialize the Mips16 SP Alias register in the
88 // first MBB of the function.
89 //
90 void Mips16DAGToDAGISel::initMips16SPAliasReg(MachineFunction &MF) {
91   MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
92
93   if (!MipsFI->mips16SPAliasRegSet())
94     return;
95
96   MachineBasicBlock &MBB = MF.front();
97   MachineBasicBlock::iterator I = MBB.begin();
98   const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
99   DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc();
100   unsigned Mips16SPAliasReg = MipsFI->getMips16SPAliasReg();
101
102   BuildMI(MBB, I, DL, TII.get(Mips::MoveR3216), Mips16SPAliasReg)
103     .addReg(Mips::SP);
104 }
105
106 void Mips16DAGToDAGISel::processFunctionAfterISel(MachineFunction &MF) {
107   initGlobalBaseReg(MF);
108   initMips16SPAliasReg(MF);
109 }
110
111 /// getMips16SPAliasReg - Output the instructions required to put the
112 /// SP into a Mips16 accessible aliased register.
113 SDValue Mips16DAGToDAGISel::getMips16SPAliasReg() {
114   unsigned Mips16SPAliasReg =
115     MF->getInfo<MipsFunctionInfo>()->getMips16SPAliasReg();
116   return CurDAG->getRegister(Mips16SPAliasReg, TLI.getPointerTy());
117 }
118
119 void Mips16DAGToDAGISel::getMips16SPRefReg(SDNode *Parent, SDValue &AliasReg) {
120   SDValue AliasFPReg = CurDAG->getRegister(Mips::S0, TLI.getPointerTy());
121   if (Parent) {
122     switch (Parent->getOpcode()) {
123       case ISD::LOAD: {
124         LoadSDNode *SD = dyn_cast<LoadSDNode>(Parent);
125         switch (SD->getMemoryVT().getSizeInBits()) {
126         case 8:
127         case 16:
128           AliasReg = TM.getFrameLowering()->hasFP(*MF)?
129             AliasFPReg: getMips16SPAliasReg();
130           return;
131         }
132         break;
133       }
134       case ISD::STORE: {
135         StoreSDNode *SD = dyn_cast<StoreSDNode>(Parent);
136         switch (SD->getMemoryVT().getSizeInBits()) {
137         case 8:
138         case 16:
139           AliasReg = TM.getFrameLowering()->hasFP(*MF)?
140             AliasFPReg: getMips16SPAliasReg();
141           return;
142         }
143         break;
144       }
145     }
146   }
147   AliasReg = CurDAG->getRegister(Mips::SP, TLI.getPointerTy());
148   return;
149
150 }
151
152 bool Mips16DAGToDAGISel::selectAddr16(
153   SDNode *Parent, SDValue Addr, SDValue &Base, SDValue &Offset,
154   SDValue &Alias) {
155   EVT ValTy = Addr.getValueType();
156
157   Alias = CurDAG->getTargetConstant(0, ValTy);
158
159   // if Address is FI, get the TargetFrameIndex.
160   if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
161     Base   = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy);
162     Offset = CurDAG->getTargetConstant(0, ValTy);
163     getMips16SPRefReg(Parent, Alias);
164     return true;
165   }
166   // on PIC code Load GA
167   if (Addr.getOpcode() == MipsISD::Wrapper) {
168     Base   = Addr.getOperand(0);
169     Offset = Addr.getOperand(1);
170     return true;
171   }
172   if (TM.getRelocationModel() != Reloc::PIC_) {
173     if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
174         Addr.getOpcode() == ISD::TargetGlobalAddress))
175       return false;
176   }
177   // Addresses of the form FI+const or FI|const
178   if (CurDAG->isBaseWithConstantOffset(Addr)) {
179     ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1));
180     if (isInt<16>(CN->getSExtValue())) {
181
182       // If the first operand is a FI, get the TargetFI Node
183       if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>
184                                   (Addr.getOperand(0))) {
185         Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy);
186         getMips16SPRefReg(Parent, Alias);
187       }
188       else
189         Base = Addr.getOperand(0);
190
191       Offset = CurDAG->getTargetConstant(CN->getZExtValue(), ValTy);
192       return true;
193     }
194   }
195   // Operand is a result from an ADD.
196   if (Addr.getOpcode() == ISD::ADD) {
197     // When loading from constant pools, load the lower address part in
198     // the instruction itself. Example, instead of:
199     //  lui $2, %hi($CPI1_0)
200     //  addiu $2, $2, %lo($CPI1_0)
201     //  lwc1 $f0, 0($2)
202     // Generate:
203     //  lui $2, %hi($CPI1_0)
204     //  lwc1 $f0, %lo($CPI1_0)($2)
205     if (Addr.getOperand(1).getOpcode() == MipsISD::Lo ||
206         Addr.getOperand(1).getOpcode() == MipsISD::GPRel) {
207       SDValue Opnd0 = Addr.getOperand(1).getOperand(0);
208       if (isa<ConstantPoolSDNode>(Opnd0) || isa<GlobalAddressSDNode>(Opnd0) ||
209           isa<JumpTableSDNode>(Opnd0)) {
210         Base = Addr.getOperand(0);
211         Offset = Opnd0;
212         return true;
213       }
214     }
215
216     // If an indexed floating point load/store can be emitted, return false.
217     const LSBaseSDNode *LS = dyn_cast<LSBaseSDNode>(Parent);
218
219     if (LS &&
220         (LS->getMemoryVT() == MVT::f32 || LS->getMemoryVT() == MVT::f64) &&
221         Subtarget.hasFPIdx())
222       return false;
223   }
224   Base   = Addr;
225   Offset = CurDAG->getTargetConstant(0, ValTy);
226   return true;
227 }
228
229 /// Select instructions not customized! Used for
230 /// expanded, promoted and normal instructions
231 std::pair<bool, SDNode*> Mips16DAGToDAGISel::selectNode(SDNode *Node) {
232   unsigned Opcode = Node->getOpcode();
233   DebugLoc DL = Node->getDebugLoc();
234
235   ///
236   // Instruction Selection not handled by the auto-generated
237   // tablegen selection should be handled here.
238   ///
239   EVT NodeTy = Node->getValueType(0);
240   unsigned MultOpc;
241
242   switch(Opcode) {
243   default: break;
244
245   case ISD::SUBE:
246   case ISD::ADDE: {
247     SDValue InFlag = Node->getOperand(2), CmpLHS;
248     unsigned Opc = InFlag.getOpcode(); (void)Opc;
249     assert(((Opc == ISD::ADDC || Opc == ISD::ADDE) ||
250             (Opc == ISD::SUBC || Opc == ISD::SUBE)) &&
251            "(ADD|SUB)E flag operand must come from (ADD|SUB)C/E insn");
252
253     unsigned MOp;
254     if (Opcode == ISD::ADDE) {
255       CmpLHS = InFlag.getValue(0);
256       MOp = Mips::AdduRxRyRz16;
257     } else {
258       CmpLHS = InFlag.getOperand(0);
259       MOp = Mips::SubuRxRyRz16;
260     }
261
262     SDValue Ops[] = { CmpLHS, InFlag.getOperand(1) };
263
264     SDValue LHS = Node->getOperand(0);
265     SDValue RHS = Node->getOperand(1);
266
267     EVT VT = LHS.getValueType();
268
269     unsigned Sltu_op = Mips::SltuRxRyRz16;
270     SDNode *Carry = CurDAG->getMachineNode(Sltu_op, DL, VT, Ops, 2);
271     unsigned Addu_op = Mips::AdduRxRyRz16;
272     SDNode *AddCarry = CurDAG->getMachineNode(Addu_op, DL, VT,
273                                               SDValue(Carry,0), RHS);
274
275     SDNode *Result = CurDAG->SelectNodeTo(Node, MOp, VT, MVT::Glue, LHS,
276                                           SDValue(AddCarry,0));
277     return std::make_pair(true, Result);
278   }
279
280   /// Mul with two results
281   case ISD::SMUL_LOHI:
282   case ISD::UMUL_LOHI: {
283     MultOpc = (Opcode == ISD::UMUL_LOHI ? Mips::MultuRxRy16 : Mips::MultRxRy16);
284     std::pair<SDNode*, SDNode*> LoHi = selectMULT(Node, MultOpc, DL, NodeTy,
285                                                   true, true);
286     if (!SDValue(Node, 0).use_empty())
287       ReplaceUses(SDValue(Node, 0), SDValue(LoHi.first, 0));
288
289     if (!SDValue(Node, 1).use_empty())
290       ReplaceUses(SDValue(Node, 1), SDValue(LoHi.second, 0));
291
292     return std::make_pair(true, (SDNode*)NULL);
293   }
294
295   case ISD::MULHS:
296   case ISD::MULHU: {
297     MultOpc = (Opcode == ISD::MULHU ? Mips::MultuRxRy16 : Mips::MultRxRy16);
298     SDNode *Result = selectMULT(Node, MultOpc, DL, NodeTy, false, true).second;
299     return std::make_pair(true, Result);
300   }
301   }
302
303   return std::make_pair(false, (SDNode*)NULL);
304 }
305
306 FunctionPass *llvm::createMips16ISelDag(MipsTargetMachine &TM) {
307   return new Mips16DAGToDAGISel(TM);
308 }