1249259Sdim//===-- MipsSEISelDAGToDAG.cpp - A Dag to Dag Inst Selector for MipsSE ----===//
2249259Sdim//
3249259Sdim//                     The LLVM Compiler Infrastructure
4249259Sdim//
5249259Sdim// This file is distributed under the University of Illinois Open Source
6249259Sdim// License. See LICENSE.TXT for details.
7249259Sdim//
8249259Sdim//===----------------------------------------------------------------------===//
9249259Sdim//
10249259Sdim// Subclass of MipsDAGToDAGISel specialized for mips32/64.
11249259Sdim//
12249259Sdim//===----------------------------------------------------------------------===//
13249259Sdim
14249259Sdim#define DEBUG_TYPE "mips-isel"
15249259Sdim#include "MipsSEISelDAGToDAG.h"
16249259Sdim#include "Mips.h"
17249259Sdim#include "MCTargetDesc/MipsBaseInfo.h"
18249259Sdim#include "MipsAnalyzeImmediate.h"
19249259Sdim#include "MipsMachineFunction.h"
20249259Sdim#include "MipsRegisterInfo.h"
21249259Sdim#include "llvm/CodeGen/MachineConstantPool.h"
22249259Sdim#include "llvm/CodeGen/MachineFrameInfo.h"
23249259Sdim#include "llvm/CodeGen/MachineFunction.h"
24249259Sdim#include "llvm/CodeGen/MachineInstrBuilder.h"
25249259Sdim#include "llvm/CodeGen/MachineRegisterInfo.h"
26249259Sdim#include "llvm/CodeGen/SelectionDAGNodes.h"
27249259Sdim#include "llvm/IR/GlobalValue.h"
28249259Sdim#include "llvm/IR/Instructions.h"
29249259Sdim#include "llvm/IR/Intrinsics.h"
30249259Sdim#include "llvm/IR/Type.h"
31249259Sdim#include "llvm/Support/CFG.h"
32249259Sdim#include "llvm/Support/Debug.h"
33249259Sdim#include "llvm/Support/ErrorHandling.h"
34249259Sdim#include "llvm/Support/raw_ostream.h"
35249259Sdim#include "llvm/Target/TargetMachine.h"
36249259Sdimusing namespace llvm;
37249259Sdim
38251662Sdimbool MipsSEDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
39251662Sdim  if (Subtarget.inMips16Mode())
40251662Sdim    return false;
41251662Sdim  return MipsDAGToDAGISel::runOnMachineFunction(MF);
42251662Sdim}
43249259Sdim
44251662Sdimvoid MipsSEDAGToDAGISel::addDSPCtrlRegOperands(bool IsDef, MachineInstr &MI,
45251662Sdim                                               MachineFunction &MF) {
46251662Sdim  MachineInstrBuilder MIB(MF, &MI);
47251662Sdim  unsigned Mask = MI.getOperand(1).getImm();
48251662Sdim  unsigned Flag = IsDef ? RegState::ImplicitDefine : RegState::Implicit;
49251662Sdim
50251662Sdim  if (Mask & 1)
51251662Sdim    MIB.addReg(Mips::DSPPos, Flag);
52251662Sdim
53251662Sdim  if (Mask & 2)
54251662Sdim    MIB.addReg(Mips::DSPSCount, Flag);
55251662Sdim
56251662Sdim  if (Mask & 4)
57251662Sdim    MIB.addReg(Mips::DSPCarry, Flag);
58251662Sdim
59251662Sdim  if (Mask & 8)
60251662Sdim    MIB.addReg(Mips::DSPOutFlag, Flag);
61251662Sdim
62251662Sdim  if (Mask & 16)
63251662Sdim    MIB.addReg(Mips::DSPCCond, Flag);
64251662Sdim
65251662Sdim  if (Mask & 32)
66251662Sdim    MIB.addReg(Mips::DSPEFI, Flag);
67251662Sdim}
68251662Sdim
69263508Sdimunsigned MipsSEDAGToDAGISel::getMSACtrlReg(const SDValue RegIdx) const {
70263508Sdim  switch (cast<ConstantSDNode>(RegIdx)->getZExtValue()) {
71263508Sdim  default:
72263508Sdim    llvm_unreachable("Could not map int to register");
73263508Sdim  case 0: return Mips::MSAIR;
74263508Sdim  case 1: return Mips::MSACSR;
75263508Sdim  case 2: return Mips::MSAAccess;
76263508Sdim  case 3: return Mips::MSASave;
77263508Sdim  case 4: return Mips::MSAModify;
78263508Sdim  case 5: return Mips::MSARequest;
79263508Sdim  case 6: return Mips::MSAMap;
80263508Sdim  case 7: return Mips::MSAUnmap;
81263508Sdim  }
82263508Sdim}
83263508Sdim
84249259Sdimbool MipsSEDAGToDAGISel::replaceUsesWithZeroReg(MachineRegisterInfo *MRI,
85249259Sdim                                                const MachineInstr& MI) {
86249259Sdim  unsigned DstReg = 0, ZeroReg = 0;
87249259Sdim
88249259Sdim  // Check if MI is "addiu $dst, $zero, 0" or "daddiu $dst, $zero, 0".
89249259Sdim  if ((MI.getOpcode() == Mips::ADDiu) &&
90249259Sdim      (MI.getOperand(1).getReg() == Mips::ZERO) &&
91249259Sdim      (MI.getOperand(2).getImm() == 0)) {
92249259Sdim    DstReg = MI.getOperand(0).getReg();
93249259Sdim    ZeroReg = Mips::ZERO;
94249259Sdim  } else if ((MI.getOpcode() == Mips::DADDiu) &&
95249259Sdim             (MI.getOperand(1).getReg() == Mips::ZERO_64) &&
96249259Sdim             (MI.getOperand(2).getImm() == 0)) {
97249259Sdim    DstReg = MI.getOperand(0).getReg();
98249259Sdim    ZeroReg = Mips::ZERO_64;
99249259Sdim  }
100249259Sdim
101249259Sdim  if (!DstReg)
102249259Sdim    return false;
103249259Sdim
104249259Sdim  // Replace uses with ZeroReg.
105249259Sdim  for (MachineRegisterInfo::use_iterator U = MRI->use_begin(DstReg),
106249259Sdim       E = MRI->use_end(); U != E;) {
107249259Sdim    MachineOperand &MO = U.getOperand();
108249259Sdim    unsigned OpNo = U.getOperandNo();
109249259Sdim    MachineInstr *MI = MO.getParent();
110249259Sdim    ++U;
111249259Sdim
112249259Sdim    // Do not replace if it is a phi's operand or is tied to def operand.
113249259Sdim    if (MI->isPHI() || MI->isRegTiedToDefOperand(OpNo) || MI->isPseudo())
114249259Sdim      continue;
115249259Sdim
116249259Sdim    MO.setReg(ZeroReg);
117249259Sdim  }
118249259Sdim
119249259Sdim  return true;
120249259Sdim}
121249259Sdim
122249259Sdimvoid MipsSEDAGToDAGISel::initGlobalBaseReg(MachineFunction &MF) {
123249259Sdim  MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
124249259Sdim
125249259Sdim  if (!MipsFI->globalBaseRegSet())
126249259Sdim    return;
127249259Sdim
128249259Sdim  MachineBasicBlock &MBB = MF.front();
129249259Sdim  MachineBasicBlock::iterator I = MBB.begin();
130249259Sdim  MachineRegisterInfo &RegInfo = MF.getRegInfo();
131249259Sdim  const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
132249259Sdim  DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc();
133249259Sdim  unsigned V0, V1, GlobalBaseReg = MipsFI->getGlobalBaseReg();
134249259Sdim  const TargetRegisterClass *RC;
135249259Sdim
136249259Sdim  if (Subtarget.isABI_N64())
137263508Sdim    RC = (const TargetRegisterClass*)&Mips::GPR64RegClass;
138249259Sdim  else
139263508Sdim    RC = (const TargetRegisterClass*)&Mips::GPR32RegClass;
140249259Sdim
141249259Sdim  V0 = RegInfo.createVirtualRegister(RC);
142249259Sdim  V1 = RegInfo.createVirtualRegister(RC);
143249259Sdim
144249259Sdim  if (Subtarget.isABI_N64()) {
145249259Sdim    MF.getRegInfo().addLiveIn(Mips::T9_64);
146249259Sdim    MBB.addLiveIn(Mips::T9_64);
147249259Sdim
148249259Sdim    // lui $v0, %hi(%neg(%gp_rel(fname)))
149249259Sdim    // daddu $v1, $v0, $t9
150249259Sdim    // daddiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname)))
151249259Sdim    const GlobalValue *FName = MF.getFunction();
152249259Sdim    BuildMI(MBB, I, DL, TII.get(Mips::LUi64), V0)
153249259Sdim      .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI);
154249259Sdim    BuildMI(MBB, I, DL, TII.get(Mips::DADDu), V1).addReg(V0)
155249259Sdim      .addReg(Mips::T9_64);
156249259Sdim    BuildMI(MBB, I, DL, TII.get(Mips::DADDiu), GlobalBaseReg).addReg(V1)
157249259Sdim      .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO);
158249259Sdim    return;
159249259Sdim  }
160249259Sdim
161249259Sdim  if (MF.getTarget().getRelocationModel() == Reloc::Static) {
162249259Sdim    // Set global register to __gnu_local_gp.
163249259Sdim    //
164249259Sdim    // lui   $v0, %hi(__gnu_local_gp)
165249259Sdim    // addiu $globalbasereg, $v0, %lo(__gnu_local_gp)
166249259Sdim    BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0)
167249259Sdim      .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_HI);
168249259Sdim    BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V0)
169249259Sdim      .addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_LO);
170249259Sdim    return;
171249259Sdim  }
172249259Sdim
173249259Sdim  MF.getRegInfo().addLiveIn(Mips::T9);
174249259Sdim  MBB.addLiveIn(Mips::T9);
175249259Sdim
176249259Sdim  if (Subtarget.isABI_N32()) {
177249259Sdim    // lui $v0, %hi(%neg(%gp_rel(fname)))
178249259Sdim    // addu $v1, $v0, $t9
179249259Sdim    // addiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname)))
180249259Sdim    const GlobalValue *FName = MF.getFunction();
181249259Sdim    BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0)
182249259Sdim      .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI);
183249259Sdim    BuildMI(MBB, I, DL, TII.get(Mips::ADDu), V1).addReg(V0).addReg(Mips::T9);
184249259Sdim    BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V1)
185249259Sdim      .addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO);
186249259Sdim    return;
187249259Sdim  }
188249259Sdim
189249259Sdim  assert(Subtarget.isABI_O32());
190249259Sdim
191249259Sdim  // For O32 ABI, the following instruction sequence is emitted to initialize
192249259Sdim  // the global base register:
193249259Sdim  //
194249259Sdim  //  0. lui   $2, %hi(_gp_disp)
195249259Sdim  //  1. addiu $2, $2, %lo(_gp_disp)
196249259Sdim  //  2. addu  $globalbasereg, $2, $t9
197249259Sdim  //
198249259Sdim  // We emit only the last instruction here.
199249259Sdim  //
200249259Sdim  // GNU linker requires that the first two instructions appear at the beginning
201249259Sdim  // of a function and no instructions be inserted before or between them.
202249259Sdim  // The two instructions are emitted during lowering to MC layer in order to
203249259Sdim  // avoid any reordering.
204249259Sdim  //
205249259Sdim  // Register $2 (Mips::V0) is added to the list of live-in registers to ensure
206249259Sdim  // the value instruction 1 (addiu) defines is valid when instruction 2 (addu)
207249259Sdim  // reads it.
208249259Sdim  MF.getRegInfo().addLiveIn(Mips::V0);
209249259Sdim  MBB.addLiveIn(Mips::V0);
210249259Sdim  BuildMI(MBB, I, DL, TII.get(Mips::ADDu), GlobalBaseReg)
211249259Sdim    .addReg(Mips::V0).addReg(Mips::T9);
212249259Sdim}
213249259Sdim
214249259Sdimvoid MipsSEDAGToDAGISel::processFunctionAfterISel(MachineFunction &MF) {
215249259Sdim  initGlobalBaseReg(MF);
216249259Sdim
217249259Sdim  MachineRegisterInfo *MRI = &MF.getRegInfo();
218249259Sdim
219249259Sdim  for (MachineFunction::iterator MFI = MF.begin(), MFE = MF.end(); MFI != MFE;
220249259Sdim       ++MFI)
221251662Sdim    for (MachineBasicBlock::iterator I = MFI->begin(); I != MFI->end(); ++I) {
222251662Sdim      if (I->getOpcode() == Mips::RDDSP)
223251662Sdim        addDSPCtrlRegOperands(false, *I, MF);
224251662Sdim      else if (I->getOpcode() == Mips::WRDSP)
225251662Sdim        addDSPCtrlRegOperands(true, *I, MF);
226251662Sdim      else
227251662Sdim        replaceUsesWithZeroReg(MRI, *I);
228251662Sdim    }
229249259Sdim}
230249259Sdim
231249259SdimSDNode *MipsSEDAGToDAGISel::selectAddESubE(unsigned MOp, SDValue InFlag,
232263508Sdim                                           SDValue CmpLHS, SDLoc DL,
233249259Sdim                                           SDNode *Node) const {
234249259Sdim  unsigned Opc = InFlag.getOpcode(); (void)Opc;
235249259Sdim
236249259Sdim  assert(((Opc == ISD::ADDC || Opc == ISD::ADDE) ||
237249259Sdim          (Opc == ISD::SUBC || Opc == ISD::SUBE)) &&
238249259Sdim         "(ADD|SUB)E flag operand must come from (ADD|SUB)C/E insn");
239249259Sdim
240249259Sdim  SDValue Ops[] = { CmpLHS, InFlag.getOperand(1) };
241249259Sdim  SDValue LHS = Node->getOperand(0), RHS = Node->getOperand(1);
242249259Sdim  EVT VT = LHS.getValueType();
243249259Sdim
244251662Sdim  SDNode *Carry = CurDAG->getMachineNode(Mips::SLTu, DL, VT, Ops);
245249259Sdim  SDNode *AddCarry = CurDAG->getMachineNode(Mips::ADDu, DL, VT,
246249259Sdim                                            SDValue(Carry, 0), RHS);
247249259Sdim  return CurDAG->SelectNodeTo(Node, MOp, VT, MVT::Glue, LHS,
248249259Sdim                              SDValue(AddCarry, 0));
249249259Sdim}
250249259Sdim
251249259Sdim/// ComplexPattern used on MipsInstrInfo
252249259Sdim/// Used on Mips Load/Store instructions
253249259Sdimbool MipsSEDAGToDAGISel::selectAddrRegImm(SDValue Addr, SDValue &Base,
254249259Sdim                                          SDValue &Offset) const {
255249259Sdim  EVT ValTy = Addr.getValueType();
256249259Sdim
257249259Sdim  // if Address is FI, get the TargetFrameIndex.
258249259Sdim  if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
259249259Sdim    Base   = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy);
260249259Sdim    Offset = CurDAG->getTargetConstant(0, ValTy);
261249259Sdim    return true;
262249259Sdim  }
263249259Sdim
264249259Sdim  // on PIC code Load GA
265249259Sdim  if (Addr.getOpcode() == MipsISD::Wrapper) {
266249259Sdim    Base   = Addr.getOperand(0);
267249259Sdim    Offset = Addr.getOperand(1);
268249259Sdim    return true;
269249259Sdim  }
270249259Sdim
271249259Sdim  if (TM.getRelocationModel() != Reloc::PIC_) {
272249259Sdim    if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
273249259Sdim        Addr.getOpcode() == ISD::TargetGlobalAddress))
274249259Sdim      return false;
275249259Sdim  }
276249259Sdim
277249259Sdim  // Addresses of the form FI+const or FI|const
278249259Sdim  if (CurDAG->isBaseWithConstantOffset(Addr)) {
279249259Sdim    ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1));
280249259Sdim    if (isInt<16>(CN->getSExtValue())) {
281249259Sdim
282249259Sdim      // If the first operand is a FI, get the TargetFI Node
283249259Sdim      if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>
284249259Sdim                                  (Addr.getOperand(0)))
285249259Sdim        Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy);
286249259Sdim      else
287249259Sdim        Base = Addr.getOperand(0);
288249259Sdim
289249259Sdim      Offset = CurDAG->getTargetConstant(CN->getZExtValue(), ValTy);
290249259Sdim      return true;
291249259Sdim    }
292249259Sdim  }
293249259Sdim
294249259Sdim  // Operand is a result from an ADD.
295249259Sdim  if (Addr.getOpcode() == ISD::ADD) {
296249259Sdim    // When loading from constant pools, load the lower address part in
297249259Sdim    // the instruction itself. Example, instead of:
298249259Sdim    //  lui $2, %hi($CPI1_0)
299249259Sdim    //  addiu $2, $2, %lo($CPI1_0)
300249259Sdim    //  lwc1 $f0, 0($2)
301249259Sdim    // Generate:
302249259Sdim    //  lui $2, %hi($CPI1_0)
303249259Sdim    //  lwc1 $f0, %lo($CPI1_0)($2)
304249259Sdim    if (Addr.getOperand(1).getOpcode() == MipsISD::Lo ||
305249259Sdim        Addr.getOperand(1).getOpcode() == MipsISD::GPRel) {
306249259Sdim      SDValue Opnd0 = Addr.getOperand(1).getOperand(0);
307249259Sdim      if (isa<ConstantPoolSDNode>(Opnd0) || isa<GlobalAddressSDNode>(Opnd0) ||
308249259Sdim          isa<JumpTableSDNode>(Opnd0)) {
309249259Sdim        Base = Addr.getOperand(0);
310249259Sdim        Offset = Opnd0;
311249259Sdim        return true;
312249259Sdim      }
313249259Sdim    }
314249259Sdim  }
315249259Sdim
316249259Sdim  return false;
317249259Sdim}
318249259Sdim
319263508Sdim/// ComplexPattern used on MipsInstrInfo
320263508Sdim/// Used on Mips Load/Store instructions
321263508Sdimbool MipsSEDAGToDAGISel::selectAddrRegReg(SDValue Addr, SDValue &Base,
322263508Sdim                                          SDValue &Offset) const {
323263508Sdim  // Operand is a result from an ADD.
324263508Sdim  if (Addr.getOpcode() == ISD::ADD) {
325263508Sdim    Base = Addr.getOperand(0);
326263508Sdim    Offset = Addr.getOperand(1);
327263508Sdim    return true;
328263508Sdim  }
329263508Sdim
330263508Sdim  return false;
331263508Sdim}
332263508Sdim
333249259Sdimbool MipsSEDAGToDAGISel::selectAddrDefault(SDValue Addr, SDValue &Base,
334249259Sdim                                           SDValue &Offset) const {
335249259Sdim  Base = Addr;
336249259Sdim  Offset = CurDAG->getTargetConstant(0, Addr.getValueType());
337249259Sdim  return true;
338249259Sdim}
339249259Sdim
340249259Sdimbool MipsSEDAGToDAGISel::selectIntAddr(SDValue Addr, SDValue &Base,
341249259Sdim                                       SDValue &Offset) const {
342249259Sdim  return selectAddrRegImm(Addr, Base, Offset) ||
343249259Sdim    selectAddrDefault(Addr, Base, Offset);
344249259Sdim}
345249259Sdim
346263508Sdim/// Used on microMIPS Load/Store unaligned instructions (12-bit offset)
347263508Sdimbool MipsSEDAGToDAGISel::selectAddrRegImm12(SDValue Addr, SDValue &Base,
348263508Sdim                                            SDValue &Offset) const {
349263508Sdim  EVT ValTy = Addr.getValueType();
350263508Sdim
351263508Sdim  // Addresses of the form FI+const or FI|const
352263508Sdim  if (CurDAG->isBaseWithConstantOffset(Addr)) {
353263508Sdim    ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1));
354263508Sdim    if (isInt<12>(CN->getSExtValue())) {
355263508Sdim
356263508Sdim      // If the first operand is a FI then get the TargetFI Node
357263508Sdim      if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>
358263508Sdim                                  (Addr.getOperand(0)))
359263508Sdim        Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy);
360263508Sdim      else
361263508Sdim        Base = Addr.getOperand(0);
362263508Sdim
363263508Sdim      Offset = CurDAG->getTargetConstant(CN->getZExtValue(), ValTy);
364263508Sdim      return true;
365263508Sdim    }
366263508Sdim  }
367263508Sdim
368263508Sdim  return false;
369263508Sdim}
370263508Sdim
371263508Sdimbool MipsSEDAGToDAGISel::selectIntAddrMM(SDValue Addr, SDValue &Base,
372263508Sdim                                         SDValue &Offset) const {
373263508Sdim  return selectAddrRegImm12(Addr, Base, Offset) ||
374263508Sdim    selectAddrDefault(Addr, Base, Offset);
375263508Sdim}
376263508Sdim
377263508Sdim// Select constant vector splats.
378263508Sdim//
379263508Sdim// Returns true and sets Imm if:
380263508Sdim// * MSA is enabled
381263508Sdim// * N is a ISD::BUILD_VECTOR representing a constant splat
382263508Sdimbool MipsSEDAGToDAGISel::selectVSplat(SDNode *N, APInt &Imm) const {
383263508Sdim  if (!Subtarget.hasMSA())
384263508Sdim    return false;
385263508Sdim
386263508Sdim  BuildVectorSDNode *Node = dyn_cast<BuildVectorSDNode>(N);
387263508Sdim
388263508Sdim  if (Node == NULL)
389263508Sdim    return false;
390263508Sdim
391263508Sdim  APInt SplatValue, SplatUndef;
392263508Sdim  unsigned SplatBitSize;
393263508Sdim  bool HasAnyUndefs;
394263508Sdim
395263508Sdim  if (!Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
396263508Sdim                             HasAnyUndefs, 8,
397263508Sdim                             !Subtarget.isLittle()))
398263508Sdim    return false;
399263508Sdim
400263508Sdim  Imm = SplatValue;
401263508Sdim
402263508Sdim  return true;
403263508Sdim}
404263508Sdim
405263508Sdim// Select constant vector splats.
406263508Sdim//
407263508Sdim// In addition to the requirements of selectVSplat(), this function returns
408263508Sdim// true and sets Imm if:
409263508Sdim// * The splat value is the same width as the elements of the vector
410263508Sdim// * The splat value fits in an integer with the specified signed-ness and
411263508Sdim//   width.
412263508Sdim//
413263508Sdim// This function looks through ISD::BITCAST nodes.
414263508Sdim// TODO: This might not be appropriate for big-endian MSA since BITCAST is
415263508Sdim//       sometimes a shuffle in big-endian mode.
416263508Sdim//
417263508Sdim// It's worth noting that this function is not used as part of the selection
418263508Sdim// of ldi.[bhwd] since it does not permit using the wrong-typed ldi.[bhwd]
419263508Sdim// instruction to achieve the desired bit pattern. ldi.[bhwd] is selected in
420263508Sdim// MipsSEDAGToDAGISel::selectNode.
421263508Sdimbool MipsSEDAGToDAGISel::
422263508SdimselectVSplatCommon(SDValue N, SDValue &Imm, bool Signed,
423263508Sdim                   unsigned ImmBitSize) const {
424263508Sdim  APInt ImmValue;
425263508Sdim  EVT EltTy = N->getValueType(0).getVectorElementType();
426263508Sdim
427263508Sdim  if (N->getOpcode() == ISD::BITCAST)
428263508Sdim    N = N->getOperand(0);
429263508Sdim
430263508Sdim  if (selectVSplat (N.getNode(), ImmValue) &&
431263508Sdim      ImmValue.getBitWidth() == EltTy.getSizeInBits()) {
432263508Sdim    if (( Signed && ImmValue.isSignedIntN(ImmBitSize)) ||
433263508Sdim        (!Signed && ImmValue.isIntN(ImmBitSize))) {
434263508Sdim      Imm = CurDAG->getTargetConstant(ImmValue, EltTy);
435263508Sdim      return true;
436263508Sdim    }
437263508Sdim  }
438263508Sdim
439263508Sdim  return false;
440263508Sdim}
441263508Sdim
442263508Sdim// Select constant vector splats.
443263508Sdimbool MipsSEDAGToDAGISel::
444263508SdimselectVSplatUimm1(SDValue N, SDValue &Imm) const {
445263508Sdim  return selectVSplatCommon(N, Imm, false, 1);
446263508Sdim}
447263508Sdim
448263508Sdimbool MipsSEDAGToDAGISel::
449263508SdimselectVSplatUimm2(SDValue N, SDValue &Imm) const {
450263508Sdim  return selectVSplatCommon(N, Imm, false, 2);
451263508Sdim}
452263508Sdim
453263508Sdimbool MipsSEDAGToDAGISel::
454263508SdimselectVSplatUimm3(SDValue N, SDValue &Imm) const {
455263508Sdim  return selectVSplatCommon(N, Imm, false, 3);
456263508Sdim}
457263508Sdim
458263508Sdim// Select constant vector splats.
459263508Sdimbool MipsSEDAGToDAGISel::
460263508SdimselectVSplatUimm4(SDValue N, SDValue &Imm) const {
461263508Sdim  return selectVSplatCommon(N, Imm, false, 4);
462263508Sdim}
463263508Sdim
464263508Sdim// Select constant vector splats.
465263508Sdimbool MipsSEDAGToDAGISel::
466263508SdimselectVSplatUimm5(SDValue N, SDValue &Imm) const {
467263508Sdim  return selectVSplatCommon(N, Imm, false, 5);
468263508Sdim}
469263508Sdim
470263508Sdim// Select constant vector splats.
471263508Sdimbool MipsSEDAGToDAGISel::
472263508SdimselectVSplatUimm6(SDValue N, SDValue &Imm) const {
473263508Sdim  return selectVSplatCommon(N, Imm, false, 6);
474263508Sdim}
475263508Sdim
476263508Sdim// Select constant vector splats.
477263508Sdimbool MipsSEDAGToDAGISel::
478263508SdimselectVSplatUimm8(SDValue N, SDValue &Imm) const {
479263508Sdim  return selectVSplatCommon(N, Imm, false, 8);
480263508Sdim}
481263508Sdim
482263508Sdim// Select constant vector splats.
483263508Sdimbool MipsSEDAGToDAGISel::
484263508SdimselectVSplatSimm5(SDValue N, SDValue &Imm) const {
485263508Sdim  return selectVSplatCommon(N, Imm, true, 5);
486263508Sdim}
487263508Sdim
488263508Sdim// Select constant vector splats whose value is a power of 2.
489263508Sdim//
490263508Sdim// In addition to the requirements of selectVSplat(), this function returns
491263508Sdim// true and sets Imm if:
492263508Sdim// * The splat value is the same width as the elements of the vector
493263508Sdim// * The splat value is a power of two.
494263508Sdim//
495263508Sdim// This function looks through ISD::BITCAST nodes.
496263508Sdim// TODO: This might not be appropriate for big-endian MSA since BITCAST is
497263508Sdim//       sometimes a shuffle in big-endian mode.
498263508Sdimbool MipsSEDAGToDAGISel::selectVSplatUimmPow2(SDValue N, SDValue &Imm) const {
499263508Sdim  APInt ImmValue;
500263508Sdim  EVT EltTy = N->getValueType(0).getVectorElementType();
501263508Sdim
502263508Sdim  if (N->getOpcode() == ISD::BITCAST)
503263508Sdim    N = N->getOperand(0);
504263508Sdim
505263508Sdim  if (selectVSplat (N.getNode(), ImmValue) &&
506263508Sdim      ImmValue.getBitWidth() == EltTy.getSizeInBits()) {
507263508Sdim    int32_t Log2 = ImmValue.exactLogBase2();
508263508Sdim
509263508Sdim    if (Log2 != -1) {
510263508Sdim      Imm = CurDAG->getTargetConstant(Log2, EltTy);
511263508Sdim      return true;
512263508Sdim    }
513263508Sdim  }
514263508Sdim
515263508Sdim  return false;
516263508Sdim}
517263508Sdim
518263508Sdim// Select constant vector splats whose value only has a consecutive sequence
519263508Sdim// of left-most bits set (e.g. 0b11...1100...00).
520263508Sdim//
521263508Sdim// In addition to the requirements of selectVSplat(), this function returns
522263508Sdim// true and sets Imm if:
523263508Sdim// * The splat value is the same width as the elements of the vector
524263508Sdim// * The splat value is a consecutive sequence of left-most bits.
525263508Sdim//
526263508Sdim// This function looks through ISD::BITCAST nodes.
527263508Sdim// TODO: This might not be appropriate for big-endian MSA since BITCAST is
528263508Sdim//       sometimes a shuffle in big-endian mode.
529263508Sdimbool MipsSEDAGToDAGISel::selectVSplatMaskL(SDValue N, SDValue &Imm) const {
530263508Sdim  APInt ImmValue;
531263508Sdim  EVT EltTy = N->getValueType(0).getVectorElementType();
532263508Sdim
533263508Sdim  if (N->getOpcode() == ISD::BITCAST)
534263508Sdim    N = N->getOperand(0);
535263508Sdim
536263508Sdim  if (selectVSplat(N.getNode(), ImmValue) &&
537263508Sdim      ImmValue.getBitWidth() == EltTy.getSizeInBits()) {
538263508Sdim    // Extract the run of set bits starting with bit zero from the bitwise
539263508Sdim    // inverse of ImmValue, and test that the inverse of this is the same
540263508Sdim    // as the original value.
541263508Sdim    if (ImmValue == ~(~ImmValue & ~(~ImmValue + 1))) {
542263508Sdim
543263508Sdim      Imm = CurDAG->getTargetConstant(ImmValue.countPopulation(), EltTy);
544263508Sdim      return true;
545263508Sdim    }
546263508Sdim  }
547263508Sdim
548263508Sdim  return false;
549263508Sdim}
550263508Sdim
551263508Sdim// Select constant vector splats whose value only has a consecutive sequence
552263508Sdim// of right-most bits set (e.g. 0b00...0011...11).
553263508Sdim//
554263508Sdim// In addition to the requirements of selectVSplat(), this function returns
555263508Sdim// true and sets Imm if:
556263508Sdim// * The splat value is the same width as the elements of the vector
557263508Sdim// * The splat value is a consecutive sequence of right-most bits.
558263508Sdim//
559263508Sdim// This function looks through ISD::BITCAST nodes.
560263508Sdim// TODO: This might not be appropriate for big-endian MSA since BITCAST is
561263508Sdim//       sometimes a shuffle in big-endian mode.
562263508Sdimbool MipsSEDAGToDAGISel::selectVSplatMaskR(SDValue N, SDValue &Imm) const {
563263508Sdim  APInt ImmValue;
564263508Sdim  EVT EltTy = N->getValueType(0).getVectorElementType();
565263508Sdim
566263508Sdim  if (N->getOpcode() == ISD::BITCAST)
567263508Sdim    N = N->getOperand(0);
568263508Sdim
569263508Sdim  if (selectVSplat(N.getNode(), ImmValue) &&
570263508Sdim      ImmValue.getBitWidth() == EltTy.getSizeInBits()) {
571263508Sdim    // Extract the run of set bits starting with bit zero, and test that the
572263508Sdim    // result is the same as the original value
573263508Sdim    if (ImmValue == (ImmValue & ~(ImmValue + 1))) {
574263508Sdim      Imm = CurDAG->getTargetConstant(ImmValue.countPopulation(), EltTy);
575263508Sdim      return true;
576263508Sdim    }
577263508Sdim  }
578263508Sdim
579263508Sdim  return false;
580263508Sdim}
581263508Sdim
582263508Sdimbool MipsSEDAGToDAGISel::selectVSplatUimmInvPow2(SDValue N,
583263508Sdim                                                 SDValue &Imm) const {
584263508Sdim  APInt ImmValue;
585263508Sdim  EVT EltTy = N->getValueType(0).getVectorElementType();
586263508Sdim
587263508Sdim  if (N->getOpcode() == ISD::BITCAST)
588263508Sdim    N = N->getOperand(0);
589263508Sdim
590263508Sdim  if (selectVSplat(N.getNode(), ImmValue) &&
591263508Sdim      ImmValue.getBitWidth() == EltTy.getSizeInBits()) {
592263508Sdim    int32_t Log2 = (~ImmValue).exactLogBase2();
593263508Sdim
594263508Sdim    if (Log2 != -1) {
595263508Sdim      Imm = CurDAG->getTargetConstant(Log2, EltTy);
596263508Sdim      return true;
597263508Sdim    }
598263508Sdim  }
599263508Sdim
600263508Sdim  return false;
601263508Sdim}
602263508Sdim
603249259Sdimstd::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) {
604249259Sdim  unsigned Opcode = Node->getOpcode();
605263508Sdim  SDLoc DL(Node);
606249259Sdim
607249259Sdim  ///
608249259Sdim  // Instruction Selection not handled by the auto-generated
609249259Sdim  // tablegen selection should be handled here.
610249259Sdim  ///
611249259Sdim  SDNode *Result;
612249259Sdim
613249259Sdim  switch(Opcode) {
614249259Sdim  default: break;
615249259Sdim
616249259Sdim  case ISD::SUBE: {
617249259Sdim    SDValue InFlag = Node->getOperand(2);
618249259Sdim    Result = selectAddESubE(Mips::SUBu, InFlag, InFlag.getOperand(0), DL, Node);
619249259Sdim    return std::make_pair(true, Result);
620249259Sdim  }
621249259Sdim
622249259Sdim  case ISD::ADDE: {
623251662Sdim    if (Subtarget.hasDSP()) // Select DSP instructions, ADDSC and ADDWC.
624251662Sdim      break;
625249259Sdim    SDValue InFlag = Node->getOperand(2);
626249259Sdim    Result = selectAddESubE(Mips::ADDu, InFlag, InFlag.getValue(0), DL, Node);
627249259Sdim    return std::make_pair(true, Result);
628249259Sdim  }
629249259Sdim
630249259Sdim  case ISD::ConstantFP: {
631249259Sdim    ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(Node);
632249259Sdim    if (Node->getValueType(0) == MVT::f64 && CN->isExactlyValue(+0.0)) {
633249259Sdim      if (Subtarget.hasMips64()) {
634249259Sdim        SDValue Zero = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL,
635249259Sdim                                              Mips::ZERO_64, MVT::i64);
636249259Sdim        Result = CurDAG->getMachineNode(Mips::DMTC1, DL, MVT::f64, Zero);
637263508Sdim      } else if (Subtarget.isFP64bit()) {
638263508Sdim        SDValue Zero = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL,
639263508Sdim                                              Mips::ZERO, MVT::i32);
640263508Sdim        Result = CurDAG->getMachineNode(Mips::BuildPairF64_64, DL, MVT::f64,
641263508Sdim                                        Zero, Zero);
642249259Sdim      } else {
643249259Sdim        SDValue Zero = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL,
644249259Sdim                                              Mips::ZERO, MVT::i32);
645249259Sdim        Result = CurDAG->getMachineNode(Mips::BuildPairF64, DL, MVT::f64, Zero,
646249259Sdim                                        Zero);
647249259Sdim      }
648249259Sdim
649249259Sdim      return std::make_pair(true, Result);
650249259Sdim    }
651249259Sdim    break;
652249259Sdim  }
653249259Sdim
654249259Sdim  case ISD::Constant: {
655249259Sdim    const ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Node);
656249259Sdim    unsigned Size = CN->getValueSizeInBits(0);
657249259Sdim
658249259Sdim    if (Size == 32)
659249259Sdim      break;
660249259Sdim
661249259Sdim    MipsAnalyzeImmediate AnalyzeImm;
662249259Sdim    int64_t Imm = CN->getSExtValue();
663249259Sdim
664249259Sdim    const MipsAnalyzeImmediate::InstSeq &Seq =
665249259Sdim      AnalyzeImm.Analyze(Imm, Size, false);
666249259Sdim
667249259Sdim    MipsAnalyzeImmediate::InstSeq::const_iterator Inst = Seq.begin();
668263508Sdim    SDLoc DL(CN);
669249259Sdim    SDNode *RegOpnd;
670249259Sdim    SDValue ImmOpnd = CurDAG->getTargetConstant(SignExtend64<16>(Inst->ImmOpnd),
671249259Sdim                                                MVT::i64);
672249259Sdim
673249259Sdim    // The first instruction can be a LUi which is different from other
674249259Sdim    // instructions (ADDiu, ORI and SLL) in that it does not have a register
675249259Sdim    // operand.
676249259Sdim    if (Inst->Opc == Mips::LUi64)
677249259Sdim      RegOpnd = CurDAG->getMachineNode(Inst->Opc, DL, MVT::i64, ImmOpnd);
678249259Sdim    else
679249259Sdim      RegOpnd =
680249259Sdim        CurDAG->getMachineNode(Inst->Opc, DL, MVT::i64,
681249259Sdim                               CurDAG->getRegister(Mips::ZERO_64, MVT::i64),
682249259Sdim                               ImmOpnd);
683249259Sdim
684249259Sdim    // The remaining instructions in the sequence are handled here.
685249259Sdim    for (++Inst; Inst != Seq.end(); ++Inst) {
686249259Sdim      ImmOpnd = CurDAG->getTargetConstant(SignExtend64<16>(Inst->ImmOpnd),
687249259Sdim                                          MVT::i64);
688249259Sdim      RegOpnd = CurDAG->getMachineNode(Inst->Opc, DL, MVT::i64,
689249259Sdim                                       SDValue(RegOpnd, 0), ImmOpnd);
690249259Sdim    }
691249259Sdim
692249259Sdim    return std::make_pair(true, RegOpnd);
693249259Sdim  }
694249259Sdim
695263508Sdim  case ISD::INTRINSIC_W_CHAIN: {
696263508Sdim    switch (cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue()) {
697263508Sdim    default:
698263508Sdim      break;
699263508Sdim
700263508Sdim    case Intrinsic::mips_cfcmsa: {
701263508Sdim      SDValue ChainIn = Node->getOperand(0);
702263508Sdim      SDValue RegIdx = Node->getOperand(2);
703263508Sdim      SDValue Reg = CurDAG->getCopyFromReg(ChainIn, DL,
704263508Sdim                                           getMSACtrlReg(RegIdx), MVT::i32);
705263508Sdim      return std::make_pair(true, Reg.getNode());
706263508Sdim    }
707263508Sdim    }
708263508Sdim    break;
709263508Sdim  }
710263508Sdim
711263508Sdim  case ISD::INTRINSIC_WO_CHAIN: {
712263508Sdim    switch (cast<ConstantSDNode>(Node->getOperand(0))->getZExtValue()) {
713263508Sdim    default:
714263508Sdim      break;
715263508Sdim
716263508Sdim    case Intrinsic::mips_move_v:
717263508Sdim      // Like an assignment but will always produce a move.v even if
718263508Sdim      // unnecessary.
719263508Sdim      return std::make_pair(true,
720263508Sdim                            CurDAG->getMachineNode(Mips::MOVE_V, DL,
721263508Sdim                                                   Node->getValueType(0),
722263508Sdim                                                   Node->getOperand(1)));
723263508Sdim    }
724263508Sdim    break;
725263508Sdim  }
726263508Sdim
727263508Sdim  case ISD::INTRINSIC_VOID: {
728263508Sdim    switch (cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue()) {
729263508Sdim    default:
730263508Sdim      break;
731263508Sdim
732263508Sdim    case Intrinsic::mips_ctcmsa: {
733263508Sdim      SDValue ChainIn = Node->getOperand(0);
734263508Sdim      SDValue RegIdx  = Node->getOperand(2);
735263508Sdim      SDValue Value   = Node->getOperand(3);
736263508Sdim      SDValue ChainOut = CurDAG->getCopyToReg(ChainIn, DL,
737263508Sdim                                              getMSACtrlReg(RegIdx), Value);
738263508Sdim      return std::make_pair(true, ChainOut.getNode());
739263508Sdim    }
740263508Sdim    }
741263508Sdim    break;
742263508Sdim  }
743263508Sdim
744249259Sdim  case MipsISD::ThreadPointer: {
745263508Sdim    EVT PtrVT = getTargetLowering()->getPointerTy();
746263508Sdim    unsigned RdhwrOpc, DestReg;
747249259Sdim
748249259Sdim    if (PtrVT == MVT::i32) {
749249259Sdim      RdhwrOpc = Mips::RDHWR;
750249259Sdim      DestReg = Mips::V1;
751249259Sdim    } else {
752249259Sdim      RdhwrOpc = Mips::RDHWR64;
753249259Sdim      DestReg = Mips::V1_64;
754249259Sdim    }
755249259Sdim
756249259Sdim    SDNode *Rdhwr =
757263508Sdim      CurDAG->getMachineNode(RdhwrOpc, SDLoc(Node),
758249259Sdim                             Node->getValueType(0),
759263508Sdim                             CurDAG->getRegister(Mips::HWR29, MVT::i32));
760249259Sdim    SDValue Chain = CurDAG->getCopyToReg(CurDAG->getEntryNode(), DL, DestReg,
761249259Sdim                                         SDValue(Rdhwr, 0));
762249259Sdim    SDValue ResNode = CurDAG->getCopyFromReg(Chain, DL, DestReg, PtrVT);
763249259Sdim    ReplaceUses(SDValue(Node, 0), ResNode);
764249259Sdim    return std::make_pair(true, ResNode.getNode());
765249259Sdim  }
766249259Sdim
767263508Sdim  case ISD::BUILD_VECTOR: {
768263508Sdim    // Select appropriate ldi.[bhwd] instructions for constant splats of
769263508Sdim    // 128-bit when MSA is enabled. Fixup any register class mismatches that
770263508Sdim    // occur as a result.
771263508Sdim    //
772263508Sdim    // This allows the compiler to use a wider range of immediates than would
773263508Sdim    // otherwise be allowed. If, for example, v4i32 could only use ldi.h then
774263508Sdim    // it would not be possible to load { 0x01010101, 0x01010101, 0x01010101,
775263508Sdim    // 0x01010101 } without using a constant pool. This would be sub-optimal
776263508Sdim    // when // 'ldi.b wd, 1' is capable of producing that bit-pattern in the
777263508Sdim    // same set/ of registers. Similarly, ldi.h isn't capable of producing {
778263508Sdim    // 0x00000000, 0x00000001, 0x00000000, 0x00000001 } but 'ldi.d wd, 1' can.
779263508Sdim
780263508Sdim    BuildVectorSDNode *BVN = cast<BuildVectorSDNode>(Node);
781263508Sdim    APInt SplatValue, SplatUndef;
782263508Sdim    unsigned SplatBitSize;
783263508Sdim    bool HasAnyUndefs;
784263508Sdim    unsigned LdiOp;
785263508Sdim    EVT ResVecTy = BVN->getValueType(0);
786263508Sdim    EVT ViaVecTy;
787263508Sdim
788263508Sdim    if (!Subtarget.hasMSA() || !BVN->getValueType(0).is128BitVector())
789263508Sdim      return std::make_pair(false, (SDNode*)NULL);
790263508Sdim
791263508Sdim    if (!BVN->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
792263508Sdim                              HasAnyUndefs, 8,
793263508Sdim                              !Subtarget.isLittle()))
794263508Sdim      return std::make_pair(false, (SDNode*)NULL);
795263508Sdim
796263508Sdim    switch (SplatBitSize) {
797263508Sdim    default:
798263508Sdim      return std::make_pair(false, (SDNode*)NULL);
799263508Sdim    case 8:
800263508Sdim      LdiOp = Mips::LDI_B;
801263508Sdim      ViaVecTy = MVT::v16i8;
802263508Sdim      break;
803263508Sdim    case 16:
804263508Sdim      LdiOp = Mips::LDI_H;
805263508Sdim      ViaVecTy = MVT::v8i16;
806263508Sdim      break;
807263508Sdim    case 32:
808263508Sdim      LdiOp = Mips::LDI_W;
809263508Sdim      ViaVecTy = MVT::v4i32;
810263508Sdim      break;
811263508Sdim    case 64:
812263508Sdim      LdiOp = Mips::LDI_D;
813263508Sdim      ViaVecTy = MVT::v2i64;
814263508Sdim      break;
815263508Sdim    }
816263508Sdim
817263508Sdim    if (!SplatValue.isSignedIntN(10))
818263508Sdim      return std::make_pair(false, (SDNode*)NULL);
819263508Sdim
820263508Sdim    SDValue Imm = CurDAG->getTargetConstant(SplatValue,
821263508Sdim                                            ViaVecTy.getVectorElementType());
822263508Sdim
823263508Sdim    SDNode *Res = CurDAG->getMachineNode(LdiOp, SDLoc(Node), ViaVecTy, Imm);
824263508Sdim
825263508Sdim    if (ResVecTy != ViaVecTy) {
826263508Sdim      // If LdiOp is writing to a different register class to ResVecTy, then
827263508Sdim      // fix it up here. This COPY_TO_REGCLASS should never cause a move.v
828263508Sdim      // since the source and destination register sets contain the same
829263508Sdim      // registers.
830263508Sdim      const TargetLowering *TLI = getTargetLowering();
831263508Sdim      MVT ResVecTySimple = ResVecTy.getSimpleVT();
832263508Sdim      const TargetRegisterClass *RC = TLI->getRegClassFor(ResVecTySimple);
833263508Sdim      Res = CurDAG->getMachineNode(Mips::COPY_TO_REGCLASS, SDLoc(Node),
834263508Sdim                                   ResVecTy, SDValue(Res, 0),
835263508Sdim                                   CurDAG->getTargetConstant(RC->getID(),
836263508Sdim                                                             MVT::i32));
837263508Sdim    }
838263508Sdim
839249259Sdim    return std::make_pair(true, Res);
840249259Sdim  }
841263508Sdim
842249259Sdim  }
843249259Sdim
844249259Sdim  return std::make_pair(false, (SDNode*)NULL);
845249259Sdim}
846249259Sdim
847249259SdimFunctionPass *llvm::createMipsSEISelDag(MipsTargetMachine &TM) {
848249259Sdim  return new MipsSEDAGToDAGISel(TM);
849249259Sdim}
850