1894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===-- SPUISelLowering.cpp - Cell SPU DAG Lowering Implementation --------===//
2894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//                     The LLVM Compiler Infrastructure
3894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
4894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// This file is distributed under the University of Illinois Open Source
5894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// License. See LICENSE.TXT for details.
6894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
7894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===----------------------------------------------------------------------===//
8894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
9894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// This file implements the SPUTargetLowering class.
10894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//
11894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===----------------------------------------------------------------------===//
12894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
13894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "SPUISelLowering.h"
14894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "SPUTargetMachine.h"
1519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "SPUFrameLowering.h"
16894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "SPUMachineFunction.h"
17894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/Constants.h"
18894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/Function.h"
19894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/Intrinsics.h"
20894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/CallingConv.h"
2119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Type.h"
22894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/CodeGen/CallingConvLower.h"
23894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/CodeGen/MachineFrameInfo.h"
24894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/CodeGen/MachineFunction.h"
25894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/CodeGen/MachineInstrBuilder.h"
26894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/CodeGen/MachineRegisterInfo.h"
27894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/CodeGen/SelectionDAG.h"
28894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
29894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/Target/TargetOptions.h"
30894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/ADT/VectorExtras.h"
31894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/Support/Debug.h"
32894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/Support/ErrorHandling.h"
33894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/Support/MathExtras.h"
34894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "llvm/Support/raw_ostream.h"
35894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include <map>
36894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
37894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanusing namespace llvm;
38894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
39894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// Used in getTargetNodeName() below
40894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumannamespace {
41894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  std::map<unsigned, const char *> node_names;
42894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
4319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // Byte offset of the preferred slot (counted from the MSB)
4419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  int prefslotOffset(EVT VT) {
4519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    int retval=0;
4619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (VT==MVT::i1) retval=3;
4719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (VT==MVT::i8) retval=3;
4819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (VT==MVT::i16) retval=2;
49894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
50894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return retval;
51894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
52894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
53894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  //! Expand a library call into an actual call DAG node
54894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /*!
55894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman   \note
56894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman   This code is taken from SelectionDAGLegalize, since it is not exposed as
57894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman   part of the LLVM SelectionDAG API.
58894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman   */
59894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
60894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue
61894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  ExpandLibCall(RTLIB::Libcall LC, SDValue Op, SelectionDAG &DAG,
62894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                bool isSigned, SDValue &Hi, const SPUTargetLowering &TLI) {
63894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // The input chain to this libcall is the entry node of the function.
64894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Legalizing the call will automatically add the previous call to the
65894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // dependence.
66894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue InChain = DAG.getEntryNode();
67894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
68894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    TargetLowering::ArgListTy Args;
69894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    TargetLowering::ArgListEntry Entry;
70894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    for (unsigned i = 0, e = Op.getNumOperands(); i != e; ++i) {
71894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      EVT ArgVT = Op.getOperand(i).getValueType();
7219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      Type *ArgTy = ArgVT.getTypeForEVT(*DAG.getContext());
73894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      Entry.Node = Op.getOperand(i);
74894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      Entry.Ty = ArgTy;
75894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      Entry.isSExt = isSigned;
76894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      Entry.isZExt = !isSigned;
77894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      Args.push_back(Entry);
78894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
79894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue Callee = DAG.getExternalSymbol(TLI.getLibcallName(LC),
80894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                           TLI.getPointerTy());
81894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
82894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Splice the libcall in wherever FindInputOutputChains tells us to.
8319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    Type *RetTy =
84894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                Op.getNode()->getValueType(0).getTypeForEVT(*DAG.getContext());
85894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    std::pair<SDValue, SDValue> CallInfo =
86894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman            TLI.LowerCallTo(InChain, RetTy, isSigned, !isSigned, false, false,
87894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                            0, TLI.getLibcallCallingConv(LC), false,
88894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                            /*isReturnValueUsed=*/true,
89894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                            Callee, Args, DAG, Op.getDebugLoc());
90894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
91894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return CallInfo.first;
92894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
93894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
94894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
95894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSPUTargetLowering::SPUTargetLowering(SPUTargetMachine &TM)
96894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  : TargetLowering(TM, new TargetLoweringObjectFileELF()),
97894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SPUTM(TM) {
98894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
99894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Use _setjmp/_longjmp instead of setjmp/longjmp.
100894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setUseUnderscoreSetJmp(true);
101894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setUseUnderscoreLongJmp(true);
102894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
103894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Set RTLIB libcall names as used by SPU:
104894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setLibcallName(RTLIB::DIV_F64, "__fast_divdf3");
105894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
106894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Set up the SPU's register classes:
107894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  addRegisterClass(MVT::i8,   SPU::R8CRegisterClass);
108894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  addRegisterClass(MVT::i16,  SPU::R16CRegisterClass);
109894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  addRegisterClass(MVT::i32,  SPU::R32CRegisterClass);
110894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  addRegisterClass(MVT::i64,  SPU::R64CRegisterClass);
111894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  addRegisterClass(MVT::f32,  SPU::R32FPRegisterClass);
112894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  addRegisterClass(MVT::f64,  SPU::R64FPRegisterClass);
113894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  addRegisterClass(MVT::i128, SPU::GPRCRegisterClass);
114894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
115894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // SPU has no sign or zero extended loads for i1, i8, i16:
116894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setLoadExtAction(ISD::EXTLOAD,  MVT::i1, Promote);
117894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
118894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote);
119894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
120894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setLoadExtAction(ISD::EXTLOAD,  MVT::f32, Expand);
121894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setLoadExtAction(ISD::EXTLOAD,  MVT::f64, Expand);
122894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
123894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setTruncStoreAction(MVT::i128, MVT::i64, Expand);
124894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setTruncStoreAction(MVT::i128, MVT::i32, Expand);
125894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setTruncStoreAction(MVT::i128, MVT::i16, Expand);
126894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setTruncStoreAction(MVT::i128, MVT::i8, Expand);
127894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
128894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setTruncStoreAction(MVT::f64, MVT::f32, Expand);
129894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
130894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // SPU constant load actions are custom lowered:
131894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::ConstantFP, MVT::f32, Legal);
132894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::ConstantFP, MVT::f64, Custom);
133894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
134894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // SPU's loads and stores have to be custom lowered:
135894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  for (unsigned sctype = (unsigned) MVT::i8; sctype < (unsigned) MVT::i128;
136894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman       ++sctype) {
137894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    MVT::SimpleValueType VT = (MVT::SimpleValueType)sctype;
138894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
139894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    setOperationAction(ISD::LOAD,   VT, Custom);
140894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    setOperationAction(ISD::STORE,  VT, Custom);
141894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    setLoadExtAction(ISD::EXTLOAD,  VT, Custom);
142894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    setLoadExtAction(ISD::ZEXTLOAD, VT, Custom);
143894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    setLoadExtAction(ISD::SEXTLOAD, VT, Custom);
144894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
145894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    for (unsigned stype = sctype - 1; stype >= (unsigned) MVT::i8; --stype) {
146894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      MVT::SimpleValueType StoreVT = (MVT::SimpleValueType) stype;
147894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      setTruncStoreAction(VT, StoreVT, Expand);
148894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
149894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
150894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
151894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  for (unsigned sctype = (unsigned) MVT::f32; sctype < (unsigned) MVT::f64;
152894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman       ++sctype) {
153894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    MVT::SimpleValueType VT = (MVT::SimpleValueType) sctype;
154894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
155894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    setOperationAction(ISD::LOAD,   VT, Custom);
156894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    setOperationAction(ISD::STORE,  VT, Custom);
157894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
158894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    for (unsigned stype = sctype - 1; stype >= (unsigned) MVT::f32; --stype) {
159894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      MVT::SimpleValueType StoreVT = (MVT::SimpleValueType) stype;
160894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      setTruncStoreAction(VT, StoreVT, Expand);
161894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
162894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
163894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
164894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Expand the jumptable branches
165894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::BR_JT,        MVT::Other, Expand);
166894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::BR_CC,        MVT::Other, Expand);
167894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
168894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Custom lower SELECT_CC for most cases, but expand by default
169894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SELECT_CC,    MVT::Other, Expand);
170894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SELECT_CC,    MVT::i8,    Custom);
171894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SELECT_CC,    MVT::i16,   Custom);
172894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SELECT_CC,    MVT::i32,   Custom);
173894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SELECT_CC,    MVT::i64,   Custom);
174894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
175894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // SPU has no intrinsics for these particular operations:
176894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
17719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand);
178894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
179894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // SPU has no division/remainder instructions
180894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SREM,    MVT::i8,   Expand);
181894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::UREM,    MVT::i8,   Expand);
182894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SDIV,    MVT::i8,   Expand);
183894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::UDIV,    MVT::i8,   Expand);
184894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SDIVREM, MVT::i8,   Expand);
185894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::UDIVREM, MVT::i8,   Expand);
186894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SREM,    MVT::i16,  Expand);
187894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::UREM,    MVT::i16,  Expand);
188894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SDIV,    MVT::i16,  Expand);
189894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::UDIV,    MVT::i16,  Expand);
190894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SDIVREM, MVT::i16,  Expand);
191894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::UDIVREM, MVT::i16,  Expand);
192894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SREM,    MVT::i32,  Expand);
193894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::UREM,    MVT::i32,  Expand);
194894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SDIV,    MVT::i32,  Expand);
195894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::UDIV,    MVT::i32,  Expand);
196894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SDIVREM, MVT::i32,  Expand);
197894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::UDIVREM, MVT::i32,  Expand);
198894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SREM,    MVT::i64,  Expand);
199894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::UREM,    MVT::i64,  Expand);
200894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SDIV,    MVT::i64,  Expand);
201894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::UDIV,    MVT::i64,  Expand);
202894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SDIVREM, MVT::i64,  Expand);
203894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::UDIVREM, MVT::i64,  Expand);
204894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SREM,    MVT::i128, Expand);
205894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::UREM,    MVT::i128, Expand);
206894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SDIV,    MVT::i128, Expand);
207894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::UDIV,    MVT::i128, Expand);
208894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SDIVREM, MVT::i128, Expand);
209894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::UDIVREM, MVT::i128, Expand);
210894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
211894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // We don't support sin/cos/sqrt/fmod
212894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::FSIN , MVT::f64, Expand);
213894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::FCOS , MVT::f64, Expand);
214894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::FREM , MVT::f64, Expand);
215894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::FSIN , MVT::f32, Expand);
216894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::FCOS , MVT::f32, Expand);
217894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::FREM , MVT::f32, Expand);
218894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
219894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Expand fsqrt to the appropriate libcall (NOTE: should use h/w fsqrt
220894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // for f32!)
221894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::FSQRT, MVT::f64, Expand);
222894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::FSQRT, MVT::f32, Expand);
223894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
22419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  setOperationAction(ISD::FMA, MVT::f64, Expand);
22519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  setOperationAction(ISD::FMA, MVT::f32, Expand);
22619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
227894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
228894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
229894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
230894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // SPU can do rotate right and left, so legalize it... but customize for i8
231894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // because instructions don't exist.
232894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
233894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // FIXME: Change from "expand" to appropriate type once ROTR is supported in
234894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  //        .td files.
235894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::ROTR, MVT::i32,    Expand /*Legal*/);
236894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::ROTR, MVT::i16,    Expand /*Legal*/);
237894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::ROTR, MVT::i8,     Expand /*Custom*/);
238894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
239894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::ROTL, MVT::i32,    Legal);
240894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::ROTL, MVT::i16,    Legal);
241894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::ROTL, MVT::i8,     Custom);
242894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
243894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // SPU has no native version of shift left/right for i8
244894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SHL,  MVT::i8,     Custom);
245894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SRL,  MVT::i8,     Custom);
246894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SRA,  MVT::i8,     Custom);
247894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
248894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Make these operations legal and handle them during instruction selection:
249894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SHL,  MVT::i64,    Legal);
250894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SRL,  MVT::i64,    Legal);
251894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SRA,  MVT::i64,    Legal);
252894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
253894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Custom lower i8, i32 and i64 multiplications
254894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::MUL,  MVT::i8,     Custom);
255894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::MUL,  MVT::i32,    Legal);
256894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::MUL,  MVT::i64,    Legal);
257894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
258894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Expand double-width multiplication
259894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // FIXME: It would probably be reasonable to support some of these operations
260894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::UMUL_LOHI, MVT::i8,  Expand);
261894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SMUL_LOHI, MVT::i8,  Expand);
262894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::MULHU,     MVT::i8,  Expand);
263894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::MULHS,     MVT::i8,  Expand);
264894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::UMUL_LOHI, MVT::i16, Expand);
265894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SMUL_LOHI, MVT::i16, Expand);
266894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::MULHU,     MVT::i16, Expand);
267894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::MULHS,     MVT::i16, Expand);
268894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand);
269894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand);
270894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::MULHU,     MVT::i32, Expand);
271894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::MULHS,     MVT::i32, Expand);
272894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand);
273894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand);
274894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::MULHU,     MVT::i64, Expand);
275894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::MULHS,     MVT::i64, Expand);
276894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
277894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Need to custom handle (some) common i8, i64 math ops
278894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::ADD,  MVT::i8,     Custom);
279894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::ADD,  MVT::i64,    Legal);
280894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SUB,  MVT::i8,     Custom);
281894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SUB,  MVT::i64,    Legal);
282894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
283894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // SPU does not have BSWAP. It does have i32 support CTLZ.
284894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // CTPOP has to be custom lowered.
285894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::BSWAP, MVT::i32,   Expand);
286894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::BSWAP, MVT::i64,   Expand);
287894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
288894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::CTPOP, MVT::i8,    Custom);
289894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::CTPOP, MVT::i16,   Custom);
290894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::CTPOP, MVT::i32,   Custom);
291894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::CTPOP, MVT::i64,   Custom);
292894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::CTPOP, MVT::i128,  Expand);
293894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
294894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::CTTZ , MVT::i8,    Expand);
295894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::CTTZ , MVT::i16,   Expand);
296894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::CTTZ , MVT::i32,   Expand);
297894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::CTTZ , MVT::i64,   Expand);
298894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::CTTZ , MVT::i128,  Expand);
299894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
300894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::CTLZ , MVT::i8,    Promote);
301894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::CTLZ , MVT::i16,   Promote);
302894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::CTLZ , MVT::i32,   Legal);
303894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::CTLZ , MVT::i64,   Expand);
304894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::CTLZ , MVT::i128,  Expand);
305894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
306894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // SPU has a version of select that implements (a&~c)|(b&c), just like
307894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // select ought to work:
308894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SELECT, MVT::i8,   Legal);
309894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SELECT, MVT::i16,  Legal);
310894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SELECT, MVT::i32,  Legal);
311894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SELECT, MVT::i64,  Legal);
312894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
313894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SETCC, MVT::i8,    Legal);
314894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SETCC, MVT::i16,   Legal);
315894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SETCC, MVT::i32,   Legal);
316894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SETCC, MVT::i64,   Legal);
317894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SETCC, MVT::f64,   Custom);
318894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
319894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Custom lower i128 -> i64 truncates
320894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::TRUNCATE, MVT::i64, Custom);
321894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
322894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Custom lower i32/i64 -> i128 sign extend
323894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SIGN_EXTEND, MVT::i128, Custom);
324894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
325894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::FP_TO_SINT, MVT::i8, Promote);
326894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::FP_TO_UINT, MVT::i8, Promote);
327894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::FP_TO_SINT, MVT::i16, Promote);
328894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::FP_TO_UINT, MVT::i16, Promote);
329894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // SPU has a legal FP -> signed INT instruction for f32, but for f64, need
330894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // to expand to a libcall, hence the custom lowering:
331894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
332894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom);
333894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::FP_TO_SINT, MVT::i64, Expand);
334894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::FP_TO_UINT, MVT::i64, Expand);
335894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::FP_TO_SINT, MVT::i128, Expand);
336894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::FP_TO_UINT, MVT::i128, Expand);
337894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
338894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // FDIV on SPU requires custom lowering
339894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::FDIV, MVT::f64, Expand);      // to libcall
340894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
341894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // SPU has [U|S]INT_TO_FP for f32->i32, but not for f64->i32, f64->i64:
342894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom);
343894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote);
344894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SINT_TO_FP, MVT::i8,  Promote);
345894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::UINT_TO_FP, MVT::i32, Custom);
346894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::UINT_TO_FP, MVT::i16, Promote);
347894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::UINT_TO_FP, MVT::i8,  Promote);
348894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
349894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
350894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
35119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  setOperationAction(ISD::BITCAST, MVT::i32, Legal);
35219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  setOperationAction(ISD::BITCAST, MVT::f32, Legal);
35319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  setOperationAction(ISD::BITCAST, MVT::i64, Legal);
35419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  setOperationAction(ISD::BITCAST, MVT::f64, Legal);
355894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
356894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // We cannot sextinreg(i1).  Expand to shifts.
357894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
358894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
359894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // We want to legalize GlobalAddress and ConstantPool nodes into the
360894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // appropriate instructions to materialize the address.
361894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  for (unsigned sctype = (unsigned) MVT::i8; sctype < (unsigned) MVT::f128;
362894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman       ++sctype) {
363894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    MVT::SimpleValueType VT = (MVT::SimpleValueType)sctype;
364894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
365894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    setOperationAction(ISD::GlobalAddress,  VT, Custom);
366894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    setOperationAction(ISD::ConstantPool,   VT, Custom);
367894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    setOperationAction(ISD::JumpTable,      VT, Custom);
368894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
369894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
370894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // VASTART needs to be custom lowered to use the VarArgsFrameIndex
371894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::VASTART           , MVT::Other, Custom);
372894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
373894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Use the default implementation.
374894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::VAARG             , MVT::Other, Expand);
375894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::VACOPY            , MVT::Other, Expand);
376894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::VAEND             , MVT::Other, Expand);
377894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::STACKSAVE         , MVT::Other, Expand);
378894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::STACKRESTORE      , MVT::Other, Expand);
379894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32  , Expand);
380894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64  , Expand);
381894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
382894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Cell SPU has instructions for converting between i64 and fp.
383894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
384894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
385894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
386894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // To take advantage of the above i64 FP_TO_SINT, promote i32 FP_TO_UINT
387894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote);
388894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
389894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // BUILD_PAIR can't be handled natively, and should be expanded to shl/or
390894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
391894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
392894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // First set operation action for all vector types to expand. Then we
393894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // will selectively turn on ones that can be effectively codegen'd.
394894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  addRegisterClass(MVT::v16i8, SPU::VECREGRegisterClass);
395894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  addRegisterClass(MVT::v8i16, SPU::VECREGRegisterClass);
396894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  addRegisterClass(MVT::v4i32, SPU::VECREGRegisterClass);
397894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  addRegisterClass(MVT::v2i64, SPU::VECREGRegisterClass);
398894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  addRegisterClass(MVT::v4f32, SPU::VECREGRegisterClass);
399894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  addRegisterClass(MVT::v2f64, SPU::VECREGRegisterClass);
400894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
401894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE;
402894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman       i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) {
403894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    MVT::SimpleValueType VT = (MVT::SimpleValueType)i;
404894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
40519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // Set operation actions to legal types only.
40619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (!isTypeLegal(VT)) continue;
40719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
408894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // add/sub are legal for all supported vector VT's.
409894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    setOperationAction(ISD::ADD,     VT, Legal);
410894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    setOperationAction(ISD::SUB,     VT, Legal);
411894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // mul has to be custom lowered.
412894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    setOperationAction(ISD::MUL,     VT, Legal);
413894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
414894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    setOperationAction(ISD::AND,     VT, Legal);
415894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    setOperationAction(ISD::OR,      VT, Legal);
416894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    setOperationAction(ISD::XOR,     VT, Legal);
41719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    setOperationAction(ISD::LOAD,    VT, Custom);
418894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    setOperationAction(ISD::SELECT,  VT, Legal);
41919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    setOperationAction(ISD::STORE,   VT, Custom);
420894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
421894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // These operations need to be expanded:
422894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    setOperationAction(ISD::SDIV,    VT, Expand);
423894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    setOperationAction(ISD::SREM,    VT, Expand);
424894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    setOperationAction(ISD::UDIV,    VT, Expand);
425894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    setOperationAction(ISD::UREM,    VT, Expand);
426894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
427894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Custom lower build_vector, constant pool spills, insert and
428894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // extract vector elements:
429894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    setOperationAction(ISD::BUILD_VECTOR, VT, Custom);
430894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    setOperationAction(ISD::ConstantPool, VT, Custom);
431894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Custom);
432894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Custom);
433894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Custom);
434894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom);
435894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
436894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
437894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::AND, MVT::v16i8, Custom);
438894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::OR,  MVT::v16i8, Custom);
439894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::XOR, MVT::v16i8, Custom);
440894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4f32, Custom);
441894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
442894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setOperationAction(ISD::FDIV, MVT::v4f32, Legal);
443894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
444894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setBooleanContents(ZeroOrNegativeOneBooleanContent);
44519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  setBooleanVectorContents(ZeroOrNegativeOneBooleanContent); // FIXME: Is this correct?
446894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
447894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setStackPointerRegisterToSaveRestore(SPU::R1);
448894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
449894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // We have target-specific dag combine patterns for the following nodes:
450894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setTargetDAGCombine(ISD::ADD);
451894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setTargetDAGCombine(ISD::ZERO_EXTEND);
452894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setTargetDAGCombine(ISD::SIGN_EXTEND);
453894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setTargetDAGCombine(ISD::ANY_EXTEND);
454894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
45519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  setMinFunctionAlignment(3);
45619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
457894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  computeRegisterProperties();
458894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
459894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Set pre-RA register scheduler default to BURR, which produces slightly
460894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // better code than the default (could also be TDRR, but TargetLowering.h
461894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // needs a mod to support that model):
462894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  setSchedulingPreference(Sched::RegPressure);
463894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
464894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
465894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanconst char *
466894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSPUTargetLowering::getTargetNodeName(unsigned Opcode) const
467894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman{
468894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (node_names.empty()) {
469894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    node_names[(unsigned) SPUISD::RET_FLAG] = "SPUISD::RET_FLAG";
470894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    node_names[(unsigned) SPUISD::Hi] = "SPUISD::Hi";
471894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    node_names[(unsigned) SPUISD::Lo] = "SPUISD::Lo";
472894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    node_names[(unsigned) SPUISD::PCRelAddr] = "SPUISD::PCRelAddr";
473894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    node_names[(unsigned) SPUISD::AFormAddr] = "SPUISD::AFormAddr";
474894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    node_names[(unsigned) SPUISD::IndirectAddr] = "SPUISD::IndirectAddr";
475894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    node_names[(unsigned) SPUISD::LDRESULT] = "SPUISD::LDRESULT";
476894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    node_names[(unsigned) SPUISD::CALL] = "SPUISD::CALL";
477894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    node_names[(unsigned) SPUISD::SHUFB] = "SPUISD::SHUFB";
478894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    node_names[(unsigned) SPUISD::SHUFFLE_MASK] = "SPUISD::SHUFFLE_MASK";
479894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    node_names[(unsigned) SPUISD::CNTB] = "SPUISD::CNTB";
480894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    node_names[(unsigned) SPUISD::PREFSLOT2VEC] = "SPUISD::PREFSLOT2VEC";
481894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    node_names[(unsigned) SPUISD::VEC2PREFSLOT] = "SPUISD::VEC2PREFSLOT";
48219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    node_names[(unsigned) SPUISD::SHL_BITS] = "SPUISD::SHL_BITS";
48319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    node_names[(unsigned) SPUISD::SHL_BYTES] = "SPUISD::SHL_BYTES";
484894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    node_names[(unsigned) SPUISD::VEC_ROTL] = "SPUISD::VEC_ROTL";
485894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    node_names[(unsigned) SPUISD::VEC_ROTR] = "SPUISD::VEC_ROTR";
486894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    node_names[(unsigned) SPUISD::ROTBYTES_LEFT] = "SPUISD::ROTBYTES_LEFT";
487894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    node_names[(unsigned) SPUISD::ROTBYTES_LEFT_BITS] =
488894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman            "SPUISD::ROTBYTES_LEFT_BITS";
489894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    node_names[(unsigned) SPUISD::SELECT_MASK] = "SPUISD::SELECT_MASK";
490894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    node_names[(unsigned) SPUISD::SELB] = "SPUISD::SELB";
491894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    node_names[(unsigned) SPUISD::ADD64_MARKER] = "SPUISD::ADD64_MARKER";
492894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    node_names[(unsigned) SPUISD::SUB64_MARKER] = "SPUISD::SUB64_MARKER";
493894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    node_names[(unsigned) SPUISD::MUL64_MARKER] = "SPUISD::MUL64_MARKER";
494894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
495894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
496894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  std::map<unsigned, const char *>::iterator i = node_names.find(Opcode);
497894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
498894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return ((i != node_names.end()) ? i->second : 0);
499894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
500894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
501894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===----------------------------------------------------------------------===//
502894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// Return the Cell SPU's SETCC result type
503894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===----------------------------------------------------------------------===//
504894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
50519bac1e08be200c31efd26f0f5fd144c9b3eefd3John BaumanEVT SPUTargetLowering::getSetCCResultType(EVT VT) const {
50619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // i8, i16 and i32 are valid SETCC result types
50719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  MVT::SimpleValueType retval;
50819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
50919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  switch(VT.getSimpleVT().SimpleTy){
51019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    case MVT::i1:
51119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    case MVT::i8:
51219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      retval = MVT::i8; break;
51319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    case MVT::i16:
51419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      retval = MVT::i16; break;
51519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    case MVT::i32:
51619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    default:
51719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      retval = MVT::i32;
51819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
51919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return retval;
520894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
521894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
522894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===----------------------------------------------------------------------===//
523894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// Calling convention code:
524894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===----------------------------------------------------------------------===//
525894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
526894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#include "SPUGenCallingConv.inc"
527894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
528894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===----------------------------------------------------------------------===//
529894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//  LowerOperation implementation
530894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===----------------------------------------------------------------------===//
531894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
532894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// Custom lower loads for CellSPU
533894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/*!
534894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman All CellSPU loads and stores are aligned to 16-byte boundaries, so for elements
535894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman within a 16-byte block, we have to rotate to extract the requested element.
536894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
537894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman For extending loads, we also want to ensure that the following sequence is
538894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman emitted, e.g. for MVT::f32 extending load to MVT::f64:
539894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
540894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman\verbatim
541894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman%1  v16i8,ch = load
542894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman%2  v16i8,ch = rotate %1
543894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman%3  v4f8, ch = bitconvert %2
544894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman%4  f32      = vec2perfslot %3
545894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman%5  f64      = fp_extend %4
546894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman\endverbatim
547894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman*/
548894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic SDValue
549894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanLowerLOAD(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
550894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  LoadSDNode *LN = cast<LoadSDNode>(Op);
551894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue the_chain = LN->getChain();
552894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
553894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT InVT = LN->getMemoryVT();
554894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT OutVT = Op.getValueType();
555894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  ISD::LoadExtType ExtType = LN->getExtensionType();
556894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  unsigned alignment = LN->getAlignment();
55719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  int pso = prefslotOffset(InVT);
558894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  DebugLoc dl = Op.getDebugLoc();
55919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  EVT vecVT = InVT.isVector()? InVT: EVT::getVectorVT(*DAG.getContext(), InVT,
56019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                                  (128 / InVT.getSizeInBits()));
56119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
56219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // two sanity checks
56319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  assert( LN->getAddressingMode() == ISD::UNINDEXED
56419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman          && "we should get only UNINDEXED adresses");
56519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // clean aligned loads can be selected as-is
56619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (InVT.getSizeInBits() == 128 && (alignment%16) == 0)
56719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return SDValue();
568894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
56919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // Get pointerinfos to the memory chunk(s) that contain the data to load
57019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  uint64_t mpi_offset = LN->getPointerInfo().Offset;
57119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  mpi_offset -= mpi_offset%16;
57219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  MachinePointerInfo lowMemPtr(LN->getPointerInfo().V, mpi_offset);
57319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  MachinePointerInfo highMemPtr(LN->getPointerInfo().V, mpi_offset+16);
574894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
57519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SDValue result;
57619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SDValue basePtr = LN->getBasePtr();
57719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SDValue rotate;
578894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
57919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if ((alignment%16) == 0) {
58019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    ConstantSDNode *CN;
581894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
58219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // Special cases for a known aligned load to simplify the base pointer
58319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // and the rotation amount:
58419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (basePtr.getOpcode() == ISD::ADD
58519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        && (CN = dyn_cast<ConstantSDNode > (basePtr.getOperand(1))) != 0) {
58619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      // Known offset into basePtr
58719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      int64_t offset = CN->getSExtValue();
58819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      int64_t rotamt = int64_t((offset & 0xf) - pso);
589894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
59019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      if (rotamt < 0)
59119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        rotamt += 16;
592894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
59319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      rotate = DAG.getConstant(rotamt, MVT::i16);
59419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
59519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      // Simplify the base pointer for this case:
59619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      basePtr = basePtr.getOperand(0);
59719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      if ((offset & ~0xf) > 0) {
598894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        basePtr = DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT,
599894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                              basePtr,
60019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                              DAG.getConstant((offset & ~0xf), PtrVT));
601894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      }
60219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    } else if ((basePtr.getOpcode() == SPUISD::AFormAddr)
60319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman               || (basePtr.getOpcode() == SPUISD::IndirectAddr
60419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                   && basePtr.getOperand(0).getOpcode() == SPUISD::Hi
60519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                   && basePtr.getOperand(1).getOpcode() == SPUISD::Lo)) {
60619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      // Plain aligned a-form address: rotate into preferred slot
60719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      // Same for (SPUindirect (SPUhi ...), (SPUlo ...))
60819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      int64_t rotamt = -pso;
60919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      if (rotamt < 0)
61019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        rotamt += 16;
61119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      rotate = DAG.getConstant(rotamt, MVT::i16);
61219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    } else {
613894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // Offset the rotate amount by the basePtr and the preferred slot
614894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // byte offset
61519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      int64_t rotamt = -pso;
61619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      if (rotamt < 0)
61719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        rotamt += 16;
618894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      rotate = DAG.getNode(ISD::ADD, dl, PtrVT,
619894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                           basePtr,
62019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                           DAG.getConstant(rotamt, PtrVT));
621894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
62219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  } else {
62319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // Unaligned load: must be more pessimistic about addressing modes:
62419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (basePtr.getOpcode() == ISD::ADD) {
62519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      MachineFunction &MF = DAG.getMachineFunction();
62619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      MachineRegisterInfo &RegInfo = MF.getRegInfo();
62719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
62819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      SDValue Flag;
62919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
63019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      SDValue Op0 = basePtr.getOperand(0);
63119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      SDValue Op1 = basePtr.getOperand(1);
63219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
63319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      if (isa<ConstantSDNode>(Op1)) {
63419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        // Convert the (add <ptr>, <const>) to an indirect address contained
63519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        // in a register. Note that this is done because we need to avoid
63619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        // creating a 0(reg) d-form address due to the SPU's block loads.
63719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        basePtr = DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT, Op0, Op1);
63819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        the_chain = DAG.getCopyToReg(the_chain, dl, VReg, basePtr, Flag);
63919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        basePtr = DAG.getCopyFromReg(the_chain, dl, VReg, PtrVT);
64019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      } else {
64119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        // Convert the (add <arg1>, <arg2>) to an indirect address, which
64219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        // will likely be lowered as a reg(reg) x-form address.
64319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        basePtr = DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT, Op0, Op1);
64419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      }
64519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    } else {
64619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      basePtr = DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT,
64719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                            basePtr,
64819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                            DAG.getConstant(0, PtrVT));
64919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman   }
65019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
65119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // Offset the rotate amount by the basePtr and the preferred slot
65219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // byte offset
65319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    rotate = DAG.getNode(ISD::ADD, dl, PtrVT,
65419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                         basePtr,
65519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                         DAG.getConstant(-pso, PtrVT));
65619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
65719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
65819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // Do the load as a i128 to allow possible shifting
65919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SDValue low = DAG.getLoad(MVT::i128, dl, the_chain, basePtr,
66019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                       lowMemPtr,
66119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                       LN->isVolatile(), LN->isNonTemporal(), 16);
66219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
66319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // When the size is not greater than alignment we get all data with just
66419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // one load
66519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (alignment >= InVT.getSizeInBits()/8) {
666894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Update the chain
66719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    the_chain = low.getValue(1);
668894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
669894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Rotate into the preferred slot:
67019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    result = DAG.getNode(SPUISD::ROTBYTES_LEFT, dl, MVT::i128,
67119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                         low.getValue(0), rotate);
672894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
673894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Convert the loaded v16i8 vector to the appropriate vector type
674894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // specified by the operand:
67519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    EVT vecVT = EVT::getVectorVT(*DAG.getContext(),
676894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                 InVT, (128 / InVT.getSizeInBits()));
677894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    result = DAG.getNode(SPUISD::VEC2PREFSLOT, dl, InVT,
67819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                         DAG.getNode(ISD::BITCAST, dl, vecVT, result));
67919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
68019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // When alignment is less than the size, we might need (known only at
68119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // run-time) two loads
68219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // TODO: if the memory address is composed only from constants, we have
68319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // extra kowledge, and might avoid the second load
68419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  else {
68519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // storage position offset from lower 16 byte aligned memory chunk
68619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    SDValue offset = DAG.getNode(ISD::AND, dl, MVT::i32,
68719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                  basePtr, DAG.getConstant( 0xf, MVT::i32 ) );
68819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // get a registerfull of ones. (this implementation is a workaround: LLVM
68919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // cannot handle 128 bit signed int constants)
69019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    SDValue ones = DAG.getConstant(-1, MVT::v4i32 );
69119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    ones = DAG.getNode(ISD::BITCAST, dl, MVT::i128, ones);
69219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
69319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    SDValue high = DAG.getLoad(MVT::i128, dl, the_chain,
69419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                               DAG.getNode(ISD::ADD, dl, PtrVT,
69519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                           basePtr,
69619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                           DAG.getConstant(16, PtrVT)),
69719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                               highMemPtr,
69819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                               LN->isVolatile(), LN->isNonTemporal(), 16);
69919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
70019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    the_chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, low.getValue(1),
70119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                                              high.getValue(1));
70219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
70319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // Shift the (possible) high part right to compensate the misalignemnt.
70419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // if there is no highpart (i.e. value is i64 and offset is 4), this
70519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // will zero out the high value.
70619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    high = DAG.getNode(SPUISD::SRL_BYTES, dl, MVT::i128, high,
70719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                     DAG.getNode(ISD::SUB, dl, MVT::i32,
70819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                                 DAG.getConstant( 16, MVT::i32),
70919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                                 offset
71019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                                ));
71119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
71219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // Shift the low similarly
71319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // TODO: add SPUISD::SHL_BYTES
71419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    low = DAG.getNode(SPUISD::SHL_BYTES, dl, MVT::i128, low, offset );
71519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
71619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // Merge the two parts
71719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    result = DAG.getNode(ISD::BITCAST, dl, vecVT,
71819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                          DAG.getNode(ISD::OR, dl, MVT::i128, low, high));
71919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
72019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (!InVT.isVector()) {
72119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      result = DAG.getNode(SPUISD::VEC2PREFSLOT, dl, InVT, result );
72219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman     }
723894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
72419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
725894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Handle extending loads by extending the scalar result:
726894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (ExtType == ISD::SEXTLOAD) {
727894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      result = DAG.getNode(ISD::SIGN_EXTEND, dl, OutVT, result);
728894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    } else if (ExtType == ISD::ZEXTLOAD) {
729894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      result = DAG.getNode(ISD::ZERO_EXTEND, dl, OutVT, result);
730894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    } else if (ExtType == ISD::EXTLOAD) {
731894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      unsigned NewOpc = ISD::ANY_EXTEND;
732894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
733894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      if (OutVT.isFloatingPoint())
734894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        NewOpc = ISD::FP_EXTEND;
735894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
736894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      result = DAG.getNode(NewOpc, dl, OutVT, result);
737894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
738894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
739894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDVTList retvts = DAG.getVTList(OutVT, MVT::Other);
740894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue retops[2] = {
741894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      result,
742894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      the_chain
743894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    };
744894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
745894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    result = DAG.getNode(SPUISD::LDRESULT, dl, retvts,
746894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                         retops, sizeof(retops) / sizeof(retops[0]));
747894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return result;
748894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
749894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
750894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// Custom lower stores for CellSPU
751894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/*!
752894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman All CellSPU stores are aligned to 16-byte boundaries, so for elements
753894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman within a 16-byte block, we have to generate a shuffle to insert the
754894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman requested element into its place, then store the resulting block.
755894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman */
756894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic SDValue
757894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanLowerSTORE(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
758894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  StoreSDNode *SN = cast<StoreSDNode>(Op);
759894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue Value = SN->getValue();
760894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT VT = Value.getValueType();
761894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT StVT = (!SN->isTruncatingStore() ? VT : SN->getMemoryVT());
762894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
763894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  DebugLoc dl = Op.getDebugLoc();
764894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  unsigned alignment = SN->getAlignment();
76519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SDValue result;
76619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  EVT vecVT = StVT.isVector()? StVT: EVT::getVectorVT(*DAG.getContext(), StVT,
76719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                                 (128 / StVT.getSizeInBits()));
76819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // Get pointerinfos to the memory chunk(s) that contain the data to load
76919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  uint64_t mpi_offset = SN->getPointerInfo().Offset;
77019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  mpi_offset -= mpi_offset%16;
77119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  MachinePointerInfo lowMemPtr(SN->getPointerInfo().V, mpi_offset);
77219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  MachinePointerInfo highMemPtr(SN->getPointerInfo().V, mpi_offset+16);
77319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
77419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
77519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // two sanity checks
77619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  assert( SN->getAddressingMode() == ISD::UNINDEXED
77719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman          && "we should get only UNINDEXED adresses");
77819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // clean aligned loads can be selected as-is
77919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (StVT.getSizeInBits() == 128 && (alignment%16) == 0)
78019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return SDValue();
781894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
78219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SDValue alignLoadVec;
78319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SDValue basePtr = SN->getBasePtr();
78419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SDValue the_chain = SN->getChain();
78519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SDValue insertEltOffs;
78619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
78719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if ((alignment%16) == 0) {
78819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    ConstantSDNode *CN;
78919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // Special cases for a known aligned load to simplify the base pointer
79019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // and insertion byte:
79119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (basePtr.getOpcode() == ISD::ADD
79219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        && (CN = dyn_cast<ConstantSDNode>(basePtr.getOperand(1))) != 0) {
79319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      // Known offset into basePtr
79419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      int64_t offset = CN->getSExtValue();
79519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
79619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      // Simplify the base pointer for this case:
79719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      basePtr = basePtr.getOperand(0);
79819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      insertEltOffs = DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT,
79919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                  basePtr,
80019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                  DAG.getConstant((offset & 0xf), PtrVT));
80119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
80219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      if ((offset & ~0xf) > 0) {
803894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        basePtr = DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT,
804894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                              basePtr,
80519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                              DAG.getConstant((offset & ~0xf), PtrVT));
806894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      }
80719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    } else {
80819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      // Otherwise, assume it's at byte 0 of basePtr
80919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      insertEltOffs = DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT,
81019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                  basePtr,
81119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                  DAG.getConstant(0, PtrVT));
81219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      basePtr = DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT,
813894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                  basePtr,
814894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                  DAG.getConstant(0, PtrVT));
815894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
81619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  } else {
81719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // Unaligned load: must be more pessimistic about addressing modes:
81819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (basePtr.getOpcode() == ISD::ADD) {
81919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      MachineFunction &MF = DAG.getMachineFunction();
82019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      MachineRegisterInfo &RegInfo = MF.getRegInfo();
82119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      unsigned VReg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
82219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      SDValue Flag;
82319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
82419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      SDValue Op0 = basePtr.getOperand(0);
82519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      SDValue Op1 = basePtr.getOperand(1);
82619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
82719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      if (isa<ConstantSDNode>(Op1)) {
82819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        // Convert the (add <ptr>, <const>) to an indirect address contained
82919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        // in a register. Note that this is done because we need to avoid
83019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        // creating a 0(reg) d-form address due to the SPU's block loads.
83119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        basePtr = DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT, Op0, Op1);
83219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        the_chain = DAG.getCopyToReg(the_chain, dl, VReg, basePtr, Flag);
83319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        basePtr = DAG.getCopyFromReg(the_chain, dl, VReg, PtrVT);
83419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      } else {
83519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        // Convert the (add <arg1>, <arg2>) to an indirect address, which
83619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        // will likely be lowered as a reg(reg) x-form address.
83719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        basePtr = DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT, Op0, Op1);
83819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      }
83919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    } else {
84019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      basePtr = DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT,
84119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                            basePtr,
84219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                            DAG.getConstant(0, PtrVT));
84319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    }
844894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
84519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // Insertion point is solely determined by basePtr's contents
84619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    insertEltOffs = DAG.getNode(ISD::ADD, dl, PtrVT,
84719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                basePtr,
84819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                DAG.getConstant(0, PtrVT));
84919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
850894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
85119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // Load the lower part of the memory to which to store.
85219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SDValue low = DAG.getLoad(vecVT, dl, the_chain, basePtr,
85319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                          lowMemPtr, SN->isVolatile(), SN->isNonTemporal(), 16);
85419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
85519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // if we don't need to store over the 16 byte boundary, one store suffices
85619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (alignment >= StVT.getSizeInBits()/8) {
857894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Update the chain
85819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    the_chain = low.getValue(1);
859894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
86019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    LoadSDNode *LN = cast<LoadSDNode>(low);
861894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue theValue = SN->getValue();
862894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
863894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (StVT != VT
864894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        && (theValue.getOpcode() == ISD::AssertZext
865894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman            || theValue.getOpcode() == ISD::AssertSext)) {
866894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // Drill down and get the value for zero- and sign-extended
867894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // quantities
868894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      theValue = theValue.getOperand(0);
869894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
870894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
871894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // If the base pointer is already a D-form address, then just create
872894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // a new D-form address with a slot offset and the orignal base pointer.
873894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Otherwise generate a D-form address with the slot offset relative
874894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // to the stack pointer, which is always aligned.
875894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#if !defined(NDEBUG)
876894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
877894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        errs() << "CellSPU LowerSTORE: basePtr = ";
878894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        basePtr.getNode()->dump(&DAG);
879894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        errs() << "\n";
880894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      }
881894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#endif
882894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
88319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    SDValue insertEltOp = DAG.getNode(SPUISD::SHUFFLE_MASK, dl, vecVT,
88419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                      insertEltOffs);
88519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    SDValue vectorizeOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, vecVT,
88619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                      theValue);
88719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
888894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    result = DAG.getNode(SPUISD::SHUFB, dl, vecVT,
88919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                         vectorizeOp, low,
89019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                         DAG.getNode(ISD::BITCAST, dl,
891894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                     MVT::v4i32, insertEltOp));
892894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
893894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    result = DAG.getStore(the_chain, dl, result, basePtr,
89419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                          lowMemPtr,
895894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                          LN->isVolatile(), LN->isNonTemporal(),
89619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                          16);
89719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
89819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
89919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // do the store when it might cross the 16 byte memory access boundary.
90019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  else {
90119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // TODO issue a warning if SN->isVolatile()== true? This is likely not
90219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // what the user wanted.
90319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
90419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // address offset from nearest lower 16byte alinged address
90519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    SDValue offset = DAG.getNode(ISD::AND, dl, MVT::i32,
90619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                    SN->getBasePtr(),
90719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                    DAG.getConstant(0xf, MVT::i32));
90819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // 16 - offset
90919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    SDValue offset_compl = DAG.getNode(ISD::SUB, dl, MVT::i32,
91019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                           DAG.getConstant( 16, MVT::i32),
91119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                           offset);
91219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // 16 - sizeof(Value)
91319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    SDValue surplus = DAG.getNode(ISD::SUB, dl, MVT::i32,
91419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                     DAG.getConstant( 16, MVT::i32),
91519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                     DAG.getConstant( VT.getSizeInBits()/8,
91619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                                      MVT::i32));
91719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // get a registerfull of ones
91819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    SDValue ones = DAG.getConstant(-1, MVT::v4i32);
91919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    ones = DAG.getNode(ISD::BITCAST, dl, MVT::i128, ones);
92019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
92119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // Create the 128 bit masks that have ones where the data to store is
92219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // located.
92319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    SDValue lowmask, himask;
92419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // if the value to store don't fill up the an entire 128 bits, zero
92519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // out the last bits of the mask so that only the value we want to store
92619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // is masked.
92719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // this is e.g. in the case of store i32, align 2
92819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (!VT.isVector()){
92919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      Value = DAG.getNode(SPUISD::PREFSLOT2VEC, dl, vecVT, Value);
93019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      lowmask = DAG.getNode(SPUISD::SRL_BYTES, dl, MVT::i128, ones, surplus);
93119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      lowmask = DAG.getNode(SPUISD::SHL_BYTES, dl, MVT::i128, lowmask,
93219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                                               surplus);
93319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      Value = DAG.getNode(ISD::BITCAST, dl, MVT::i128, Value);
93419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      Value = DAG.getNode(ISD::AND, dl, MVT::i128, Value, lowmask);
93519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
93619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    }
93719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    else {
93819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      lowmask = ones;
93919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      Value = DAG.getNode(ISD::BITCAST, dl, MVT::i128, Value);
94019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    }
94119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // this will zero, if there are no data that goes to the high quad
94219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    himask = DAG.getNode(SPUISD::SHL_BYTES, dl, MVT::i128, lowmask,
94319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                                            offset_compl);
94419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    lowmask = DAG.getNode(SPUISD::SRL_BYTES, dl, MVT::i128, lowmask,
94519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                                             offset);
94619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
94719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // Load in the old data and zero out the parts that will be overwritten with
94819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // the new data to store.
94919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    SDValue hi = DAG.getLoad(MVT::i128, dl, the_chain,
95019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                               DAG.getNode(ISD::ADD, dl, PtrVT, basePtr,
95119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                           DAG.getConstant( 16, PtrVT)),
95219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                               highMemPtr,
95319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                               SN->isVolatile(), SN->isNonTemporal(), 16);
95419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    the_chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, low.getValue(1),
95519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                                              hi.getValue(1));
95619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
95719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    low = DAG.getNode(ISD::AND, dl, MVT::i128,
95819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                        DAG.getNode( ISD::BITCAST, dl, MVT::i128, low),
95919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                        DAG.getNode( ISD::XOR, dl, MVT::i128, lowmask, ones));
96019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    hi = DAG.getNode(ISD::AND, dl, MVT::i128,
96119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                        DAG.getNode( ISD::BITCAST, dl, MVT::i128, hi),
96219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                        DAG.getNode( ISD::XOR, dl, MVT::i128, himask, ones));
96319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
96419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // Shift the Value to store into place. rlow contains the parts that go to
96519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // the lower memory chunk, rhi has the parts that go to the upper one.
96619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    SDValue rlow = DAG.getNode(SPUISD::SRL_BYTES, dl, MVT::i128, Value, offset);
96719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    rlow = DAG.getNode(ISD::AND, dl, MVT::i128, rlow, lowmask);
96819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    SDValue rhi = DAG.getNode(SPUISD::SHL_BYTES, dl, MVT::i128, Value,
96919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                                            offset_compl);
97019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
97119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // Merge the old data and the new data and store the results
97219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // Need to convert vectors here to integer as 'OR'ing floats assert
97319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    rlow = DAG.getNode(ISD::OR, dl, MVT::i128,
97419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                          DAG.getNode(ISD::BITCAST, dl, MVT::i128, low),
97519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                          DAG.getNode(ISD::BITCAST, dl, MVT::i128, rlow));
97619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    rhi = DAG.getNode(ISD::OR, dl, MVT::i128,
97719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                         DAG.getNode(ISD::BITCAST, dl, MVT::i128, hi),
97819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                         DAG.getNode(ISD::BITCAST, dl, MVT::i128, rhi));
97919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
98019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    low = DAG.getStore(the_chain, dl, rlow, basePtr,
98119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                          lowMemPtr,
98219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                          SN->isVolatile(), SN->isNonTemporal(), 16);
98319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    hi  = DAG.getStore(the_chain, dl, rhi,
98419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                            DAG.getNode(ISD::ADD, dl, PtrVT, basePtr,
98519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                        DAG.getConstant( 16, PtrVT)),
98619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                            highMemPtr,
98719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                            SN->isVolatile(), SN->isNonTemporal(), 16);
98819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    result = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, low.getValue(0),
98919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                                           hi.getValue(0));
990894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
991894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
99219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return result;
993894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
994894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
995894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//! Generate the address of a constant pool entry.
996894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic SDValue
997894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanLowerConstantPool(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
998894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT PtrVT = Op.getValueType();
999894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
1000894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  const Constant *C = CP->getConstVal();
1001894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment());
1002894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue Zero = DAG.getConstant(0, PtrVT);
1003894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  const TargetMachine &TM = DAG.getTarget();
1004894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // FIXME there is no actual debug info here
1005894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  DebugLoc dl = Op.getDebugLoc();
1006894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1007894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (TM.getRelocationModel() == Reloc::Static) {
1008894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (!ST->usingLargeMem()) {
1009894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // Just return the SDValue with the constant pool address in it.
1010894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      return DAG.getNode(SPUISD::AFormAddr, dl, PtrVT, CPI, Zero);
1011894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    } else {
1012894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SDValue Hi = DAG.getNode(SPUISD::Hi, dl, PtrVT, CPI, Zero);
1013894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SDValue Lo = DAG.getNode(SPUISD::Lo, dl, PtrVT, CPI, Zero);
1014894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      return DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT, Hi, Lo);
1015894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
1016894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1017894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1018894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  llvm_unreachable("LowerConstantPool: Relocation model other than static"
1019894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                   " not supported.");
1020894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return SDValue();
1021894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
1022894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1023894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//! Alternate entry point for generating the address of a constant pool entry
1024894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSDValue
1025894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSPU::LowerConstantPool(SDValue Op, SelectionDAG &DAG, const SPUTargetMachine &TM) {
1026894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return ::LowerConstantPool(Op, DAG, TM.getSubtargetImpl());
1027894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
1028894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1029894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic SDValue
1030894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanLowerJumpTable(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
1031894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT PtrVT = Op.getValueType();
1032894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
1033894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
1034894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue Zero = DAG.getConstant(0, PtrVT);
1035894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  const TargetMachine &TM = DAG.getTarget();
1036894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // FIXME there is no actual debug info here
1037894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  DebugLoc dl = Op.getDebugLoc();
1038894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1039894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (TM.getRelocationModel() == Reloc::Static) {
1040894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (!ST->usingLargeMem()) {
1041894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      return DAG.getNode(SPUISD::AFormAddr, dl, PtrVT, JTI, Zero);
1042894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    } else {
1043894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SDValue Hi = DAG.getNode(SPUISD::Hi, dl, PtrVT, JTI, Zero);
1044894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SDValue Lo = DAG.getNode(SPUISD::Lo, dl, PtrVT, JTI, Zero);
1045894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      return DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT, Hi, Lo);
1046894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
1047894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1048894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1049894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  llvm_unreachable("LowerJumpTable: Relocation model other than static"
1050894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                   " not supported.");
1051894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return SDValue();
1052894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
1053894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1054894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic SDValue
1055894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanLowerGlobalAddress(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) {
1056894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT PtrVT = Op.getValueType();
1057894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
1058894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  const GlobalValue *GV = GSDN->getGlobal();
1059894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue GA = DAG.getTargetGlobalAddress(GV, Op.getDebugLoc(),
1060894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                          PtrVT, GSDN->getOffset());
1061894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  const TargetMachine &TM = DAG.getTarget();
1062894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue Zero = DAG.getConstant(0, PtrVT);
1063894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // FIXME there is no actual debug info here
1064894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  DebugLoc dl = Op.getDebugLoc();
1065894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1066894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (TM.getRelocationModel() == Reloc::Static) {
1067894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (!ST->usingLargeMem()) {
1068894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      return DAG.getNode(SPUISD::AFormAddr, dl, PtrVT, GA, Zero);
1069894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    } else {
1070894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SDValue Hi = DAG.getNode(SPUISD::Hi, dl, PtrVT, GA, Zero);
1071894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SDValue Lo = DAG.getNode(SPUISD::Lo, dl, PtrVT, GA, Zero);
1072894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      return DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT, Hi, Lo);
1073894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
1074894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  } else {
1075894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    report_fatal_error("LowerGlobalAddress: Relocation model other than static"
1076894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                      "not supported.");
1077894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    /*NOTREACHED*/
1078894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1079894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1080894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return SDValue();
1081894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
1082894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1083894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//! Custom lower double precision floating point constants
1084894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic SDValue
1085894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanLowerConstantFP(SDValue Op, SelectionDAG &DAG) {
1086894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT VT = Op.getValueType();
1087894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // FIXME there is no actual debug info here
1088894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  DebugLoc dl = Op.getDebugLoc();
1089894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1090894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (VT == MVT::f64) {
1091894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ConstantFPSDNode *FP = cast<ConstantFPSDNode>(Op.getNode());
1092894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1093894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    assert((FP != 0) &&
1094894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman           "LowerConstantFP: Node is not ConstantFPSDNode");
1095894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1096894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    uint64_t dbits = DoubleToBits(FP->getValueAPF().convertToDouble());
1097894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue T = DAG.getConstant(dbits, MVT::i64);
1098894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue Tvec = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v2i64, T, T);
1099894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return DAG.getNode(SPUISD::VEC2PREFSLOT, dl, VT,
110019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                       DAG.getNode(ISD::BITCAST, dl, MVT::v2f64, Tvec));
1101894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1102894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1103894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return SDValue();
1104894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
1105894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1106894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSDValue
1107894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSPUTargetLowering::LowerFormalArguments(SDValue Chain,
1108894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                        CallingConv::ID CallConv, bool isVarArg,
1109894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                        const SmallVectorImpl<ISD::InputArg>
1110894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                          &Ins,
1111894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                        DebugLoc dl, SelectionDAG &DAG,
1112894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                        SmallVectorImpl<SDValue> &InVals)
1113894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                          const {
1114894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1115894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  MachineFunction &MF = DAG.getMachineFunction();
1116894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  MachineFrameInfo *MFI = MF.getFrameInfo();
1117894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  MachineRegisterInfo &RegInfo = MF.getRegInfo();
1118894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SPUFunctionInfo *FuncInfo = MF.getInfo<SPUFunctionInfo>();
1119894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
112019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  unsigned ArgOffset = SPUFrameLowering::minStackSize();
1121894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  unsigned ArgRegIdx = 0;
112219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  unsigned StackSlotSize = SPUFrameLowering::stackSlotSize();
1123894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1124894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
1125894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1126894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SmallVector<CCValAssign, 16> ArgLocs;
112719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
112819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		 getTargetMachine(), ArgLocs, *DAG.getContext());
1129894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // FIXME: allow for other calling conventions
1130894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  CCInfo.AnalyzeFormalArguments(Ins, CCC_SPU);
1131894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1132894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Add DAG nodes to load the arguments or copy them out of registers.
1133894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  for (unsigned ArgNo = 0, e = Ins.size(); ArgNo != e; ++ArgNo) {
1134894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    EVT ObjectVT = Ins[ArgNo].VT;
1135894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    unsigned ObjSize = ObjectVT.getSizeInBits()/8;
1136894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue ArgVal;
1137894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    CCValAssign &VA = ArgLocs[ArgNo];
1138894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1139894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (VA.isRegLoc()) {
1140894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      const TargetRegisterClass *ArgRegClass;
1141894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1142894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      switch (ObjectVT.getSimpleVT().SimpleTy) {
1143894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      default:
1144894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        report_fatal_error("LowerFormalArguments Unhandled argument type: " +
1145894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                           Twine(ObjectVT.getEVTString()));
1146894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      case MVT::i8:
1147894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        ArgRegClass = &SPU::R8CRegClass;
1148894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        break;
1149894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      case MVT::i16:
1150894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        ArgRegClass = &SPU::R16CRegClass;
1151894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        break;
1152894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      case MVT::i32:
1153894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        ArgRegClass = &SPU::R32CRegClass;
1154894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        break;
1155894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      case MVT::i64:
1156894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        ArgRegClass = &SPU::R64CRegClass;
1157894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        break;
1158894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      case MVT::i128:
1159894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        ArgRegClass = &SPU::GPRCRegClass;
1160894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        break;
1161894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      case MVT::f32:
1162894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        ArgRegClass = &SPU::R32FPRegClass;
1163894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        break;
1164894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      case MVT::f64:
1165894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        ArgRegClass = &SPU::R64FPRegClass;
1166894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        break;
1167894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      case MVT::v2f64:
1168894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      case MVT::v4f32:
1169894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      case MVT::v2i64:
1170894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      case MVT::v4i32:
1171894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      case MVT::v8i16:
1172894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      case MVT::v16i8:
1173894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        ArgRegClass = &SPU::VECREGRegClass;
1174894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        break;
1175894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      }
1176894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1177894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      unsigned VReg = RegInfo.createVirtualRegister(ArgRegClass);
1178894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      RegInfo.addLiveIn(VA.getLocReg(), VReg);
1179894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      ArgVal = DAG.getCopyFromReg(Chain, dl, VReg, ObjectVT);
1180894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      ++ArgRegIdx;
1181894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    } else {
1182894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // We need to load the argument to a virtual register if we determined
1183894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // above that we ran out of physical registers of the appropriate type
1184894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // or we're forced to do vararg
1185894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      int FI = MFI->CreateFixedObject(ObjSize, ArgOffset, true);
1186894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
118719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      ArgVal = DAG.getLoad(ObjectVT, dl, Chain, FIN, MachinePointerInfo(),
118819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                           false, false, 0);
1189894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      ArgOffset += StackSlotSize;
1190894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
1191894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1192894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    InVals.push_back(ArgVal);
1193894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Update the chain
1194894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    Chain = ArgVal.getOperand(0);
1195894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1196894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1197894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // vararg handling:
1198894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (isVarArg) {
119919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // FIXME: we should be able to query the argument registers from
120019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    //        tablegen generated code.
1201894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    static const unsigned ArgRegs[] = {
1202894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SPU::R3,  SPU::R4,  SPU::R5,  SPU::R6,  SPU::R7,  SPU::R8,  SPU::R9,
1203894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SPU::R10, SPU::R11, SPU::R12, SPU::R13, SPU::R14, SPU::R15, SPU::R16,
1204894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SPU::R17, SPU::R18, SPU::R19, SPU::R20, SPU::R21, SPU::R22, SPU::R23,
1205894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SPU::R24, SPU::R25, SPU::R26, SPU::R27, SPU::R28, SPU::R29, SPU::R30,
1206894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SPU::R31, SPU::R32, SPU::R33, SPU::R34, SPU::R35, SPU::R36, SPU::R37,
1207894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SPU::R38, SPU::R39, SPU::R40, SPU::R41, SPU::R42, SPU::R43, SPU::R44,
1208894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SPU::R45, SPU::R46, SPU::R47, SPU::R48, SPU::R49, SPU::R50, SPU::R51,
1209894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SPU::R52, SPU::R53, SPU::R54, SPU::R55, SPU::R56, SPU::R57, SPU::R58,
1210894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SPU::R59, SPU::R60, SPU::R61, SPU::R62, SPU::R63, SPU::R64, SPU::R65,
1211894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SPU::R66, SPU::R67, SPU::R68, SPU::R69, SPU::R70, SPU::R71, SPU::R72,
1212894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SPU::R73, SPU::R74, SPU::R75, SPU::R76, SPU::R77, SPU::R78, SPU::R79
1213894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    };
1214894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // size of ArgRegs array
1215894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    unsigned NumArgRegs = 77;
1216894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1217894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // We will spill (79-3)+1 registers to the stack
1218894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SmallVector<SDValue, 79-3+1> MemOps;
1219894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1220894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Create the frame slot
1221894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    for (; ArgRegIdx != NumArgRegs; ++ArgRegIdx) {
1222894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      FuncInfo->setVarArgsFrameIndex(
1223894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        MFI->CreateFixedObject(StackSlotSize, ArgOffset, true));
1224894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SDValue FIN = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), PtrVT);
122519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      unsigned VReg = MF.addLiveIn(ArgRegs[ArgRegIdx], &SPU::VECREGRegClass);
1226894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SDValue ArgVal = DAG.getRegister(VReg, MVT::v16i8);
122719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      SDValue Store = DAG.getStore(Chain, dl, ArgVal, FIN, MachinePointerInfo(),
1228894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                   false, false, 0);
1229894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      Chain = Store.getOperand(0);
1230894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      MemOps.push_back(Store);
1231894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1232894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // Increment address by stack slot size for the next stored argument
1233894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      ArgOffset += StackSlotSize;
1234894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
1235894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (!MemOps.empty())
1236894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
1237894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                          &MemOps[0], MemOps.size());
1238894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1239894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1240894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return Chain;
1241894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
1242894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1243894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// isLSAAddress - Return the immediate to use if the specified
1244894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// value is representable as a LSA address.
1245894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic SDNode *isLSAAddress(SDValue Op, SelectionDAG &DAG) {
1246894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
1247894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (!C) return 0;
1248894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1249894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  int Addr = C->getZExtValue();
1250894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if ((Addr & 3) != 0 ||  // Low 2 bits are implicitly zero.
1251894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      (Addr << 14 >> 14) != Addr)
1252894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return 0;  // Top 14 bits have to be sext of immediate.
1253894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1254894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return DAG.getConstant((int)C->getZExtValue() >> 2, MVT::i32).getNode();
1255894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
1256894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1257894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSDValue
1258894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSPUTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
1259894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                             CallingConv::ID CallConv, bool isVarArg,
1260894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                             bool &isTailCall,
1261894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                             const SmallVectorImpl<ISD::OutputArg> &Outs,
1262894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                             const SmallVectorImpl<SDValue> &OutVals,
1263894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                             const SmallVectorImpl<ISD::InputArg> &Ins,
1264894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                             DebugLoc dl, SelectionDAG &DAG,
1265894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                             SmallVectorImpl<SDValue> &InVals) const {
1266894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // CellSPU target does not yet support tail call optimization.
1267894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  isTailCall = false;
1268894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1269894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
1270894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  unsigned NumOps     = Outs.size();
127119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  unsigned StackSlotSize = SPUFrameLowering::stackSlotSize();
1272894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1273894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SmallVector<CCValAssign, 16> ArgLocs;
127419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
127519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		 getTargetMachine(), ArgLocs, *DAG.getContext());
1276894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // FIXME: allow for other calling conventions
1277894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  CCInfo.AnalyzeCallOperands(Outs, CCC_SPU);
127819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
1279894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  const unsigned NumArgRegs = ArgLocs.size();
1280894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1281894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1282894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Handy pointer type
1283894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
1284894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1285894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Set up a copy of the stack pointer for use loading and storing any
1286894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // arguments that may not fit in the registers available for argument
1287894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // passing.
1288894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue StackPtr = DAG.getRegister(SPU::R1, MVT::i32);
1289894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1290894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Figure out which arguments are going to go in registers, and which in
1291894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // memory.
129219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  unsigned ArgOffset = SPUFrameLowering::minStackSize(); // Just below [LR]
1293894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  unsigned ArgRegIdx = 0;
1294894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1295894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Keep track of registers passing arguments
1296894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  std::vector<std::pair<unsigned, SDValue> > RegsToPass;
1297894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // And the arguments passed on the stack
1298894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SmallVector<SDValue, 8> MemOpChains;
1299894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1300894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  for (; ArgRegIdx != NumOps; ++ArgRegIdx) {
1301894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue Arg = OutVals[ArgRegIdx];
1302894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    CCValAssign &VA = ArgLocs[ArgRegIdx];
1303894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1304894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // PtrOff will be used to store the current argument to the stack if a
1305894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // register cannot be found for it.
1306894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType());
1307894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    PtrOff = DAG.getNode(ISD::ADD, dl, PtrVT, StackPtr, PtrOff);
1308894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1309894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    switch (Arg.getValueType().getSimpleVT().SimpleTy) {
1310894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    default: llvm_unreachable("Unexpected ValueType for argument!");
1311894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::i8:
1312894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::i16:
1313894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::i32:
1314894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::i64:
1315894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::i128:
1316894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::f32:
1317894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::f64:
1318894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::v2i64:
1319894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::v2f64:
1320894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::v4f32:
1321894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::v4i32:
1322894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::v8i16:
1323894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::v16i8:
1324894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      if (ArgRegIdx != NumArgRegs) {
1325894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
1326894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      } else {
132719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff,
132819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                           MachinePointerInfo(),
1329894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                           false, false, 0));
1330894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        ArgOffset += StackSlotSize;
1331894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      }
1332894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      break;
1333894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
1334894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1335894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1336894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Accumulate how many bytes are to be pushed on the stack, including the
1337894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // linkage area, and parameter passing area.  According to the SPU ABI,
1338894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // we minimally need space for [LR] and [SP].
133919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  unsigned NumStackBytes = ArgOffset - SPUFrameLowering::minStackSize();
1340894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1341894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Insert a call sequence start
1342894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumStackBytes,
1343894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                                            true));
1344894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1345894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (!MemOpChains.empty()) {
1346894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Adjust the stack pointer for the stack arguments.
1347894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
1348894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                        &MemOpChains[0], MemOpChains.size());
1349894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1350894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1351894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Build a sequence of copy-to-reg nodes chained together with token chain
1352894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // and flag operands which copy the outgoing args into the appropriate regs.
1353894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue InFlag;
1354894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1355894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
1356894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                             RegsToPass[i].second, InFlag);
1357894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    InFlag = Chain.getValue(1);
1358894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1359894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1360894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SmallVector<SDValue, 8> Ops;
1361894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  unsigned CallOpc = SPUISD::CALL;
1362894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1363894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
1364894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
1365894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // node so that legalize doesn't hack it.
1366894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
1367894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    const GlobalValue *GV = G->getGlobal();
1368894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    EVT CalleeVT = Callee.getValueType();
1369894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue Zero = DAG.getConstant(0, PtrVT);
1370894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue GA = DAG.getTargetGlobalAddress(GV, dl, CalleeVT);
1371894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1372894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (!ST->usingLargeMem()) {
1373894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // Turn calls to targets that are defined (i.e., have bodies) into BRSL
1374894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // style calls, otherwise, external symbols are BRASL calls. This assumes
1375894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // that declared/defined symbols are in the same compilation unit and can
1376894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // be reached through PC-relative jumps.
1377894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      //
1378894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // NOTE:
1379894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // This may be an unsafe assumption for JIT and really large compilation
1380894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // units.
1381894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      if (GV->isDeclaration()) {
1382894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        Callee = DAG.getNode(SPUISD::AFormAddr, dl, CalleeVT, GA, Zero);
1383894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      } else {
1384894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        Callee = DAG.getNode(SPUISD::PCRelAddr, dl, CalleeVT, GA, Zero);
1385894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      }
1386894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    } else {
1387894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // "Large memory" mode: Turn all calls into indirect calls with a X-form
1388894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // address pairs:
1389894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      Callee = DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT, GA, Zero);
1390894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
1391894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
1392894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    EVT CalleeVT = Callee.getValueType();
1393894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue Zero = DAG.getConstant(0, PtrVT);
1394894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue ExtSym = DAG.getTargetExternalSymbol(S->getSymbol(),
1395894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        Callee.getValueType());
1396894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1397894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (!ST->usingLargeMem()) {
1398894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      Callee = DAG.getNode(SPUISD::AFormAddr, dl, CalleeVT, ExtSym, Zero);
1399894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    } else {
1400894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      Callee = DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT, ExtSym, Zero);
1401894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
1402894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  } else if (SDNode *Dest = isLSAAddress(Callee, DAG)) {
1403894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // If this is an absolute destination address that appears to be a legal
1404894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // local store address, use the munged value.
1405894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    Callee = SDValue(Dest, 0);
1406894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1407894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1408894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  Ops.push_back(Chain);
1409894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  Ops.push_back(Callee);
1410894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1411894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Add argument registers to the end of the list so that they are known live
1412894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // into the call.
1413894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
1414894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    Ops.push_back(DAG.getRegister(RegsToPass[i].first,
1415894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                  RegsToPass[i].second.getValueType()));
1416894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1417894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (InFlag.getNode())
1418894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    Ops.push_back(InFlag);
1419894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Returns a chain and a flag for retval copy to use.
142019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  Chain = DAG.getNode(CallOpc, dl, DAG.getVTList(MVT::Other, MVT::Glue),
1421894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                      &Ops[0], Ops.size());
1422894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  InFlag = Chain.getValue(1);
1423894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1424894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumStackBytes, true),
1425894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                             DAG.getIntPtrConstant(0, true), InFlag);
1426894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (!Ins.empty())
1427894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    InFlag = Chain.getValue(1);
1428894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1429894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // If the function returns void, just return the chain.
1430894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (Ins.empty())
1431894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return Chain;
1432894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
143319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // Now handle the return value(s)
143419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SmallVector<CCValAssign, 16> RVLocs;
143519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  CCState CCRetInfo(CallConv, isVarArg, DAG.getMachineFunction(),
143619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		    getTargetMachine(), RVLocs, *DAG.getContext());
143719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  CCRetInfo.AnalyzeCallResult(Ins, CCC_SPU);
143819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
143919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
1440894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // If the call has results, copy the values out of the ret val registers.
144119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  for (unsigned i = 0; i != RVLocs.size(); ++i) {
144219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    CCValAssign VA = RVLocs[i];
144319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
144419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    SDValue Val = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getLocVT(),
144519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                     InFlag);
144619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    Chain = Val.getValue(1);
144719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    InFlag = Val.getValue(2);
144819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    InVals.push_back(Val);
144919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman   }
1450894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1451894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return Chain;
1452894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
1453894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1454894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSDValue
1455894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSPUTargetLowering::LowerReturn(SDValue Chain,
1456894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                               CallingConv::ID CallConv, bool isVarArg,
1457894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                               const SmallVectorImpl<ISD::OutputArg> &Outs,
1458894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                               const SmallVectorImpl<SDValue> &OutVals,
1459894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                               DebugLoc dl, SelectionDAG &DAG) const {
1460894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1461894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SmallVector<CCValAssign, 16> RVLocs;
146219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
146319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman		 getTargetMachine(), RVLocs, *DAG.getContext());
1464894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  CCInfo.AnalyzeReturn(Outs, RetCC_SPU);
1465894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1466894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // If this is the first return lowered for this function, add the regs to the
1467894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // liveout set for the function.
1468894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
1469894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    for (unsigned i = 0; i != RVLocs.size(); ++i)
1470894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
1471894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1472894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1473894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue Flag;
1474894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1475894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Copy the result values into the output registers.
1476894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  for (unsigned i = 0; i != RVLocs.size(); ++i) {
1477894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    CCValAssign &VA = RVLocs[i];
1478894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    assert(VA.isRegLoc() && "Can only return in registers!");
1479894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(),
1480894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                             OutVals[i], Flag);
1481894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    Flag = Chain.getValue(1);
1482894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1483894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1484894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (Flag.getNode())
1485894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return DAG.getNode(SPUISD::RET_FLAG, dl, MVT::Other, Chain, Flag);
1486894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  else
1487894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return DAG.getNode(SPUISD::RET_FLAG, dl, MVT::Other, Chain);
1488894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
1489894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1490894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1491894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===----------------------------------------------------------------------===//
1492894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// Vector related lowering:
1493894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===----------------------------------------------------------------------===//
1494894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1495894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic ConstantSDNode *
1496894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumangetVecImm(SDNode *N) {
1497894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue OpVal(0, 0);
1498894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1499894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Check to see if this buildvec has a single non-undef value in its elements.
1500894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
1501894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue;
1502894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (OpVal.getNode() == 0)
1503894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      OpVal = N->getOperand(i);
1504894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    else if (OpVal != N->getOperand(i))
1505894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      return 0;
1506894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1507894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1508894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (OpVal.getNode() != 0) {
1509894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) {
1510894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      return CN;
1511894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
1512894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1513894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1514894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return 0;
1515894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
1516894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1517894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// get_vec_i18imm - Test if this vector is a vector filled with the same value
1518894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// and the value fits into an unsigned 18-bit constant, and if so, return the
1519894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// constant
1520894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSDValue SPU::get_vec_u18imm(SDNode *N, SelectionDAG &DAG,
1521894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                              EVT ValueType) {
1522894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (ConstantSDNode *CN = getVecImm(N)) {
1523894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    uint64_t Value = CN->getZExtValue();
1524894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (ValueType == MVT::i64) {
1525894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      uint64_t UValue = CN->getZExtValue();
1526894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      uint32_t upper = uint32_t(UValue >> 32);
1527894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      uint32_t lower = uint32_t(UValue);
1528894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      if (upper != lower)
1529894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        return SDValue();
1530894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      Value = Value >> 32;
1531894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
1532894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (Value <= 0x3ffff)
1533894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      return DAG.getTargetConstant(Value, ValueType);
1534894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1535894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1536894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return SDValue();
1537894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
1538894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1539894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// get_vec_i16imm - Test if this vector is a vector filled with the same value
1540894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// and the value fits into a signed 16-bit constant, and if so, return the
1541894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// constant
1542894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSDValue SPU::get_vec_i16imm(SDNode *N, SelectionDAG &DAG,
1543894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                              EVT ValueType) {
1544894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (ConstantSDNode *CN = getVecImm(N)) {
1545894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    int64_t Value = CN->getSExtValue();
1546894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (ValueType == MVT::i64) {
1547894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      uint64_t UValue = CN->getZExtValue();
1548894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      uint32_t upper = uint32_t(UValue >> 32);
1549894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      uint32_t lower = uint32_t(UValue);
1550894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      if (upper != lower)
1551894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        return SDValue();
1552894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      Value = Value >> 32;
1553894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
1554894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (Value >= -(1 << 15) && Value <= ((1 << 15) - 1)) {
1555894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      return DAG.getTargetConstant(Value, ValueType);
1556894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
1557894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1558894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1559894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return SDValue();
1560894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
1561894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1562894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// get_vec_i10imm - Test if this vector is a vector filled with the same value
1563894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// and the value fits into a signed 10-bit constant, and if so, return the
1564894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// constant
1565894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSDValue SPU::get_vec_i10imm(SDNode *N, SelectionDAG &DAG,
1566894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                              EVT ValueType) {
1567894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (ConstantSDNode *CN = getVecImm(N)) {
1568894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    int64_t Value = CN->getSExtValue();
1569894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (ValueType == MVT::i64) {
1570894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      uint64_t UValue = CN->getZExtValue();
1571894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      uint32_t upper = uint32_t(UValue >> 32);
1572894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      uint32_t lower = uint32_t(UValue);
1573894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      if (upper != lower)
1574894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        return SDValue();
1575894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      Value = Value >> 32;
1576894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
1577894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (isInt<10>(Value))
1578894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      return DAG.getTargetConstant(Value, ValueType);
1579894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1580894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1581894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return SDValue();
1582894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
1583894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1584894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// get_vec_i8imm - Test if this vector is a vector filled with the same value
1585894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// and the value fits into a signed 8-bit constant, and if so, return the
1586894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// constant.
1587894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman///
1588894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// @note: The incoming vector is v16i8 because that's the only way we can load
1589894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// constant vectors. Thus, we test to see if the upper and lower bytes are the
1590894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// same value.
1591894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSDValue SPU::get_vec_i8imm(SDNode *N, SelectionDAG &DAG,
1592894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                             EVT ValueType) {
1593894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (ConstantSDNode *CN = getVecImm(N)) {
1594894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    int Value = (int) CN->getZExtValue();
1595894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (ValueType == MVT::i16
1596894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        && Value <= 0xffff                 /* truncated from uint64_t */
1597894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        && ((short) Value >> 8) == ((short) Value & 0xff))
1598894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      return DAG.getTargetConstant(Value & 0xff, ValueType);
1599894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    else if (ValueType == MVT::i8
1600894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman             && (Value & 0xff) == Value)
1601894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      return DAG.getTargetConstant(Value, ValueType);
1602894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1603894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1604894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return SDValue();
1605894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
1606894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1607894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// get_ILHUvec_imm - Test if this vector is a vector filled with the same value
1608894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// and the value fits into a signed 16-bit constant, and if so, return the
1609894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// constant
1610894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSDValue SPU::get_ILHUvec_imm(SDNode *N, SelectionDAG &DAG,
1611894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                               EVT ValueType) {
1612894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (ConstantSDNode *CN = getVecImm(N)) {
1613894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    uint64_t Value = CN->getZExtValue();
1614894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if ((ValueType == MVT::i32
1615894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          && ((unsigned) Value & 0xffff0000) == (unsigned) Value)
1616894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        || (ValueType == MVT::i64 && (Value & 0xffff0000) == Value))
1617894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      return DAG.getTargetConstant(Value >> 16, ValueType);
1618894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1619894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1620894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return SDValue();
1621894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
1622894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1623894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// get_v4i32_imm - Catch-all for general 32-bit constant vectors
1624894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSDValue SPU::get_v4i32_imm(SDNode *N, SelectionDAG &DAG) {
1625894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (ConstantSDNode *CN = getVecImm(N)) {
1626894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i32);
1627894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1628894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1629894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return SDValue();
1630894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
1631894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1632894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// get_v4i32_imm - Catch-all for general 64-bit constant vectors
1633894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSDValue SPU::get_v2i64_imm(SDNode *N, SelectionDAG &DAG) {
1634894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (ConstantSDNode *CN = getVecImm(N)) {
1635894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return DAG.getTargetConstant((unsigned) CN->getZExtValue(), MVT::i64);
1636894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1637894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1638894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return SDValue();
1639894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
1640894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1641894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//! Lower a BUILD_VECTOR instruction creatively:
1642894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic SDValue
1643894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanLowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
1644894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT VT = Op.getValueType();
1645894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT EltVT = VT.getVectorElementType();
1646894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  DebugLoc dl = Op.getDebugLoc();
1647894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  BuildVectorSDNode *BCN = dyn_cast<BuildVectorSDNode>(Op.getNode());
1648894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  assert(BCN != 0 && "Expected BuildVectorSDNode in SPU LowerBUILD_VECTOR");
1649894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  unsigned minSplatBits = EltVT.getSizeInBits();
1650894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1651894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (minSplatBits < 16)
1652894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    minSplatBits = 16;
1653894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1654894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  APInt APSplatBits, APSplatUndef;
1655894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  unsigned SplatBitSize;
1656894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  bool HasAnyUndefs;
1657894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1658894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (!BCN->isConstantSplat(APSplatBits, APSplatUndef, SplatBitSize,
1659894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                            HasAnyUndefs, minSplatBits)
1660894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      || minSplatBits < SplatBitSize)
1661894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return SDValue();   // Wasn't a constant vector or splat exceeded min
1662894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1663894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  uint64_t SplatBits = APSplatBits.getZExtValue();
1664894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1665894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  switch (VT.getSimpleVT().SimpleTy) {
1666894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  default:
1667894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    report_fatal_error("CellSPU: Unhandled VT in LowerBUILD_VECTOR, VT = " +
1668894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                       Twine(VT.getEVTString()));
1669894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    /*NOTREACHED*/
1670894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case MVT::v4f32: {
1671894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    uint32_t Value32 = uint32_t(SplatBits);
1672894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    assert(SplatBitSize == 32
1673894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman           && "LowerBUILD_VECTOR: Unexpected floating point vector element.");
1674894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // NOTE: pretend the constant is an integer. LLVM won't load FP constants
1675894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue T = DAG.getConstant(Value32, MVT::i32);
167619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return DAG.getNode(ISD::BITCAST, dl, MVT::v4f32,
1677894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                       DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, T,T,T,T));
1678894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    break;
1679894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1680894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case MVT::v2f64: {
1681894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    uint64_t f64val = uint64_t(SplatBits);
1682894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    assert(SplatBitSize == 64
1683894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman           && "LowerBUILD_VECTOR: 64-bit float vector size > 8 bytes.");
1684894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // NOTE: pretend the constant is an integer. LLVM won't load FP constants
1685894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue T = DAG.getConstant(f64val, MVT::i64);
168619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return DAG.getNode(ISD::BITCAST, dl, MVT::v2f64,
1687894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                       DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v2i64, T, T));
1688894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    break;
1689894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1690894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case MVT::v16i8: {
1691894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman   // 8-bit constants have to be expanded to 16-bits
1692894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman   unsigned short Value16 = SplatBits /* | (SplatBits << 8) */;
1693894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman   SmallVector<SDValue, 8> Ops;
1694894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1695894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman   Ops.assign(8, DAG.getConstant(Value16, MVT::i16));
169619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman   return DAG.getNode(ISD::BITCAST, dl, VT,
1697894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                      DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v8i16, &Ops[0], Ops.size()));
1698894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1699894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case MVT::v8i16: {
1700894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    unsigned short Value16 = SplatBits;
1701894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue T = DAG.getConstant(Value16, EltVT);
1702894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SmallVector<SDValue, 8> Ops;
1703894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1704894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    Ops.assign(8, T);
1705894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return DAG.getNode(ISD::BUILD_VECTOR, dl, VT, &Ops[0], Ops.size());
1706894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1707894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case MVT::v4i32: {
1708894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue T = DAG.getConstant(unsigned(SplatBits), VT.getVectorElementType());
1709894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return DAG.getNode(ISD::BUILD_VECTOR, dl, VT, T, T, T, T);
1710894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1711894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case MVT::v2i64: {
1712894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return SPU::LowerV2I64Splat(VT, DAG, SplatBits, dl);
1713894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1714894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1715894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1716894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return SDValue();
1717894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
1718894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1719894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/*!
1720894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman */
1721894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSDValue
1722894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSPU::LowerV2I64Splat(EVT OpVT, SelectionDAG& DAG, uint64_t SplatVal,
1723894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                     DebugLoc dl) {
1724894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  uint32_t upper = uint32_t(SplatVal >> 32);
1725894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  uint32_t lower = uint32_t(SplatVal);
1726894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1727894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (upper == lower) {
1728894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Magic constant that can be matched by IL, ILA, et. al.
1729894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue Val = DAG.getTargetConstant(upper, MVT::i32);
173019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return DAG.getNode(ISD::BITCAST, dl, OpVT,
1731894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                       DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
1732894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                   Val, Val, Val, Val));
1733894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  } else {
1734894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    bool upper_special, lower_special;
1735894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1736894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // NOTE: This code creates common-case shuffle masks that can be easily
1737894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // detected as common expressions. It is not attempting to create highly
1738894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // specialized masks to replace any and all 0's, 0xff's and 0x80's.
1739894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1740894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Detect if the upper or lower half is a special shuffle mask pattern:
1741894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    upper_special = (upper == 0 || upper == 0xffffffff || upper == 0x80000000);
1742894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    lower_special = (lower == 0 || lower == 0xffffffff || lower == 0x80000000);
1743894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1744894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Both upper and lower are special, lower to a constant pool load:
1745894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (lower_special && upper_special) {
1746894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SDValue SplatValCN = DAG.getConstant(SplatVal, MVT::i64);
1747894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      return DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v2i64,
1748894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                         SplatValCN, SplatValCN);
1749894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
1750894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1751894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue LO32;
1752894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue HI32;
1753894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SmallVector<SDValue, 16> ShufBytes;
1754894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue Result;
1755894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1756894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Create lower vector if not a special pattern
1757894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (!lower_special) {
1758894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SDValue LO32C = DAG.getConstant(lower, MVT::i32);
175919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      LO32 = DAG.getNode(ISD::BITCAST, dl, OpVT,
1760894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                         DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
1761894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                     LO32C, LO32C, LO32C, LO32C));
1762894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
1763894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1764894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Create upper vector if not a special pattern
1765894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (!upper_special) {
1766894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SDValue HI32C = DAG.getConstant(upper, MVT::i32);
176719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      HI32 = DAG.getNode(ISD::BITCAST, dl, OpVT,
1768894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                         DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
1769894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                     HI32C, HI32C, HI32C, HI32C));
1770894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
1771894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1772894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // If either upper or lower are special, then the two input operands are
1773894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // the same (basically, one of them is a "don't care")
1774894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (lower_special)
1775894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      LO32 = HI32;
1776894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (upper_special)
1777894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      HI32 = LO32;
1778894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1779894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    for (int i = 0; i < 4; ++i) {
1780894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      uint64_t val = 0;
1781894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      for (int j = 0; j < 4; ++j) {
1782894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        SDValue V;
1783894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        bool process_upper, process_lower;
1784894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        val <<= 8;
1785894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        process_upper = (upper_special && (i & 1) == 0);
1786894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        process_lower = (lower_special && (i & 1) == 1);
1787894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1788894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        if (process_upper || process_lower) {
1789894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          if ((process_upper && upper == 0)
1790894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                  || (process_lower && lower == 0))
1791894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman            val |= 0x80;
1792894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          else if ((process_upper && upper == 0xffffffff)
1793894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                  || (process_lower && lower == 0xffffffff))
1794894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman            val |= 0xc0;
1795894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          else if ((process_upper && upper == 0x80000000)
1796894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                  || (process_lower && lower == 0x80000000))
1797894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman            val |= (j == 0 ? 0xe0 : 0x80);
1798894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        } else
1799894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          val |= i * 4 + j + ((i & 1) * 16);
1800894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      }
1801894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1802894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      ShufBytes.push_back(DAG.getConstant(val, MVT::i32));
1803894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
1804894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1805894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return DAG.getNode(SPUISD::SHUFB, dl, OpVT, HI32, LO32,
1806894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                       DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
1807894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                   &ShufBytes[0], ShufBytes.size()));
1808894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1809894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
1810894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1811894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// LowerVECTOR_SHUFFLE - Lower a vector shuffle (V1, V2, V3) to something on
1812894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// which the Cell can operate. The code inspects V3 to ascertain whether the
1813894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// permutation vector, V3, is monotonically increasing with one "exception"
1814894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// element, e.g., (0, 1, _, 3). If this is the case, then generate a
1815894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// SHUFFLE_MASK synthetic instruction. Otherwise, spill V3 to the constant pool.
1816894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// In either case, the net result is going to eventually invoke SHUFB to
1817894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// permute/shuffle the bytes from V1 and V2.
1818894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// \note
1819894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// SHUFFLE_MASK is eventually selected as one of the C*D instructions, generate
1820894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// control word for byte/halfword/word insertion. This takes care of a single
1821894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// element move from V2 into V1.
1822894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// \note
1823894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// SPUISD::SHUFB is eventually selected as Cell's <i>shufb</i> instructions.
1824894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) {
1825894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  const ShuffleVectorSDNode *SVN = cast<ShuffleVectorSDNode>(Op);
1826894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue V1 = Op.getOperand(0);
1827894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue V2 = Op.getOperand(1);
1828894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  DebugLoc dl = Op.getDebugLoc();
1829894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1830894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (V2.getOpcode() == ISD::UNDEF) V2 = V1;
1831894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1832894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // If we have a single element being moved from V1 to V2, this can be handled
1833894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // using the C*[DX] compute mask instructions, but the vector elements have
183419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // to be monotonically increasing with one exception element, and the source
183519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // slot of the element to move must be the same as the destination.
1836894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT VecVT = V1.getValueType();
1837894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT EltVT = VecVT.getVectorElementType();
1838894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  unsigned EltsFromV2 = 0;
183919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  unsigned V2EltOffset = 0;
1840894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  unsigned V2EltIdx0 = 0;
1841894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  unsigned CurrElt = 0;
1842894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  unsigned MaxElts = VecVT.getVectorNumElements();
1843894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  unsigned PrevElt = 0;
1844894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  bool monotonic = true;
1845894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  bool rotate = true;
184619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  int rotamt=0;
1847894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT maskVT;             // which of the c?d instructions to use
1848894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1849894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (EltVT == MVT::i8) {
1850894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    V2EltIdx0 = 16;
185119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    maskVT = MVT::v16i8;
1852894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  } else if (EltVT == MVT::i16) {
1853894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    V2EltIdx0 = 8;
1854894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    maskVT = MVT::v8i16;
1855894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  } else if (EltVT == MVT::i32 || EltVT == MVT::f32) {
1856894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    V2EltIdx0 = 4;
1857894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    maskVT = MVT::v4i32;
1858894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  } else if (EltVT == MVT::i64 || EltVT == MVT::f64) {
1859894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    V2EltIdx0 = 2;
1860894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    maskVT = MVT::v2i64;
1861894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  } else
1862894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    llvm_unreachable("Unhandled vector type in LowerVECTOR_SHUFFLE");
1863894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1864894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  for (unsigned i = 0; i != MaxElts; ++i) {
1865894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (SVN->getMaskElt(i) < 0)
1866894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      continue;
186719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
1868894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    unsigned SrcElt = SVN->getMaskElt(i);
1869894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1870894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (monotonic) {
1871894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      if (SrcElt >= V2EltIdx0) {
187219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        // TODO: optimize for the monotonic case when several consecutive
187319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        // elements are taken form V2. Do we ever get such a case?
187419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        if (EltsFromV2 == 0 && CurrElt == (SrcElt - V2EltIdx0))
187519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman          V2EltOffset = (SrcElt - V2EltIdx0) * (EltVT.getSizeInBits()/8);
187619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        else
187719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman          monotonic = false;
187819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        ++EltsFromV2;
1879894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      } else if (CurrElt != SrcElt) {
1880894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        monotonic = false;
1881894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      }
1882894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1883894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      ++CurrElt;
1884894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
1885894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1886894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (rotate) {
1887894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      if (PrevElt > 0 && SrcElt < MaxElts) {
1888894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        if ((PrevElt == SrcElt - 1)
1889894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman            || (PrevElt == MaxElts - 1 && SrcElt == 0)) {
1890894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          PrevElt = SrcElt;
1891894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        } else {
1892894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          rotate = false;
1893894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        }
189419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      } else if (i == 0 || (PrevElt==0 && SrcElt==1)) {
189519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        // First time or after a "wrap around"
189619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        rotamt = SrcElt-i;
1897894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        PrevElt = SrcElt;
1898894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      } else {
1899894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        // This isn't a rotation, takes elements from vector 2
1900894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        rotate = false;
1901894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      }
1902894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
1903894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1904894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1905894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (EltsFromV2 == 1 && monotonic) {
1906894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Compute mask and shuffle
1907894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
1908894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1909894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // As SHUFFLE_MASK becomes a c?d instruction, feed it an address
1910894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // R1 ($sp) is used here only as it is guaranteed to have last bits zero
1911894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue Pointer = DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT,
1912894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                DAG.getRegister(SPU::R1, PtrVT),
191319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                DAG.getConstant(V2EltOffset, MVT::i32));
191419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    SDValue ShufMaskOp = DAG.getNode(SPUISD::SHUFFLE_MASK, dl,
1915894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                     maskVT, Pointer);
1916894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1917894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Use shuffle mask in SHUFB synthetic instruction:
1918894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return DAG.getNode(SPUISD::SHUFB, dl, V1.getValueType(), V2, V1,
1919894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                       ShufMaskOp);
1920894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  } else if (rotate) {
192119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (rotamt < 0)
192219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      rotamt +=MaxElts;
192319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    rotamt *= EltVT.getSizeInBits()/8;
1924894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return DAG.getNode(SPUISD::ROTBYTES_LEFT, dl, V1.getValueType(),
1925894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                       V1, DAG.getConstant(rotamt, MVT::i16));
1926894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  } else {
1927894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman   // Convert the SHUFFLE_VECTOR mask's input element units to the
1928894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman   // actual bytes.
1929894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    unsigned BytesPerElement = EltVT.getSizeInBits()/8;
1930894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1931894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SmallVector<SDValue, 16> ResultMask;
1932894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    for (unsigned i = 0, e = MaxElts; i != e; ++i) {
1933894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      unsigned SrcElt = SVN->getMaskElt(i) < 0 ? 0 : SVN->getMaskElt(i);
1934894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1935894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      for (unsigned j = 0; j < BytesPerElement; ++j)
1936894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j,MVT::i8));
1937894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
1938894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v16i8,
1939894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                    &ResultMask[0], ResultMask.size());
1940894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return DAG.getNode(SPUISD::SHUFB, dl, V1.getValueType(), V1, V2, VPermMask);
1941894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1942894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
1943894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1944894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) {
1945894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue Op0 = Op.getOperand(0);                     // Op0 = the scalar
1946894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  DebugLoc dl = Op.getDebugLoc();
1947894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1948894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (Op0.getNode()->getOpcode() == ISD::Constant) {
1949894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // For a constant, build the appropriate constant vector, which will
1950894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // eventually simplify to a vector register load.
1951894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1952894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ConstantSDNode *CN = cast<ConstantSDNode>(Op0.getNode());
1953894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SmallVector<SDValue, 16> ConstVecValues;
1954894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    EVT VT;
1955894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    size_t n_copies;
1956894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1957894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Create a constant vector:
1958894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    switch (Op.getValueType().getSimpleVT().SimpleTy) {
1959894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    default: llvm_unreachable("Unexpected constant value type in "
1960894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                              "LowerSCALAR_TO_VECTOR");
1961894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::v16i8: n_copies = 16; VT = MVT::i8; break;
1962894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::v8i16: n_copies = 8; VT = MVT::i16; break;
1963894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::v4i32: n_copies = 4; VT = MVT::i32; break;
1964894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::v4f32: n_copies = 4; VT = MVT::f32; break;
1965894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::v2i64: n_copies = 2; VT = MVT::i64; break;
1966894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::v2f64: n_copies = 2; VT = MVT::f64; break;
1967894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
1968894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1969894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue CValue = DAG.getConstant(CN->getZExtValue(), VT);
1970894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    for (size_t j = 0; j < n_copies; ++j)
1971894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      ConstVecValues.push_back(CValue);
1972894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1973894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return DAG.getNode(ISD::BUILD_VECTOR, dl, Op.getValueType(),
1974894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                       &ConstVecValues[0], ConstVecValues.size());
1975894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  } else {
1976894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Otherwise, copy the value from one register to another:
1977894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    switch (Op0.getValueType().getSimpleVT().SimpleTy) {
1978894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    default: llvm_unreachable("Unexpected value type in LowerSCALAR_TO_VECTOR");
1979894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::i8:
1980894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::i16:
1981894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::i32:
1982894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::i64:
1983894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::f32:
1984894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::f64:
1985894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      return DAG.getNode(SPUISD::PREFSLOT2VEC, dl, Op.getValueType(), Op0, Op0);
1986894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
1987894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
1988894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1989894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return SDValue();
1990894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
1991894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1992894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
1993894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT VT = Op.getValueType();
1994894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue N = Op.getOperand(0);
1995894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue Elt = Op.getOperand(1);
1996894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  DebugLoc dl = Op.getDebugLoc();
1997894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue retval;
1998894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
1999894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Elt)) {
2000894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Constant argument:
2001894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    int EltNo = (int) C->getZExtValue();
2002894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2003894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // sanity checks:
2004894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (VT == MVT::i8 && EltNo >= 16)
2005894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      llvm_unreachable("SPU LowerEXTRACT_VECTOR_ELT: i8 extraction slot > 15");
2006894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    else if (VT == MVT::i16 && EltNo >= 8)
2007894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      llvm_unreachable("SPU LowerEXTRACT_VECTOR_ELT: i16 extraction slot > 7");
2008894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    else if (VT == MVT::i32 && EltNo >= 4)
2009894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      llvm_unreachable("SPU LowerEXTRACT_VECTOR_ELT: i32 extraction slot > 4");
2010894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    else if (VT == MVT::i64 && EltNo >= 2)
2011894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      llvm_unreachable("SPU LowerEXTRACT_VECTOR_ELT: i64 extraction slot > 2");
2012894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2013894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (EltNo == 0 && (VT == MVT::i32 || VT == MVT::i64)) {
2014894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // i32 and i64: Element 0 is the preferred slot
2015894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      return DAG.getNode(SPUISD::VEC2PREFSLOT, dl, VT, N);
2016894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
2017894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2018894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Need to generate shuffle mask and extract:
2019894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    int prefslot_begin = -1, prefslot_end = -1;
2020894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    int elt_byte = EltNo * VT.getSizeInBits() / 8;
2021894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2022894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    switch (VT.getSimpleVT().SimpleTy) {
2023894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    default:
2024894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      assert(false && "Invalid value type!");
2025894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::i8: {
2026894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      prefslot_begin = prefslot_end = 3;
2027894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      break;
2028894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
2029894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::i16: {
2030894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      prefslot_begin = 2; prefslot_end = 3;
2031894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      break;
2032894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
2033894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::i32:
2034894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::f32: {
2035894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      prefslot_begin = 0; prefslot_end = 3;
2036894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      break;
2037894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
2038894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::i64:
2039894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::f64: {
2040894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      prefslot_begin = 0; prefslot_end = 7;
2041894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      break;
2042894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
2043894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
2044894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2045894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    assert(prefslot_begin != -1 && prefslot_end != -1 &&
2046894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman           "LowerEXTRACT_VECTOR_ELT: preferred slots uninitialized");
2047894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2048894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    unsigned int ShufBytes[16] = {
2049894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
2050894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    };
2051894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    for (int i = 0; i < 16; ++i) {
2052894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // zero fill uppper part of preferred slot, don't care about the
2053894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // other slots:
2054894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      unsigned int mask_val;
2055894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      if (i <= prefslot_end) {
2056894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        mask_val =
2057894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          ((i < prefslot_begin)
2058894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman           ? 0x80
2059894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman           : elt_byte + (i - prefslot_begin));
2060894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2061894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        ShufBytes[i] = mask_val;
2062894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      } else
2063894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        ShufBytes[i] = ShufBytes[i % (prefslot_end + 1)];
2064894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
2065894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2066894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue ShufMask[4];
2067894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    for (unsigned i = 0; i < sizeof(ShufMask)/sizeof(ShufMask[0]); ++i) {
2068894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      unsigned bidx = i * 4;
2069894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      unsigned int bits = ((ShufBytes[bidx] << 24) |
2070894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                           (ShufBytes[bidx+1] << 16) |
2071894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                           (ShufBytes[bidx+2] << 8) |
2072894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                           ShufBytes[bidx+3]);
2073894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      ShufMask[i] = DAG.getConstant(bits, MVT::i32);
2074894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
2075894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2076894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue ShufMaskVec =
2077894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
2078894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                  &ShufMask[0], sizeof(ShufMask)/sizeof(ShufMask[0]));
2079894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2080894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    retval = DAG.getNode(SPUISD::VEC2PREFSLOT, dl, VT,
2081894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                         DAG.getNode(SPUISD::SHUFB, dl, N.getValueType(),
2082894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                     N, N, ShufMaskVec));
2083894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  } else {
2084894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Variable index: Rotate the requested element into slot 0, then replicate
2085894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // slot 0 across the vector
2086894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    EVT VecVT = N.getValueType();
2087894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (!VecVT.isSimple() || !VecVT.isVector()) {
2088894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      report_fatal_error("LowerEXTRACT_VECTOR_ELT: Must have a simple, 128-bit"
2089894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                        "vector type!");
2090894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
2091894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2092894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Make life easier by making sure the index is zero-extended to i32
2093894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (Elt.getValueType() != MVT::i32)
2094894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      Elt = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i32, Elt);
2095894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2096894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Scale the index to a bit/byte shift quantity
2097894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    APInt scaleFactor =
2098894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman            APInt(32, uint64_t(16 / N.getValueType().getVectorNumElements()), false);
2099894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    unsigned scaleShift = scaleFactor.logBase2();
2100894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue vecShift;
2101894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2102894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (scaleShift > 0) {
2103894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // Scale the shift factor:
2104894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      Elt = DAG.getNode(ISD::SHL, dl, MVT::i32, Elt,
2105894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                        DAG.getConstant(scaleShift, MVT::i32));
2106894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
2107894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
210819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    vecShift = DAG.getNode(SPUISD::SHL_BYTES, dl, VecVT, N, Elt);
2109894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2110894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Replicate the bytes starting at byte 0 across the entire vector (for
2111894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // consistency with the notion of a unified register set)
2112894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue replicate;
2113894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2114894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    switch (VT.getSimpleVT().SimpleTy) {
2115894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    default:
2116894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      report_fatal_error("LowerEXTRACT_VECTOR_ELT(varable): Unhandled vector"
2117894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                        "type");
2118894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      /*NOTREACHED*/
2119894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::i8: {
2120894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SDValue factor = DAG.getConstant(0x00000000, MVT::i32);
2121894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      replicate = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
2122894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                              factor, factor, factor, factor);
2123894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      break;
2124894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
2125894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::i16: {
2126894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SDValue factor = DAG.getConstant(0x00010001, MVT::i32);
2127894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      replicate = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
2128894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                              factor, factor, factor, factor);
2129894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      break;
2130894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
2131894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::i32:
2132894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::f32: {
2133894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SDValue factor = DAG.getConstant(0x00010203, MVT::i32);
2134894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      replicate = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
2135894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                              factor, factor, factor, factor);
2136894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      break;
2137894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
2138894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::i64:
2139894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case MVT::f64: {
2140894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SDValue loFactor = DAG.getConstant(0x00010203, MVT::i32);
2141894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SDValue hiFactor = DAG.getConstant(0x04050607, MVT::i32);
2142894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      replicate = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
2143894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                              loFactor, hiFactor, loFactor, hiFactor);
2144894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      break;
2145894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
2146894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
2147894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2148894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    retval = DAG.getNode(SPUISD::VEC2PREFSLOT, dl, VT,
2149894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                         DAG.getNode(SPUISD::SHUFB, dl, VecVT,
2150894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                     vecShift, vecShift, replicate));
2151894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
2152894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2153894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return retval;
2154894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
2155894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2156894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
2157894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue VecOp = Op.getOperand(0);
2158894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue ValOp = Op.getOperand(1);
2159894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue IdxOp = Op.getOperand(2);
2160894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  DebugLoc dl = Op.getDebugLoc();
2161894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT VT = Op.getValueType();
216219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  EVT eltVT = ValOp.getValueType();
2163894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2164894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // use 0 when the lane to insert to is 'undef'
216519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  int64_t Offset=0;
2166894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (IdxOp.getOpcode() != ISD::UNDEF) {
2167894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    ConstantSDNode *CN = cast<ConstantSDNode>(IdxOp);
2168894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    assert(CN != 0 && "LowerINSERT_VECTOR_ELT: Index is not constant!");
216919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    Offset = (CN->getSExtValue()) * eltVT.getSizeInBits()/8;
2170894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
2171894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2172894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
2173894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Use $sp ($1) because it's always 16-byte aligned and it's available:
2174894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue Pointer = DAG.getNode(SPUISD::IndirectAddr, dl, PtrVT,
2175894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                DAG.getRegister(SPU::R1, PtrVT),
217619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                DAG.getConstant(Offset, PtrVT));
2177894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // widen the mask when dealing with half vectors
217819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  EVT maskVT = EVT::getVectorVT(*(DAG.getContext()), VT.getVectorElementType(),
2179894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                128/ VT.getVectorElementType().getSizeInBits());
2180894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue ShufMask = DAG.getNode(SPUISD::SHUFFLE_MASK, dl, maskVT, Pointer);
2181894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2182894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue result =
2183894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    DAG.getNode(SPUISD::SHUFB, dl, VT,
2184894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, ValOp),
2185894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                VecOp,
218619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                DAG.getNode(ISD::BITCAST, dl, MVT::v4i32, ShufMask));
2187894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2188894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return result;
2189894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
2190894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2191894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc,
2192894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                           const TargetLowering &TLI)
2193894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman{
2194894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue N0 = Op.getOperand(0);      // Everything has at least one operand
2195894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  DebugLoc dl = Op.getDebugLoc();
219619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  EVT ShiftVT = TLI.getShiftAmountTy(N0.getValueType());
2197894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2198894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  assert(Op.getValueType() == MVT::i8);
2199894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  switch (Opc) {
2200894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  default:
2201894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    llvm_unreachable("Unhandled i8 math operator");
2202894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    /*NOTREACHED*/
2203894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    break;
2204894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::ADD: {
2205894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // 8-bit addition: Promote the arguments up to 16-bits and truncate
2206894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // the result:
2207894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue N1 = Op.getOperand(1);
2208894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    N0 = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i16, N0);
2209894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    N1 = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i16, N1);
2210894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return DAG.getNode(ISD::TRUNCATE, dl, MVT::i8,
2211894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                       DAG.getNode(Opc, dl, MVT::i16, N0, N1));
2212894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2213894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
2214894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2215894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::SUB: {
2216894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // 8-bit subtraction: Promote the arguments up to 16-bits and truncate
2217894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // the result:
2218894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue N1 = Op.getOperand(1);
2219894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    N0 = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i16, N0);
2220894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    N1 = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i16, N1);
2221894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return DAG.getNode(ISD::TRUNCATE, dl, MVT::i8,
2222894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                       DAG.getNode(Opc, dl, MVT::i16, N0, N1));
2223894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
2224894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::ROTR:
2225894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::ROTL: {
2226894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue N1 = Op.getOperand(1);
2227894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    EVT N1VT = N1.getValueType();
2228894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2229894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    N0 = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i16, N0);
2230894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (!N1VT.bitsEq(ShiftVT)) {
2231894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      unsigned N1Opc = N1.getValueType().bitsLT(ShiftVT)
2232894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                       ? ISD::ZERO_EXTEND
2233894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                       : ISD::TRUNCATE;
2234894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      N1 = DAG.getNode(N1Opc, dl, ShiftVT, N1);
2235894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
2236894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2237894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Replicate lower 8-bits into upper 8:
2238894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue ExpandArg =
2239894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      DAG.getNode(ISD::OR, dl, MVT::i16, N0,
2240894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                  DAG.getNode(ISD::SHL, dl, MVT::i16,
2241894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                              N0, DAG.getConstant(8, MVT::i32)));
2242894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2243894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Truncate back down to i8
2244894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return DAG.getNode(ISD::TRUNCATE, dl, MVT::i8,
2245894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                       DAG.getNode(Opc, dl, MVT::i16, ExpandArg, N1));
2246894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
2247894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::SRL:
2248894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::SHL: {
2249894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue N1 = Op.getOperand(1);
2250894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    EVT N1VT = N1.getValueType();
2251894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2252894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    N0 = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i16, N0);
2253894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (!N1VT.bitsEq(ShiftVT)) {
2254894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      unsigned N1Opc = ISD::ZERO_EXTEND;
2255894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2256894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      if (N1.getValueType().bitsGT(ShiftVT))
2257894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        N1Opc = ISD::TRUNCATE;
2258894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2259894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      N1 = DAG.getNode(N1Opc, dl, ShiftVT, N1);
2260894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
2261894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2262894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return DAG.getNode(ISD::TRUNCATE, dl, MVT::i8,
2263894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                       DAG.getNode(Opc, dl, MVT::i16, N0, N1));
2264894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
2265894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::SRA: {
2266894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue N1 = Op.getOperand(1);
2267894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    EVT N1VT = N1.getValueType();
2268894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2269894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    N0 = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i16, N0);
2270894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (!N1VT.bitsEq(ShiftVT)) {
2271894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      unsigned N1Opc = ISD::SIGN_EXTEND;
2272894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2273894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      if (N1VT.bitsGT(ShiftVT))
2274894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        N1Opc = ISD::TRUNCATE;
2275894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      N1 = DAG.getNode(N1Opc, dl, ShiftVT, N1);
2276894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
2277894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2278894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return DAG.getNode(ISD::TRUNCATE, dl, MVT::i8,
2279894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                       DAG.getNode(Opc, dl, MVT::i16, N0, N1));
2280894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
2281894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::MUL: {
2282894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue N1 = Op.getOperand(1);
2283894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2284894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    N0 = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i16, N0);
2285894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    N1 = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i16, N1);
2286894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return DAG.getNode(ISD::TRUNCATE, dl, MVT::i8,
2287894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                       DAG.getNode(Opc, dl, MVT::i16, N0, N1));
2288894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    break;
2289894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
2290894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
2291894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2292894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return SDValue();
2293894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
2294894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2295894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//! Lower byte immediate operations for v16i8 vectors:
2296894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic SDValue
2297894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanLowerByteImmed(SDValue Op, SelectionDAG &DAG) {
2298894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue ConstVec;
2299894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue Arg;
2300894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT VT = Op.getValueType();
2301894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  DebugLoc dl = Op.getDebugLoc();
2302894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2303894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  ConstVec = Op.getOperand(0);
2304894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  Arg = Op.getOperand(1);
2305894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (ConstVec.getNode()->getOpcode() != ISD::BUILD_VECTOR) {
230619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (ConstVec.getNode()->getOpcode() == ISD::BITCAST) {
2307894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      ConstVec = ConstVec.getOperand(0);
2308894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    } else {
2309894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      ConstVec = Op.getOperand(1);
2310894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      Arg = Op.getOperand(0);
231119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      if (ConstVec.getNode()->getOpcode() == ISD::BITCAST) {
2312894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        ConstVec = ConstVec.getOperand(0);
2313894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      }
2314894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
2315894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
2316894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2317894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (ConstVec.getNode()->getOpcode() == ISD::BUILD_VECTOR) {
2318894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    BuildVectorSDNode *BCN = dyn_cast<BuildVectorSDNode>(ConstVec.getNode());
2319894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    assert(BCN != 0 && "Expected BuildVectorSDNode in SPU LowerByteImmed");
2320894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2321894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    APInt APSplatBits, APSplatUndef;
2322894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    unsigned SplatBitSize;
2323894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    bool HasAnyUndefs;
2324894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    unsigned minSplatBits = VT.getVectorElementType().getSizeInBits();
2325894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2326894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (BCN->isConstantSplat(APSplatBits, APSplatUndef, SplatBitSize,
2327894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                              HasAnyUndefs, minSplatBits)
2328894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        && minSplatBits <= SplatBitSize) {
2329894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      uint64_t SplatBits = APSplatBits.getZExtValue();
2330894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SDValue tc = DAG.getTargetConstant(SplatBits & 0xff, MVT::i8);
2331894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2332894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SmallVector<SDValue, 16> tcVec;
2333894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      tcVec.assign(16, tc);
2334894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      return DAG.getNode(Op.getNode()->getOpcode(), dl, VT, Arg,
2335894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                         DAG.getNode(ISD::BUILD_VECTOR, dl, VT, &tcVec[0], tcVec.size()));
2336894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
2337894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
2338894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2339894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // These operations (AND, OR, XOR) are legal, they just couldn't be custom
2340894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // lowered.  Return the operation, rather than a null SDValue.
2341894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return Op;
2342894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
2343894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2344894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//! Custom lowering for CTPOP (count population)
2345894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/*!
2346894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  Custom lowering code that counts the number ones in the input
2347894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  operand. SPU has such an instruction, but it counts the number of
2348894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  ones per byte, which then have to be accumulated.
2349894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman*/
2350894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic SDValue LowerCTPOP(SDValue Op, SelectionDAG &DAG) {
2351894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT VT = Op.getValueType();
235219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  EVT vecVT = EVT::getVectorVT(*DAG.getContext(),
2353894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                               VT, (128 / VT.getSizeInBits()));
2354894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  DebugLoc dl = Op.getDebugLoc();
2355894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2356894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  switch (VT.getSimpleVT().SimpleTy) {
2357894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  default:
2358894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    assert(false && "Invalid value type!");
2359894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case MVT::i8: {
2360894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue N = Op.getOperand(0);
2361894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2362894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2363894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue Promote = DAG.getNode(SPUISD::PREFSLOT2VEC, dl, vecVT, N, N);
2364894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue CNTB = DAG.getNode(SPUISD::CNTB, dl, vecVT, Promote);
2365894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2366894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i8, CNTB, Elt0);
2367894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
2368894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2369894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case MVT::i16: {
2370894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    MachineFunction &MF = DAG.getMachineFunction();
2371894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    MachineRegisterInfo &RegInfo = MF.getRegInfo();
2372894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2373894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R16CRegClass);
2374894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2375894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue N = Op.getOperand(0);
2376894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue Elt0 = DAG.getConstant(0, MVT::i16);
2377894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue Mask0 = DAG.getConstant(0x0f, MVT::i16);
2378894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue Shift1 = DAG.getConstant(8, MVT::i32);
2379894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2380894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue Promote = DAG.getNode(SPUISD::PREFSLOT2VEC, dl, vecVT, N, N);
2381894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue CNTB = DAG.getNode(SPUISD::CNTB, dl, vecVT, Promote);
2382894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2383894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // CNTB_result becomes the chain to which all of the virtual registers
2384894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // CNTB_reg, SUM1_reg become associated:
2385894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue CNTB_result =
2386894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i16, CNTB, Elt0);
2387894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2388894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue CNTB_rescopy =
2389894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      DAG.getCopyToReg(CNTB_result, dl, CNTB_reg, CNTB_result);
2390894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2391894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue Tmp1 = DAG.getCopyFromReg(CNTB_rescopy, dl, CNTB_reg, MVT::i16);
2392894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2393894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return DAG.getNode(ISD::AND, dl, MVT::i16,
2394894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                       DAG.getNode(ISD::ADD, dl, MVT::i16,
2395894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                   DAG.getNode(ISD::SRL, dl, MVT::i16,
2396894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                               Tmp1, Shift1),
2397894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                   Tmp1),
2398894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                       Mask0);
2399894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
2400894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2401894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case MVT::i32: {
2402894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    MachineFunction &MF = DAG.getMachineFunction();
2403894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    MachineRegisterInfo &RegInfo = MF.getRegInfo();
2404894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2405894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    unsigned CNTB_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2406894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    unsigned SUM1_reg = RegInfo.createVirtualRegister(&SPU::R32CRegClass);
2407894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2408894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue N = Op.getOperand(0);
2409894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue Elt0 = DAG.getConstant(0, MVT::i32);
2410894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue Mask0 = DAG.getConstant(0xff, MVT::i32);
2411894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue Shift1 = DAG.getConstant(16, MVT::i32);
2412894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue Shift2 = DAG.getConstant(8, MVT::i32);
2413894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2414894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue Promote = DAG.getNode(SPUISD::PREFSLOT2VEC, dl, vecVT, N, N);
2415894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue CNTB = DAG.getNode(SPUISD::CNTB, dl, vecVT, Promote);
2416894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2417894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // CNTB_result becomes the chain to which all of the virtual registers
2418894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // CNTB_reg, SUM1_reg become associated:
2419894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue CNTB_result =
2420894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i32, CNTB, Elt0);
2421894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2422894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue CNTB_rescopy =
2423894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      DAG.getCopyToReg(CNTB_result, dl, CNTB_reg, CNTB_result);
2424894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2425894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue Comp1 =
2426894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      DAG.getNode(ISD::SRL, dl, MVT::i32,
2427894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                  DAG.getCopyFromReg(CNTB_rescopy, dl, CNTB_reg, MVT::i32),
2428894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                  Shift1);
2429894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2430894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue Sum1 =
2431894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      DAG.getNode(ISD::ADD, dl, MVT::i32, Comp1,
2432894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                  DAG.getCopyFromReg(CNTB_rescopy, dl, CNTB_reg, MVT::i32));
2433894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2434894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue Sum1_rescopy =
2435894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      DAG.getCopyToReg(CNTB_result, dl, SUM1_reg, Sum1);
2436894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2437894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue Comp2 =
2438894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      DAG.getNode(ISD::SRL, dl, MVT::i32,
2439894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                  DAG.getCopyFromReg(Sum1_rescopy, dl, SUM1_reg, MVT::i32),
2440894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                  Shift2);
2441894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue Sum2 =
2442894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      DAG.getNode(ISD::ADD, dl, MVT::i32, Comp2,
2443894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                  DAG.getCopyFromReg(Sum1_rescopy, dl, SUM1_reg, MVT::i32));
2444894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2445894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return DAG.getNode(ISD::AND, dl, MVT::i32, Sum2, Mask0);
2446894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
2447894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2448894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case MVT::i64:
2449894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    break;
2450894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
2451894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2452894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return SDValue();
2453894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
2454894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2455894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//! Lower ISD::FP_TO_SINT, ISD::FP_TO_UINT for i32
2456894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/*!
2457894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman f32->i32 passes through unchanged, whereas f64->i32 expands to a libcall.
2458894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman All conversions to i64 are expanded to a libcall.
2459894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman */
2460894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic SDValue LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG,
2461894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                              const SPUTargetLowering &TLI) {
2462894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT OpVT = Op.getValueType();
2463894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue Op0 = Op.getOperand(0);
2464894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT Op0VT = Op0.getValueType();
2465894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2466894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if ((OpVT == MVT::i32 && Op0VT == MVT::f64)
2467894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      || OpVT == MVT::i64) {
2468894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Convert f32 / f64 to i32 / i64 via libcall.
2469894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    RTLIB::Libcall LC =
2470894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman            (Op.getOpcode() == ISD::FP_TO_SINT)
2471894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman             ? RTLIB::getFPTOSINT(Op0VT, OpVT)
2472894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman             : RTLIB::getFPTOUINT(Op0VT, OpVT);
2473894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unexpectd fp-to-int conversion!");
2474894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue Dummy;
2475894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return ExpandLibCall(LC, Op, DAG, false, Dummy, TLI);
2476894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
2477894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2478894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return Op;
2479894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
2480894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2481894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//! Lower ISD::SINT_TO_FP, ISD::UINT_TO_FP for i32
2482894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/*!
2483894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman i32->f32 passes through unchanged, whereas i32->f64 is expanded to a libcall.
2484894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman All conversions from i64 are expanded to a libcall.
2485894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman */
2486894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic SDValue LowerINT_TO_FP(SDValue Op, SelectionDAG &DAG,
2487894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                              const SPUTargetLowering &TLI) {
2488894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT OpVT = Op.getValueType();
2489894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue Op0 = Op.getOperand(0);
2490894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT Op0VT = Op0.getValueType();
2491894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2492894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if ((OpVT == MVT::f64 && Op0VT == MVT::i32)
2493894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      || Op0VT == MVT::i64) {
2494894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Convert i32, i64 to f64 via libcall:
2495894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    RTLIB::Libcall LC =
2496894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman            (Op.getOpcode() == ISD::SINT_TO_FP)
2497894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman             ? RTLIB::getSINTTOFP(Op0VT, OpVT)
2498894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman             : RTLIB::getUINTTOFP(Op0VT, OpVT);
2499894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unexpectd int-to-fp conversion!");
2500894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue Dummy;
2501894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return ExpandLibCall(LC, Op, DAG, false, Dummy, TLI);
2502894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
2503894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2504894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return Op;
2505894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
2506894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2507894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//! Lower ISD::SETCC
2508894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/*!
2509894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman This handles MVT::f64 (double floating point) condition lowering
2510894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman */
2511894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG,
2512894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                          const TargetLowering &TLI) {
2513894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  CondCodeSDNode *CC = dyn_cast<CondCodeSDNode>(Op.getOperand(2));
2514894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  DebugLoc dl = Op.getDebugLoc();
2515894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  assert(CC != 0 && "LowerSETCC: CondCodeSDNode should not be null here!\n");
2516894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2517894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue lhs = Op.getOperand(0);
2518894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue rhs = Op.getOperand(1);
2519894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT lhsVT = lhs.getValueType();
2520894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  assert(lhsVT == MVT::f64 && "LowerSETCC: type other than MVT::64\n");
2521894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2522894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT ccResultVT = TLI.getSetCCResultType(lhs.getValueType());
2523894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  APInt ccResultOnes = APInt::getAllOnesValue(ccResultVT.getSizeInBits());
2524894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT IntVT(MVT::i64);
2525894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2526894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Take advantage of the fact that (truncate (sra arg, 32)) is efficiently
2527894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // selected to a NOP:
252819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SDValue i64lhs = DAG.getNode(ISD::BITCAST, dl, IntVT, lhs);
2529894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue lhsHi32 =
2530894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          DAG.getNode(ISD::TRUNCATE, dl, MVT::i32,
2531894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                      DAG.getNode(ISD::SRL, dl, IntVT,
2532894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                  i64lhs, DAG.getConstant(32, MVT::i32)));
2533894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue lhsHi32abs =
2534894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          DAG.getNode(ISD::AND, dl, MVT::i32,
2535894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                      lhsHi32, DAG.getConstant(0x7fffffff, MVT::i32));
2536894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue lhsLo32 =
2537894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, i64lhs);
2538894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2539894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // SETO and SETUO only use the lhs operand:
2540894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (CC->get() == ISD::SETO) {
2541894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Evaluates to true if Op0 is not [SQ]NaN - lowers to the inverse of
2542894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // SETUO
2543894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    APInt ccResultAllOnes = APInt::getAllOnesValue(ccResultVT.getSizeInBits());
2544894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return DAG.getNode(ISD::XOR, dl, ccResultVT,
2545894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                       DAG.getSetCC(dl, ccResultVT,
2546894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                    lhs, DAG.getConstantFP(0.0, lhsVT),
2547894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                    ISD::SETUO),
2548894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                       DAG.getConstant(ccResultAllOnes, ccResultVT));
2549894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  } else if (CC->get() == ISD::SETUO) {
2550894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Evaluates to true if Op0 is [SQ]NaN
2551894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return DAG.getNode(ISD::AND, dl, ccResultVT,
2552894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                       DAG.getSetCC(dl, ccResultVT,
2553894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                    lhsHi32abs,
2554894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                    DAG.getConstant(0x7ff00000, MVT::i32),
2555894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                    ISD::SETGE),
2556894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                       DAG.getSetCC(dl, ccResultVT,
2557894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                    lhsLo32,
2558894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                    DAG.getConstant(0, MVT::i32),
2559894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                    ISD::SETGT));
2560894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
2561894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
256219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SDValue i64rhs = DAG.getNode(ISD::BITCAST, dl, IntVT, rhs);
2563894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue rhsHi32 =
2564894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          DAG.getNode(ISD::TRUNCATE, dl, MVT::i32,
2565894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                      DAG.getNode(ISD::SRL, dl, IntVT,
2566894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                  i64rhs, DAG.getConstant(32, MVT::i32)));
2567894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2568894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // If a value is negative, subtract from the sign magnitude constant:
2569894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue signMag2TC = DAG.getConstant(0x8000000000000000ULL, IntVT);
2570894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2571894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Convert the sign-magnitude representation into 2's complement:
2572894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue lhsSelectMask = DAG.getNode(ISD::SRA, dl, ccResultVT,
2573894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                      lhsHi32, DAG.getConstant(31, MVT::i32));
2574894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue lhsSignMag2TC = DAG.getNode(ISD::SUB, dl, IntVT, signMag2TC, i64lhs);
2575894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue lhsSelect =
2576894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          DAG.getNode(ISD::SELECT, dl, IntVT,
2577894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                      lhsSelectMask, lhsSignMag2TC, i64lhs);
2578894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2579894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue rhsSelectMask = DAG.getNode(ISD::SRA, dl, ccResultVT,
2580894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                      rhsHi32, DAG.getConstant(31, MVT::i32));
2581894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue rhsSignMag2TC = DAG.getNode(ISD::SUB, dl, IntVT, signMag2TC, i64rhs);
2582894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue rhsSelect =
2583894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          DAG.getNode(ISD::SELECT, dl, IntVT,
2584894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                      rhsSelectMask, rhsSignMag2TC, i64rhs);
2585894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2586894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  unsigned compareOp;
2587894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2588894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  switch (CC->get()) {
2589894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::SETOEQ:
2590894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::SETUEQ:
2591894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    compareOp = ISD::SETEQ; break;
2592894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::SETOGT:
2593894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::SETUGT:
2594894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    compareOp = ISD::SETGT; break;
2595894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::SETOGE:
2596894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::SETUGE:
2597894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    compareOp = ISD::SETGE; break;
2598894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::SETOLT:
2599894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::SETULT:
2600894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    compareOp = ISD::SETLT; break;
2601894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::SETOLE:
2602894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::SETULE:
2603894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    compareOp = ISD::SETLE; break;
2604894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::SETUNE:
2605894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::SETONE:
2606894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    compareOp = ISD::SETNE; break;
2607894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  default:
2608894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    report_fatal_error("CellSPU ISel Select: unimplemented f64 condition");
2609894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
2610894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2611894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue result =
2612894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          DAG.getSetCC(dl, ccResultVT, lhsSelect, rhsSelect,
2613894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                       (ISD::CondCode) compareOp);
2614894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2615894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if ((CC->get() & 0x8) == 0) {
2616894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Ordered comparison:
2617894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue lhsNaN = DAG.getSetCC(dl, ccResultVT,
2618894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                  lhs, DAG.getConstantFP(0.0, MVT::f64),
2619894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                  ISD::SETO);
2620894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue rhsNaN = DAG.getSetCC(dl, ccResultVT,
2621894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                  rhs, DAG.getConstantFP(0.0, MVT::f64),
2622894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                  ISD::SETO);
2623894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue ordered = DAG.getNode(ISD::AND, dl, ccResultVT, lhsNaN, rhsNaN);
2624894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2625894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    result = DAG.getNode(ISD::AND, dl, ccResultVT, ordered, result);
2626894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
2627894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2628894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return result;
2629894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
2630894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2631894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//! Lower ISD::SELECT_CC
2632894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/*!
2633894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  ISD::SELECT_CC can (generally) be implemented directly on the SPU using the
2634894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SELB instruction.
2635894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2636894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  \note Need to revisit this in the future: if the code path through the true
2637894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  and false value computations is longer than the latency of a branch (6
2638894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  cycles), then it would be more advantageous to branch and insert a new basic
2639894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  block and branch on the condition. However, this code does not make that
2640894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  assumption, given the simplisitc uses so far.
2641894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman */
2642894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2643894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG,
2644894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                              const TargetLowering &TLI) {
2645894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT VT = Op.getValueType();
2646894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue lhs = Op.getOperand(0);
2647894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue rhs = Op.getOperand(1);
2648894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue trueval = Op.getOperand(2);
2649894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue falseval = Op.getOperand(3);
2650894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue condition = Op.getOperand(4);
2651894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  DebugLoc dl = Op.getDebugLoc();
2652894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2653894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // NOTE: SELB's arguments: $rA, $rB, $mask
2654894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  //
2655894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // SELB selects bits from $rA where bits in $mask are 0, bits from $rB
2656894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // where bits in $mask are 1. CCond will be inverted, having 1s where the
2657894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // condition was true and 0s where the condition was false. Hence, the
2658894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // arguments to SELB get reversed.
2659894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2660894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Note: Really should be ISD::SELECT instead of SPUISD::SELB, but LLVM's
2661894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // legalizer insists on combining SETCC/SELECT into SELECT_CC, so we end up
2662894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // with another "cannot select select_cc" assert:
2663894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2664894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue compare = DAG.getNode(ISD::SETCC, dl,
2665894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                TLI.getSetCCResultType(Op.getValueType()),
2666894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                lhs, rhs, condition);
2667894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return DAG.getNode(SPUISD::SELB, dl, VT, falseval, trueval, compare);
2668894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
2669894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2670894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//! Custom lower ISD::TRUNCATE
2671894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic SDValue LowerTRUNCATE(SDValue Op, SelectionDAG &DAG)
2672894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman{
2673894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Type to truncate to
2674894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT VT = Op.getValueType();
2675894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  MVT simpleVT = VT.getSimpleVT();
267619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  EVT VecVT = EVT::getVectorVT(*DAG.getContext(),
2677894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                               VT, (128 / VT.getSizeInBits()));
2678894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  DebugLoc dl = Op.getDebugLoc();
2679894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2680894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Type to truncate from
2681894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue Op0 = Op.getOperand(0);
2682894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT Op0VT = Op0.getValueType();
2683894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
268419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (Op0VT == MVT::i128 && simpleVT == MVT::i64) {
2685894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Create shuffle mask, least significant doubleword of quadword
2686894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    unsigned maskHigh = 0x08090a0b;
2687894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    unsigned maskLow = 0x0c0d0e0f;
2688894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Use a shuffle to perform the truncation
2689894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue shufMask = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
2690894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                   DAG.getConstant(maskHigh, MVT::i32),
2691894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                   DAG.getConstant(maskLow, MVT::i32),
2692894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                   DAG.getConstant(maskHigh, MVT::i32),
2693894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                   DAG.getConstant(maskLow, MVT::i32));
2694894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2695894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue truncShuffle = DAG.getNode(SPUISD::SHUFB, dl, VecVT,
2696894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                       Op0, Op0, shufMask);
2697894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2698894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return DAG.getNode(SPUISD::VEC2PREFSLOT, dl, VT, truncShuffle);
2699894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
2700894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2701894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return SDValue();             // Leave the truncate unmolested
2702894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
2703894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2704894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/*!
2705894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman * Emit the instruction sequence for i64/i32 -> i128 sign extend. The basic
2706894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman * algorithm is to duplicate the sign bit using rotmai to generate at
2707894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman * least one byte full of sign bits. Then propagate the "sign-byte" into
2708894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman * the leftmost words and the i64/i32 into the rightmost words using shufb.
2709894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman *
2710894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman * @param Op The sext operand
2711894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman * @param DAG The current DAG
2712894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman * @return The SDValue with the entire instruction sequence
2713894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman */
2714894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstatic SDValue LowerSIGN_EXTEND(SDValue Op, SelectionDAG &DAG)
2715894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman{
2716894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  DebugLoc dl = Op.getDebugLoc();
2717894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2718894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Type to extend to
2719894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  MVT OpVT = Op.getValueType().getSimpleVT();
2720894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2721894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Type to extend from
2722894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue Op0 = Op.getOperand(0);
2723894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  MVT Op0VT = Op0.getValueType().getSimpleVT();
2724894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
272519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // extend i8 & i16 via i32
272619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (Op0VT == MVT::i8 || Op0VT == MVT::i16) {
272719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    Op0 = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i32, Op0);
272819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    Op0VT = MVT::i32;
272919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
273019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
2731894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // The type to extend to needs to be a i128 and
2732894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // the type to extend from needs to be i64 or i32.
2733894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  assert((OpVT == MVT::i128 && (Op0VT == MVT::i64 || Op0VT == MVT::i32)) &&
2734894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          "LowerSIGN_EXTEND: input and/or output operand have wrong size");
273519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  (void)OpVT;
2736894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2737894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Create shuffle mask
2738894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  unsigned mask1 = 0x10101010; // byte 0 - 3 and 4 - 7
2739894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  unsigned mask2 = Op0VT == MVT::i64 ? 0x00010203 : 0x10101010; // byte  8 - 11
2740894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  unsigned mask3 = Op0VT == MVT::i64 ? 0x04050607 : 0x00010203; // byte 12 - 15
2741894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue shufMask = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
2742894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                 DAG.getConstant(mask1, MVT::i32),
2743894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                 DAG.getConstant(mask1, MVT::i32),
2744894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                 DAG.getConstant(mask2, MVT::i32),
2745894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                 DAG.getConstant(mask3, MVT::i32));
2746894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2747894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Word wise arithmetic right shift to generate at least one byte
2748894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // that contains sign bits.
2749894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  MVT mvt = Op0VT == MVT::i64 ? MVT::v2i64 : MVT::v4i32;
2750894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue sraVal = DAG.getNode(ISD::SRA,
2751894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                 dl,
2752894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                 mvt,
2753894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                 DAG.getNode(SPUISD::PREFSLOT2VEC, dl, mvt, Op0, Op0),
2754894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                 DAG.getConstant(31, MVT::i32));
2755894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
275619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // reinterpret as a i128 (SHUFB requires it). This gets lowered away.
275719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SDValue extended = SDValue(DAG.getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
275819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                        dl, Op0VT, Op0,
275919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                        DAG.getTargetConstant(
276019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                                  SPU::GPRCRegClass.getID(),
276119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                                  MVT::i32)), 0);
2762894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Shuffle bytes - Copy the sign bits into the upper 64 bits
2763894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // and the input value into the lower 64 bits.
2764894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue extShuffle = DAG.getNode(SPUISD::SHUFB, dl, mvt,
276519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        extended, sraVal, shufMask);
276619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return DAG.getNode(ISD::BITCAST, dl, MVT::i128, extShuffle);
2767894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
2768894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2769894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//! Custom (target-specific) lowering entry point
2770894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/*!
2771894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  This is where LLVM's DAG selection process calls to do target-specific
2772894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  lowering of nodes.
2773894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman */
2774894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSDValue
2775894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const
2776894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman{
2777894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  unsigned Opc = (unsigned) Op.getOpcode();
2778894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT VT = Op.getValueType();
2779894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2780894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  switch (Opc) {
2781894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  default: {
2782894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#ifndef NDEBUG
2783894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    errs() << "SPUTargetLowering::LowerOperation(): need to lower this!\n";
2784894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    errs() << "Op.getOpcode() = " << Opc << "\n";
2785894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    errs() << "*Op.getNode():\n";
2786894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    Op.getNode()->dump();
2787894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#endif
2788894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    llvm_unreachable(0);
2789894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
2790894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::LOAD:
2791894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::EXTLOAD:
2792894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::SEXTLOAD:
2793894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::ZEXTLOAD:
2794894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return LowerLOAD(Op, DAG, SPUTM.getSubtargetImpl());
2795894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::STORE:
2796894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return LowerSTORE(Op, DAG, SPUTM.getSubtargetImpl());
2797894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::ConstantPool:
2798894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return LowerConstantPool(Op, DAG, SPUTM.getSubtargetImpl());
2799894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::GlobalAddress:
2800894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return LowerGlobalAddress(Op, DAG, SPUTM.getSubtargetImpl());
2801894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::JumpTable:
2802894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return LowerJumpTable(Op, DAG, SPUTM.getSubtargetImpl());
2803894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::ConstantFP:
2804894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return LowerConstantFP(Op, DAG);
2805894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2806894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // i8, i64 math ops:
2807894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::ADD:
2808894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::SUB:
2809894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::ROTR:
2810894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::ROTL:
2811894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::SRL:
2812894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::SHL:
2813894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::SRA: {
2814894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (VT == MVT::i8)
2815894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      return LowerI8Math(Op, DAG, Opc, *this);
2816894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    break;
2817894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
2818894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2819894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::FP_TO_SINT:
2820894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::FP_TO_UINT:
2821894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return LowerFP_TO_INT(Op, DAG, *this);
2822894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2823894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::SINT_TO_FP:
2824894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::UINT_TO_FP:
2825894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return LowerINT_TO_FP(Op, DAG, *this);
2826894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2827894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Vector-related lowering.
2828894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::BUILD_VECTOR:
2829894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return LowerBUILD_VECTOR(Op, DAG);
2830894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::SCALAR_TO_VECTOR:
2831894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return LowerSCALAR_TO_VECTOR(Op, DAG);
2832894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::VECTOR_SHUFFLE:
2833894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return LowerVECTOR_SHUFFLE(Op, DAG);
2834894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::EXTRACT_VECTOR_ELT:
2835894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return LowerEXTRACT_VECTOR_ELT(Op, DAG);
2836894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::INSERT_VECTOR_ELT:
2837894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return LowerINSERT_VECTOR_ELT(Op, DAG);
2838894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2839894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Look for ANDBI, ORBI and XORBI opportunities and lower appropriately:
2840894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::AND:
2841894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::OR:
2842894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::XOR:
2843894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return LowerByteImmed(Op, DAG);
2844894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2845894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Vector and i8 multiply:
2846894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::MUL:
2847894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (VT == MVT::i8)
2848894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      return LowerI8Math(Op, DAG, Opc, *this);
2849894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2850894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::CTPOP:
2851894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return LowerCTPOP(Op, DAG);
2852894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2853894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::SELECT_CC:
2854894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return LowerSELECT_CC(Op, DAG, *this);
2855894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2856894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::SETCC:
2857894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return LowerSETCC(Op, DAG, *this);
2858894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2859894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::TRUNCATE:
2860894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return LowerTRUNCATE(Op, DAG);
2861894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2862894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::SIGN_EXTEND:
2863894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return LowerSIGN_EXTEND(Op, DAG);
2864894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
2865894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2866894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return SDValue();
2867894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
2868894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2869894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanvoid SPUTargetLowering::ReplaceNodeResults(SDNode *N,
2870894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                           SmallVectorImpl<SDValue>&Results,
2871894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                           SelectionDAG &DAG) const
2872894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman{
2873894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#if 0
2874894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  unsigned Opc = (unsigned) N->getOpcode();
2875894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT OpVT = N->getValueType(0);
2876894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2877894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  switch (Opc) {
2878894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  default: {
2879894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    errs() << "SPUTargetLowering::ReplaceNodeResults(): need to fix this!\n";
2880894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    errs() << "Op.getOpcode() = " << Opc << "\n";
2881894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    errs() << "*Op.getNode():\n";
2882894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    N->dump();
2883894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    abort();
2884894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    /*NOTREACHED*/
2885894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
2886894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
2887894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#endif
2888894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2889894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  /* Otherwise, return unchanged */
2890894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
2891894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2892894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===----------------------------------------------------------------------===//
2893894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// Target Optimization Hooks
2894894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===----------------------------------------------------------------------===//
2895894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2896894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSDValue
2897894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSPUTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const
2898894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman{
2899894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#if 0
2900894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  TargetMachine &TM = getTargetMachine();
2901894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#endif
2902894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  const SPUSubtarget *ST = SPUTM.getSubtargetImpl();
2903894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SelectionDAG &DAG = DCI.DAG;
2904894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue Op0 = N->getOperand(0);       // everything has at least one operand
2905894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT NodeVT = N->getValueType(0);      // The node's value type
2906894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  EVT Op0VT = Op0.getValueType();       // The first operand's result
2907894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  SDValue Result;                       // Initially, empty result
2908894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  DebugLoc dl = N->getDebugLoc();
2909894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2910894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  switch (N->getOpcode()) {
2911894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  default: break;
2912894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::ADD: {
2913894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue Op1 = N->getOperand(1);
2914894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2915894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (Op0.getOpcode() == SPUISD::IndirectAddr
2916894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        || Op1.getOpcode() == SPUISD::IndirectAddr) {
2917894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // Normalize the operands to reduce repeated code
2918894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SDValue IndirectArg = Op0, AddArg = Op1;
2919894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2920894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      if (Op1.getOpcode() == SPUISD::IndirectAddr) {
2921894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        IndirectArg = Op1;
2922894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        AddArg = Op0;
2923894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      }
2924894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2925894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      if (isa<ConstantSDNode>(AddArg)) {
2926894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        ConstantSDNode *CN0 = cast<ConstantSDNode > (AddArg);
2927894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        SDValue IndOp1 = IndirectArg.getOperand(1);
2928894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2929894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        if (CN0->isNullValue()) {
2930894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          // (add (SPUindirect <arg>, <arg>), 0) ->
2931894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          // (SPUindirect <arg>, <arg>)
2932894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2933894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#if !defined(NDEBUG)
2934894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
2935894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman            errs() << "\n"
2936894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                 << "Replace: (add (SPUindirect <arg>, <arg>), 0)\n"
2937894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                 << "With:    (SPUindirect <arg>, <arg>)\n";
2938894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          }
2939894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#endif
2940894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2941894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          return IndirectArg;
2942894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        } else if (isa<ConstantSDNode>(IndOp1)) {
2943894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          // (add (SPUindirect <arg>, <const>), <const>) ->
2944894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          // (SPUindirect <arg>, <const + const>)
2945894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          ConstantSDNode *CN1 = cast<ConstantSDNode > (IndOp1);
2946894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          int64_t combinedConst = CN0->getSExtValue() + CN1->getSExtValue();
2947894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          SDValue combinedValue = DAG.getConstant(combinedConst, Op0VT);
2948894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2949894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#if !defined(NDEBUG)
2950894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
2951894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman            errs() << "\n"
2952894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                 << "Replace: (add (SPUindirect <arg>, " << CN1->getSExtValue()
2953894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                 << "), " << CN0->getSExtValue() << ")\n"
2954894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                 << "With:    (SPUindirect <arg>, "
2955894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                 << combinedConst << ")\n";
2956894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          }
2957894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#endif
2958894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2959894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          return DAG.getNode(SPUISD::IndirectAddr, dl, Op0VT,
2960894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                             IndirectArg, combinedValue);
2961894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        }
2962894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      }
2963894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
2964894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    break;
2965894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
2966894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::SIGN_EXTEND:
2967894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::ZERO_EXTEND:
2968894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::ANY_EXTEND: {
2969894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (Op0.getOpcode() == SPUISD::VEC2PREFSLOT && NodeVT == Op0VT) {
2970894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // (any_extend (SPUextract_elt0 <arg>)) ->
2971894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // (SPUextract_elt0 <arg>)
2972894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // Types must match, however...
2973894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#if !defined(NDEBUG)
2974894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
2975894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        errs() << "\nReplace: ";
2976894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        N->dump(&DAG);
2977894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        errs() << "\nWith:    ";
2978894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        Op0.getNode()->dump(&DAG);
2979894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        errs() << "\n";
2980894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      }
2981894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#endif
2982894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2983894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      return Op0;
2984894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
2985894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    break;
2986894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
2987894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case SPUISD::IndirectAddr: {
2988894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (!ST->usingLargeMem() && Op0.getOpcode() == SPUISD::AFormAddr) {
2989894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N->getOperand(1));
2990894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      if (CN != 0 && CN->isNullValue()) {
2991894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        // (SPUindirect (SPUaform <addr>, 0), 0) ->
2992894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        // (SPUaform <addr>, 0)
2993894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
2994894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        DEBUG(errs() << "Replace: ");
2995894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        DEBUG(N->dump(&DAG));
2996894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        DEBUG(errs() << "\nWith:    ");
2997894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        DEBUG(Op0.getNode()->dump(&DAG));
2998894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        DEBUG(errs() << "\n");
2999894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
3000894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        return Op0;
3001894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      }
3002894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    } else if (Op0.getOpcode() == ISD::ADD) {
3003894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SDValue Op1 = N->getOperand(1);
3004894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      if (ConstantSDNode *CN1 = dyn_cast<ConstantSDNode>(Op1)) {
3005894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        // (SPUindirect (add <arg>, <arg>), 0) ->
3006894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        // (SPUindirect <arg>, <arg>)
3007894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        if (CN1->isNullValue()) {
3008894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
3009894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#if !defined(NDEBUG)
3010894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) {
3011894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman            errs() << "\n"
3012894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                 << "Replace: (SPUindirect (add <arg>, <arg>), 0)\n"
3013894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                 << "With:    (SPUindirect <arg>, <arg>)\n";
3014894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          }
3015894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#endif
3016894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
3017894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          return DAG.getNode(SPUISD::IndirectAddr, dl, Op0VT,
3018894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                             Op0.getOperand(0), Op0.getOperand(1));
3019894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        }
3020894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      }
3021894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
3022894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    break;
3023894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
302419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  case SPUISD::SHL_BITS:
302519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  case SPUISD::SHL_BYTES:
3026894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case SPUISD::ROTBYTES_LEFT: {
3027894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    SDValue Op1 = N->getOperand(1);
3028894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
3029894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // Kill degenerate vector shifts:
3030894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op1)) {
3031894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      if (CN->isNullValue()) {
3032894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        Result = Op0;
3033894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      }
3034894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
3035894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    break;
3036894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
3037894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case SPUISD::PREFSLOT2VEC: {
3038894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    switch (Op0.getOpcode()) {
3039894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    default:
3040894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      break;
3041894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case ISD::ANY_EXTEND:
3042894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case ISD::ZERO_EXTEND:
3043894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case ISD::SIGN_EXTEND: {
3044894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // (SPUprefslot2vec (any|zero|sign_extend (SPUvec2prefslot <arg>))) ->
3045894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // <arg>
3046894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // but only if the SPUprefslot2vec and <arg> types match.
3047894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      SDValue Op00 = Op0.getOperand(0);
3048894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      if (Op00.getOpcode() == SPUISD::VEC2PREFSLOT) {
3049894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        SDValue Op000 = Op00.getOperand(0);
3050894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        if (Op000.getValueType() == NodeVT) {
3051894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman          Result = Op000;
3052894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        }
3053894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      }
3054894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      break;
3055894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
3056894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case SPUISD::VEC2PREFSLOT: {
3057894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // (SPUprefslot2vec (SPUvec2prefslot <arg>)) ->
3058894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      // <arg>
3059894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      Result = Op0.getOperand(0);
3060894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      break;
3061894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
3062894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
3063894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    break;
3064894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
3065894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
3066894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
3067894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Otherwise, return unchanged.
3068894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#ifndef NDEBUG
3069894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (Result.getNode()) {
3070894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    DEBUG(errs() << "\nReplace.SPU: ");
3071894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    DEBUG(N->dump(&DAG));
3072894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    DEBUG(errs() << "\nWith:        ");
3073894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    DEBUG(Result.getNode()->dump(&DAG));
3074894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    DEBUG(errs() << "\n");
3075894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
3076894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#endif
3077894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
3078894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return Result;
3079894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
3080894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
3081894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===----------------------------------------------------------------------===//
3082894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// Inline Assembly Support
3083894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//===----------------------------------------------------------------------===//
3084894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
3085894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// getConstraintType - Given a constraint letter, return the type of
3086894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// constraint it is for this target.
3087894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSPUTargetLowering::ConstraintType
3088894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSPUTargetLowering::getConstraintType(const std::string &ConstraintLetter) const {
3089894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (ConstraintLetter.size() == 1) {
3090894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    switch (ConstraintLetter[0]) {
3091894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    default: break;
3092894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case 'b':
3093894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case 'r':
3094894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case 'f':
3095894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case 'v':
3096894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case 'y':
3097894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      return C_RegisterClass;
3098894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
3099894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
3100894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return TargetLowering::getConstraintType(ConstraintLetter);
3101894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
3102894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
310319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman/// Examine constraint type and operand type and determine a weight value.
310419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman/// This object must already have been set up with the operand type
310519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman/// and the current alternative constraint selected.
310619bac1e08be200c31efd26f0f5fd144c9b3eefd3John BaumanTargetLowering::ConstraintWeight
310719bac1e08be200c31efd26f0f5fd144c9b3eefd3John BaumanSPUTargetLowering::getSingleConstraintMatchWeight(
310819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    AsmOperandInfo &info, const char *constraint) const {
310919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  ConstraintWeight weight = CW_Invalid;
311019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  Value *CallOperandVal = info.CallOperandVal;
311119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // If we don't have a value, we can't do a match,
311219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // but allow it at the lowest weight.
311319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (CallOperandVal == NULL)
311419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return CW_Default;
311519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // Look at the constraint type.
311619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  switch (*constraint) {
311719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  default:
311819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint);
311919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    break;
312019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    //FIXME: Seems like the supported constraint letters were just copied
312119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // from PPC, as the following doesn't correspond to the GCC docs.
312219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // I'm leaving it so until someone adds the corresponding lowering support.
312319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  case 'b':
312419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  case 'r':
312519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  case 'f':
312619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  case 'd':
312719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  case 'v':
312819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  case 'y':
312919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    weight = CW_Register;
313019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    break;
313119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
313219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return weight;
313319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
313419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
3135894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanstd::pair<unsigned, const TargetRegisterClass*>
3136894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSPUTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
3137894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                                EVT VT) const
3138894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman{
3139894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  if (Constraint.size() == 1) {
3140894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // GCC RS6000 Constraint Letters
3141894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    switch (Constraint[0]) {
3142894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case 'b':   // R1-R31
3143894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case 'r':   // R0-R31
3144894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      if (VT == MVT::i64)
3145894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        return std::make_pair(0U, SPU::R64CRegisterClass);
3146894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      return std::make_pair(0U, SPU::R32CRegisterClass);
3147894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case 'f':
3148894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      if (VT == MVT::f32)
3149894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        return std::make_pair(0U, SPU::R32FPRegisterClass);
3150894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      else if (VT == MVT::f64)
3151894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman        return std::make_pair(0U, SPU::R64FPRegisterClass);
3152894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      break;
3153894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    case 'v':
3154894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      return std::make_pair(0U, SPU::GPRCRegisterClass);
3155894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
3156894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
3157894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
3158894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
3159894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
3160894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
3161894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman//! Compute used/known bits for a SPU operand
3162894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanvoid
3163894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSPUTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
3164894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                                  const APInt &Mask,
3165894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                                  APInt &KnownZero,
3166894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                                  APInt &KnownOne,
3167894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                                  const SelectionDAG &DAG,
3168894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                                  unsigned Depth ) const {
3169894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#if 0
3170894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  const uint64_t uint64_sizebits = sizeof(uint64_t) * CHAR_BIT;
3171894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
3172894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  switch (Op.getOpcode()) {
3173894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  default:
3174894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    // KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
3175894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    break;
3176894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case CALL:
3177894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case SHUFB:
3178894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case SHUFFLE_MASK:
3179894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case CNTB:
3180894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case SPUISD::PREFSLOT2VEC:
3181894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case SPUISD::LDRESULT:
3182894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case SPUISD::VEC2PREFSLOT:
3183894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case SPUISD::SHLQUAD_L_BITS:
3184894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case SPUISD::SHLQUAD_L_BYTES:
3185894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case SPUISD::VEC_ROTL:
3186894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case SPUISD::VEC_ROTR:
3187894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case SPUISD::ROTBYTES_LEFT:
3188894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case SPUISD::SELECT_MASK:
3189894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case SPUISD::SELB:
3190894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
3191894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman#endif
3192894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
3193894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
3194894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanunsigned
3195894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSPUTargetLowering::ComputeNumSignBitsForTargetNode(SDValue Op,
3196894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                                   unsigned Depth) const {
3197894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  switch (Op.getOpcode()) {
3198894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  default:
3199894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return 1;
3200894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
3201894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  case ISD::SETCC: {
3202894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    EVT VT = Op.getValueType();
3203894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
3204894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    if (VT != MVT::i8 && VT != MVT::i16 && VT != MVT::i32) {
3205894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman      VT = MVT::i32;
3206894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    }
3207894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman    return VT.getSizeInBits();
3208894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
3209894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  }
3210894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
3211894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
3212894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman// LowerAsmOperandForConstraint
3213894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanvoid
3214894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSPUTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
321519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                                std::string &Constraint,
3216894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                                std::vector<SDValue> &Ops,
3217894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman                                                SelectionDAG &DAG) const {
3218894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // Default, for the time being, to the base class handler
321919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG);
3220894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
3221894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
3222894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// isLegalAddressImmediate - Return true if the integer value can be used
3223894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman/// as the offset of the target addressing mode.
3224894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanbool SPUTargetLowering::isLegalAddressImmediate(int64_t V,
322519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                                Type *Ty) const {
3226894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // SPU's addresses are 256K:
3227894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return (V > -(1 << 18) && V < (1 << 18) - 1);
3228894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
3229894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
3230894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanbool SPUTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const {
3231894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return false;
3232894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
3233894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman
3234894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Baumanbool
3235894018228b0e0bdbd7aa7e8f47d4a9458789ca82John BaumanSPUTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
3236894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  // The SPU target isn't yet aware of offsets.
3237894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman  return false;
3238894018228b0e0bdbd7aa7e8f47d4a9458789ca82John Bauman}
323919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
324019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// can we compare to Imm without writing it into a register?
324119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanbool SPUTargetLowering::isLegalICmpImmediate(int64_t Imm) const {
324219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  //ceqi, cgti, etc. all take s10 operand
324319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return isInt<10>(Imm);
324419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
324519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
324619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanbool
324719bac1e08be200c31efd26f0f5fd144c9b3eefd3John BaumanSPUTargetLowering::isLegalAddressingMode(const AddrMode &AM,
324819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                         Type * ) const{
324919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
325019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // A-form: 18bit absolute address.
325119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (AM.BaseGV && !AM.HasBaseReg && AM.Scale == 0 && AM.BaseOffs == 0)
325219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return true;
325319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
325419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // D-form: reg + 14bit offset
325519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (AM.BaseGV ==0 && AM.HasBaseReg && AM.Scale == 0 && isInt<14>(AM.BaseOffs))
325619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return true;
325719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
325819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // X-form: reg+reg
325919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (AM.BaseGV == 0 && AM.HasBaseReg && AM.Scale == 1 && AM.BaseOffs ==0)
326019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return true;
326119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
326219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return false;
326319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
3264