XCoreISelLowering.cpp revision 223017
1193323Sed//===-- XCoreISelLowering.cpp - XCore DAG Lowering Implementation   ------===//
2193323Sed//
3193323Sed//                     The LLVM Compiler Infrastructure
4193323Sed//
5193323Sed// This file is distributed under the University of Illinois Open Source
6193323Sed// License. See LICENSE.TXT for details.
7193323Sed//
8193323Sed//===----------------------------------------------------------------------===//
9193323Sed//
10193323Sed// This file implements the XCoreTargetLowering class.
11193323Sed//
12193323Sed//===----------------------------------------------------------------------===//
13193323Sed
14193323Sed#define DEBUG_TYPE "xcore-lower"
15193323Sed
16193323Sed#include "XCoreISelLowering.h"
17193323Sed#include "XCoreMachineFunctionInfo.h"
18193323Sed#include "XCore.h"
19198090Srdivacky#include "XCoreTargetObjectFile.h"
20193323Sed#include "XCoreTargetMachine.h"
21193323Sed#include "XCoreSubtarget.h"
22193323Sed#include "llvm/DerivedTypes.h"
23193323Sed#include "llvm/Function.h"
24193323Sed#include "llvm/Intrinsics.h"
25193323Sed#include "llvm/CallingConv.h"
26193323Sed#include "llvm/GlobalVariable.h"
27193323Sed#include "llvm/GlobalAlias.h"
28193323Sed#include "llvm/CodeGen/CallingConvLower.h"
29193323Sed#include "llvm/CodeGen/MachineFrameInfo.h"
30193323Sed#include "llvm/CodeGen/MachineFunction.h"
31193323Sed#include "llvm/CodeGen/MachineInstrBuilder.h"
32204642Srdivacky#include "llvm/CodeGen/MachineJumpTableInfo.h"
33193323Sed#include "llvm/CodeGen/MachineRegisterInfo.h"
34193323Sed#include "llvm/CodeGen/SelectionDAGISel.h"
35193323Sed#include "llvm/CodeGen/ValueTypes.h"
36193323Sed#include "llvm/Support/Debug.h"
37198090Srdivacky#include "llvm/Support/ErrorHandling.h"
38198090Srdivacky#include "llvm/Support/raw_ostream.h"
39193323Sed#include "llvm/ADT/VectorExtras.h"
40193323Sedusing namespace llvm;
41193323Sed
42193323Sedconst char *XCoreTargetLowering::
43219077SdimgetTargetNodeName(unsigned Opcode) const
44193323Sed{
45219077Sdim  switch (Opcode)
46193323Sed  {
47193323Sed    case XCoreISD::BL                : return "XCoreISD::BL";
48193323Sed    case XCoreISD::PCRelativeWrapper : return "XCoreISD::PCRelativeWrapper";
49193323Sed    case XCoreISD::DPRelativeWrapper : return "XCoreISD::DPRelativeWrapper";
50193323Sed    case XCoreISD::CPRelativeWrapper : return "XCoreISD::CPRelativeWrapper";
51193323Sed    case XCoreISD::STWSP             : return "XCoreISD::STWSP";
52193323Sed    case XCoreISD::RETSP             : return "XCoreISD::RETSP";
53198090Srdivacky    case XCoreISD::LADD              : return "XCoreISD::LADD";
54198090Srdivacky    case XCoreISD::LSUB              : return "XCoreISD::LSUB";
55204961Srdivacky    case XCoreISD::LMUL              : return "XCoreISD::LMUL";
56204961Srdivacky    case XCoreISD::MACCU             : return "XCoreISD::MACCU";
57204961Srdivacky    case XCoreISD::MACCS             : return "XCoreISD::MACCS";
58204642Srdivacky    case XCoreISD::BR_JT             : return "XCoreISD::BR_JT";
59204642Srdivacky    case XCoreISD::BR_JT32           : return "XCoreISD::BR_JT32";
60204961Srdivacky    default                          : return NULL;
61193323Sed  }
62193323Sed}
63193323Sed
64193323SedXCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM)
65198090Srdivacky  : TargetLowering(XTM, new XCoreTargetObjectFile()),
66193323Sed    TM(XTM),
67193323Sed    Subtarget(*XTM.getSubtargetImpl()) {
68193323Sed
69193323Sed  // Set up the register classes.
70193323Sed  addRegisterClass(MVT::i32, XCore::GRRegsRegisterClass);
71193323Sed
72193323Sed  // Compute derived properties from the register classes
73193323Sed  computeRegisterProperties();
74193323Sed
75193323Sed  // Division is expensive
76193323Sed  setIntDivIsCheap(false);
77193323Sed
78193323Sed  setStackPointerRegisterToSaveRestore(XCore::SP);
79193323Sed
80208599Srdivacky  setSchedulingPreference(Sched::RegPressure);
81193323Sed
82193323Sed  // Use i32 for setcc operations results (slt, sgt, ...).
83193323Sed  setBooleanContents(ZeroOrOneBooleanContent);
84193323Sed
85193323Sed  // XCore does not have the NodeTypes below.
86193323Sed  setOperationAction(ISD::BR_CC,     MVT::Other, Expand);
87193323Sed  setOperationAction(ISD::SELECT_CC, MVT::i32,   Custom);
88193323Sed  setOperationAction(ISD::ADDC, MVT::i32, Expand);
89193323Sed  setOperationAction(ISD::ADDE, MVT::i32, Expand);
90193323Sed  setOperationAction(ISD::SUBC, MVT::i32, Expand);
91193323Sed  setOperationAction(ISD::SUBE, MVT::i32, Expand);
92193323Sed
93193323Sed  // Stop the combiner recombining select and set_cc
94193323Sed  setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
95219077Sdim
96193323Sed  // 64bit
97198090Srdivacky  setOperationAction(ISD::ADD, MVT::i64, Custom);
98198090Srdivacky  setOperationAction(ISD::SUB, MVT::i64, Custom);
99204961Srdivacky  setOperationAction(ISD::SMUL_LOHI, MVT::i32, Custom);
100204961Srdivacky  setOperationAction(ISD::UMUL_LOHI, MVT::i32, Custom);
101193323Sed  setOperationAction(ISD::MULHS, MVT::i32, Expand);
102193323Sed  setOperationAction(ISD::MULHU, MVT::i32, Expand);
103193323Sed  setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
104193323Sed  setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
105193323Sed  setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);
106219077Sdim
107193323Sed  // Bit Manipulation
108193323Sed  setOperationAction(ISD::CTPOP, MVT::i32, Expand);
109193323Sed  setOperationAction(ISD::ROTL , MVT::i32, Expand);
110193323Sed  setOperationAction(ISD::ROTR , MVT::i32, Expand);
111219077Sdim
112193323Sed  setOperationAction(ISD::TRAP, MVT::Other, Legal);
113219077Sdim
114204642Srdivacky  // Jump tables.
115204642Srdivacky  setOperationAction(ISD::BR_JT, MVT::Other, Custom);
116193323Sed
117193323Sed  setOperationAction(ISD::GlobalAddress, MVT::i32,   Custom);
118199511Srdivacky  setOperationAction(ISD::BlockAddress, MVT::i32 , Custom);
119199511Srdivacky
120193323Sed  // Thread Local Storage
121193323Sed  setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom);
122219077Sdim
123193323Sed  // Conversion of i64 -> double produces constantpool nodes
124193323Sed  setOperationAction(ISD::ConstantPool, MVT::i32,   Custom);
125193323Sed
126193323Sed  // Loads
127193323Sed  setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote);
128193323Sed  setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote);
129193323Sed  setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
130193323Sed
131193323Sed  setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Expand);
132193323Sed  setLoadExtAction(ISD::ZEXTLOAD, MVT::i16, Expand);
133198090Srdivacky
134198090Srdivacky  // Custom expand misaligned loads / stores.
135198090Srdivacky  setOperationAction(ISD::LOAD, MVT::i32, Custom);
136198090Srdivacky  setOperationAction(ISD::STORE, MVT::i32, Custom);
137198090Srdivacky
138193323Sed  // Varargs
139193323Sed  setOperationAction(ISD::VAEND, MVT::Other, Expand);
140193323Sed  setOperationAction(ISD::VACOPY, MVT::Other, Expand);
141193323Sed  setOperationAction(ISD::VAARG, MVT::Other, Custom);
142193323Sed  setOperationAction(ISD::VASTART, MVT::Other, Custom);
143219077Sdim
144193323Sed  // Dynamic stack
145193323Sed  setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
146193323Sed  setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
147193323Sed  setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand);
148198090Srdivacky
149218893Sdim  // TRAMPOLINE is custom lowered.
150218893Sdim  setOperationAction(ISD::TRAMPOLINE, MVT::Other, Custom);
151218893Sdim
152218893Sdim  maxStoresPerMemset = maxStoresPerMemsetOptSize = 4;
153218893Sdim  maxStoresPerMemmove = maxStoresPerMemmoveOptSize
154218893Sdim    = maxStoresPerMemcpy = maxStoresPerMemcpyOptSize = 2;
155218893Sdim
156198090Srdivacky  // We have target-specific dag combine patterns for the following nodes:
157198090Srdivacky  setTargetDAGCombine(ISD::STORE);
158204961Srdivacky  setTargetDAGCombine(ISD::ADD);
159223017Sdim
160223017Sdim  setMinFunctionAlignment(1);
161193323Sed}
162193323Sed
163193323SedSDValue XCoreTargetLowering::
164207618SrdivackyLowerOperation(SDValue Op, SelectionDAG &DAG) const {
165219077Sdim  switch (Op.getOpcode())
166193323Sed  {
167193323Sed  case ISD::GlobalAddress:    return LowerGlobalAddress(Op, DAG);
168193323Sed  case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG);
169199511Srdivacky  case ISD::BlockAddress:     return LowerBlockAddress(Op, DAG);
170193323Sed  case ISD::ConstantPool:     return LowerConstantPool(Op, DAG);
171204642Srdivacky  case ISD::BR_JT:            return LowerBR_JT(Op, DAG);
172198090Srdivacky  case ISD::LOAD:             return LowerLOAD(Op, DAG);
173198090Srdivacky  case ISD::STORE:            return LowerSTORE(Op, DAG);
174193323Sed  case ISD::SELECT_CC:        return LowerSELECT_CC(Op, DAG);
175193323Sed  case ISD::VAARG:            return LowerVAARG(Op, DAG);
176193323Sed  case ISD::VASTART:          return LowerVASTART(Op, DAG);
177204961Srdivacky  case ISD::SMUL_LOHI:        return LowerSMUL_LOHI(Op, DAG);
178204961Srdivacky  case ISD::UMUL_LOHI:        return LowerUMUL_LOHI(Op, DAG);
179193323Sed  // FIXME: Remove these when LegalizeDAGTypes lands.
180193323Sed  case ISD::ADD:
181193323Sed  case ISD::SUB:              return ExpandADDSUB(Op.getNode(), DAG);
182193323Sed  case ISD::FRAMEADDR:        return LowerFRAMEADDR(Op, DAG);
183218893Sdim  case ISD::TRAMPOLINE:       return LowerTRAMPOLINE(Op, DAG);
184193323Sed  default:
185198090Srdivacky    llvm_unreachable("unimplemented operand");
186193323Sed    return SDValue();
187193323Sed  }
188193323Sed}
189193323Sed
190193323Sed/// ReplaceNodeResults - Replace the results of node with an illegal result
191193323Sed/// type with new values built out of custom code.
192193323Sedvoid XCoreTargetLowering::ReplaceNodeResults(SDNode *N,
193193323Sed                                             SmallVectorImpl<SDValue>&Results,
194207618Srdivacky                                             SelectionDAG &DAG) const {
195193323Sed  switch (N->getOpcode()) {
196193323Sed  default:
197198090Srdivacky    llvm_unreachable("Don't know how to custom expand this!");
198193323Sed    return;
199193323Sed  case ISD::ADD:
200193323Sed  case ISD::SUB:
201193323Sed    Results.push_back(ExpandADDSUB(N, DAG));
202193323Sed    return;
203193323Sed  }
204193323Sed}
205193323Sed
206193323Sed//===----------------------------------------------------------------------===//
207193323Sed//  Misc Lower Operation implementation
208193323Sed//===----------------------------------------------------------------------===//
209193323Sed
210193323SedSDValue XCoreTargetLowering::
211207618SrdivackyLowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const
212193323Sed{
213193323Sed  DebugLoc dl = Op.getDebugLoc();
214193323Sed  SDValue Cond = DAG.getNode(ISD::SETCC, dl, MVT::i32, Op.getOperand(2),
215193323Sed                             Op.getOperand(3), Op.getOperand(4));
216193323Sed  return DAG.getNode(ISD::SELECT, dl, MVT::i32, Cond, Op.getOperand(0),
217193323Sed                     Op.getOperand(1));
218193323Sed}
219193323Sed
220193323SedSDValue XCoreTargetLowering::
221207618SrdivackygetGlobalAddressWrapper(SDValue GA, const GlobalValue *GV,
222207618Srdivacky                        SelectionDAG &DAG) const
223193323Sed{
224193323Sed  // FIXME there is no actual debug info here
225193323Sed  DebugLoc dl = GA.getDebugLoc();
226193323Sed  if (isa<Function>(GV)) {
227193323Sed    return DAG.getNode(XCoreISD::PCRelativeWrapper, dl, MVT::i32, GA);
228193323Sed  }
229198090Srdivacky  const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
230198090Srdivacky  if (!GVar) {
231198090Srdivacky    // If GV is an alias then use the aliasee to determine constness
232198090Srdivacky    if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
233198090Srdivacky      GVar = dyn_cast_or_null<GlobalVariable>(GA->resolveAliasedGlobal());
234198090Srdivacky  }
235198090Srdivacky  bool isConst = GVar && GVar->isConstant();
236198090Srdivacky  if (isConst) {
237198090Srdivacky    return DAG.getNode(XCoreISD::CPRelativeWrapper, dl, MVT::i32, GA);
238198090Srdivacky  }
239193323Sed  return DAG.getNode(XCoreISD::DPRelativeWrapper, dl, MVT::i32, GA);
240193323Sed}
241193323Sed
242193323SedSDValue XCoreTargetLowering::
243207618SrdivackyLowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const
244193323Sed{
245207618Srdivacky  const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
246210299Sed  SDValue GA = DAG.getTargetGlobalAddress(GV, Op.getDebugLoc(), MVT::i32);
247193323Sed  return getGlobalAddressWrapper(GA, GV, DAG);
248193323Sed}
249193323Sed
250193323Sedstatic inline SDValue BuildGetId(SelectionDAG &DAG, DebugLoc dl) {
251193323Sed  return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::i32,
252193323Sed                     DAG.getConstant(Intrinsic::xcore_getid, MVT::i32));
253193323Sed}
254193323Sed
255193323Sedstatic inline bool isZeroLengthArray(const Type *Ty) {
256193323Sed  const ArrayType *AT = dyn_cast_or_null<ArrayType>(Ty);
257193323Sed  return AT && (AT->getNumElements() == 0);
258193323Sed}
259193323Sed
260193323SedSDValue XCoreTargetLowering::
261207618SrdivackyLowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const
262193323Sed{
263193323Sed  // FIXME there isn't really debug info here
264193323Sed  DebugLoc dl = Op.getDebugLoc();
265193323Sed  // transform to label + getid() * size
266207618Srdivacky  const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
267210299Sed  SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32);
268193323Sed  const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
269193323Sed  if (!GVar) {
270193323Sed    // If GV is an alias then use the aliasee to determine size
271193323Sed    if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
272193323Sed      GVar = dyn_cast_or_null<GlobalVariable>(GA->resolveAliasedGlobal());
273193323Sed  }
274193323Sed  if (! GVar) {
275198090Srdivacky    llvm_unreachable("Thread local object not a GlobalVariable?");
276193323Sed    return SDValue();
277193323Sed  }
278193323Sed  const Type *Ty = cast<PointerType>(GV->getType())->getElementType();
279193323Sed  if (!Ty->isSized() || isZeroLengthArray(Ty)) {
280198090Srdivacky#ifndef NDEBUG
281198090Srdivacky    errs() << "Size of thread local object " << GVar->getName()
282198090Srdivacky           << " is unknown\n";
283198090Srdivacky#endif
284198090Srdivacky    llvm_unreachable(0);
285193323Sed  }
286193323Sed  SDValue base = getGlobalAddressWrapper(GA, GV, DAG);
287193323Sed  const TargetData *TD = TM.getTargetData();
288193323Sed  unsigned Size = TD->getTypeAllocSize(Ty);
289193323Sed  SDValue offset = DAG.getNode(ISD::MUL, dl, MVT::i32, BuildGetId(DAG, dl),
290193323Sed                       DAG.getConstant(Size, MVT::i32));
291193323Sed  return DAG.getNode(ISD::ADD, dl, MVT::i32, base, offset);
292193323Sed}
293193323Sed
294193323SedSDValue XCoreTargetLowering::
295207618SrdivackyLowerBlockAddress(SDValue Op, SelectionDAG &DAG) const
296199511Srdivacky{
297199511Srdivacky  DebugLoc DL = Op.getDebugLoc();
298199511Srdivacky
299207618Srdivacky  const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress();
300199989Srdivacky  SDValue Result = DAG.getBlockAddress(BA, getPointerTy(), /*isTarget=*/true);
301199511Srdivacky
302199511Srdivacky  return DAG.getNode(XCoreISD::PCRelativeWrapper, DL, getPointerTy(), Result);
303199511Srdivacky}
304199511Srdivacky
305199511SrdivackySDValue XCoreTargetLowering::
306207618SrdivackyLowerConstantPool(SDValue Op, SelectionDAG &DAG) const
307193323Sed{
308193323Sed  ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
309193323Sed  // FIXME there isn't really debug info here
310193323Sed  DebugLoc dl = CP->getDebugLoc();
311198090Srdivacky  EVT PtrVT = Op.getValueType();
312198090Srdivacky  SDValue Res;
313198090Srdivacky  if (CP->isMachineConstantPoolEntry()) {
314198090Srdivacky    Res = DAG.getTargetConstantPool(CP->getMachineCPVal(), PtrVT,
315198090Srdivacky                                    CP->getAlignment());
316193323Sed  } else {
317198090Srdivacky    Res = DAG.getTargetConstantPool(CP->getConstVal(), PtrVT,
318198090Srdivacky                                    CP->getAlignment());
319193323Sed  }
320198090Srdivacky  return DAG.getNode(XCoreISD::CPRelativeWrapper, dl, MVT::i32, Res);
321193323Sed}
322193323Sed
323205218Srdivackyunsigned XCoreTargetLowering::getJumpTableEncoding() const {
324205218Srdivacky  return MachineJumpTableInfo::EK_Inline;
325205218Srdivacky}
326205218Srdivacky
327193323SedSDValue XCoreTargetLowering::
328207618SrdivackyLowerBR_JT(SDValue Op, SelectionDAG &DAG) const
329193323Sed{
330204642Srdivacky  SDValue Chain = Op.getOperand(0);
331204642Srdivacky  SDValue Table = Op.getOperand(1);
332204642Srdivacky  SDValue Index = Op.getOperand(2);
333193323Sed  DebugLoc dl = Op.getDebugLoc();
334204642Srdivacky  JumpTableSDNode *JT = cast<JumpTableSDNode>(Table);
335204642Srdivacky  unsigned JTI = JT->getIndex();
336204642Srdivacky  MachineFunction &MF = DAG.getMachineFunction();
337204642Srdivacky  const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo();
338204642Srdivacky  SDValue TargetJT = DAG.getTargetJumpTable(JT->getIndex(), MVT::i32);
339204642Srdivacky
340204642Srdivacky  unsigned NumEntries = MJTI->getJumpTables()[JTI].MBBs.size();
341204642Srdivacky  if (NumEntries <= 32) {
342204642Srdivacky    return DAG.getNode(XCoreISD::BR_JT, dl, MVT::Other, Chain, TargetJT, Index);
343204642Srdivacky  }
344204642Srdivacky  assert((NumEntries >> 31) == 0);
345204642Srdivacky  SDValue ScaledIndex = DAG.getNode(ISD::SHL, dl, MVT::i32, Index,
346204642Srdivacky                                    DAG.getConstant(1, MVT::i32));
347204642Srdivacky  return DAG.getNode(XCoreISD::BR_JT32, dl, MVT::Other, Chain, TargetJT,
348204642Srdivacky                     ScaledIndex);
349193323Sed}
350193323Sed
351198090Srdivackystatic bool
352198090SrdivackyIsWordAlignedBasePlusConstantOffset(SDValue Addr, SDValue &AlignedBase,
353198090Srdivacky                                    int64_t &Offset)
354198090Srdivacky{
355198090Srdivacky  if (Addr.getOpcode() != ISD::ADD) {
356198090Srdivacky    return false;
357198090Srdivacky  }
358198090Srdivacky  ConstantSDNode *CN = 0;
359198090Srdivacky  if (!(CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))) {
360198090Srdivacky    return false;
361198090Srdivacky  }
362198090Srdivacky  int64_t off = CN->getSExtValue();
363198090Srdivacky  const SDValue &Base = Addr.getOperand(0);
364198090Srdivacky  const SDValue *Root = &Base;
365198090Srdivacky  if (Base.getOpcode() == ISD::ADD &&
366198090Srdivacky      Base.getOperand(1).getOpcode() == ISD::SHL) {
367198090Srdivacky    ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Base.getOperand(1)
368198090Srdivacky                                                      .getOperand(1));
369198090Srdivacky    if (CN && (CN->getSExtValue() >= 2)) {
370198090Srdivacky      Root = &Base.getOperand(0);
371198090Srdivacky    }
372198090Srdivacky  }
373198090Srdivacky  if (isa<FrameIndexSDNode>(*Root)) {
374198090Srdivacky    // All frame indicies are word aligned
375198090Srdivacky    AlignedBase = Base;
376198090Srdivacky    Offset = off;
377198090Srdivacky    return true;
378198090Srdivacky  }
379198090Srdivacky  if (Root->getOpcode() == XCoreISD::DPRelativeWrapper ||
380198090Srdivacky      Root->getOpcode() == XCoreISD::CPRelativeWrapper) {
381198090Srdivacky    // All dp / cp relative addresses are word aligned
382198090Srdivacky    AlignedBase = Base;
383198090Srdivacky    Offset = off;
384198090Srdivacky    return true;
385198090Srdivacky  }
386198090Srdivacky  return false;
387198090Srdivacky}
388198090Srdivacky
389193323SedSDValue XCoreTargetLowering::
390218893SdimLowerLOAD(SDValue Op, SelectionDAG &DAG) const {
391198090Srdivacky  LoadSDNode *LD = cast<LoadSDNode>(Op);
392198090Srdivacky  assert(LD->getExtensionType() == ISD::NON_EXTLOAD &&
393198090Srdivacky         "Unexpected extension type");
394198090Srdivacky  assert(LD->getMemoryVT() == MVT::i32 && "Unexpected load EVT");
395218893Sdim  if (allowsUnalignedMemoryAccesses(LD->getMemoryVT()))
396198090Srdivacky    return SDValue();
397218893Sdim
398198090Srdivacky  unsigned ABIAlignment = getTargetData()->
399198090Srdivacky    getABITypeAlignment(LD->getMemoryVT().getTypeForEVT(*DAG.getContext()));
400198090Srdivacky  // Leave aligned load alone.
401218893Sdim  if (LD->getAlignment() >= ABIAlignment)
402198090Srdivacky    return SDValue();
403218893Sdim
404198090Srdivacky  SDValue Chain = LD->getChain();
405198090Srdivacky  SDValue BasePtr = LD->getBasePtr();
406218893Sdim  DebugLoc DL = Op.getDebugLoc();
407219077Sdim
408198090Srdivacky  SDValue Base;
409198090Srdivacky  int64_t Offset;
410198090Srdivacky  if (!LD->isVolatile() &&
411198090Srdivacky      IsWordAlignedBasePlusConstantOffset(BasePtr, Base, Offset)) {
412198090Srdivacky    if (Offset % 4 == 0) {
413198090Srdivacky      // We've managed to infer better alignment information than the load
414198090Srdivacky      // already has. Use an aligned load.
415203954Srdivacky      //
416218893Sdim      return DAG.getLoad(getPointerTy(), DL, Chain, BasePtr,
417218893Sdim                         MachinePointerInfo(),
418203954Srdivacky                         false, false, 0);
419198090Srdivacky    }
420198090Srdivacky    // Lower to
421198090Srdivacky    // ldw low, base[offset >> 2]
422198090Srdivacky    // ldw high, base[(offset >> 2) + 1]
423198090Srdivacky    // shr low_shifted, low, (offset & 0x3) * 8
424198090Srdivacky    // shl high_shifted, high, 32 - (offset & 0x3) * 8
425198090Srdivacky    // or result, low_shifted, high_shifted
426198090Srdivacky    SDValue LowOffset = DAG.getConstant(Offset & ~0x3, MVT::i32);
427198090Srdivacky    SDValue HighOffset = DAG.getConstant((Offset & ~0x3) + 4, MVT::i32);
428198090Srdivacky    SDValue LowShift = DAG.getConstant((Offset & 0x3) * 8, MVT::i32);
429198090Srdivacky    SDValue HighShift = DAG.getConstant(32 - (Offset & 0x3) * 8, MVT::i32);
430219077Sdim
431218893Sdim    SDValue LowAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, Base, LowOffset);
432218893Sdim    SDValue HighAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, Base, HighOffset);
433219077Sdim
434218893Sdim    SDValue Low = DAG.getLoad(getPointerTy(), DL, Chain,
435218893Sdim                              LowAddr, MachinePointerInfo(), false, false, 0);
436218893Sdim    SDValue High = DAG.getLoad(getPointerTy(), DL, Chain,
437218893Sdim                               HighAddr, MachinePointerInfo(), false, false, 0);
438218893Sdim    SDValue LowShifted = DAG.getNode(ISD::SRL, DL, MVT::i32, Low, LowShift);
439218893Sdim    SDValue HighShifted = DAG.getNode(ISD::SHL, DL, MVT::i32, High, HighShift);
440218893Sdim    SDValue Result = DAG.getNode(ISD::OR, DL, MVT::i32, LowShifted, HighShifted);
441218893Sdim    Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Low.getValue(1),
442198090Srdivacky                             High.getValue(1));
443198090Srdivacky    SDValue Ops[] = { Result, Chain };
444218893Sdim    return DAG.getMergeValues(Ops, 2, DL);
445198090Srdivacky  }
446219077Sdim
447198090Srdivacky  if (LD->getAlignment() == 2) {
448218893Sdim    SDValue Low = DAG.getExtLoad(ISD::ZEXTLOAD, DL, MVT::i32, Chain,
449218893Sdim                                 BasePtr, LD->getPointerInfo(), MVT::i16,
450203954Srdivacky                                 LD->isVolatile(), LD->isNonTemporal(), 2);
451218893Sdim    SDValue HighAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, BasePtr,
452198090Srdivacky                                   DAG.getConstant(2, MVT::i32));
453218893Sdim    SDValue High = DAG.getExtLoad(ISD::EXTLOAD, DL, MVT::i32, Chain,
454218893Sdim                                  HighAddr,
455218893Sdim                                  LD->getPointerInfo().getWithOffset(2),
456203954Srdivacky                                  MVT::i16, LD->isVolatile(),
457203954Srdivacky                                  LD->isNonTemporal(), 2);
458218893Sdim    SDValue HighShifted = DAG.getNode(ISD::SHL, DL, MVT::i32, High,
459198090Srdivacky                                      DAG.getConstant(16, MVT::i32));
460218893Sdim    SDValue Result = DAG.getNode(ISD::OR, DL, MVT::i32, Low, HighShifted);
461218893Sdim    Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Low.getValue(1),
462198090Srdivacky                             High.getValue(1));
463198090Srdivacky    SDValue Ops[] = { Result, Chain };
464218893Sdim    return DAG.getMergeValues(Ops, 2, DL);
465198090Srdivacky  }
466219077Sdim
467198090Srdivacky  // Lower to a call to __misaligned_load(BasePtr).
468198090Srdivacky  const Type *IntPtrTy = getTargetData()->getIntPtrType(*DAG.getContext());
469198090Srdivacky  TargetLowering::ArgListTy Args;
470198090Srdivacky  TargetLowering::ArgListEntry Entry;
471219077Sdim
472198090Srdivacky  Entry.Ty = IntPtrTy;
473198090Srdivacky  Entry.Node = BasePtr;
474198090Srdivacky  Args.push_back(Entry);
475219077Sdim
476198090Srdivacky  std::pair<SDValue, SDValue> CallResult =
477198090Srdivacky        LowerCallTo(Chain, IntPtrTy, false, false,
478198090Srdivacky                    false, false, 0, CallingConv::C, false,
479198090Srdivacky                    /*isReturnValueUsed=*/true,
480198090Srdivacky                    DAG.getExternalSymbol("__misaligned_load", getPointerTy()),
481218893Sdim                    Args, DAG, DL);
482198090Srdivacky
483198090Srdivacky  SDValue Ops[] =
484198090Srdivacky    { CallResult.first, CallResult.second };
485198090Srdivacky
486218893Sdim  return DAG.getMergeValues(Ops, 2, DL);
487198090Srdivacky}
488198090Srdivacky
489198090SrdivackySDValue XCoreTargetLowering::
490207618SrdivackyLowerSTORE(SDValue Op, SelectionDAG &DAG) const
491198090Srdivacky{
492198090Srdivacky  StoreSDNode *ST = cast<StoreSDNode>(Op);
493198090Srdivacky  assert(!ST->isTruncatingStore() && "Unexpected store type");
494198090Srdivacky  assert(ST->getMemoryVT() == MVT::i32 && "Unexpected store EVT");
495198090Srdivacky  if (allowsUnalignedMemoryAccesses(ST->getMemoryVT())) {
496198090Srdivacky    return SDValue();
497198090Srdivacky  }
498198090Srdivacky  unsigned ABIAlignment = getTargetData()->
499198090Srdivacky    getABITypeAlignment(ST->getMemoryVT().getTypeForEVT(*DAG.getContext()));
500198090Srdivacky  // Leave aligned store alone.
501198090Srdivacky  if (ST->getAlignment() >= ABIAlignment) {
502198090Srdivacky    return SDValue();
503198090Srdivacky  }
504198090Srdivacky  SDValue Chain = ST->getChain();
505198090Srdivacky  SDValue BasePtr = ST->getBasePtr();
506198090Srdivacky  SDValue Value = ST->getValue();
507198090Srdivacky  DebugLoc dl = Op.getDebugLoc();
508219077Sdim
509198090Srdivacky  if (ST->getAlignment() == 2) {
510198090Srdivacky    SDValue Low = Value;
511198090Srdivacky    SDValue High = DAG.getNode(ISD::SRL, dl, MVT::i32, Value,
512198090Srdivacky                                      DAG.getConstant(16, MVT::i32));
513198090Srdivacky    SDValue StoreLow = DAG.getTruncStore(Chain, dl, Low, BasePtr,
514218893Sdim                                         ST->getPointerInfo(), MVT::i16,
515203954Srdivacky                                         ST->isVolatile(), ST->isNonTemporal(),
516203954Srdivacky                                         2);
517198090Srdivacky    SDValue HighAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, BasePtr,
518198090Srdivacky                                   DAG.getConstant(2, MVT::i32));
519198090Srdivacky    SDValue StoreHigh = DAG.getTruncStore(Chain, dl, High, HighAddr,
520218893Sdim                                          ST->getPointerInfo().getWithOffset(2),
521203954Srdivacky                                          MVT::i16, ST->isVolatile(),
522203954Srdivacky                                          ST->isNonTemporal(), 2);
523198090Srdivacky    return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, StoreLow, StoreHigh);
524198090Srdivacky  }
525219077Sdim
526198090Srdivacky  // Lower to a call to __misaligned_store(BasePtr, Value).
527198090Srdivacky  const Type *IntPtrTy = getTargetData()->getIntPtrType(*DAG.getContext());
528198090Srdivacky  TargetLowering::ArgListTy Args;
529198090Srdivacky  TargetLowering::ArgListEntry Entry;
530219077Sdim
531198090Srdivacky  Entry.Ty = IntPtrTy;
532198090Srdivacky  Entry.Node = BasePtr;
533198090Srdivacky  Args.push_back(Entry);
534219077Sdim
535198090Srdivacky  Entry.Node = Value;
536198090Srdivacky  Args.push_back(Entry);
537219077Sdim
538198090Srdivacky  std::pair<SDValue, SDValue> CallResult =
539198090Srdivacky        LowerCallTo(Chain, Type::getVoidTy(*DAG.getContext()), false, false,
540198090Srdivacky                    false, false, 0, CallingConv::C, false,
541198090Srdivacky                    /*isReturnValueUsed=*/true,
542198090Srdivacky                    DAG.getExternalSymbol("__misaligned_store", getPointerTy()),
543204642Srdivacky                    Args, DAG, dl);
544198090Srdivacky
545198090Srdivacky  return CallResult.second;
546198090Srdivacky}
547198090Srdivacky
548198090SrdivackySDValue XCoreTargetLowering::
549207618SrdivackyLowerSMUL_LOHI(SDValue Op, SelectionDAG &DAG) const
550204961Srdivacky{
551204961Srdivacky  assert(Op.getValueType() == MVT::i32 && Op.getOpcode() == ISD::SMUL_LOHI &&
552204961Srdivacky         "Unexpected operand to lower!");
553204961Srdivacky  DebugLoc dl = Op.getDebugLoc();
554204961Srdivacky  SDValue LHS = Op.getOperand(0);
555204961Srdivacky  SDValue RHS = Op.getOperand(1);
556204961Srdivacky  SDValue Zero = DAG.getConstant(0, MVT::i32);
557204961Srdivacky  SDValue Hi = DAG.getNode(XCoreISD::MACCS, dl,
558204961Srdivacky                           DAG.getVTList(MVT::i32, MVT::i32), Zero, Zero,
559204961Srdivacky                           LHS, RHS);
560204961Srdivacky  SDValue Lo(Hi.getNode(), 1);
561204961Srdivacky  SDValue Ops[] = { Lo, Hi };
562204961Srdivacky  return DAG.getMergeValues(Ops, 2, dl);
563204961Srdivacky}
564204961Srdivacky
565204961SrdivackySDValue XCoreTargetLowering::
566207618SrdivackyLowerUMUL_LOHI(SDValue Op, SelectionDAG &DAG) const
567204961Srdivacky{
568204961Srdivacky  assert(Op.getValueType() == MVT::i32 && Op.getOpcode() == ISD::UMUL_LOHI &&
569204961Srdivacky         "Unexpected operand to lower!");
570204961Srdivacky  DebugLoc dl = Op.getDebugLoc();
571204961Srdivacky  SDValue LHS = Op.getOperand(0);
572204961Srdivacky  SDValue RHS = Op.getOperand(1);
573204961Srdivacky  SDValue Zero = DAG.getConstant(0, MVT::i32);
574204961Srdivacky  SDValue Hi = DAG.getNode(XCoreISD::LMUL, dl,
575204961Srdivacky                           DAG.getVTList(MVT::i32, MVT::i32), LHS, RHS,
576204961Srdivacky                           Zero, Zero);
577204961Srdivacky  SDValue Lo(Hi.getNode(), 1);
578204961Srdivacky  SDValue Ops[] = { Lo, Hi };
579204961Srdivacky  return DAG.getMergeValues(Ops, 2, dl);
580204961Srdivacky}
581204961Srdivacky
582204961Srdivacky/// isADDADDMUL - Return whether Op is in a form that is equivalent to
583204961Srdivacky/// add(add(mul(x,y),a),b). If requireIntermediatesHaveOneUse is true then
584204961Srdivacky/// each intermediate result in the calculation must also have a single use.
585204961Srdivacky/// If the Op is in the correct form the constituent parts are written to Mul0,
586204961Srdivacky/// Mul1, Addend0 and Addend1.
587204961Srdivackystatic bool
588204961SrdivackyisADDADDMUL(SDValue Op, SDValue &Mul0, SDValue &Mul1, SDValue &Addend0,
589204961Srdivacky            SDValue &Addend1, bool requireIntermediatesHaveOneUse)
590204961Srdivacky{
591204961Srdivacky  if (Op.getOpcode() != ISD::ADD)
592204961Srdivacky    return false;
593204961Srdivacky  SDValue N0 = Op.getOperand(0);
594204961Srdivacky  SDValue N1 = Op.getOperand(1);
595204961Srdivacky  SDValue AddOp;
596204961Srdivacky  SDValue OtherOp;
597204961Srdivacky  if (N0.getOpcode() == ISD::ADD) {
598204961Srdivacky    AddOp = N0;
599204961Srdivacky    OtherOp = N1;
600204961Srdivacky  } else if (N1.getOpcode() == ISD::ADD) {
601204961Srdivacky    AddOp = N1;
602204961Srdivacky    OtherOp = N0;
603204961Srdivacky  } else {
604204961Srdivacky    return false;
605204961Srdivacky  }
606204961Srdivacky  if (requireIntermediatesHaveOneUse && !AddOp.hasOneUse())
607204961Srdivacky    return false;
608204961Srdivacky  if (OtherOp.getOpcode() == ISD::MUL) {
609204961Srdivacky    // add(add(a,b),mul(x,y))
610204961Srdivacky    if (requireIntermediatesHaveOneUse && !OtherOp.hasOneUse())
611204961Srdivacky      return false;
612204961Srdivacky    Mul0 = OtherOp.getOperand(0);
613204961Srdivacky    Mul1 = OtherOp.getOperand(1);
614204961Srdivacky    Addend0 = AddOp.getOperand(0);
615204961Srdivacky    Addend1 = AddOp.getOperand(1);
616204961Srdivacky    return true;
617204961Srdivacky  }
618204961Srdivacky  if (AddOp.getOperand(0).getOpcode() == ISD::MUL) {
619204961Srdivacky    // add(add(mul(x,y),a),b)
620204961Srdivacky    if (requireIntermediatesHaveOneUse && !AddOp.getOperand(0).hasOneUse())
621204961Srdivacky      return false;
622204961Srdivacky    Mul0 = AddOp.getOperand(0).getOperand(0);
623204961Srdivacky    Mul1 = AddOp.getOperand(0).getOperand(1);
624204961Srdivacky    Addend0 = AddOp.getOperand(1);
625204961Srdivacky    Addend1 = OtherOp;
626204961Srdivacky    return true;
627204961Srdivacky  }
628204961Srdivacky  if (AddOp.getOperand(1).getOpcode() == ISD::MUL) {
629204961Srdivacky    // add(add(a,mul(x,y)),b)
630204961Srdivacky    if (requireIntermediatesHaveOneUse && !AddOp.getOperand(1).hasOneUse())
631204961Srdivacky      return false;
632204961Srdivacky    Mul0 = AddOp.getOperand(1).getOperand(0);
633204961Srdivacky    Mul1 = AddOp.getOperand(1).getOperand(1);
634204961Srdivacky    Addend0 = AddOp.getOperand(0);
635204961Srdivacky    Addend1 = OtherOp;
636204961Srdivacky    return true;
637204961Srdivacky  }
638204961Srdivacky  return false;
639204961Srdivacky}
640204961Srdivacky
641204961SrdivackySDValue XCoreTargetLowering::
642207618SrdivackyTryExpandADDWithMul(SDNode *N, SelectionDAG &DAG) const
643204961Srdivacky{
644204961Srdivacky  SDValue Mul;
645204961Srdivacky  SDValue Other;
646204961Srdivacky  if (N->getOperand(0).getOpcode() == ISD::MUL) {
647204961Srdivacky    Mul = N->getOperand(0);
648204961Srdivacky    Other = N->getOperand(1);
649204961Srdivacky  } else if (N->getOperand(1).getOpcode() == ISD::MUL) {
650204961Srdivacky    Mul = N->getOperand(1);
651204961Srdivacky    Other = N->getOperand(0);
652204961Srdivacky  } else {
653204961Srdivacky    return SDValue();
654204961Srdivacky  }
655204961Srdivacky  DebugLoc dl = N->getDebugLoc();
656204961Srdivacky  SDValue LL, RL, AddendL, AddendH;
657204961Srdivacky  LL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
658204961Srdivacky                   Mul.getOperand(0),  DAG.getConstant(0, MVT::i32));
659204961Srdivacky  RL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
660204961Srdivacky                   Mul.getOperand(1),  DAG.getConstant(0, MVT::i32));
661204961Srdivacky  AddendL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
662204961Srdivacky                        Other,  DAG.getConstant(0, MVT::i32));
663204961Srdivacky  AddendH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
664204961Srdivacky                        Other,  DAG.getConstant(1, MVT::i32));
665204961Srdivacky  APInt HighMask = APInt::getHighBitsSet(64, 32);
666204961Srdivacky  unsigned LHSSB = DAG.ComputeNumSignBits(Mul.getOperand(0));
667204961Srdivacky  unsigned RHSSB = DAG.ComputeNumSignBits(Mul.getOperand(1));
668204961Srdivacky  if (DAG.MaskedValueIsZero(Mul.getOperand(0), HighMask) &&
669204961Srdivacky      DAG.MaskedValueIsZero(Mul.getOperand(1), HighMask)) {
670204961Srdivacky    // The inputs are both zero-extended.
671204961Srdivacky    SDValue Hi = DAG.getNode(XCoreISD::MACCU, dl,
672204961Srdivacky                             DAG.getVTList(MVT::i32, MVT::i32), AddendH,
673204961Srdivacky                             AddendL, LL, RL);
674204961Srdivacky    SDValue Lo(Hi.getNode(), 1);
675204961Srdivacky    return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);
676204961Srdivacky  }
677204961Srdivacky  if (LHSSB > 32 && RHSSB > 32) {
678204961Srdivacky    // The inputs are both sign-extended.
679204961Srdivacky    SDValue Hi = DAG.getNode(XCoreISD::MACCS, dl,
680204961Srdivacky                             DAG.getVTList(MVT::i32, MVT::i32), AddendH,
681204961Srdivacky                             AddendL, LL, RL);
682204961Srdivacky    SDValue Lo(Hi.getNode(), 1);
683204961Srdivacky    return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);
684204961Srdivacky  }
685204961Srdivacky  SDValue LH, RH;
686204961Srdivacky  LH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
687204961Srdivacky                   Mul.getOperand(0),  DAG.getConstant(1, MVT::i32));
688204961Srdivacky  RH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
689204961Srdivacky                   Mul.getOperand(1),  DAG.getConstant(1, MVT::i32));
690204961Srdivacky  SDValue Hi = DAG.getNode(XCoreISD::MACCU, dl,
691204961Srdivacky                           DAG.getVTList(MVT::i32, MVT::i32), AddendH,
692204961Srdivacky                           AddendL, LL, RL);
693204961Srdivacky  SDValue Lo(Hi.getNode(), 1);
694204961Srdivacky  RH = DAG.getNode(ISD::MUL, dl, MVT::i32, LL, RH);
695204961Srdivacky  LH = DAG.getNode(ISD::MUL, dl, MVT::i32, LH, RL);
696204961Srdivacky  Hi = DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, RH);
697204961Srdivacky  Hi = DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, LH);
698204961Srdivacky  return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);
699204961Srdivacky}
700204961Srdivacky
701204961SrdivackySDValue XCoreTargetLowering::
702207618SrdivackyExpandADDSUB(SDNode *N, SelectionDAG &DAG) const
703193323Sed{
704193323Sed  assert(N->getValueType(0) == MVT::i64 &&
705193323Sed         (N->getOpcode() == ISD::ADD || N->getOpcode() == ISD::SUB) &&
706193323Sed        "Unknown operand to lower!");
707204961Srdivacky
708204961Srdivacky  if (N->getOpcode() == ISD::ADD) {
709204961Srdivacky    SDValue Result = TryExpandADDWithMul(N, DAG);
710204961Srdivacky    if (Result.getNode() != 0)
711204961Srdivacky      return Result;
712204961Srdivacky  }
713204961Srdivacky
714193323Sed  DebugLoc dl = N->getDebugLoc();
715219077Sdim
716193323Sed  // Extract components
717193323Sed  SDValue LHSL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
718193323Sed                            N->getOperand(0),  DAG.getConstant(0, MVT::i32));
719193323Sed  SDValue LHSH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
720193323Sed                            N->getOperand(0),  DAG.getConstant(1, MVT::i32));
721193323Sed  SDValue RHSL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
722193323Sed                             N->getOperand(1), DAG.getConstant(0, MVT::i32));
723193323Sed  SDValue RHSH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
724193323Sed                             N->getOperand(1), DAG.getConstant(1, MVT::i32));
725219077Sdim
726193323Sed  // Expand
727193323Sed  unsigned Opcode = (N->getOpcode() == ISD::ADD) ? XCoreISD::LADD :
728193323Sed                                                   XCoreISD::LSUB;
729193323Sed  SDValue Zero = DAG.getConstant(0, MVT::i32);
730193323Sed  SDValue Carry = DAG.getNode(Opcode, dl, DAG.getVTList(MVT::i32, MVT::i32),
731193323Sed                                  LHSL, RHSL, Zero);
732193323Sed  SDValue Lo(Carry.getNode(), 1);
733219077Sdim
734193323Sed  SDValue Ignored = DAG.getNode(Opcode, dl, DAG.getVTList(MVT::i32, MVT::i32),
735193323Sed                                  LHSH, RHSH, Carry);
736193323Sed  SDValue Hi(Ignored.getNode(), 1);
737193323Sed  // Merge the pieces
738193323Sed  return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);
739193323Sed}
740193323Sed
741193323SedSDValue XCoreTargetLowering::
742207618SrdivackyLowerVAARG(SDValue Op, SelectionDAG &DAG) const
743193323Sed{
744198090Srdivacky  llvm_unreachable("unimplemented");
745193323Sed  // FIX Arguments passed by reference need a extra dereference.
746193323Sed  SDNode *Node = Op.getNode();
747193323Sed  DebugLoc dl = Node->getDebugLoc();
748193323Sed  const Value *V = cast<SrcValueSDNode>(Node->getOperand(2))->getValue();
749198090Srdivacky  EVT VT = Node->getValueType(0);
750193323Sed  SDValue VAList = DAG.getLoad(getPointerTy(), dl, Node->getOperand(0),
751218893Sdim                               Node->getOperand(1), MachinePointerInfo(V),
752218893Sdim                               false, false, 0);
753193323Sed  // Increment the pointer, VAList, to the next vararg
754219077Sdim  SDValue Tmp3 = DAG.getNode(ISD::ADD, dl, getPointerTy(), VAList,
755219077Sdim                     DAG.getConstant(VT.getSizeInBits(),
756193323Sed                                     getPointerTy()));
757193323Sed  // Store the incremented VAList to the legalized pointer
758218893Sdim  Tmp3 = DAG.getStore(VAList.getValue(1), dl, Tmp3, Node->getOperand(1),
759218893Sdim                      MachinePointerInfo(V), false, false, 0);
760193323Sed  // Load the actual argument out of the pointer VAList
761218893Sdim  return DAG.getLoad(VT, dl, Tmp3, VAList, MachinePointerInfo(),
762218893Sdim                     false, false, 0);
763193323Sed}
764193323Sed
765193323SedSDValue XCoreTargetLowering::
766207618SrdivackyLowerVASTART(SDValue Op, SelectionDAG &DAG) const
767193323Sed{
768193323Sed  DebugLoc dl = Op.getDebugLoc();
769193323Sed  // vastart stores the address of the VarArgsFrameIndex slot into the
770193323Sed  // memory location argument
771193323Sed  MachineFunction &MF = DAG.getMachineFunction();
772193323Sed  XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
773193323Sed  SDValue Addr = DAG.getFrameIndex(XFI->getVarArgsFrameIndex(), MVT::i32);
774219077Sdim  return DAG.getStore(Op.getOperand(0), dl, Addr, Op.getOperand(1),
775218893Sdim                      MachinePointerInfo(), false, false, 0);
776193323Sed}
777193323Sed
778207618SrdivackySDValue XCoreTargetLowering::LowerFRAMEADDR(SDValue Op,
779207618Srdivacky                                            SelectionDAG &DAG) const {
780193323Sed  DebugLoc dl = Op.getDebugLoc();
781219077Sdim  // Depths > 0 not supported yet!
782193323Sed  if (cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() > 0)
783193323Sed    return SDValue();
784219077Sdim
785193323Sed  MachineFunction &MF = DAG.getMachineFunction();
786193323Sed  const TargetRegisterInfo *RegInfo = getTargetMachine().getRegisterInfo();
787219077Sdim  return DAG.getCopyFromReg(DAG.getEntryNode(), dl,
788193323Sed                            RegInfo->getFrameRegister(MF), MVT::i32);
789193323Sed}
790193323Sed
791218893SdimSDValue XCoreTargetLowering::
792218893SdimLowerTRAMPOLINE(SDValue Op, SelectionDAG &DAG) const {
793218893Sdim  SDValue Chain = Op.getOperand(0);
794218893Sdim  SDValue Trmp = Op.getOperand(1); // trampoline
795218893Sdim  SDValue FPtr = Op.getOperand(2); // nested function
796218893Sdim  SDValue Nest = Op.getOperand(3); // 'nest' parameter value
797218893Sdim
798218893Sdim  const Value *TrmpAddr = cast<SrcValueSDNode>(Op.getOperand(4))->getValue();
799218893Sdim
800218893Sdim  // .align 4
801218893Sdim  // LDAPF_u10 r11, nest
802218893Sdim  // LDW_2rus r11, r11[0]
803218893Sdim  // STWSP_ru6 r11, sp[0]
804218893Sdim  // LDAPF_u10 r11, fptr
805218893Sdim  // LDW_2rus r11, r11[0]
806218893Sdim  // BAU_1r r11
807218893Sdim  // nest:
808218893Sdim  // .word nest
809218893Sdim  // fptr:
810218893Sdim  // .word fptr
811218893Sdim  SDValue OutChains[5];
812218893Sdim
813218893Sdim  SDValue Addr = Trmp;
814218893Sdim
815218893Sdim  DebugLoc dl = Op.getDebugLoc();
816218893Sdim  OutChains[0] = DAG.getStore(Chain, dl, DAG.getConstant(0x0a3cd805, MVT::i32),
817218893Sdim                              Addr, MachinePointerInfo(TrmpAddr), false, false,
818218893Sdim                              0);
819218893Sdim
820218893Sdim  Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp,
821218893Sdim                     DAG.getConstant(4, MVT::i32));
822218893Sdim  OutChains[1] = DAG.getStore(Chain, dl, DAG.getConstant(0xd80456c0, MVT::i32),
823218893Sdim                              Addr, MachinePointerInfo(TrmpAddr, 4), false,
824218893Sdim                              false, 0);
825218893Sdim
826218893Sdim  Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp,
827218893Sdim                     DAG.getConstant(8, MVT::i32));
828218893Sdim  OutChains[2] = DAG.getStore(Chain, dl, DAG.getConstant(0x27fb0a3c, MVT::i32),
829218893Sdim                              Addr, MachinePointerInfo(TrmpAddr, 8), false,
830218893Sdim                              false, 0);
831218893Sdim
832218893Sdim  Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp,
833218893Sdim                     DAG.getConstant(12, MVT::i32));
834218893Sdim  OutChains[3] = DAG.getStore(Chain, dl, Nest, Addr,
835218893Sdim                              MachinePointerInfo(TrmpAddr, 12), false, false,
836218893Sdim                              0);
837218893Sdim
838218893Sdim  Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp,
839218893Sdim                     DAG.getConstant(16, MVT::i32));
840218893Sdim  OutChains[4] = DAG.getStore(Chain, dl, FPtr, Addr,
841218893Sdim                              MachinePointerInfo(TrmpAddr, 16), false, false,
842218893Sdim                              0);
843218893Sdim
844218893Sdim  SDValue Ops[] =
845218893Sdim    { Trmp, DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains, 5) };
846218893Sdim  return DAG.getMergeValues(Ops, 2, dl);
847218893Sdim}
848218893Sdim
849193323Sed//===----------------------------------------------------------------------===//
850193323Sed//                      Calling Convention Implementation
851193323Sed//===----------------------------------------------------------------------===//
852193323Sed
853193323Sed#include "XCoreGenCallingConv.inc"
854193323Sed
855193323Sed//===----------------------------------------------------------------------===//
856198090Srdivacky//                  Call Calling Convention Implementation
857193323Sed//===----------------------------------------------------------------------===//
858193323Sed
859198090Srdivacky/// XCore call implementation
860198090SrdivackySDValue
861198090SrdivackyXCoreTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
862198090Srdivacky                               CallingConv::ID CallConv, bool isVarArg,
863203954Srdivacky                               bool &isTailCall,
864198090Srdivacky                               const SmallVectorImpl<ISD::OutputArg> &Outs,
865210299Sed                               const SmallVectorImpl<SDValue> &OutVals,
866198090Srdivacky                               const SmallVectorImpl<ISD::InputArg> &Ins,
867198090Srdivacky                               DebugLoc dl, SelectionDAG &DAG,
868207618Srdivacky                               SmallVectorImpl<SDValue> &InVals) const {
869203954Srdivacky  // XCore target does not yet support tail call optimization.
870203954Srdivacky  isTailCall = false;
871198090Srdivacky
872193323Sed  // For now, only CallingConv::C implemented
873198090Srdivacky  switch (CallConv)
874193323Sed  {
875193323Sed    default:
876198090Srdivacky      llvm_unreachable("Unsupported calling convention");
877193323Sed    case CallingConv::Fast:
878193323Sed    case CallingConv::C:
879198090Srdivacky      return LowerCCCCallTo(Chain, Callee, CallConv, isVarArg, isTailCall,
880210299Sed                            Outs, OutVals, Ins, dl, DAG, InVals);
881193323Sed  }
882193323Sed}
883193323Sed
884193323Sed/// LowerCCCCallTo - functions arguments are copied from virtual
885193323Sed/// regs to (physical regs)/(stack frame), CALLSEQ_START and
886193323Sed/// CALLSEQ_END are emitted.
887193323Sed/// TODO: isTailCall, sret.
888198090SrdivackySDValue
889198090SrdivackyXCoreTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee,
890198090Srdivacky                                    CallingConv::ID CallConv, bool isVarArg,
891198090Srdivacky                                    bool isTailCall,
892198090Srdivacky                                    const SmallVectorImpl<ISD::OutputArg> &Outs,
893210299Sed                                    const SmallVectorImpl<SDValue> &OutVals,
894198090Srdivacky                                    const SmallVectorImpl<ISD::InputArg> &Ins,
895198090Srdivacky                                    DebugLoc dl, SelectionDAG &DAG,
896207618Srdivacky                                    SmallVectorImpl<SDValue> &InVals) const {
897193323Sed
898193323Sed  // Analyze operands of the call, assigning locations to each operand.
899193323Sed  SmallVector<CCValAssign, 16> ArgLocs;
900223017Sdim  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
901223017Sdim		 getTargetMachine(), ArgLocs, *DAG.getContext());
902193323Sed
903193323Sed  // The ABI dictates there should be one stack slot available to the callee
904193323Sed  // on function entry (for saving lr).
905193323Sed  CCInfo.AllocateStack(4, 4);
906193323Sed
907198090Srdivacky  CCInfo.AnalyzeCallOperands(Outs, CC_XCore);
908193323Sed
909193323Sed  // Get a count of how many bytes are to be pushed on the stack.
910193323Sed  unsigned NumBytes = CCInfo.getNextStackOffset();
911193323Sed
912219077Sdim  Chain = DAG.getCALLSEQ_START(Chain,DAG.getConstant(NumBytes,
913193323Sed                                 getPointerTy(), true));
914193323Sed
915193323Sed  SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass;
916193323Sed  SmallVector<SDValue, 12> MemOpChains;
917193323Sed
918193323Sed  // Walk the register/memloc assignments, inserting copies/loads.
919193323Sed  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
920193323Sed    CCValAssign &VA = ArgLocs[i];
921210299Sed    SDValue Arg = OutVals[i];
922193323Sed
923193323Sed    // Promote the value if needed.
924193323Sed    switch (VA.getLocInfo()) {
925198090Srdivacky      default: llvm_unreachable("Unknown loc info!");
926193323Sed      case CCValAssign::Full: break;
927193323Sed      case CCValAssign::SExt:
928193323Sed        Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);
929193323Sed        break;
930193323Sed      case CCValAssign::ZExt:
931193323Sed        Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);
932193323Sed        break;
933193323Sed      case CCValAssign::AExt:
934193323Sed        Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);
935193323Sed        break;
936193323Sed    }
937219077Sdim
938219077Sdim    // Arguments that can be passed on register must be kept at
939193323Sed    // RegsToPass vector
940193323Sed    if (VA.isRegLoc()) {
941193323Sed      RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
942193323Sed    } else {
943193323Sed      assert(VA.isMemLoc());
944193323Sed
945193323Sed      int Offset = VA.getLocMemOffset();
946193323Sed
947219077Sdim      MemOpChains.push_back(DAG.getNode(XCoreISD::STWSP, dl, MVT::Other,
948193323Sed                                        Chain, Arg,
949193323Sed                                        DAG.getConstant(Offset/4, MVT::i32)));
950193323Sed    }
951193323Sed  }
952193323Sed
953193323Sed  // Transform all store nodes into one single node because
954193323Sed  // all store nodes are independent of each other.
955193323Sed  if (!MemOpChains.empty())
956219077Sdim    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
957193323Sed                        &MemOpChains[0], MemOpChains.size());
958193323Sed
959219077Sdim  // Build a sequence of copy-to-reg nodes chained together with token
960193323Sed  // chain and flag operands which copy the outgoing args into registers.
961221345Sdim  // The InFlag in necessary since all emitted instructions must be
962193323Sed  // stuck together.
963193323Sed  SDValue InFlag;
964193323Sed  for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
965219077Sdim    Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
966193323Sed                             RegsToPass[i].second, InFlag);
967193323Sed    InFlag = Chain.getValue(1);
968193323Sed  }
969193323Sed
970193323Sed  // If the callee is a GlobalAddress node (quite common, every direct call is)
971193323Sed  // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
972193323Sed  // Likewise ExternalSymbol -> TargetExternalSymbol.
973193323Sed  if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
974210299Sed    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32);
975193323Sed  else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
976193323Sed    Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32);
977193323Sed
978193323Sed  // XCoreBranchLink = #chain, #target_address, #opt_in_flags...
979219077Sdim  //             = Chain, Callee, Reg#1, Reg#2, ...
980193323Sed  //
981193323Sed  // Returns a chain & a flag for retval copy to use.
982218893Sdim  SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
983193323Sed  SmallVector<SDValue, 8> Ops;
984193323Sed  Ops.push_back(Chain);
985193323Sed  Ops.push_back(Callee);
986193323Sed
987219077Sdim  // Add argument registers to the end of the list so that they are
988193323Sed  // known live into the call.
989193323Sed  for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
990193323Sed    Ops.push_back(DAG.getRegister(RegsToPass[i].first,
991193323Sed                                  RegsToPass[i].second.getValueType()));
992193323Sed
993193323Sed  if (InFlag.getNode())
994193323Sed    Ops.push_back(InFlag);
995193323Sed
996193323Sed  Chain  = DAG.getNode(XCoreISD::BL, dl, NodeTys, &Ops[0], Ops.size());
997193323Sed  InFlag = Chain.getValue(1);
998193323Sed
999193323Sed  // Create the CALLSEQ_END node.
1000193323Sed  Chain = DAG.getCALLSEQ_END(Chain,
1001193323Sed                             DAG.getConstant(NumBytes, getPointerTy(), true),
1002193323Sed                             DAG.getConstant(0, getPointerTy(), true),
1003193323Sed                             InFlag);
1004193323Sed  InFlag = Chain.getValue(1);
1005193323Sed
1006193323Sed  // Handle result values, copying them out of physregs into vregs that we
1007193323Sed  // return.
1008198090Srdivacky  return LowerCallResult(Chain, InFlag, CallConv, isVarArg,
1009198090Srdivacky                         Ins, dl, DAG, InVals);
1010193323Sed}
1011193323Sed
1012198090Srdivacky/// LowerCallResult - Lower the result values of a call into the
1013198090Srdivacky/// appropriate copies out of appropriate physical registers.
1014198090SrdivackySDValue
1015198090SrdivackyXCoreTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag,
1016198090Srdivacky                                     CallingConv::ID CallConv, bool isVarArg,
1017198090Srdivacky                                     const SmallVectorImpl<ISD::InputArg> &Ins,
1018198090Srdivacky                                     DebugLoc dl, SelectionDAG &DAG,
1019207618Srdivacky                                     SmallVectorImpl<SDValue> &InVals) const {
1020193323Sed
1021193323Sed  // Assign locations to each value returned by this call.
1022193323Sed  SmallVector<CCValAssign, 16> RVLocs;
1023223017Sdim  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
1024223017Sdim		 getTargetMachine(), RVLocs, *DAG.getContext());
1025193323Sed
1026198090Srdivacky  CCInfo.AnalyzeCallResult(Ins, RetCC_XCore);
1027193323Sed
1028193323Sed  // Copy all of the result registers out of their specified physreg.
1029193323Sed  for (unsigned i = 0; i != RVLocs.size(); ++i) {
1030193323Sed    Chain = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(),
1031193323Sed                                 RVLocs[i].getValVT(), InFlag).getValue(1);
1032193323Sed    InFlag = Chain.getValue(2);
1033198090Srdivacky    InVals.push_back(Chain.getValue(0));
1034193323Sed  }
1035193323Sed
1036198090Srdivacky  return Chain;
1037193323Sed}
1038193323Sed
1039193323Sed//===----------------------------------------------------------------------===//
1040198090Srdivacky//             Formal Arguments Calling Convention Implementation
1041193323Sed//===----------------------------------------------------------------------===//
1042193323Sed
1043198090Srdivacky/// XCore formal arguments implementation
1044198090SrdivackySDValue
1045198090SrdivackyXCoreTargetLowering::LowerFormalArguments(SDValue Chain,
1046198090Srdivacky                                          CallingConv::ID CallConv,
1047198090Srdivacky                                          bool isVarArg,
1048198090Srdivacky                                      const SmallVectorImpl<ISD::InputArg> &Ins,
1049198090Srdivacky                                          DebugLoc dl,
1050198090Srdivacky                                          SelectionDAG &DAG,
1051207618Srdivacky                                          SmallVectorImpl<SDValue> &InVals)
1052207618Srdivacky                                            const {
1053198090Srdivacky  switch (CallConv)
1054193323Sed  {
1055193323Sed    default:
1056198090Srdivacky      llvm_unreachable("Unsupported calling convention");
1057193323Sed    case CallingConv::C:
1058193323Sed    case CallingConv::Fast:
1059198090Srdivacky      return LowerCCCArguments(Chain, CallConv, isVarArg,
1060198090Srdivacky                               Ins, dl, DAG, InVals);
1061193323Sed  }
1062193323Sed}
1063193323Sed
1064193323Sed/// LowerCCCArguments - transform physical registers into
1065193323Sed/// virtual registers and generate load operations for
1066193323Sed/// arguments places on the stack.
1067193323Sed/// TODO: sret
1068198090SrdivackySDValue
1069198090SrdivackyXCoreTargetLowering::LowerCCCArguments(SDValue Chain,
1070198090Srdivacky                                       CallingConv::ID CallConv,
1071198090Srdivacky                                       bool isVarArg,
1072198090Srdivacky                                       const SmallVectorImpl<ISD::InputArg>
1073198090Srdivacky                                         &Ins,
1074198090Srdivacky                                       DebugLoc dl,
1075198090Srdivacky                                       SelectionDAG &DAG,
1076207618Srdivacky                                       SmallVectorImpl<SDValue> &InVals) const {
1077193323Sed  MachineFunction &MF = DAG.getMachineFunction();
1078193323Sed  MachineFrameInfo *MFI = MF.getFrameInfo();
1079193323Sed  MachineRegisterInfo &RegInfo = MF.getRegInfo();
1080193323Sed
1081193323Sed  // Assign locations to all of the incoming arguments.
1082193323Sed  SmallVector<CCValAssign, 16> ArgLocs;
1083223017Sdim  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
1084223017Sdim		 getTargetMachine(), ArgLocs, *DAG.getContext());
1085193323Sed
1086198090Srdivacky  CCInfo.AnalyzeFormalArguments(Ins, CC_XCore);
1087193323Sed
1088218893Sdim  unsigned StackSlotSize = XCoreFrameLowering::stackSlotSize();
1089193323Sed
1090193323Sed  unsigned LRSaveSize = StackSlotSize;
1091219077Sdim
1092193323Sed  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
1093193323Sed
1094193323Sed    CCValAssign &VA = ArgLocs[i];
1095219077Sdim
1096193323Sed    if (VA.isRegLoc()) {
1097193323Sed      // Arguments passed in registers
1098198090Srdivacky      EVT RegVT = VA.getLocVT();
1099198090Srdivacky      switch (RegVT.getSimpleVT().SimpleTy) {
1100193323Sed      default:
1101198090Srdivacky        {
1102198090Srdivacky#ifndef NDEBUG
1103198090Srdivacky          errs() << "LowerFormalArguments Unhandled argument type: "
1104198090Srdivacky                 << RegVT.getSimpleVT().SimpleTy << "\n";
1105198090Srdivacky#endif
1106198090Srdivacky          llvm_unreachable(0);
1107198090Srdivacky        }
1108193323Sed      case MVT::i32:
1109193323Sed        unsigned VReg = RegInfo.createVirtualRegister(
1110193323Sed                          XCore::GRRegsRegisterClass);
1111193323Sed        RegInfo.addLiveIn(VA.getLocReg(), VReg);
1112198090Srdivacky        InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT));
1113193323Sed      }
1114193323Sed    } else {
1115193323Sed      // sanity check
1116193323Sed      assert(VA.isMemLoc());
1117193323Sed      // Load the argument to a virtual register
1118193323Sed      unsigned ObjSize = VA.getLocVT().getSizeInBits()/8;
1119193323Sed      if (ObjSize > StackSlotSize) {
1120198090Srdivacky        errs() << "LowerFormalArguments Unhandled argument type: "
1121218893Sdim               << EVT(VA.getLocVT()).getEVTString()
1122198090Srdivacky               << "\n";
1123193323Sed      }
1124193323Sed      // Create the frame index object for this incoming parameter...
1125193323Sed      int FI = MFI->CreateFixedObject(ObjSize,
1126199481Srdivacky                                      LRSaveSize + VA.getLocMemOffset(),
1127210299Sed                                      true);
1128193323Sed
1129193323Sed      // Create the SelectionDAG nodes corresponding to a load
1130193323Sed      //from this parameter
1131193323Sed      SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
1132219077Sdim      InVals.push_back(DAG.getLoad(VA.getLocVT(), dl, Chain, FIN,
1133218893Sdim                                   MachinePointerInfo::getFixedStack(FI),
1134203954Srdivacky                                   false, false, 0));
1135193323Sed    }
1136193323Sed  }
1137219077Sdim
1138193323Sed  if (isVarArg) {
1139193323Sed    /* Argument registers */
1140193323Sed    static const unsigned ArgRegs[] = {
1141193323Sed      XCore::R0, XCore::R1, XCore::R2, XCore::R3
1142193323Sed    };
1143193323Sed    XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
1144193323Sed    unsigned FirstVAReg = CCInfo.getFirstUnallocated(ArgRegs,
1145193323Sed                                                     array_lengthof(ArgRegs));
1146193323Sed    if (FirstVAReg < array_lengthof(ArgRegs)) {
1147193323Sed      SmallVector<SDValue, 4> MemOps;
1148193323Sed      int offset = 0;
1149193323Sed      // Save remaining registers, storing higher register numbers at a higher
1150193323Sed      // address
1151193323Sed      for (unsigned i = array_lengthof(ArgRegs) - 1; i >= FirstVAReg; --i) {
1152193323Sed        // Create a stack slot
1153210299Sed        int FI = MFI->CreateFixedObject(4, offset, true);
1154193323Sed        if (i == FirstVAReg) {
1155193323Sed          XFI->setVarArgsFrameIndex(FI);
1156193323Sed        }
1157193323Sed        offset -= StackSlotSize;
1158193323Sed        SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
1159193323Sed        // Move argument from phys reg -> virt reg
1160193323Sed        unsigned VReg = RegInfo.createVirtualRegister(
1161193323Sed                          XCore::GRRegsRegisterClass);
1162193323Sed        RegInfo.addLiveIn(ArgRegs[i], VReg);
1163198090Srdivacky        SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
1164193323Sed        // Move argument from virt reg -> stack
1165218893Sdim        SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN,
1166218893Sdim                                     MachinePointerInfo(), false, false, 0);
1167193323Sed        MemOps.push_back(Store);
1168193323Sed      }
1169193323Sed      if (!MemOps.empty())
1170198090Srdivacky        Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
1171198090Srdivacky                            &MemOps[0], MemOps.size());
1172193323Sed    } else {
1173193323Sed      // This will point to the next argument passed via stack.
1174193323Sed      XFI->setVarArgsFrameIndex(
1175199481Srdivacky        MFI->CreateFixedObject(4, LRSaveSize + CCInfo.getNextStackOffset(),
1176210299Sed                               true));
1177193323Sed    }
1178193323Sed  }
1179219077Sdim
1180198090Srdivacky  return Chain;
1181193323Sed}
1182193323Sed
1183193323Sed//===----------------------------------------------------------------------===//
1184193323Sed//               Return Value Calling Convention Implementation
1185193323Sed//===----------------------------------------------------------------------===//
1186193323Sed
1187199481Srdivackybool XCoreTargetLowering::
1188223017SdimCanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
1189223017Sdim	       bool isVarArg,
1190210299Sed               const SmallVectorImpl<ISD::OutputArg> &Outs,
1191210299Sed               LLVMContext &Context) const {
1192199481Srdivacky  SmallVector<CCValAssign, 16> RVLocs;
1193223017Sdim  CCState CCInfo(CallConv, isVarArg, MF, getTargetMachine(), RVLocs, Context);
1194210299Sed  return CCInfo.CheckReturn(Outs, RetCC_XCore);
1195199481Srdivacky}
1196199481Srdivacky
1197198090SrdivackySDValue
1198198090SrdivackyXCoreTargetLowering::LowerReturn(SDValue Chain,
1199198090Srdivacky                                 CallingConv::ID CallConv, bool isVarArg,
1200198090Srdivacky                                 const SmallVectorImpl<ISD::OutputArg> &Outs,
1201210299Sed                                 const SmallVectorImpl<SDValue> &OutVals,
1202207618Srdivacky                                 DebugLoc dl, SelectionDAG &DAG) const {
1203198090Srdivacky
1204193323Sed  // CCValAssign - represent the assignment of
1205193323Sed  // the return value to a location
1206193323Sed  SmallVector<CCValAssign, 16> RVLocs;
1207193323Sed
1208193323Sed  // CCState - Info about the registers and stack slot.
1209223017Sdim  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
1210223017Sdim		 getTargetMachine(), RVLocs, *DAG.getContext());
1211193323Sed
1212223017Sdim  // Analyze return values.
1213198090Srdivacky  CCInfo.AnalyzeReturn(Outs, RetCC_XCore);
1214193323Sed
1215219077Sdim  // If this is the first return lowered for this function, add
1216193323Sed  // the regs to the liveout set for the function.
1217193323Sed  if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
1218193323Sed    for (unsigned i = 0; i != RVLocs.size(); ++i)
1219193323Sed      if (RVLocs[i].isRegLoc())
1220193323Sed        DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
1221193323Sed  }
1222193323Sed
1223193323Sed  SDValue Flag;
1224193323Sed
1225193323Sed  // Copy the result values into the output registers.
1226193323Sed  for (unsigned i = 0; i != RVLocs.size(); ++i) {
1227193323Sed    CCValAssign &VA = RVLocs[i];
1228193323Sed    assert(VA.isRegLoc() && "Can only return in registers!");
1229193323Sed
1230219077Sdim    Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(),
1231210299Sed                             OutVals[i], Flag);
1232193323Sed
1233193323Sed    // guarantee that all emitted copies are
1234193323Sed    // stuck together, avoiding something bad
1235193323Sed    Flag = Chain.getValue(1);
1236193323Sed  }
1237193323Sed
1238193323Sed  // Return on XCore is always a "retsp 0"
1239193323Sed  if (Flag.getNode())
1240193323Sed    return DAG.getNode(XCoreISD::RETSP, dl, MVT::Other,
1241193323Sed                       Chain, DAG.getConstant(0, MVT::i32), Flag);
1242193323Sed  else // Return Void
1243193323Sed    return DAG.getNode(XCoreISD::RETSP, dl, MVT::Other,
1244193323Sed                       Chain, DAG.getConstant(0, MVT::i32));
1245193323Sed}
1246193323Sed
1247193323Sed//===----------------------------------------------------------------------===//
1248193323Sed//  Other Lowering Code
1249193323Sed//===----------------------------------------------------------------------===//
1250193323Sed
1251193323SedMachineBasicBlock *
1252193323SedXCoreTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
1253207618Srdivacky                                                 MachineBasicBlock *BB) const {
1254193323Sed  const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo();
1255193323Sed  DebugLoc dl = MI->getDebugLoc();
1256193323Sed  assert((MI->getOpcode() == XCore::SELECT_CC) &&
1257193323Sed         "Unexpected instr type to insert");
1258219077Sdim
1259193323Sed  // To "insert" a SELECT_CC instruction, we actually have to insert the diamond
1260193323Sed  // control-flow pattern.  The incoming instruction knows the destination vreg
1261193323Sed  // to set, the condition code register to branch on, the true/false values to
1262193323Sed  // select between, and a branch opcode to use.
1263193323Sed  const BasicBlock *LLVM_BB = BB->getBasicBlock();
1264193323Sed  MachineFunction::iterator It = BB;
1265193323Sed  ++It;
1266219077Sdim
1267193323Sed  //  thisMBB:
1268193323Sed  //  ...
1269193323Sed  //   TrueVal = ...
1270193323Sed  //   cmpTY ccX, r1, r2
1271193323Sed  //   bCC copy1MBB
1272193323Sed  //   fallthrough --> copy0MBB
1273193323Sed  MachineBasicBlock *thisMBB = BB;
1274193323Sed  MachineFunction *F = BB->getParent();
1275193323Sed  MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
1276193323Sed  MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
1277193323Sed  F->insert(It, copy0MBB);
1278193323Sed  F->insert(It, sinkMBB);
1279210299Sed
1280210299Sed  // Transfer the remainder of BB and its successor edges to sinkMBB.
1281210299Sed  sinkMBB->splice(sinkMBB->begin(), BB,
1282210299Sed                  llvm::next(MachineBasicBlock::iterator(MI)),
1283210299Sed                  BB->end());
1284210299Sed  sinkMBB->transferSuccessorsAndUpdatePHIs(BB);
1285210299Sed
1286193323Sed  // Next, add the true and fallthrough blocks as its successors.
1287193323Sed  BB->addSuccessor(copy0MBB);
1288193323Sed  BB->addSuccessor(sinkMBB);
1289219077Sdim
1290210299Sed  BuildMI(BB, dl, TII.get(XCore::BRFT_lru6))
1291210299Sed    .addReg(MI->getOperand(1).getReg()).addMBB(sinkMBB);
1292210299Sed
1293193323Sed  //  copy0MBB:
1294193323Sed  //   %FalseValue = ...
1295193323Sed  //   # fallthrough to sinkMBB
1296193323Sed  BB = copy0MBB;
1297219077Sdim
1298193323Sed  // Update machine-CFG edges
1299193323Sed  BB->addSuccessor(sinkMBB);
1300219077Sdim
1301193323Sed  //  sinkMBB:
1302193323Sed  //   %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ]
1303193323Sed  //  ...
1304193323Sed  BB = sinkMBB;
1305210299Sed  BuildMI(*BB, BB->begin(), dl,
1306210299Sed          TII.get(XCore::PHI), MI->getOperand(0).getReg())
1307193323Sed    .addReg(MI->getOperand(3).getReg()).addMBB(copy0MBB)
1308193323Sed    .addReg(MI->getOperand(2).getReg()).addMBB(thisMBB);
1309219077Sdim
1310210299Sed  MI->eraseFromParent();   // The pseudo instruction is gone now.
1311193323Sed  return BB;
1312193323Sed}
1313193323Sed
1314193323Sed//===----------------------------------------------------------------------===//
1315198090Srdivacky// Target Optimization Hooks
1316198090Srdivacky//===----------------------------------------------------------------------===//
1317198090Srdivacky
1318198090SrdivackySDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N,
1319198090Srdivacky                                             DAGCombinerInfo &DCI) const {
1320198090Srdivacky  SelectionDAG &DAG = DCI.DAG;
1321198090Srdivacky  DebugLoc dl = N->getDebugLoc();
1322198090Srdivacky  switch (N->getOpcode()) {
1323198090Srdivacky  default: break;
1324204961Srdivacky  case XCoreISD::LADD: {
1325204961Srdivacky    SDValue N0 = N->getOperand(0);
1326204961Srdivacky    SDValue N1 = N->getOperand(1);
1327204961Srdivacky    SDValue N2 = N->getOperand(2);
1328204961Srdivacky    ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
1329204961Srdivacky    ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
1330204961Srdivacky    EVT VT = N0.getValueType();
1331204961Srdivacky
1332204961Srdivacky    // canonicalize constant to RHS
1333204961Srdivacky    if (N0C && !N1C)
1334204961Srdivacky      return DAG.getNode(XCoreISD::LADD, dl, DAG.getVTList(VT, VT), N1, N0, N2);
1335204961Srdivacky
1336204961Srdivacky    // fold (ladd 0, 0, x) -> 0, x & 1
1337204961Srdivacky    if (N0C && N0C->isNullValue() && N1C && N1C->isNullValue()) {
1338204961Srdivacky      SDValue Carry = DAG.getConstant(0, VT);
1339204961Srdivacky      SDValue Result = DAG.getNode(ISD::AND, dl, VT, N2,
1340204961Srdivacky                                   DAG.getConstant(1, VT));
1341204961Srdivacky      SDValue Ops [] = { Carry, Result };
1342204961Srdivacky      return DAG.getMergeValues(Ops, 2, dl);
1343204961Srdivacky    }
1344204961Srdivacky
1345204961Srdivacky    // fold (ladd x, 0, y) -> 0, add x, y iff carry is unused and y has only the
1346204961Srdivacky    // low bit set
1347219077Sdim    if (N1C && N1C->isNullValue() && N->hasNUsesOfValue(0, 0)) {
1348204961Srdivacky      APInt KnownZero, KnownOne;
1349204961Srdivacky      APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(),
1350204961Srdivacky                                         VT.getSizeInBits() - 1);
1351204961Srdivacky      DAG.ComputeMaskedBits(N2, Mask, KnownZero, KnownOne);
1352204961Srdivacky      if (KnownZero == Mask) {
1353204961Srdivacky        SDValue Carry = DAG.getConstant(0, VT);
1354204961Srdivacky        SDValue Result = DAG.getNode(ISD::ADD, dl, VT, N0, N2);
1355204961Srdivacky        SDValue Ops [] = { Carry, Result };
1356204961Srdivacky        return DAG.getMergeValues(Ops, 2, dl);
1357204961Srdivacky      }
1358204961Srdivacky    }
1359204961Srdivacky  }
1360204961Srdivacky  break;
1361204961Srdivacky  case XCoreISD::LSUB: {
1362204961Srdivacky    SDValue N0 = N->getOperand(0);
1363204961Srdivacky    SDValue N1 = N->getOperand(1);
1364204961Srdivacky    SDValue N2 = N->getOperand(2);
1365204961Srdivacky    ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
1366204961Srdivacky    ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
1367204961Srdivacky    EVT VT = N0.getValueType();
1368204961Srdivacky
1369204961Srdivacky    // fold (lsub 0, 0, x) -> x, -x iff x has only the low bit set
1370219077Sdim    if (N0C && N0C->isNullValue() && N1C && N1C->isNullValue()) {
1371204961Srdivacky      APInt KnownZero, KnownOne;
1372204961Srdivacky      APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(),
1373204961Srdivacky                                         VT.getSizeInBits() - 1);
1374204961Srdivacky      DAG.ComputeMaskedBits(N2, Mask, KnownZero, KnownOne);
1375204961Srdivacky      if (KnownZero == Mask) {
1376204961Srdivacky        SDValue Borrow = N2;
1377204961Srdivacky        SDValue Result = DAG.getNode(ISD::SUB, dl, VT,
1378204961Srdivacky                                     DAG.getConstant(0, VT), N2);
1379204961Srdivacky        SDValue Ops [] = { Borrow, Result };
1380204961Srdivacky        return DAG.getMergeValues(Ops, 2, dl);
1381204961Srdivacky      }
1382204961Srdivacky    }
1383204961Srdivacky
1384204961Srdivacky    // fold (lsub x, 0, y) -> 0, sub x, y iff borrow is unused and y has only the
1385204961Srdivacky    // low bit set
1386219077Sdim    if (N1C && N1C->isNullValue() && N->hasNUsesOfValue(0, 0)) {
1387204961Srdivacky      APInt KnownZero, KnownOne;
1388204961Srdivacky      APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(),
1389204961Srdivacky                                         VT.getSizeInBits() - 1);
1390204961Srdivacky      DAG.ComputeMaskedBits(N2, Mask, KnownZero, KnownOne);
1391204961Srdivacky      if (KnownZero == Mask) {
1392204961Srdivacky        SDValue Borrow = DAG.getConstant(0, VT);
1393204961Srdivacky        SDValue Result = DAG.getNode(ISD::SUB, dl, VT, N0, N2);
1394204961Srdivacky        SDValue Ops [] = { Borrow, Result };
1395204961Srdivacky        return DAG.getMergeValues(Ops, 2, dl);
1396204961Srdivacky      }
1397204961Srdivacky    }
1398204961Srdivacky  }
1399204961Srdivacky  break;
1400205218Srdivacky  case XCoreISD::LMUL: {
1401205218Srdivacky    SDValue N0 = N->getOperand(0);
1402205218Srdivacky    SDValue N1 = N->getOperand(1);
1403205218Srdivacky    SDValue N2 = N->getOperand(2);
1404205218Srdivacky    SDValue N3 = N->getOperand(3);
1405205218Srdivacky    ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
1406205218Srdivacky    ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
1407205218Srdivacky    EVT VT = N0.getValueType();
1408205218Srdivacky    // Canonicalize multiplicative constant to RHS. If both multiplicative
1409205218Srdivacky    // operands are constant canonicalize smallest to RHS.
1410205218Srdivacky    if ((N0C && !N1C) ||
1411205218Srdivacky        (N0C && N1C && N0C->getZExtValue() < N1C->getZExtValue()))
1412205218Srdivacky      return DAG.getNode(XCoreISD::LMUL, dl, DAG.getVTList(VT, VT), N1, N0, N2, N3);
1413205218Srdivacky
1414205218Srdivacky    // lmul(x, 0, a, b)
1415205218Srdivacky    if (N1C && N1C->isNullValue()) {
1416205218Srdivacky      // If the high result is unused fold to add(a, b)
1417205218Srdivacky      if (N->hasNUsesOfValue(0, 0)) {
1418205218Srdivacky        SDValue Lo = DAG.getNode(ISD::ADD, dl, VT, N2, N3);
1419205218Srdivacky        SDValue Ops [] = { Lo, Lo };
1420205218Srdivacky        return DAG.getMergeValues(Ops, 2, dl);
1421205218Srdivacky      }
1422205218Srdivacky      // Otherwise fold to ladd(a, b, 0)
1423205218Srdivacky      return DAG.getNode(XCoreISD::LADD, dl, DAG.getVTList(VT, VT), N2, N3, N1);
1424205218Srdivacky    }
1425205218Srdivacky  }
1426205218Srdivacky  break;
1427204961Srdivacky  case ISD::ADD: {
1428205218Srdivacky    // Fold 32 bit expressions such as add(add(mul(x,y),a),b) ->
1429205218Srdivacky    // lmul(x, y, a, b). The high result of lmul will be ignored.
1430204961Srdivacky    // This is only profitable if the intermediate results are unused
1431204961Srdivacky    // elsewhere.
1432204961Srdivacky    SDValue Mul0, Mul1, Addend0, Addend1;
1433205218Srdivacky    if (N->getValueType(0) == MVT::i32 &&
1434205218Srdivacky        isADDADDMUL(SDValue(N, 0), Mul0, Mul1, Addend0, Addend1, true)) {
1435204961Srdivacky      SDValue Ignored = DAG.getNode(XCoreISD::LMUL, dl,
1436204961Srdivacky                                    DAG.getVTList(MVT::i32, MVT::i32), Mul0,
1437204961Srdivacky                                    Mul1, Addend0, Addend1);
1438204961Srdivacky      SDValue Result(Ignored.getNode(), 1);
1439204961Srdivacky      return Result;
1440204961Srdivacky    }
1441205218Srdivacky    APInt HighMask = APInt::getHighBitsSet(64, 32);
1442205218Srdivacky    // Fold 64 bit expression such as add(add(mul(x,y),a),b) ->
1443205218Srdivacky    // lmul(x, y, a, b) if all operands are zero-extended. We do this
1444205218Srdivacky    // before type legalization as it is messy to match the operands after
1445205218Srdivacky    // that.
1446205218Srdivacky    if (N->getValueType(0) == MVT::i64 &&
1447205218Srdivacky        isADDADDMUL(SDValue(N, 0), Mul0, Mul1, Addend0, Addend1, false) &&
1448205218Srdivacky        DAG.MaskedValueIsZero(Mul0, HighMask) &&
1449205218Srdivacky        DAG.MaskedValueIsZero(Mul1, HighMask) &&
1450205218Srdivacky        DAG.MaskedValueIsZero(Addend0, HighMask) &&
1451205218Srdivacky        DAG.MaskedValueIsZero(Addend1, HighMask)) {
1452205218Srdivacky      SDValue Mul0L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
1453205218Srdivacky                                  Mul0, DAG.getConstant(0, MVT::i32));
1454205218Srdivacky      SDValue Mul1L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
1455205218Srdivacky                                  Mul1, DAG.getConstant(0, MVT::i32));
1456205218Srdivacky      SDValue Addend0L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
1457205218Srdivacky                                     Addend0, DAG.getConstant(0, MVT::i32));
1458205218Srdivacky      SDValue Addend1L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
1459205218Srdivacky                                     Addend1, DAG.getConstant(0, MVT::i32));
1460205218Srdivacky      SDValue Hi = DAG.getNode(XCoreISD::LMUL, dl,
1461205218Srdivacky                               DAG.getVTList(MVT::i32, MVT::i32), Mul0L, Mul1L,
1462205218Srdivacky                               Addend0L, Addend1L);
1463205218Srdivacky      SDValue Lo(Hi.getNode(), 1);
1464205218Srdivacky      return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);
1465205218Srdivacky    }
1466204961Srdivacky  }
1467204961Srdivacky  break;
1468198090Srdivacky  case ISD::STORE: {
1469198090Srdivacky    // Replace unaligned store of unaligned load with memmove.
1470198090Srdivacky    StoreSDNode *ST  = cast<StoreSDNode>(N);
1471198090Srdivacky    if (!DCI.isBeforeLegalize() ||
1472198090Srdivacky        allowsUnalignedMemoryAccesses(ST->getMemoryVT()) ||
1473198090Srdivacky        ST->isVolatile() || ST->isIndexed()) {
1474198090Srdivacky      break;
1475198090Srdivacky    }
1476198090Srdivacky    SDValue Chain = ST->getChain();
1477198090Srdivacky
1478198090Srdivacky    unsigned StoreBits = ST->getMemoryVT().getStoreSizeInBits();
1479198090Srdivacky    if (StoreBits % 8) {
1480198090Srdivacky      break;
1481198090Srdivacky    }
1482198090Srdivacky    unsigned ABIAlignment = getTargetData()->getABITypeAlignment(
1483198090Srdivacky        ST->getMemoryVT().getTypeForEVT(*DCI.DAG.getContext()));
1484198090Srdivacky    unsigned Alignment = ST->getAlignment();
1485198090Srdivacky    if (Alignment >= ABIAlignment) {
1486198090Srdivacky      break;
1487198090Srdivacky    }
1488198090Srdivacky
1489198090Srdivacky    if (LoadSDNode *LD = dyn_cast<LoadSDNode>(ST->getValue())) {
1490198090Srdivacky      if (LD->hasNUsesOfValue(1, 0) && ST->getMemoryVT() == LD->getMemoryVT() &&
1491198090Srdivacky        LD->getAlignment() == Alignment &&
1492198090Srdivacky        !LD->isVolatile() && !LD->isIndexed() &&
1493198090Srdivacky        Chain.reachesChainWithoutSideEffects(SDValue(LD, 1))) {
1494198090Srdivacky        return DAG.getMemmove(Chain, dl, ST->getBasePtr(),
1495198090Srdivacky                              LD->getBasePtr(),
1496198090Srdivacky                              DAG.getConstant(StoreBits/8, MVT::i32),
1497218893Sdim                              Alignment, false, ST->getPointerInfo(),
1498218893Sdim                              LD->getPointerInfo());
1499198090Srdivacky      }
1500198090Srdivacky    }
1501198090Srdivacky    break;
1502198090Srdivacky  }
1503198090Srdivacky  }
1504198090Srdivacky  return SDValue();
1505198090Srdivacky}
1506198090Srdivacky
1507204961Srdivackyvoid XCoreTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
1508204961Srdivacky                                                         const APInt &Mask,
1509204961Srdivacky                                                         APInt &KnownZero,
1510204961Srdivacky                                                         APInt &KnownOne,
1511204961Srdivacky                                                         const SelectionDAG &DAG,
1512204961Srdivacky                                                         unsigned Depth) const {
1513204961Srdivacky  KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
1514204961Srdivacky  switch (Op.getOpcode()) {
1515204961Srdivacky  default: break;
1516204961Srdivacky  case XCoreISD::LADD:
1517204961Srdivacky  case XCoreISD::LSUB:
1518204961Srdivacky    if (Op.getResNo() == 0) {
1519204961Srdivacky      // Top bits of carry / borrow are clear.
1520204961Srdivacky      KnownZero = APInt::getHighBitsSet(Mask.getBitWidth(),
1521204961Srdivacky                                        Mask.getBitWidth() - 1);
1522204961Srdivacky      KnownZero &= Mask;
1523204961Srdivacky    }
1524204961Srdivacky    break;
1525204961Srdivacky  }
1526204961Srdivacky}
1527204961Srdivacky
1528198090Srdivacky//===----------------------------------------------------------------------===//
1529193323Sed//  Addressing mode description hooks
1530193323Sed//===----------------------------------------------------------------------===//
1531193323Sed
1532193323Sedstatic inline bool isImmUs(int64_t val)
1533193323Sed{
1534193323Sed  return (val >= 0 && val <= 11);
1535193323Sed}
1536193323Sed
1537193323Sedstatic inline bool isImmUs2(int64_t val)
1538193323Sed{
1539193323Sed  return (val%2 == 0 && isImmUs(val/2));
1540193323Sed}
1541193323Sed
1542193323Sedstatic inline bool isImmUs4(int64_t val)
1543193323Sed{
1544193323Sed  return (val%4 == 0 && isImmUs(val/4));
1545193323Sed}
1546193323Sed
1547193323Sed/// isLegalAddressingMode - Return true if the addressing mode represented
1548193323Sed/// by AM is legal for this target, for a load/store of the specified type.
1549193323Sedbool
1550219077SdimXCoreTargetLowering::isLegalAddressingMode(const AddrMode &AM,
1551193323Sed                                              const Type *Ty) const {
1552198090Srdivacky  if (Ty->getTypeID() == Type::VoidTyID)
1553204642Srdivacky    return AM.Scale == 0 && isImmUs(AM.BaseOffs) && isImmUs4(AM.BaseOffs);
1554198090Srdivacky
1555198090Srdivacky  const TargetData *TD = TM.getTargetData();
1556198090Srdivacky  unsigned Size = TD->getTypeAllocSize(Ty);
1557193323Sed  if (AM.BaseGV) {
1558198090Srdivacky    return Size >= 4 && !AM.HasBaseReg && AM.Scale == 0 &&
1559193323Sed                 AM.BaseOffs%4 == 0;
1560193323Sed  }
1561219077Sdim
1562198090Srdivacky  switch (Size) {
1563198090Srdivacky  case 1:
1564193323Sed    // reg + imm
1565193323Sed    if (AM.Scale == 0) {
1566193323Sed      return isImmUs(AM.BaseOffs);
1567193323Sed    }
1568198090Srdivacky    // reg + reg
1569193323Sed    return AM.Scale == 1 && AM.BaseOffs == 0;
1570198090Srdivacky  case 2:
1571198090Srdivacky  case 3:
1572193323Sed    // reg + imm
1573193323Sed    if (AM.Scale == 0) {
1574193323Sed      return isImmUs2(AM.BaseOffs);
1575193323Sed    }
1576198090Srdivacky    // reg + reg<<1
1577193323Sed    return AM.Scale == 2 && AM.BaseOffs == 0;
1578198090Srdivacky  default:
1579193323Sed    // reg + imm
1580193323Sed    if (AM.Scale == 0) {
1581193323Sed      return isImmUs4(AM.BaseOffs);
1582193323Sed    }
1583193323Sed    // reg + reg<<2
1584193323Sed    return AM.Scale == 4 && AM.BaseOffs == 0;
1585193323Sed  }
1586219077Sdim
1587193323Sed  return false;
1588193323Sed}
1589193323Sed
1590193323Sed//===----------------------------------------------------------------------===//
1591193323Sed//                           XCore Inline Assembly Support
1592193323Sed//===----------------------------------------------------------------------===//
1593193323Sed
1594193323Sedstd::vector<unsigned> XCoreTargetLowering::
1595193323SedgetRegClassForInlineAsmConstraint(const std::string &Constraint,
1596219077Sdim                                  EVT VT) const
1597193323Sed{
1598193323Sed  if (Constraint.size() != 1)
1599193323Sed    return std::vector<unsigned>();
1600193323Sed
1601193323Sed  switch (Constraint[0]) {
1602193323Sed    default : break;
1603193323Sed    case 'r':
1604219077Sdim      return make_vector<unsigned>(XCore::R0, XCore::R1,  XCore::R2,
1605219077Sdim                                   XCore::R3, XCore::R4,  XCore::R5,
1606219077Sdim                                   XCore::R6, XCore::R7,  XCore::R8,
1607193323Sed                                   XCore::R9, XCore::R10, XCore::R11, 0);
1608193323Sed      break;
1609193323Sed  }
1610193323Sed  return std::vector<unsigned>();
1611193323Sed}
1612