1234353Sdim//===-- XCoreISelLowering.cpp - XCore DAG Lowering Implementation ---------===//
2193323Sed//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6193323Sed//
7193323Sed//===----------------------------------------------------------------------===//
8193323Sed//
9193323Sed// This file implements the XCoreTargetLowering class.
10193323Sed//
11193323Sed//===----------------------------------------------------------------------===//
12193323Sed
13193323Sed#include "XCoreISelLowering.h"
14249423Sdim#include "XCore.h"
15193323Sed#include "XCoreMachineFunctionInfo.h"
16249423Sdim#include "XCoreSubtarget.h"
17249423Sdim#include "XCoreTargetMachine.h"
18198090Srdivacky#include "XCoreTargetObjectFile.h"
19193323Sed#include "llvm/CodeGen/CallingConvLower.h"
20193323Sed#include "llvm/CodeGen/MachineFrameInfo.h"
21193323Sed#include "llvm/CodeGen/MachineFunction.h"
22193323Sed#include "llvm/CodeGen/MachineInstrBuilder.h"
23204642Srdivacky#include "llvm/CodeGen/MachineJumpTableInfo.h"
24193323Sed#include "llvm/CodeGen/MachineRegisterInfo.h"
25193323Sed#include "llvm/CodeGen/SelectionDAGISel.h"
26193323Sed#include "llvm/CodeGen/ValueTypes.h"
27249423Sdim#include "llvm/IR/CallingConv.h"
28276479Sdim#include "llvm/IR/Constants.h"
29249423Sdim#include "llvm/IR/DerivedTypes.h"
30249423Sdim#include "llvm/IR/Function.h"
31249423Sdim#include "llvm/IR/GlobalAlias.h"
32249423Sdim#include "llvm/IR/GlobalVariable.h"
33249423Sdim#include "llvm/IR/Intrinsics.h"
34360784Sdim#include "llvm/IR/IntrinsicsXCore.h"
35193323Sed#include "llvm/Support/Debug.h"
36198090Srdivacky#include "llvm/Support/ErrorHandling.h"
37321369Sdim#include "llvm/Support/KnownBits.h"
38198090Srdivacky#include "llvm/Support/raw_ostream.h"
39251662Sdim#include <algorithm>
40251662Sdim
41193323Sedusing namespace llvm;
42193323Sed
43276479Sdim#define DEBUG_TYPE "xcore-lower"
44276479Sdim
45193323Sedconst char *XCoreTargetLowering::
46219077SdimgetTargetNodeName(unsigned Opcode) const
47193323Sed{
48288943Sdim  switch ((XCoreISD::NodeType)Opcode)
49193323Sed  {
50288943Sdim    case XCoreISD::FIRST_NUMBER      : break;
51193323Sed    case XCoreISD::BL                : return "XCoreISD::BL";
52193323Sed    case XCoreISD::PCRelativeWrapper : return "XCoreISD::PCRelativeWrapper";
53193323Sed    case XCoreISD::DPRelativeWrapper : return "XCoreISD::DPRelativeWrapper";
54193323Sed    case XCoreISD::CPRelativeWrapper : return "XCoreISD::CPRelativeWrapper";
55276479Sdim    case XCoreISD::LDWSP             : return "XCoreISD::LDWSP";
56193323Sed    case XCoreISD::STWSP             : return "XCoreISD::STWSP";
57193323Sed    case XCoreISD::RETSP             : return "XCoreISD::RETSP";
58198090Srdivacky    case XCoreISD::LADD              : return "XCoreISD::LADD";
59198090Srdivacky    case XCoreISD::LSUB              : return "XCoreISD::LSUB";
60204961Srdivacky    case XCoreISD::LMUL              : return "XCoreISD::LMUL";
61204961Srdivacky    case XCoreISD::MACCU             : return "XCoreISD::MACCU";
62204961Srdivacky    case XCoreISD::MACCS             : return "XCoreISD::MACCS";
63249423Sdim    case XCoreISD::CRC8              : return "XCoreISD::CRC8";
64204642Srdivacky    case XCoreISD::BR_JT             : return "XCoreISD::BR_JT";
65204642Srdivacky    case XCoreISD::BR_JT32           : return "XCoreISD::BR_JT32";
66276479Sdim    case XCoreISD::FRAME_TO_ARGS_OFFSET : return "XCoreISD::FRAME_TO_ARGS_OFFSET";
67276479Sdim    case XCoreISD::EH_RETURN         : return "XCoreISD::EH_RETURN";
68261991Sdim    case XCoreISD::MEMBARRIER        : return "XCoreISD::MEMBARRIER";
69193323Sed  }
70288943Sdim  return nullptr;
71193323Sed}
72193323Sed
73288943SdimXCoreTargetLowering::XCoreTargetLowering(const TargetMachine &TM,
74288943Sdim                                         const XCoreSubtarget &Subtarget)
75288943Sdim    : TargetLowering(TM), TM(TM), Subtarget(Subtarget) {
76193323Sed
77193323Sed  // Set up the register classes.
78239462Sdim  addRegisterClass(MVT::i32, &XCore::GRRegsRegClass);
79193323Sed
80193323Sed  // Compute derived properties from the register classes
81288943Sdim  computeRegisterProperties(Subtarget.getRegisterInfo());
82193323Sed
83193323Sed  setStackPointerRegisterToSaveRestore(XCore::SP);
84193323Sed
85261991Sdim  setSchedulingPreference(Sched::Source);
86193323Sed
87193323Sed  // Use i32 for setcc operations results (slt, sgt, ...).
88193323Sed  setBooleanContents(ZeroOrOneBooleanContent);
89226633Sdim  setBooleanVectorContents(ZeroOrOneBooleanContent); // FIXME: Is this correct?
90193323Sed
91193323Sed  // XCore does not have the NodeTypes below.
92249423Sdim  setOperationAction(ISD::BR_CC,     MVT::i32,   Expand);
93276479Sdim  setOperationAction(ISD::SELECT_CC, MVT::i32,   Expand);
94193323Sed
95193323Sed  // 64bit
96198090Srdivacky  setOperationAction(ISD::ADD, MVT::i64, Custom);
97198090Srdivacky  setOperationAction(ISD::SUB, MVT::i64, Custom);
98204961Srdivacky  setOperationAction(ISD::SMUL_LOHI, MVT::i32, Custom);
99204961Srdivacky  setOperationAction(ISD::UMUL_LOHI, MVT::i32, Custom);
100193323Sed  setOperationAction(ISD::MULHS, MVT::i32, Expand);
101193323Sed  setOperationAction(ISD::MULHU, MVT::i32, Expand);
102193323Sed  setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
103193323Sed  setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
104193323Sed  setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);
105219077Sdim
106193323Sed  // Bit Manipulation
107193323Sed  setOperationAction(ISD::CTPOP, MVT::i32, Expand);
108193323Sed  setOperationAction(ISD::ROTL , MVT::i32, Expand);
109193323Sed  setOperationAction(ISD::ROTR , MVT::i32, Expand);
110219077Sdim
111193323Sed  setOperationAction(ISD::TRAP, MVT::Other, Legal);
112219077Sdim
113204642Srdivacky  // Jump tables.
114204642Srdivacky  setOperationAction(ISD::BR_JT, MVT::Other, Custom);
115193323Sed
116193323Sed  setOperationAction(ISD::GlobalAddress, MVT::i32,   Custom);
117199511Srdivacky  setOperationAction(ISD::BlockAddress, MVT::i32 , Custom);
118199511Srdivacky
119193323Sed  // Conversion of i64 -> double produces constantpool nodes
120193323Sed  setOperationAction(ISD::ConstantPool, MVT::i32,   Custom);
121193323Sed
122193323Sed  // Loads
123280031Sdim  for (MVT VT : MVT::integer_valuetypes()) {
124280031Sdim    setLoadExtAction(ISD::EXTLOAD, VT, MVT::i1, Promote);
125280031Sdim    setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i1, Promote);
126280031Sdim    setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote);
127193323Sed
128280031Sdim    setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i8, Expand);
129280031Sdim    setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i16, Expand);
130280031Sdim  }
131198090Srdivacky
132198090Srdivacky  // Custom expand misaligned loads / stores.
133198090Srdivacky  setOperationAction(ISD::LOAD, MVT::i32, Custom);
134198090Srdivacky  setOperationAction(ISD::STORE, MVT::i32, Custom);
135198090Srdivacky
136193323Sed  // Varargs
137193323Sed  setOperationAction(ISD::VAEND, MVT::Other, Expand);
138193323Sed  setOperationAction(ISD::VACOPY, MVT::Other, Expand);
139193323Sed  setOperationAction(ISD::VAARG, MVT::Other, Custom);
140193323Sed  setOperationAction(ISD::VASTART, MVT::Other, Custom);
141219077Sdim
142193323Sed  // Dynamic stack
143193323Sed  setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
144193323Sed  setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
145193323Sed  setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand);
146198090Srdivacky
147261991Sdim  // Exception handling
148276479Sdim  setOperationAction(ISD::EH_RETURN, MVT::Other, Custom);
149276479Sdim  setOperationAction(ISD::FRAME_TO_ARGS_OFFSET, MVT::i32, Custom);
150261991Sdim
151261991Sdim  // Atomic operations
152276479Sdim  // We request a fence for ATOMIC_* instructions, to reduce them to Monotonic.
153276479Sdim  // As we are always Sequential Consistent, an ATOMIC_FENCE becomes a no OP.
154261991Sdim  setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom);
155276479Sdim  setOperationAction(ISD::ATOMIC_LOAD, MVT::i32, Custom);
156276479Sdim  setOperationAction(ISD::ATOMIC_STORE, MVT::i32, Custom);
157261991Sdim
158218893Sdim  // TRAMPOLINE is custom lowered.
159226633Sdim  setOperationAction(ISD::INIT_TRAMPOLINE, MVT::Other, Custom);
160226633Sdim  setOperationAction(ISD::ADJUST_TRAMPOLINE, MVT::Other, Custom);
161218893Sdim
162249423Sdim  // We want to custom lower some of our intrinsics.
163249423Sdim  setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
164218893Sdim
165249423Sdim  MaxStoresPerMemset = MaxStoresPerMemsetOptSize = 4;
166249423Sdim  MaxStoresPerMemmove = MaxStoresPerMemmoveOptSize
167249423Sdim    = MaxStoresPerMemcpy = MaxStoresPerMemcpyOptSize = 2;
168249423Sdim
169198090Srdivacky  // We have target-specific dag combine patterns for the following nodes:
170198090Srdivacky  setTargetDAGCombine(ISD::STORE);
171204961Srdivacky  setTargetDAGCombine(ISD::ADD);
172276479Sdim  setTargetDAGCombine(ISD::INTRINSIC_VOID);
173276479Sdim  setTargetDAGCombine(ISD::INTRINSIC_W_CHAIN);
174223017Sdim
175360784Sdim  setMinFunctionAlignment(Align(2));
176360784Sdim  setPrefFunctionAlignment(Align(4));
177193323Sed}
178193323Sed
179261991Sdimbool XCoreTargetLowering::isZExtFree(SDValue Val, EVT VT2) const {
180261991Sdim  if (Val.getOpcode() != ISD::LOAD)
181261991Sdim    return false;
182261991Sdim
183261991Sdim  EVT VT1 = Val.getValueType();
184261991Sdim  if (!VT1.isSimple() || !VT1.isInteger() ||
185261991Sdim      !VT2.isSimple() || !VT2.isInteger())
186261991Sdim    return false;
187261991Sdim
188261991Sdim  switch (VT1.getSimpleVT().SimpleTy) {
189261991Sdim  default: break;
190261991Sdim  case MVT::i8:
191261991Sdim    return true;
192261991Sdim  }
193261991Sdim
194261991Sdim  return false;
195261991Sdim}
196261991Sdim
197193323SedSDValue XCoreTargetLowering::
198207618SrdivackyLowerOperation(SDValue Op, SelectionDAG &DAG) const {
199219077Sdim  switch (Op.getOpcode())
200193323Sed  {
201276479Sdim  case ISD::EH_RETURN:          return LowerEH_RETURN(Op, DAG);
202249423Sdim  case ISD::GlobalAddress:      return LowerGlobalAddress(Op, DAG);
203249423Sdim  case ISD::BlockAddress:       return LowerBlockAddress(Op, DAG);
204249423Sdim  case ISD::ConstantPool:       return LowerConstantPool(Op, DAG);
205249423Sdim  case ISD::BR_JT:              return LowerBR_JT(Op, DAG);
206249423Sdim  case ISD::LOAD:               return LowerLOAD(Op, DAG);
207249423Sdim  case ISD::STORE:              return LowerSTORE(Op, DAG);
208249423Sdim  case ISD::VAARG:              return LowerVAARG(Op, DAG);
209249423Sdim  case ISD::VASTART:            return LowerVASTART(Op, DAG);
210249423Sdim  case ISD::SMUL_LOHI:          return LowerSMUL_LOHI(Op, DAG);
211249423Sdim  case ISD::UMUL_LOHI:          return LowerUMUL_LOHI(Op, DAG);
212193323Sed  // FIXME: Remove these when LegalizeDAGTypes lands.
213193323Sed  case ISD::ADD:
214249423Sdim  case ISD::SUB:                return ExpandADDSUB(Op.getNode(), DAG);
215249423Sdim  case ISD::FRAMEADDR:          return LowerFRAMEADDR(Op, DAG);
216276479Sdim  case ISD::RETURNADDR:         return LowerRETURNADDR(Op, DAG);
217276479Sdim  case ISD::FRAME_TO_ARGS_OFFSET: return LowerFRAME_TO_ARGS_OFFSET(Op, DAG);
218249423Sdim  case ISD::INIT_TRAMPOLINE:    return LowerINIT_TRAMPOLINE(Op, DAG);
219249423Sdim  case ISD::ADJUST_TRAMPOLINE:  return LowerADJUST_TRAMPOLINE(Op, DAG);
220249423Sdim  case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG);
221261991Sdim  case ISD::ATOMIC_FENCE:       return LowerATOMIC_FENCE(Op, DAG);
222276479Sdim  case ISD::ATOMIC_LOAD:        return LowerATOMIC_LOAD(Op, DAG);
223276479Sdim  case ISD::ATOMIC_STORE:       return LowerATOMIC_STORE(Op, DAG);
224193323Sed  default:
225198090Srdivacky    llvm_unreachable("unimplemented operand");
226193323Sed  }
227193323Sed}
228193323Sed
229193323Sed/// ReplaceNodeResults - Replace the results of node with an illegal result
230193323Sed/// type with new values built out of custom code.
231193323Sedvoid XCoreTargetLowering::ReplaceNodeResults(SDNode *N,
232193323Sed                                             SmallVectorImpl<SDValue>&Results,
233207618Srdivacky                                             SelectionDAG &DAG) const {
234193323Sed  switch (N->getOpcode()) {
235193323Sed  default:
236198090Srdivacky    llvm_unreachable("Don't know how to custom expand this!");
237193323Sed  case ISD::ADD:
238193323Sed  case ISD::SUB:
239193323Sed    Results.push_back(ExpandADDSUB(N, DAG));
240193323Sed    return;
241193323Sed  }
242193323Sed}
243193323Sed
244193323Sed//===----------------------------------------------------------------------===//
245193323Sed//  Misc Lower Operation implementation
246193323Sed//===----------------------------------------------------------------------===//
247193323Sed
248276479SdimSDValue XCoreTargetLowering::getGlobalAddressWrapper(SDValue GA,
249276479Sdim                                                     const GlobalValue *GV,
250276479Sdim                                                     SelectionDAG &DAG) const {
251193323Sed  // FIXME there is no actual debug info here
252261991Sdim  SDLoc dl(GA);
253276479Sdim
254309124Sdim  if (GV->getValueType()->isFunctionTy())
255276479Sdim    return DAG.getNode(XCoreISD::PCRelativeWrapper, dl, MVT::i32, GA);
256276479Sdim
257276479Sdim  const auto *GVar = dyn_cast<GlobalVariable>(GV);
258309124Sdim  if ((GV->hasSection() && GV->getSection().startswith(".cp.")) ||
259276479Sdim      (GVar && GVar->isConstant() && GV->hasLocalLinkage()))
260276479Sdim    return DAG.getNode(XCoreISD::CPRelativeWrapper, dl, MVT::i32, GA);
261276479Sdim
262276479Sdim  return DAG.getNode(XCoreISD::DPRelativeWrapper, dl, MVT::i32, GA);
263193323Sed}
264193323Sed
265276479Sdimstatic bool IsSmallObject(const GlobalValue *GV, const XCoreTargetLowering &XTL) {
266276479Sdim  if (XTL.getTargetMachine().getCodeModel() == CodeModel::Small)
267276479Sdim    return true;
268276479Sdim
269309124Sdim  Type *ObjType = GV->getValueType();
270276479Sdim  if (!ObjType->isSized())
271276479Sdim    return false;
272276479Sdim
273288943Sdim  auto &DL = GV->getParent()->getDataLayout();
274288943Sdim  unsigned ObjSize = DL.getTypeAllocSize(ObjType);
275276479Sdim  return ObjSize < CodeModelLargeSize && ObjSize != 0;
276276479Sdim}
277276479Sdim
278193323SedSDValue XCoreTargetLowering::
279207618SrdivackyLowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const
280193323Sed{
281251662Sdim  const GlobalAddressSDNode *GN = cast<GlobalAddressSDNode>(Op);
282251662Sdim  const GlobalValue *GV = GN->getGlobal();
283276479Sdim  SDLoc DL(GN);
284251662Sdim  int64_t Offset = GN->getOffset();
285276479Sdim  if (IsSmallObject(GV, *this)) {
286276479Sdim    // We can only fold positive offsets that are a multiple of the word size.
287276479Sdim    int64_t FoldedOffset = std::max(Offset & ~3, (int64_t)0);
288276479Sdim    SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, FoldedOffset);
289276479Sdim    GA = getGlobalAddressWrapper(GA, GV, DAG);
290276479Sdim    // Handle the rest of the offset.
291276479Sdim    if (Offset != FoldedOffset) {
292288943Sdim      SDValue Remaining = DAG.getConstant(Offset - FoldedOffset, DL, MVT::i32);
293276479Sdim      GA = DAG.getNode(ISD::ADD, DL, MVT::i32, GA, Remaining);
294276479Sdim    }
295276479Sdim    return GA;
296276479Sdim  } else {
297276479Sdim    // Ideally we would not fold in offset with an index <= 11.
298276479Sdim    Type *Ty = Type::getInt8PtrTy(*DAG.getContext());
299276479Sdim    Constant *GA = ConstantExpr::getBitCast(const_cast<GlobalValue*>(GV), Ty);
300276479Sdim    Ty = Type::getInt32Ty(*DAG.getContext());
301276479Sdim    Constant *Idx = ConstantInt::get(Ty, Offset);
302288943Sdim    Constant *GAI = ConstantExpr::getGetElementPtr(
303288943Sdim        Type::getInt8Ty(*DAG.getContext()), GA, Idx);
304276479Sdim    SDValue CP = DAG.getConstantPool(GAI, MVT::i32);
305288943Sdim    return DAG.getLoad(getPointerTy(DAG.getDataLayout()), DL,
306309124Sdim                       DAG.getEntryNode(), CP, MachinePointerInfo());
307251662Sdim  }
308193323Sed}
309193323Sed
310193323SedSDValue XCoreTargetLowering::
311207618SrdivackyLowerBlockAddress(SDValue Op, SelectionDAG &DAG) const
312199511Srdivacky{
313261991Sdim  SDLoc DL(Op);
314288943Sdim  auto PtrVT = getPointerTy(DAG.getDataLayout());
315207618Srdivacky  const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress();
316288943Sdim  SDValue Result = DAG.getTargetBlockAddress(BA, PtrVT);
317199511Srdivacky
318288943Sdim  return DAG.getNode(XCoreISD::PCRelativeWrapper, DL, PtrVT, Result);
319199511Srdivacky}
320199511Srdivacky
321199511SrdivackySDValue XCoreTargetLowering::
322207618SrdivackyLowerConstantPool(SDValue Op, SelectionDAG &DAG) const
323193323Sed{
324193323Sed  ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
325193323Sed  // FIXME there isn't really debug info here
326261991Sdim  SDLoc dl(CP);
327198090Srdivacky  EVT PtrVT = Op.getValueType();
328198090Srdivacky  SDValue Res;
329198090Srdivacky  if (CP->isMachineConstantPoolEntry()) {
330198090Srdivacky    Res = DAG.getTargetConstantPool(CP->getMachineCPVal(), PtrVT,
331276479Sdim                                    CP->getAlignment(), CP->getOffset());
332193323Sed  } else {
333198090Srdivacky    Res = DAG.getTargetConstantPool(CP->getConstVal(), PtrVT,
334276479Sdim                                    CP->getAlignment(), CP->getOffset());
335193323Sed  }
336198090Srdivacky  return DAG.getNode(XCoreISD::CPRelativeWrapper, dl, MVT::i32, Res);
337193323Sed}
338193323Sed
339205218Srdivackyunsigned XCoreTargetLowering::getJumpTableEncoding() const {
340205218Srdivacky  return MachineJumpTableInfo::EK_Inline;
341205218Srdivacky}
342205218Srdivacky
343193323SedSDValue XCoreTargetLowering::
344207618SrdivackyLowerBR_JT(SDValue Op, SelectionDAG &DAG) const
345193323Sed{
346204642Srdivacky  SDValue Chain = Op.getOperand(0);
347204642Srdivacky  SDValue Table = Op.getOperand(1);
348204642Srdivacky  SDValue Index = Op.getOperand(2);
349261991Sdim  SDLoc dl(Op);
350204642Srdivacky  JumpTableSDNode *JT = cast<JumpTableSDNode>(Table);
351204642Srdivacky  unsigned JTI = JT->getIndex();
352204642Srdivacky  MachineFunction &MF = DAG.getMachineFunction();
353204642Srdivacky  const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo();
354204642Srdivacky  SDValue TargetJT = DAG.getTargetJumpTable(JT->getIndex(), MVT::i32);
355204642Srdivacky
356204642Srdivacky  unsigned NumEntries = MJTI->getJumpTables()[JTI].MBBs.size();
357204642Srdivacky  if (NumEntries <= 32) {
358204642Srdivacky    return DAG.getNode(XCoreISD::BR_JT, dl, MVT::Other, Chain, TargetJT, Index);
359204642Srdivacky  }
360204642Srdivacky  assert((NumEntries >> 31) == 0);
361204642Srdivacky  SDValue ScaledIndex = DAG.getNode(ISD::SHL, dl, MVT::i32, Index,
362288943Sdim                                    DAG.getConstant(1, dl, MVT::i32));
363204642Srdivacky  return DAG.getNode(XCoreISD::BR_JT32, dl, MVT::Other, Chain, TargetJT,
364204642Srdivacky                     ScaledIndex);
365193323Sed}
366193323Sed
367309124SdimSDValue XCoreTargetLowering::lowerLoadWordFromAlignedBasePlusOffset(
368309124Sdim    const SDLoc &DL, SDValue Chain, SDValue Base, int64_t Offset,
369309124Sdim    SelectionDAG &DAG) const {
370288943Sdim  auto PtrVT = getPointerTy(DAG.getDataLayout());
371251662Sdim  if ((Offset & 0x3) == 0) {
372309124Sdim    return DAG.getLoad(PtrVT, DL, Chain, Base, MachinePointerInfo());
373198090Srdivacky  }
374251662Sdim  // Lower to pair of consecutive word aligned loads plus some bit shifting.
375309124Sdim  int32_t HighOffset = alignTo(Offset, 4);
376251662Sdim  int32_t LowOffset = HighOffset - 4;
377251662Sdim  SDValue LowAddr, HighAddr;
378251662Sdim  if (GlobalAddressSDNode *GASD =
379251662Sdim        dyn_cast<GlobalAddressSDNode>(Base.getNode())) {
380251662Sdim    LowAddr = DAG.getGlobalAddress(GASD->getGlobal(), DL, Base.getValueType(),
381251662Sdim                                   LowOffset);
382251662Sdim    HighAddr = DAG.getGlobalAddress(GASD->getGlobal(), DL, Base.getValueType(),
383251662Sdim                                    HighOffset);
384251662Sdim  } else {
385251662Sdim    LowAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, Base,
386288943Sdim                          DAG.getConstant(LowOffset, DL, MVT::i32));
387251662Sdim    HighAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, Base,
388288943Sdim                           DAG.getConstant(HighOffset, DL, MVT::i32));
389198090Srdivacky  }
390288943Sdim  SDValue LowShift = DAG.getConstant((Offset - LowOffset) * 8, DL, MVT::i32);
391288943Sdim  SDValue HighShift = DAG.getConstant((HighOffset - Offset) * 8, DL, MVT::i32);
392251662Sdim
393309124Sdim  SDValue Low = DAG.getLoad(PtrVT, DL, Chain, LowAddr, MachinePointerInfo());
394309124Sdim  SDValue High = DAG.getLoad(PtrVT, DL, Chain, HighAddr, MachinePointerInfo());
395251662Sdim  SDValue LowShifted = DAG.getNode(ISD::SRL, DL, MVT::i32, Low, LowShift);
396251662Sdim  SDValue HighShifted = DAG.getNode(ISD::SHL, DL, MVT::i32, High, HighShift);
397251662Sdim  SDValue Result = DAG.getNode(ISD::OR, DL, MVT::i32, LowShifted, HighShifted);
398251662Sdim  Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Low.getValue(1),
399251662Sdim                      High.getValue(1));
400251662Sdim  SDValue Ops[] = { Result, Chain };
401276479Sdim  return DAG.getMergeValues(Ops, DL);
402198090Srdivacky}
403198090Srdivacky
404251662Sdimstatic bool isWordAligned(SDValue Value, SelectionDAG &DAG)
405251662Sdim{
406344779Sdim  KnownBits Known = DAG.computeKnownBits(Value);
407321369Sdim  return Known.countMinTrailingZeros() >= 2;
408251662Sdim}
409251662Sdim
410353358SdimSDValue XCoreTargetLowering::LowerLOAD(SDValue Op, SelectionDAG &DAG) const {
411251662Sdim  const TargetLowering &TLI = DAG.getTargetLoweringInfo();
412353358Sdim  LLVMContext &Context = *DAG.getContext();
413198090Srdivacky  LoadSDNode *LD = cast<LoadSDNode>(Op);
414198090Srdivacky  assert(LD->getExtensionType() == ISD::NON_EXTLOAD &&
415198090Srdivacky         "Unexpected extension type");
416198090Srdivacky  assert(LD->getMemoryVT() == MVT::i32 && "Unexpected load EVT");
417218893Sdim
418360784Sdim  if (allowsMemoryAccessForAlignment(Context, DAG.getDataLayout(),
419360784Sdim                                     LD->getMemoryVT(), *LD->getMemOperand()))
420198090Srdivacky    return SDValue();
421218893Sdim
422198090Srdivacky  SDValue Chain = LD->getChain();
423198090Srdivacky  SDValue BasePtr = LD->getBasePtr();
424261991Sdim  SDLoc DL(Op);
425219077Sdim
426251662Sdim  if (!LD->isVolatile()) {
427251662Sdim    const GlobalValue *GV;
428251662Sdim    int64_t Offset = 0;
429251662Sdim    if (DAG.isBaseWithConstantOffset(BasePtr) &&
430251662Sdim        isWordAligned(BasePtr->getOperand(0), DAG)) {
431251662Sdim      SDValue NewBasePtr = BasePtr->getOperand(0);
432251662Sdim      Offset = cast<ConstantSDNode>(BasePtr->getOperand(1))->getSExtValue();
433251662Sdim      return lowerLoadWordFromAlignedBasePlusOffset(DL, Chain, NewBasePtr,
434251662Sdim                                                    Offset, DAG);
435198090Srdivacky    }
436251662Sdim    if (TLI.isGAPlusOffset(BasePtr.getNode(), GV, Offset) &&
437251662Sdim        MinAlign(GV->getAlignment(), 4) == 4) {
438251662Sdim      SDValue NewBasePtr = DAG.getGlobalAddress(GV, DL,
439251662Sdim                                                BasePtr->getValueType(0));
440251662Sdim      return lowerLoadWordFromAlignedBasePlusOffset(DL, Chain, NewBasePtr,
441251662Sdim                                                    Offset, DAG);
442251662Sdim    }
443198090Srdivacky  }
444219077Sdim
445198090Srdivacky  if (LD->getAlignment() == 2) {
446309124Sdim    SDValue Low =
447309124Sdim        DAG.getExtLoad(ISD::ZEXTLOAD, DL, MVT::i32, Chain, BasePtr,
448309124Sdim                       LD->getPointerInfo(), MVT::i16,
449309124Sdim                       /* Alignment = */ 2, LD->getMemOperand()->getFlags());
450218893Sdim    SDValue HighAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, BasePtr,
451288943Sdim                                   DAG.getConstant(2, DL, MVT::i32));
452309124Sdim    SDValue High =
453309124Sdim        DAG.getExtLoad(ISD::EXTLOAD, DL, MVT::i32, Chain, HighAddr,
454309124Sdim                       LD->getPointerInfo().getWithOffset(2), MVT::i16,
455309124Sdim                       /* Alignment = */ 2, LD->getMemOperand()->getFlags());
456218893Sdim    SDValue HighShifted = DAG.getNode(ISD::SHL, DL, MVT::i32, High,
457288943Sdim                                      DAG.getConstant(16, DL, MVT::i32));
458218893Sdim    SDValue Result = DAG.getNode(ISD::OR, DL, MVT::i32, Low, HighShifted);
459218893Sdim    Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Low.getValue(1),
460198090Srdivacky                             High.getValue(1));
461198090Srdivacky    SDValue Ops[] = { Result, Chain };
462276479Sdim    return DAG.getMergeValues(Ops, DL);
463198090Srdivacky  }
464219077Sdim
465198090Srdivacky  // Lower to a call to __misaligned_load(BasePtr).
466353358Sdim  Type *IntPtrTy = DAG.getDataLayout().getIntPtrType(Context);
467198090Srdivacky  TargetLowering::ArgListTy Args;
468198090Srdivacky  TargetLowering::ArgListEntry Entry;
469219077Sdim
470198090Srdivacky  Entry.Ty = IntPtrTy;
471198090Srdivacky  Entry.Node = BasePtr;
472198090Srdivacky  Args.push_back(Entry);
473219077Sdim
474276479Sdim  TargetLowering::CallLoweringInfo CLI(DAG);
475321369Sdim  CLI.setDebugLoc(DL).setChain(Chain).setLibCallee(
476288943Sdim      CallingConv::C, IntPtrTy,
477288943Sdim      DAG.getExternalSymbol("__misaligned_load",
478288943Sdim                            getPointerTy(DAG.getDataLayout())),
479309124Sdim      std::move(Args));
480276479Sdim
481239462Sdim  std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI);
482276479Sdim  SDValue Ops[] = { CallResult.first, CallResult.second };
483276479Sdim  return DAG.getMergeValues(Ops, DL);
484198090Srdivacky}
485198090Srdivacky
486353358SdimSDValue XCoreTargetLowering::LowerSTORE(SDValue Op, SelectionDAG &DAG) const {
487353358Sdim  LLVMContext &Context = *DAG.getContext();
488198090Srdivacky  StoreSDNode *ST = cast<StoreSDNode>(Op);
489198090Srdivacky  assert(!ST->isTruncatingStore() && "Unexpected store type");
490198090Srdivacky  assert(ST->getMemoryVT() == MVT::i32 && "Unexpected store EVT");
491353358Sdim
492360784Sdim  if (allowsMemoryAccessForAlignment(Context, DAG.getDataLayout(),
493360784Sdim                                     ST->getMemoryVT(), *ST->getMemOperand()))
494198090Srdivacky    return SDValue();
495353358Sdim
496198090Srdivacky  SDValue Chain = ST->getChain();
497198090Srdivacky  SDValue BasePtr = ST->getBasePtr();
498198090Srdivacky  SDValue Value = ST->getValue();
499261991Sdim  SDLoc dl(Op);
500219077Sdim
501198090Srdivacky  if (ST->getAlignment() == 2) {
502198090Srdivacky    SDValue Low = Value;
503198090Srdivacky    SDValue High = DAG.getNode(ISD::SRL, dl, MVT::i32, Value,
504353358Sdim                               DAG.getConstant(16, dl, MVT::i32));
505309124Sdim    SDValue StoreLow = DAG.getTruncStore(
506309124Sdim        Chain, dl, Low, BasePtr, ST->getPointerInfo(), MVT::i16,
507309124Sdim        /* Alignment = */ 2, ST->getMemOperand()->getFlags());
508198090Srdivacky    SDValue HighAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, BasePtr,
509288943Sdim                                   DAG.getConstant(2, dl, MVT::i32));
510309124Sdim    SDValue StoreHigh = DAG.getTruncStore(
511309124Sdim        Chain, dl, High, HighAddr, ST->getPointerInfo().getWithOffset(2),
512309124Sdim        MVT::i16, /* Alignment = */ 2, ST->getMemOperand()->getFlags());
513198090Srdivacky    return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, StoreLow, StoreHigh);
514198090Srdivacky  }
515219077Sdim
516198090Srdivacky  // Lower to a call to __misaligned_store(BasePtr, Value).
517353358Sdim  Type *IntPtrTy = DAG.getDataLayout().getIntPtrType(Context);
518198090Srdivacky  TargetLowering::ArgListTy Args;
519198090Srdivacky  TargetLowering::ArgListEntry Entry;
520219077Sdim
521198090Srdivacky  Entry.Ty = IntPtrTy;
522198090Srdivacky  Entry.Node = BasePtr;
523198090Srdivacky  Args.push_back(Entry);
524219077Sdim
525198090Srdivacky  Entry.Node = Value;
526198090Srdivacky  Args.push_back(Entry);
527219077Sdim
528276479Sdim  TargetLowering::CallLoweringInfo CLI(DAG);
529288943Sdim  CLI.setDebugLoc(dl).setChain(Chain).setCallee(
530353358Sdim      CallingConv::C, Type::getVoidTy(Context),
531288943Sdim      DAG.getExternalSymbol("__misaligned_store",
532288943Sdim                            getPointerTy(DAG.getDataLayout())),
533309124Sdim      std::move(Args));
534276479Sdim
535239462Sdim  std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI);
536198090Srdivacky  return CallResult.second;
537198090Srdivacky}
538198090Srdivacky
539198090SrdivackySDValue XCoreTargetLowering::
540207618SrdivackyLowerSMUL_LOHI(SDValue Op, SelectionDAG &DAG) const
541204961Srdivacky{
542204961Srdivacky  assert(Op.getValueType() == MVT::i32 && Op.getOpcode() == ISD::SMUL_LOHI &&
543204961Srdivacky         "Unexpected operand to lower!");
544261991Sdim  SDLoc dl(Op);
545204961Srdivacky  SDValue LHS = Op.getOperand(0);
546204961Srdivacky  SDValue RHS = Op.getOperand(1);
547288943Sdim  SDValue Zero = DAG.getConstant(0, dl, MVT::i32);
548204961Srdivacky  SDValue Hi = DAG.getNode(XCoreISD::MACCS, dl,
549204961Srdivacky                           DAG.getVTList(MVT::i32, MVT::i32), Zero, Zero,
550204961Srdivacky                           LHS, RHS);
551204961Srdivacky  SDValue Lo(Hi.getNode(), 1);
552204961Srdivacky  SDValue Ops[] = { Lo, Hi };
553276479Sdim  return DAG.getMergeValues(Ops, dl);
554204961Srdivacky}
555204961Srdivacky
556204961SrdivackySDValue XCoreTargetLowering::
557207618SrdivackyLowerUMUL_LOHI(SDValue Op, SelectionDAG &DAG) const
558204961Srdivacky{
559204961Srdivacky  assert(Op.getValueType() == MVT::i32 && Op.getOpcode() == ISD::UMUL_LOHI &&
560204961Srdivacky         "Unexpected operand to lower!");
561261991Sdim  SDLoc dl(Op);
562204961Srdivacky  SDValue LHS = Op.getOperand(0);
563204961Srdivacky  SDValue RHS = Op.getOperand(1);
564288943Sdim  SDValue Zero = DAG.getConstant(0, dl, MVT::i32);
565204961Srdivacky  SDValue Hi = DAG.getNode(XCoreISD::LMUL, dl,
566204961Srdivacky                           DAG.getVTList(MVT::i32, MVT::i32), LHS, RHS,
567204961Srdivacky                           Zero, Zero);
568204961Srdivacky  SDValue Lo(Hi.getNode(), 1);
569204961Srdivacky  SDValue Ops[] = { Lo, Hi };
570276479Sdim  return DAG.getMergeValues(Ops, dl);
571204961Srdivacky}
572204961Srdivacky
573204961Srdivacky/// isADDADDMUL - Return whether Op is in a form that is equivalent to
574204961Srdivacky/// add(add(mul(x,y),a),b). If requireIntermediatesHaveOneUse is true then
575204961Srdivacky/// each intermediate result in the calculation must also have a single use.
576204961Srdivacky/// If the Op is in the correct form the constituent parts are written to Mul0,
577204961Srdivacky/// Mul1, Addend0 and Addend1.
578204961Srdivackystatic bool
579204961SrdivackyisADDADDMUL(SDValue Op, SDValue &Mul0, SDValue &Mul1, SDValue &Addend0,
580204961Srdivacky            SDValue &Addend1, bool requireIntermediatesHaveOneUse)
581204961Srdivacky{
582204961Srdivacky  if (Op.getOpcode() != ISD::ADD)
583204961Srdivacky    return false;
584204961Srdivacky  SDValue N0 = Op.getOperand(0);
585204961Srdivacky  SDValue N1 = Op.getOperand(1);
586204961Srdivacky  SDValue AddOp;
587204961Srdivacky  SDValue OtherOp;
588204961Srdivacky  if (N0.getOpcode() == ISD::ADD) {
589204961Srdivacky    AddOp = N0;
590204961Srdivacky    OtherOp = N1;
591204961Srdivacky  } else if (N1.getOpcode() == ISD::ADD) {
592204961Srdivacky    AddOp = N1;
593204961Srdivacky    OtherOp = N0;
594204961Srdivacky  } else {
595204961Srdivacky    return false;
596204961Srdivacky  }
597204961Srdivacky  if (requireIntermediatesHaveOneUse && !AddOp.hasOneUse())
598204961Srdivacky    return false;
599204961Srdivacky  if (OtherOp.getOpcode() == ISD::MUL) {
600204961Srdivacky    // add(add(a,b),mul(x,y))
601204961Srdivacky    if (requireIntermediatesHaveOneUse && !OtherOp.hasOneUse())
602204961Srdivacky      return false;
603204961Srdivacky    Mul0 = OtherOp.getOperand(0);
604204961Srdivacky    Mul1 = OtherOp.getOperand(1);
605204961Srdivacky    Addend0 = AddOp.getOperand(0);
606204961Srdivacky    Addend1 = AddOp.getOperand(1);
607204961Srdivacky    return true;
608204961Srdivacky  }
609204961Srdivacky  if (AddOp.getOperand(0).getOpcode() == ISD::MUL) {
610204961Srdivacky    // add(add(mul(x,y),a),b)
611204961Srdivacky    if (requireIntermediatesHaveOneUse && !AddOp.getOperand(0).hasOneUse())
612204961Srdivacky      return false;
613204961Srdivacky    Mul0 = AddOp.getOperand(0).getOperand(0);
614204961Srdivacky    Mul1 = AddOp.getOperand(0).getOperand(1);
615204961Srdivacky    Addend0 = AddOp.getOperand(1);
616204961Srdivacky    Addend1 = OtherOp;
617204961Srdivacky    return true;
618204961Srdivacky  }
619204961Srdivacky  if (AddOp.getOperand(1).getOpcode() == ISD::MUL) {
620204961Srdivacky    // add(add(a,mul(x,y)),b)
621204961Srdivacky    if (requireIntermediatesHaveOneUse && !AddOp.getOperand(1).hasOneUse())
622204961Srdivacky      return false;
623204961Srdivacky    Mul0 = AddOp.getOperand(1).getOperand(0);
624204961Srdivacky    Mul1 = AddOp.getOperand(1).getOperand(1);
625204961Srdivacky    Addend0 = AddOp.getOperand(0);
626204961Srdivacky    Addend1 = OtherOp;
627204961Srdivacky    return true;
628204961Srdivacky  }
629204961Srdivacky  return false;
630204961Srdivacky}
631204961Srdivacky
632204961SrdivackySDValue XCoreTargetLowering::
633207618SrdivackyTryExpandADDWithMul(SDNode *N, SelectionDAG &DAG) const
634204961Srdivacky{
635204961Srdivacky  SDValue Mul;
636204961Srdivacky  SDValue Other;
637204961Srdivacky  if (N->getOperand(0).getOpcode() == ISD::MUL) {
638204961Srdivacky    Mul = N->getOperand(0);
639204961Srdivacky    Other = N->getOperand(1);
640204961Srdivacky  } else if (N->getOperand(1).getOpcode() == ISD::MUL) {
641204961Srdivacky    Mul = N->getOperand(1);
642204961Srdivacky    Other = N->getOperand(0);
643204961Srdivacky  } else {
644204961Srdivacky    return SDValue();
645204961Srdivacky  }
646261991Sdim  SDLoc dl(N);
647204961Srdivacky  SDValue LL, RL, AddendL, AddendH;
648204961Srdivacky  LL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
649288943Sdim                   Mul.getOperand(0), DAG.getConstant(0, dl, MVT::i32));
650204961Srdivacky  RL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
651288943Sdim                   Mul.getOperand(1), DAG.getConstant(0, dl, MVT::i32));
652204961Srdivacky  AddendL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
653288943Sdim                        Other, DAG.getConstant(0, dl, MVT::i32));
654204961Srdivacky  AddendH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
655288943Sdim                        Other, DAG.getConstant(1, dl, MVT::i32));
656204961Srdivacky  APInt HighMask = APInt::getHighBitsSet(64, 32);
657204961Srdivacky  unsigned LHSSB = DAG.ComputeNumSignBits(Mul.getOperand(0));
658204961Srdivacky  unsigned RHSSB = DAG.ComputeNumSignBits(Mul.getOperand(1));
659204961Srdivacky  if (DAG.MaskedValueIsZero(Mul.getOperand(0), HighMask) &&
660204961Srdivacky      DAG.MaskedValueIsZero(Mul.getOperand(1), HighMask)) {
661204961Srdivacky    // The inputs are both zero-extended.
662204961Srdivacky    SDValue Hi = DAG.getNode(XCoreISD::MACCU, dl,
663204961Srdivacky                             DAG.getVTList(MVT::i32, MVT::i32), AddendH,
664204961Srdivacky                             AddendL, LL, RL);
665204961Srdivacky    SDValue Lo(Hi.getNode(), 1);
666204961Srdivacky    return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);
667204961Srdivacky  }
668204961Srdivacky  if (LHSSB > 32 && RHSSB > 32) {
669204961Srdivacky    // The inputs are both sign-extended.
670204961Srdivacky    SDValue Hi = DAG.getNode(XCoreISD::MACCS, dl,
671204961Srdivacky                             DAG.getVTList(MVT::i32, MVT::i32), AddendH,
672204961Srdivacky                             AddendL, LL, RL);
673204961Srdivacky    SDValue Lo(Hi.getNode(), 1);
674204961Srdivacky    return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);
675204961Srdivacky  }
676204961Srdivacky  SDValue LH, RH;
677204961Srdivacky  LH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
678288943Sdim                   Mul.getOperand(0), DAG.getConstant(1, dl, MVT::i32));
679204961Srdivacky  RH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
680288943Sdim                   Mul.getOperand(1), DAG.getConstant(1, dl, MVT::i32));
681204961Srdivacky  SDValue Hi = DAG.getNode(XCoreISD::MACCU, dl,
682204961Srdivacky                           DAG.getVTList(MVT::i32, MVT::i32), AddendH,
683204961Srdivacky                           AddendL, LL, RL);
684204961Srdivacky  SDValue Lo(Hi.getNode(), 1);
685204961Srdivacky  RH = DAG.getNode(ISD::MUL, dl, MVT::i32, LL, RH);
686204961Srdivacky  LH = DAG.getNode(ISD::MUL, dl, MVT::i32, LH, RL);
687204961Srdivacky  Hi = DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, RH);
688204961Srdivacky  Hi = DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, LH);
689204961Srdivacky  return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);
690204961Srdivacky}
691204961Srdivacky
692204961SrdivackySDValue XCoreTargetLowering::
693207618SrdivackyExpandADDSUB(SDNode *N, SelectionDAG &DAG) const
694193323Sed{
695193323Sed  assert(N->getValueType(0) == MVT::i64 &&
696193323Sed         (N->getOpcode() == ISD::ADD || N->getOpcode() == ISD::SUB) &&
697193323Sed        "Unknown operand to lower!");
698204961Srdivacky
699309124Sdim  if (N->getOpcode() == ISD::ADD)
700309124Sdim    if (SDValue Result = TryExpandADDWithMul(N, DAG))
701204961Srdivacky      return Result;
702204961Srdivacky
703261991Sdim  SDLoc dl(N);
704219077Sdim
705193323Sed  // Extract components
706193323Sed  SDValue LHSL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
707288943Sdim                             N->getOperand(0),
708288943Sdim                             DAG.getConstant(0, dl, MVT::i32));
709193323Sed  SDValue LHSH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
710288943Sdim                             N->getOperand(0),
711288943Sdim                             DAG.getConstant(1, dl, MVT::i32));
712193323Sed  SDValue RHSL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
713288943Sdim                             N->getOperand(1),
714288943Sdim                             DAG.getConstant(0, dl, MVT::i32));
715193323Sed  SDValue RHSH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
716288943Sdim                             N->getOperand(1),
717288943Sdim                             DAG.getConstant(1, dl, MVT::i32));
718219077Sdim
719193323Sed  // Expand
720193323Sed  unsigned Opcode = (N->getOpcode() == ISD::ADD) ? XCoreISD::LADD :
721193323Sed                                                   XCoreISD::LSUB;
722288943Sdim  SDValue Zero = DAG.getConstant(0, dl, MVT::i32);
723249423Sdim  SDValue Lo = DAG.getNode(Opcode, dl, DAG.getVTList(MVT::i32, MVT::i32),
724249423Sdim                           LHSL, RHSL, Zero);
725249423Sdim  SDValue Carry(Lo.getNode(), 1);
726219077Sdim
727249423Sdim  SDValue Hi = DAG.getNode(Opcode, dl, DAG.getVTList(MVT::i32, MVT::i32),
728249423Sdim                           LHSH, RHSH, Carry);
729249423Sdim  SDValue Ignored(Hi.getNode(), 1);
730193323Sed  // Merge the pieces
731193323Sed  return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);
732193323Sed}
733193323Sed
734193323SedSDValue XCoreTargetLowering::
735207618SrdivackyLowerVAARG(SDValue Op, SelectionDAG &DAG) const
736193323Sed{
737261991Sdim  // Whist llvm does not support aggregate varargs we can ignore
738261991Sdim  // the possibility of the ValueType being an implicit byVal vararg.
739193323Sed  SDNode *Node = Op.getNode();
740261991Sdim  EVT VT = Node->getValueType(0); // not an aggregate
741261991Sdim  SDValue InChain = Node->getOperand(0);
742261991Sdim  SDValue VAListPtr = Node->getOperand(1);
743261991Sdim  EVT PtrVT = VAListPtr.getValueType();
744261991Sdim  const Value *SV = cast<SrcValueSDNode>(Node->getOperand(2))->getValue();
745261991Sdim  SDLoc dl(Node);
746309124Sdim  SDValue VAList =
747309124Sdim      DAG.getLoad(PtrVT, dl, InChain, VAListPtr, MachinePointerInfo(SV));
748193323Sed  // Increment the pointer, VAList, to the next vararg
749261991Sdim  SDValue nextPtr = DAG.getNode(ISD::ADD, dl, PtrVT, VAList,
750288943Sdim                                DAG.getIntPtrConstant(VT.getSizeInBits() / 8,
751288943Sdim                                                      dl));
752193323Sed  // Store the incremented VAList to the legalized pointer
753261991Sdim  InChain = DAG.getStore(VAList.getValue(1), dl, nextPtr, VAListPtr,
754309124Sdim                         MachinePointerInfo(SV));
755193323Sed  // Load the actual argument out of the pointer VAList
756309124Sdim  return DAG.getLoad(VT, dl, InChain, VAList, MachinePointerInfo());
757193323Sed}
758193323Sed
759193323SedSDValue XCoreTargetLowering::
760207618SrdivackyLowerVASTART(SDValue Op, SelectionDAG &DAG) const
761193323Sed{
762261991Sdim  SDLoc dl(Op);
763193323Sed  // vastart stores the address of the VarArgsFrameIndex slot into the
764193323Sed  // memory location argument
765193323Sed  MachineFunction &MF = DAG.getMachineFunction();
766193323Sed  XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
767193323Sed  SDValue Addr = DAG.getFrameIndex(XFI->getVarArgsFrameIndex(), MVT::i32);
768219077Sdim  return DAG.getStore(Op.getOperand(0), dl, Addr, Op.getOperand(1),
769309124Sdim                      MachinePointerInfo());
770193323Sed}
771193323Sed
772207618SrdivackySDValue XCoreTargetLowering::LowerFRAMEADDR(SDValue Op,
773207618Srdivacky                                            SelectionDAG &DAG) const {
774276479Sdim  // This nodes represent llvm.frameaddress on the DAG.
775276479Sdim  // It takes one operand, the index of the frame address to return.
776276479Sdim  // An index of zero corresponds to the current function's frame address.
777276479Sdim  // An index of one to the parent's frame address, and so on.
778219077Sdim  // Depths > 0 not supported yet!
779193323Sed  if (cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() > 0)
780193323Sed    return SDValue();
781219077Sdim
782193323Sed  MachineFunction &MF = DAG.getMachineFunction();
783288943Sdim  const TargetRegisterInfo *RegInfo = Subtarget.getRegisterInfo();
784276479Sdim  return DAG.getCopyFromReg(DAG.getEntryNode(), SDLoc(Op),
785193323Sed                            RegInfo->getFrameRegister(MF), MVT::i32);
786193323Sed}
787193323Sed
788218893SdimSDValue XCoreTargetLowering::
789276479SdimLowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const {
790276479Sdim  // This nodes represent llvm.returnaddress on the DAG.
791276479Sdim  // It takes one operand, the index of the return address to return.
792276479Sdim  // An index of zero corresponds to the current function's return address.
793276479Sdim  // An index of one to the parent's return address, and so on.
794276479Sdim  // Depths > 0 not supported yet!
795276479Sdim  if (cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() > 0)
796276479Sdim    return SDValue();
797276479Sdim
798276479Sdim  MachineFunction &MF = DAG.getMachineFunction();
799276479Sdim  XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
800276479Sdim  int FI = XFI->createLRSpillSlot(MF);
801276479Sdim  SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
802309124Sdim  return DAG.getLoad(getPointerTy(DAG.getDataLayout()), SDLoc(Op),
803309124Sdim                     DAG.getEntryNode(), FIN,
804309124Sdim                     MachinePointerInfo::getFixedStack(MF, FI));
805276479Sdim}
806276479Sdim
807276479SdimSDValue XCoreTargetLowering::
808276479SdimLowerFRAME_TO_ARGS_OFFSET(SDValue Op, SelectionDAG &DAG) const {
809276479Sdim  // This node represents offset from frame pointer to first on-stack argument.
810276479Sdim  // This is needed for correct stack adjustment during unwind.
811276479Sdim  // However, we don't know the offset until after the frame has be finalised.
812276479Sdim  // This is done during the XCoreFTAOElim pass.
813276479Sdim  return DAG.getNode(XCoreISD::FRAME_TO_ARGS_OFFSET, SDLoc(Op), MVT::i32);
814276479Sdim}
815276479Sdim
816276479SdimSDValue XCoreTargetLowering::
817276479SdimLowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const {
818276479Sdim  // OUTCHAIN = EH_RETURN(INCHAIN, OFFSET, HANDLER)
819276479Sdim  // This node represents 'eh_return' gcc dwarf builtin, which is used to
820276479Sdim  // return from exception. The general meaning is: adjust stack by OFFSET and
821276479Sdim  // pass execution to HANDLER.
822276479Sdim  MachineFunction &MF = DAG.getMachineFunction();
823276479Sdim  SDValue Chain     = Op.getOperand(0);
824276479Sdim  SDValue Offset    = Op.getOperand(1);
825276479Sdim  SDValue Handler   = Op.getOperand(2);
826276479Sdim  SDLoc dl(Op);
827276479Sdim
828276479Sdim  // Absolute SP = (FP + FrameToArgs) + Offset
829288943Sdim  const TargetRegisterInfo *RegInfo = Subtarget.getRegisterInfo();
830276479Sdim  SDValue Stack = DAG.getCopyFromReg(DAG.getEntryNode(), dl,
831276479Sdim                            RegInfo->getFrameRegister(MF), MVT::i32);
832276479Sdim  SDValue FrameToArgs = DAG.getNode(XCoreISD::FRAME_TO_ARGS_OFFSET, dl,
833276479Sdim                                    MVT::i32);
834276479Sdim  Stack = DAG.getNode(ISD::ADD, dl, MVT::i32, Stack, FrameToArgs);
835276479Sdim  Stack = DAG.getNode(ISD::ADD, dl, MVT::i32, Stack, Offset);
836276479Sdim
837276479Sdim  // R0=ExceptionPointerRegister R1=ExceptionSelectorRegister
838276479Sdim  // which leaves 2 caller saved registers, R2 & R3 for us to use.
839276479Sdim  unsigned StackReg = XCore::R2;
840276479Sdim  unsigned HandlerReg = XCore::R3;
841276479Sdim
842276479Sdim  SDValue OutChains[] = {
843276479Sdim    DAG.getCopyToReg(Chain, dl, StackReg, Stack),
844276479Sdim    DAG.getCopyToReg(Chain, dl, HandlerReg, Handler)
845276479Sdim  };
846276479Sdim
847276479Sdim  Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);
848276479Sdim
849276479Sdim  return DAG.getNode(XCoreISD::EH_RETURN, dl, MVT::Other, Chain,
850276479Sdim                     DAG.getRegister(StackReg, MVT::i32),
851276479Sdim                     DAG.getRegister(HandlerReg, MVT::i32));
852276479Sdim
853276479Sdim}
854276479Sdim
855276479SdimSDValue XCoreTargetLowering::
856226633SdimLowerADJUST_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const {
857226633Sdim  return Op.getOperand(0);
858226633Sdim}
859226633Sdim
860226633SdimSDValue XCoreTargetLowering::
861226633SdimLowerINIT_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const {
862218893Sdim  SDValue Chain = Op.getOperand(0);
863218893Sdim  SDValue Trmp = Op.getOperand(1); // trampoline
864218893Sdim  SDValue FPtr = Op.getOperand(2); // nested function
865218893Sdim  SDValue Nest = Op.getOperand(3); // 'nest' parameter value
866218893Sdim
867218893Sdim  const Value *TrmpAddr = cast<SrcValueSDNode>(Op.getOperand(4))->getValue();
868218893Sdim
869218893Sdim  // .align 4
870218893Sdim  // LDAPF_u10 r11, nest
871218893Sdim  // LDW_2rus r11, r11[0]
872218893Sdim  // STWSP_ru6 r11, sp[0]
873218893Sdim  // LDAPF_u10 r11, fptr
874218893Sdim  // LDW_2rus r11, r11[0]
875218893Sdim  // BAU_1r r11
876218893Sdim  // nest:
877218893Sdim  // .word nest
878218893Sdim  // fptr:
879218893Sdim  // .word fptr
880218893Sdim  SDValue OutChains[5];
881218893Sdim
882218893Sdim  SDValue Addr = Trmp;
883218893Sdim
884261991Sdim  SDLoc dl(Op);
885309124Sdim  OutChains[0] =
886309124Sdim      DAG.getStore(Chain, dl, DAG.getConstant(0x0a3cd805, dl, MVT::i32), Addr,
887309124Sdim                   MachinePointerInfo(TrmpAddr));
888218893Sdim
889218893Sdim  Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp,
890288943Sdim                     DAG.getConstant(4, dl, MVT::i32));
891309124Sdim  OutChains[1] =
892309124Sdim      DAG.getStore(Chain, dl, DAG.getConstant(0xd80456c0, dl, MVT::i32), Addr,
893309124Sdim                   MachinePointerInfo(TrmpAddr, 4));
894218893Sdim
895218893Sdim  Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp,
896288943Sdim                     DAG.getConstant(8, dl, MVT::i32));
897309124Sdim  OutChains[2] =
898309124Sdim      DAG.getStore(Chain, dl, DAG.getConstant(0x27fb0a3c, dl, MVT::i32), Addr,
899309124Sdim                   MachinePointerInfo(TrmpAddr, 8));
900218893Sdim
901218893Sdim  Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp,
902288943Sdim                     DAG.getConstant(12, dl, MVT::i32));
903309124Sdim  OutChains[3] =
904309124Sdim      DAG.getStore(Chain, dl, Nest, Addr, MachinePointerInfo(TrmpAddr, 12));
905218893Sdim
906218893Sdim  Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp,
907288943Sdim                     DAG.getConstant(16, dl, MVT::i32));
908309124Sdim  OutChains[4] =
909309124Sdim      DAG.getStore(Chain, dl, FPtr, Addr, MachinePointerInfo(TrmpAddr, 16));
910218893Sdim
911276479Sdim  return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);
912218893Sdim}
913218893Sdim
914249423SdimSDValue XCoreTargetLowering::
915249423SdimLowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const {
916261991Sdim  SDLoc DL(Op);
917249423Sdim  unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
918249423Sdim  switch (IntNo) {
919249423Sdim    case Intrinsic::xcore_crc8:
920249423Sdim      EVT VT = Op.getValueType();
921249423Sdim      SDValue Data =
922249423Sdim        DAG.getNode(XCoreISD::CRC8, DL, DAG.getVTList(VT, VT),
923249423Sdim                    Op.getOperand(1), Op.getOperand(2) , Op.getOperand(3));
924249423Sdim      SDValue Crc(Data.getNode(), 1);
925249423Sdim      SDValue Results[] = { Crc, Data };
926276479Sdim      return DAG.getMergeValues(Results, DL);
927249423Sdim  }
928249423Sdim  return SDValue();
929249423Sdim}
930249423Sdim
931261991SdimSDValue XCoreTargetLowering::
932261991SdimLowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG) const {
933261991Sdim  SDLoc DL(Op);
934261991Sdim  return DAG.getNode(XCoreISD::MEMBARRIER, DL, MVT::Other, Op.getOperand(0));
935261991Sdim}
936261991Sdim
937276479SdimSDValue XCoreTargetLowering::
938276479SdimLowerATOMIC_LOAD(SDValue Op, SelectionDAG &DAG) const {
939276479Sdim  AtomicSDNode *N = cast<AtomicSDNode>(Op);
940276479Sdim  assert(N->getOpcode() == ISD::ATOMIC_LOAD && "Bad Atomic OP");
941309124Sdim  assert((N->getOrdering() == AtomicOrdering::Unordered ||
942309124Sdim          N->getOrdering() == AtomicOrdering::Monotonic) &&
943309124Sdim         "setInsertFencesForAtomic(true) expects unordered / monotonic");
944276479Sdim  if (N->getMemoryVT() == MVT::i32) {
945276479Sdim    if (N->getAlignment() < 4)
946276479Sdim      report_fatal_error("atomic load must be aligned");
947288943Sdim    return DAG.getLoad(getPointerTy(DAG.getDataLayout()), SDLoc(Op),
948288943Sdim                       N->getChain(), N->getBasePtr(), N->getPointerInfo(),
949309124Sdim                       N->getAlignment(), N->getMemOperand()->getFlags(),
950309124Sdim                       N->getAAInfo(), N->getRanges());
951276479Sdim  }
952276479Sdim  if (N->getMemoryVT() == MVT::i16) {
953276479Sdim    if (N->getAlignment() < 2)
954276479Sdim      report_fatal_error("atomic load must be aligned");
955276479Sdim    return DAG.getExtLoad(ISD::EXTLOAD, SDLoc(Op), MVT::i32, N->getChain(),
956276479Sdim                          N->getBasePtr(), N->getPointerInfo(), MVT::i16,
957309124Sdim                          N->getAlignment(), N->getMemOperand()->getFlags(),
958309124Sdim                          N->getAAInfo());
959276479Sdim  }
960276479Sdim  if (N->getMemoryVT() == MVT::i8)
961276479Sdim    return DAG.getExtLoad(ISD::EXTLOAD, SDLoc(Op), MVT::i32, N->getChain(),
962276479Sdim                          N->getBasePtr(), N->getPointerInfo(), MVT::i8,
963309124Sdim                          N->getAlignment(), N->getMemOperand()->getFlags(),
964309124Sdim                          N->getAAInfo());
965276479Sdim  return SDValue();
966276479Sdim}
967276479Sdim
968276479SdimSDValue XCoreTargetLowering::
969276479SdimLowerATOMIC_STORE(SDValue Op, SelectionDAG &DAG) const {
970276479Sdim  AtomicSDNode *N = cast<AtomicSDNode>(Op);
971276479Sdim  assert(N->getOpcode() == ISD::ATOMIC_STORE && "Bad Atomic OP");
972309124Sdim  assert((N->getOrdering() == AtomicOrdering::Unordered ||
973309124Sdim          N->getOrdering() == AtomicOrdering::Monotonic) &&
974309124Sdim         "setInsertFencesForAtomic(true) expects unordered / monotonic");
975276479Sdim  if (N->getMemoryVT() == MVT::i32) {
976276479Sdim    if (N->getAlignment() < 4)
977276479Sdim      report_fatal_error("atomic store must be aligned");
978309124Sdim    return DAG.getStore(N->getChain(), SDLoc(Op), N->getVal(), N->getBasePtr(),
979309124Sdim                        N->getPointerInfo(), N->getAlignment(),
980309124Sdim                        N->getMemOperand()->getFlags(), N->getAAInfo());
981276479Sdim  }
982276479Sdim  if (N->getMemoryVT() == MVT::i16) {
983276479Sdim    if (N->getAlignment() < 2)
984276479Sdim      report_fatal_error("atomic store must be aligned");
985276479Sdim    return DAG.getTruncStore(N->getChain(), SDLoc(Op), N->getVal(),
986276479Sdim                             N->getBasePtr(), N->getPointerInfo(), MVT::i16,
987309124Sdim                             N->getAlignment(), N->getMemOperand()->getFlags(),
988309124Sdim                             N->getAAInfo());
989276479Sdim  }
990276479Sdim  if (N->getMemoryVT() == MVT::i8)
991276479Sdim    return DAG.getTruncStore(N->getChain(), SDLoc(Op), N->getVal(),
992276479Sdim                             N->getBasePtr(), N->getPointerInfo(), MVT::i8,
993309124Sdim                             N->getAlignment(), N->getMemOperand()->getFlags(),
994309124Sdim                             N->getAAInfo());
995276479Sdim  return SDValue();
996276479Sdim}
997276479Sdim
998353358SdimMachineMemOperand::Flags
999353358SdimXCoreTargetLowering::getMMOFlags(const Instruction &I) const {
1000353358Sdim  // Because of how we convert atomic_load and atomic_store to normal loads and
1001353358Sdim  // stores in the DAG, we need to ensure that the MMOs are marked volatile
1002353358Sdim  // since DAGCombine hasn't been updated to account for atomic, but non
1003353358Sdim  // volatile loads.  (See D57601)
1004353358Sdim  if (auto *SI = dyn_cast<StoreInst>(&I))
1005353358Sdim    if (SI->isAtomic())
1006353358Sdim      return MachineMemOperand::MOVolatile;
1007353358Sdim  if (auto *LI = dyn_cast<LoadInst>(&I))
1008353358Sdim    if (LI->isAtomic())
1009353358Sdim      return MachineMemOperand::MOVolatile;
1010353358Sdim  if (auto *AI = dyn_cast<AtomicRMWInst>(&I))
1011353358Sdim    if (AI->isAtomic())
1012353358Sdim      return MachineMemOperand::MOVolatile;
1013353358Sdim  if (auto *AI = dyn_cast<AtomicCmpXchgInst>(&I))
1014353358Sdim    if (AI->isAtomic())
1015353358Sdim      return MachineMemOperand::MOVolatile;
1016353358Sdim  return MachineMemOperand::MONone;
1017353358Sdim}
1018353358Sdim
1019193323Sed//===----------------------------------------------------------------------===//
1020193323Sed//                      Calling Convention Implementation
1021193323Sed//===----------------------------------------------------------------------===//
1022193323Sed
1023193323Sed#include "XCoreGenCallingConv.inc"
1024193323Sed
1025193323Sed//===----------------------------------------------------------------------===//
1026198090Srdivacky//                  Call Calling Convention Implementation
1027193323Sed//===----------------------------------------------------------------------===//
1028193323Sed
1029198090Srdivacky/// XCore call implementation
1030198090SrdivackySDValue
1031239462SdimXCoreTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
1032207618Srdivacky                               SmallVectorImpl<SDValue> &InVals) const {
1033239462Sdim  SelectionDAG &DAG                     = CLI.DAG;
1034261991Sdim  SDLoc &dl                             = CLI.DL;
1035261991Sdim  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
1036261991Sdim  SmallVectorImpl<SDValue> &OutVals     = CLI.OutVals;
1037261991Sdim  SmallVectorImpl<ISD::InputArg> &Ins   = CLI.Ins;
1038239462Sdim  SDValue Chain                         = CLI.Chain;
1039239462Sdim  SDValue Callee                        = CLI.Callee;
1040239462Sdim  bool &isTailCall                      = CLI.IsTailCall;
1041239462Sdim  CallingConv::ID CallConv              = CLI.CallConv;
1042239462Sdim  bool isVarArg                         = CLI.IsVarArg;
1043239462Sdim
1044203954Srdivacky  // XCore target does not yet support tail call optimization.
1045203954Srdivacky  isTailCall = false;
1046198090Srdivacky
1047193323Sed  // For now, only CallingConv::C implemented
1048198090Srdivacky  switch (CallConv)
1049193323Sed  {
1050193323Sed    default:
1051327952Sdim      report_fatal_error("Unsupported calling convention");
1052193323Sed    case CallingConv::Fast:
1053193323Sed    case CallingConv::C:
1054198090Srdivacky      return LowerCCCCallTo(Chain, Callee, CallConv, isVarArg, isTailCall,
1055210299Sed                            Outs, OutVals, Ins, dl, DAG, InVals);
1056193323Sed  }
1057193323Sed}
1058193323Sed
1059276479Sdim/// LowerCallResult - Lower the result values of a call into the
1060276479Sdim/// appropriate copies out of appropriate physical registers / memory locations.
1061309124Sdimstatic SDValue LowerCallResult(SDValue Chain, SDValue InFlag,
1062309124Sdim                               const SmallVectorImpl<CCValAssign> &RVLocs,
1063309124Sdim                               const SDLoc &dl, SelectionDAG &DAG,
1064309124Sdim                               SmallVectorImpl<SDValue> &InVals) {
1065276479Sdim  SmallVector<std::pair<int, unsigned>, 4> ResultMemLocs;
1066276479Sdim  // Copy results out of physical registers.
1067276479Sdim  for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
1068276479Sdim    const CCValAssign &VA = RVLocs[i];
1069276479Sdim    if (VA.isRegLoc()) {
1070276479Sdim      Chain = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getValVT(),
1071276479Sdim                                 InFlag).getValue(1);
1072276479Sdim      InFlag = Chain.getValue(2);
1073276479Sdim      InVals.push_back(Chain.getValue(0));
1074276479Sdim    } else {
1075276479Sdim      assert(VA.isMemLoc());
1076276479Sdim      ResultMemLocs.push_back(std::make_pair(VA.getLocMemOffset(),
1077276479Sdim                                             InVals.size()));
1078276479Sdim      // Reserve space for this result.
1079276479Sdim      InVals.push_back(SDValue());
1080276479Sdim    }
1081276479Sdim  }
1082276479Sdim
1083276479Sdim  // Copy results out of memory.
1084276479Sdim  SmallVector<SDValue, 4> MemOpChains;
1085276479Sdim  for (unsigned i = 0, e = ResultMemLocs.size(); i != e; ++i) {
1086276479Sdim    int offset = ResultMemLocs[i].first;
1087276479Sdim    unsigned index = ResultMemLocs[i].second;
1088276479Sdim    SDVTList VTs = DAG.getVTList(MVT::i32, MVT::Other);
1089288943Sdim    SDValue Ops[] = { Chain, DAG.getConstant(offset / 4, dl, MVT::i32) };
1090276479Sdim    SDValue load = DAG.getNode(XCoreISD::LDWSP, dl, VTs, Ops);
1091276479Sdim    InVals[index] = load;
1092276479Sdim    MemOpChains.push_back(load.getValue(1));
1093276479Sdim  }
1094276479Sdim
1095276479Sdim  // Transform all loads nodes into one single node because
1096276479Sdim  // all load nodes are independent of each other.
1097276479Sdim  if (!MemOpChains.empty())
1098276479Sdim    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
1099276479Sdim
1100276479Sdim  return Chain;
1101276479Sdim}
1102276479Sdim
1103193323Sed/// LowerCCCCallTo - functions arguments are copied from virtual
1104193323Sed/// regs to (physical regs)/(stack frame), CALLSEQ_START and
1105193323Sed/// CALLSEQ_END are emitted.
1106193323Sed/// TODO: isTailCall, sret.
1107309124SdimSDValue XCoreTargetLowering::LowerCCCCallTo(
1108309124Sdim    SDValue Chain, SDValue Callee, CallingConv::ID CallConv, bool isVarArg,
1109309124Sdim    bool isTailCall, const SmallVectorImpl<ISD::OutputArg> &Outs,
1110309124Sdim    const SmallVectorImpl<SDValue> &OutVals,
1111309124Sdim    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
1112309124Sdim    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
1113193323Sed
1114193323Sed  // Analyze operands of the call, assigning locations to each operand.
1115193323Sed  SmallVector<CCValAssign, 16> ArgLocs;
1116280031Sdim  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
1117280031Sdim                 *DAG.getContext());
1118193323Sed
1119193323Sed  // The ABI dictates there should be one stack slot available to the callee
1120193323Sed  // on function entry (for saving lr).
1121193323Sed  CCInfo.AllocateStack(4, 4);
1122193323Sed
1123198090Srdivacky  CCInfo.AnalyzeCallOperands(Outs, CC_XCore);
1124193323Sed
1125276479Sdim  SmallVector<CCValAssign, 16> RVLocs;
1126276479Sdim  // Analyze return values to determine the number of bytes of stack required.
1127280031Sdim  CCState RetCCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
1128280031Sdim                    *DAG.getContext());
1129276479Sdim  RetCCInfo.AllocateStack(CCInfo.getNextStackOffset(), 4);
1130276479Sdim  RetCCInfo.AnalyzeCallResult(Ins, RetCC_XCore);
1131276479Sdim
1132193323Sed  // Get a count of how many bytes are to be pushed on the stack.
1133276479Sdim  unsigned NumBytes = RetCCInfo.getNextStackOffset();
1134288943Sdim  auto PtrVT = getPointerTy(DAG.getDataLayout());
1135193323Sed
1136321369Sdim  Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, dl);
1137193323Sed
1138193323Sed  SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass;
1139193323Sed  SmallVector<SDValue, 12> MemOpChains;
1140193323Sed
1141193323Sed  // Walk the register/memloc assignments, inserting copies/loads.
1142193323Sed  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
1143193323Sed    CCValAssign &VA = ArgLocs[i];
1144210299Sed    SDValue Arg = OutVals[i];
1145193323Sed
1146193323Sed    // Promote the value if needed.
1147193323Sed    switch (VA.getLocInfo()) {
1148198090Srdivacky      default: llvm_unreachable("Unknown loc info!");
1149193323Sed      case CCValAssign::Full: break;
1150193323Sed      case CCValAssign::SExt:
1151193323Sed        Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);
1152193323Sed        break;
1153193323Sed      case CCValAssign::ZExt:
1154193323Sed        Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);
1155193323Sed        break;
1156193323Sed      case CCValAssign::AExt:
1157193323Sed        Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);
1158193323Sed        break;
1159193323Sed    }
1160219077Sdim
1161219077Sdim    // Arguments that can be passed on register must be kept at
1162193323Sed    // RegsToPass vector
1163193323Sed    if (VA.isRegLoc()) {
1164193323Sed      RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
1165193323Sed    } else {
1166193323Sed      assert(VA.isMemLoc());
1167193323Sed
1168193323Sed      int Offset = VA.getLocMemOffset();
1169193323Sed
1170219077Sdim      MemOpChains.push_back(DAG.getNode(XCoreISD::STWSP, dl, MVT::Other,
1171193323Sed                                        Chain, Arg,
1172288943Sdim                                        DAG.getConstant(Offset/4, dl,
1173288943Sdim                                                        MVT::i32)));
1174193323Sed    }
1175193323Sed  }
1176193323Sed
1177193323Sed  // Transform all store nodes into one single node because
1178193323Sed  // all store nodes are independent of each other.
1179193323Sed  if (!MemOpChains.empty())
1180276479Sdim    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
1181193323Sed
1182219077Sdim  // Build a sequence of copy-to-reg nodes chained together with token
1183193323Sed  // chain and flag operands which copy the outgoing args into registers.
1184221345Sdim  // The InFlag in necessary since all emitted instructions must be
1185193323Sed  // stuck together.
1186193323Sed  SDValue InFlag;
1187193323Sed  for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1188219077Sdim    Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
1189193323Sed                             RegsToPass[i].second, InFlag);
1190193323Sed    InFlag = Chain.getValue(1);
1191193323Sed  }
1192193323Sed
1193193323Sed  // If the callee is a GlobalAddress node (quite common, every direct call is)
1194193323Sed  // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
1195193323Sed  // Likewise ExternalSymbol -> TargetExternalSymbol.
1196193323Sed  if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
1197210299Sed    Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32);
1198193323Sed  else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
1199193323Sed    Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32);
1200193323Sed
1201193323Sed  // XCoreBranchLink = #chain, #target_address, #opt_in_flags...
1202219077Sdim  //             = Chain, Callee, Reg#1, Reg#2, ...
1203193323Sed  //
1204193323Sed  // Returns a chain & a flag for retval copy to use.
1205218893Sdim  SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
1206193323Sed  SmallVector<SDValue, 8> Ops;
1207193323Sed  Ops.push_back(Chain);
1208193323Sed  Ops.push_back(Callee);
1209193323Sed
1210219077Sdim  // Add argument registers to the end of the list so that they are
1211193323Sed  // known live into the call.
1212193323Sed  for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
1213193323Sed    Ops.push_back(DAG.getRegister(RegsToPass[i].first,
1214193323Sed                                  RegsToPass[i].second.getValueType()));
1215193323Sed
1216193323Sed  if (InFlag.getNode())
1217193323Sed    Ops.push_back(InFlag);
1218193323Sed
1219276479Sdim  Chain  = DAG.getNode(XCoreISD::BL, dl, NodeTys, Ops);
1220193323Sed  InFlag = Chain.getValue(1);
1221193323Sed
1222193323Sed  // Create the CALLSEQ_END node.
1223288943Sdim  Chain = DAG.getCALLSEQ_END(Chain, DAG.getConstant(NumBytes, dl, PtrVT, true),
1224288943Sdim                             DAG.getConstant(0, dl, PtrVT, true), InFlag, dl);
1225193323Sed  InFlag = Chain.getValue(1);
1226193323Sed
1227193323Sed  // Handle result values, copying them out of physregs into vregs that we
1228193323Sed  // return.
1229276479Sdim  return LowerCallResult(Chain, InFlag, RVLocs, dl, DAG, InVals);
1230193323Sed}
1231193323Sed
1232193323Sed//===----------------------------------------------------------------------===//
1233198090Srdivacky//             Formal Arguments Calling Convention Implementation
1234193323Sed//===----------------------------------------------------------------------===//
1235193323Sed
1236261991Sdimnamespace {
1237261991Sdim  struct ArgDataPair { SDValue SDV; ISD::ArgFlagsTy Flags; };
1238261991Sdim}
1239261991Sdim
1240198090Srdivacky/// XCore formal arguments implementation
1241309124SdimSDValue XCoreTargetLowering::LowerFormalArguments(
1242309124Sdim    SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
1243309124Sdim    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
1244309124Sdim    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
1245198090Srdivacky  switch (CallConv)
1246193323Sed  {
1247193323Sed    default:
1248327952Sdim      report_fatal_error("Unsupported calling convention");
1249193323Sed    case CallingConv::C:
1250193323Sed    case CallingConv::Fast:
1251198090Srdivacky      return LowerCCCArguments(Chain, CallConv, isVarArg,
1252198090Srdivacky                               Ins, dl, DAG, InVals);
1253193323Sed  }
1254193323Sed}
1255193323Sed
1256193323Sed/// LowerCCCArguments - transform physical registers into
1257193323Sed/// virtual registers and generate load operations for
1258193323Sed/// arguments places on the stack.
1259193323Sed/// TODO: sret
1260309124SdimSDValue XCoreTargetLowering::LowerCCCArguments(
1261309124Sdim    SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
1262309124Sdim    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
1263309124Sdim    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
1264193323Sed  MachineFunction &MF = DAG.getMachineFunction();
1265314564Sdim  MachineFrameInfo &MFI = MF.getFrameInfo();
1266193323Sed  MachineRegisterInfo &RegInfo = MF.getRegInfo();
1267276479Sdim  XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
1268193323Sed
1269193323Sed  // Assign locations to all of the incoming arguments.
1270193323Sed  SmallVector<CCValAssign, 16> ArgLocs;
1271280031Sdim  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
1272280031Sdim                 *DAG.getContext());
1273193323Sed
1274198090Srdivacky  CCInfo.AnalyzeFormalArguments(Ins, CC_XCore);
1275193323Sed
1276218893Sdim  unsigned StackSlotSize = XCoreFrameLowering::stackSlotSize();
1277193323Sed
1278193323Sed  unsigned LRSaveSize = StackSlotSize;
1279219077Sdim
1280276479Sdim  if (!isVarArg)
1281276479Sdim    XFI->setReturnStackOffset(CCInfo.getNextStackOffset() + LRSaveSize);
1282276479Sdim
1283261991Sdim  // All getCopyFromReg ops must precede any getMemcpys to prevent the
1284261991Sdim  // scheduler clobbering a register before it has been copied.
1285261991Sdim  // The stages are:
1286261991Sdim  // 1. CopyFromReg (and load) arg & vararg registers.
1287261991Sdim  // 2. Chain CopyFromReg nodes into a TokenFactor.
1288261991Sdim  // 3. Memcpy 'byVal' args & push final InVals.
1289261991Sdim  // 4. Chain mem ops nodes into a TokenFactor.
1290261991Sdim  SmallVector<SDValue, 4> CFRegNode;
1291261991Sdim  SmallVector<ArgDataPair, 4> ArgData;
1292261991Sdim  SmallVector<SDValue, 4> MemOps;
1293261991Sdim
1294261991Sdim  // 1a. CopyFromReg (and load) arg registers.
1295193323Sed  for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
1296193323Sed
1297193323Sed    CCValAssign &VA = ArgLocs[i];
1298261991Sdim    SDValue ArgIn;
1299219077Sdim
1300193323Sed    if (VA.isRegLoc()) {
1301193323Sed      // Arguments passed in registers
1302198090Srdivacky      EVT RegVT = VA.getLocVT();
1303198090Srdivacky      switch (RegVT.getSimpleVT().SimpleTy) {
1304193323Sed      default:
1305198090Srdivacky        {
1306198090Srdivacky#ifndef NDEBUG
1307198090Srdivacky          errs() << "LowerFormalArguments Unhandled argument type: "
1308309124Sdim                 << RegVT.getEVTString() << "\n";
1309198090Srdivacky#endif
1310276479Sdim          llvm_unreachable(nullptr);
1311198090Srdivacky        }
1312193323Sed      case MVT::i32:
1313360784Sdim        Register VReg = RegInfo.createVirtualRegister(&XCore::GRRegsRegClass);
1314193323Sed        RegInfo.addLiveIn(VA.getLocReg(), VReg);
1315261991Sdim        ArgIn = DAG.getCopyFromReg(Chain, dl, VReg, RegVT);
1316261991Sdim        CFRegNode.push_back(ArgIn.getValue(ArgIn->getNumValues() - 1));
1317193323Sed      }
1318193323Sed    } else {
1319193323Sed      // sanity check
1320193323Sed      assert(VA.isMemLoc());
1321193323Sed      // Load the argument to a virtual register
1322193323Sed      unsigned ObjSize = VA.getLocVT().getSizeInBits()/8;
1323193323Sed      if (ObjSize > StackSlotSize) {
1324198090Srdivacky        errs() << "LowerFormalArguments Unhandled argument type: "
1325218893Sdim               << EVT(VA.getLocVT()).getEVTString()
1326198090Srdivacky               << "\n";
1327193323Sed      }
1328193323Sed      // Create the frame index object for this incoming parameter...
1329314564Sdim      int FI = MFI.CreateFixedObject(ObjSize,
1330314564Sdim                                     LRSaveSize + VA.getLocMemOffset(),
1331314564Sdim                                     true);
1332193323Sed
1333193323Sed      // Create the SelectionDAG nodes corresponding to a load
1334193323Sed      //from this parameter
1335193323Sed      SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
1336261991Sdim      ArgIn = DAG.getLoad(VA.getLocVT(), dl, Chain, FIN,
1337309124Sdim                          MachinePointerInfo::getFixedStack(MF, FI));
1338193323Sed    }
1339261991Sdim    const ArgDataPair ADP = { ArgIn, Ins[i].Flags };
1340261991Sdim    ArgData.push_back(ADP);
1341193323Sed  }
1342219077Sdim
1343261991Sdim  // 1b. CopyFromReg vararg registers.
1344193323Sed  if (isVarArg) {
1345261991Sdim    // Argument registers
1346276479Sdim    static const MCPhysReg ArgRegs[] = {
1347193323Sed      XCore::R0, XCore::R1, XCore::R2, XCore::R3
1348193323Sed    };
1349193323Sed    XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
1350288943Sdim    unsigned FirstVAReg = CCInfo.getFirstUnallocated(ArgRegs);
1351193323Sed    if (FirstVAReg < array_lengthof(ArgRegs)) {
1352193323Sed      int offset = 0;
1353193323Sed      // Save remaining registers, storing higher register numbers at a higher
1354193323Sed      // address
1355226633Sdim      for (int i = array_lengthof(ArgRegs) - 1; i >= (int)FirstVAReg; --i) {
1356193323Sed        // Create a stack slot
1357314564Sdim        int FI = MFI.CreateFixedObject(4, offset, true);
1358226633Sdim        if (i == (int)FirstVAReg) {
1359193323Sed          XFI->setVarArgsFrameIndex(FI);
1360193323Sed        }
1361193323Sed        offset -= StackSlotSize;
1362193323Sed        SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
1363193323Sed        // Move argument from phys reg -> virt reg
1364360784Sdim        Register VReg = RegInfo.createVirtualRegister(&XCore::GRRegsRegClass);
1365193323Sed        RegInfo.addLiveIn(ArgRegs[i], VReg);
1366198090Srdivacky        SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
1367261991Sdim        CFRegNode.push_back(Val.getValue(Val->getNumValues() - 1));
1368193323Sed        // Move argument from virt reg -> stack
1369309124Sdim        SDValue Store =
1370309124Sdim            DAG.getStore(Val.getValue(1), dl, Val, FIN, MachinePointerInfo());
1371193323Sed        MemOps.push_back(Store);
1372193323Sed      }
1373193323Sed    } else {
1374193323Sed      // This will point to the next argument passed via stack.
1375193323Sed      XFI->setVarArgsFrameIndex(
1376314564Sdim        MFI.CreateFixedObject(4, LRSaveSize + CCInfo.getNextStackOffset(),
1377314564Sdim                              true));
1378193323Sed    }
1379193323Sed  }
1380219077Sdim
1381261991Sdim  // 2. chain CopyFromReg nodes into a TokenFactor.
1382261991Sdim  if (!CFRegNode.empty())
1383276479Sdim    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, CFRegNode);
1384261991Sdim
1385261991Sdim  // 3. Memcpy 'byVal' args & push final InVals.
1386261991Sdim  // Aggregates passed "byVal" need to be copied by the callee.
1387261991Sdim  // The callee will use a pointer to this copy, rather than the original
1388261991Sdim  // pointer.
1389261991Sdim  for (SmallVectorImpl<ArgDataPair>::const_iterator ArgDI = ArgData.begin(),
1390261991Sdim                                                    ArgDE = ArgData.end();
1391261991Sdim       ArgDI != ArgDE; ++ArgDI) {
1392261991Sdim    if (ArgDI->Flags.isByVal() && ArgDI->Flags.getByValSize()) {
1393261991Sdim      unsigned Size = ArgDI->Flags.getByValSize();
1394261991Sdim      unsigned Align = std::max(StackSlotSize, ArgDI->Flags.getByValAlign());
1395261991Sdim      // Create a new object on the stack and copy the pointee into it.
1396314564Sdim      int FI = MFI.CreateStackObject(Size, Align, false);
1397261991Sdim      SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
1398261991Sdim      InVals.push_back(FIN);
1399261991Sdim      MemOps.push_back(DAG.getMemcpy(Chain, dl, FIN, ArgDI->SDV,
1400288943Sdim                                     DAG.getConstant(Size, dl, MVT::i32),
1401288943Sdim                                     Align, false, false, false,
1402261991Sdim                                     MachinePointerInfo(),
1403261991Sdim                                     MachinePointerInfo()));
1404261991Sdim    } else {
1405261991Sdim      InVals.push_back(ArgDI->SDV);
1406261991Sdim    }
1407261991Sdim  }
1408261991Sdim
1409261991Sdim  // 4, chain mem ops nodes into a TokenFactor.
1410261991Sdim  if (!MemOps.empty()) {
1411261991Sdim    MemOps.push_back(Chain);
1412276479Sdim    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOps);
1413261991Sdim  }
1414261991Sdim
1415198090Srdivacky  return Chain;
1416193323Sed}
1417193323Sed
1418193323Sed//===----------------------------------------------------------------------===//
1419193323Sed//               Return Value Calling Convention Implementation
1420193323Sed//===----------------------------------------------------------------------===//
1421193323Sed
1422199481Srdivackybool XCoreTargetLowering::
1423223017SdimCanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
1424239462Sdim               bool isVarArg,
1425210299Sed               const SmallVectorImpl<ISD::OutputArg> &Outs,
1426210299Sed               LLVMContext &Context) const {
1427199481Srdivacky  SmallVector<CCValAssign, 16> RVLocs;
1428280031Sdim  CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context);
1429276479Sdim  if (!CCInfo.CheckReturn(Outs, RetCC_XCore))
1430276479Sdim    return false;
1431276479Sdim  if (CCInfo.getNextStackOffset() != 0 && isVarArg)
1432276479Sdim    return false;
1433276479Sdim  return true;
1434199481Srdivacky}
1435199481Srdivacky
1436198090SrdivackySDValue
1437309124SdimXCoreTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
1438309124Sdim                                 bool isVarArg,
1439198090Srdivacky                                 const SmallVectorImpl<ISD::OutputArg> &Outs,
1440210299Sed                                 const SmallVectorImpl<SDValue> &OutVals,
1441309124Sdim                                 const SDLoc &dl, SelectionDAG &DAG) const {
1442198090Srdivacky
1443276479Sdim  XCoreFunctionInfo *XFI =
1444276479Sdim    DAG.getMachineFunction().getInfo<XCoreFunctionInfo>();
1445314564Sdim  MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
1446276479Sdim
1447193323Sed  // CCValAssign - represent the assignment of
1448193323Sed  // the return value to a location
1449193323Sed  SmallVector<CCValAssign, 16> RVLocs;
1450193323Sed
1451193323Sed  // CCState - Info about the registers and stack slot.
1452280031Sdim  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
1453280031Sdim                 *DAG.getContext());
1454193323Sed
1455223017Sdim  // Analyze return values.
1456276479Sdim  if (!isVarArg)
1457276479Sdim    CCInfo.AllocateStack(XFI->getReturnStackOffset(), 4);
1458276479Sdim
1459198090Srdivacky  CCInfo.AnalyzeReturn(Outs, RetCC_XCore);
1460193323Sed
1461193323Sed  SDValue Flag;
1462249423Sdim  SmallVector<SDValue, 4> RetOps(1, Chain);
1463193323Sed
1464249423Sdim  // Return on XCore is always a "retsp 0"
1465288943Sdim  RetOps.push_back(DAG.getConstant(0, dl, MVT::i32));
1466249423Sdim
1467276479Sdim  SmallVector<SDValue, 4> MemOpChains;
1468276479Sdim  // Handle return values that must be copied to memory.
1469276479Sdim  for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
1470193323Sed    CCValAssign &VA = RVLocs[i];
1471276479Sdim    if (VA.isRegLoc())
1472276479Sdim      continue;
1473276479Sdim    assert(VA.isMemLoc());
1474276479Sdim    if (isVarArg) {
1475276479Sdim      report_fatal_error("Can't return value from vararg function in memory");
1476276479Sdim    }
1477193323Sed
1478276479Sdim    int Offset = VA.getLocMemOffset();
1479276479Sdim    unsigned ObjSize = VA.getLocVT().getSizeInBits() / 8;
1480276479Sdim    // Create the frame index object for the memory location.
1481314564Sdim    int FI = MFI.CreateFixedObject(ObjSize, Offset, false);
1482193323Sed
1483276479Sdim    // Create a SelectionDAG node corresponding to a store
1484276479Sdim    // to this memory location.
1485276479Sdim    SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
1486296417Sdim    MemOpChains.push_back(DAG.getStore(
1487296417Sdim        Chain, dl, OutVals[i], FIN,
1488309124Sdim        MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI)));
1489276479Sdim  }
1490276479Sdim
1491276479Sdim  // Transform all store nodes into one single node because
1492276479Sdim  // all stores are independent of each other.
1493276479Sdim  if (!MemOpChains.empty())
1494276479Sdim    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
1495276479Sdim
1496276479Sdim  // Now handle return values copied to registers.
1497276479Sdim  for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
1498276479Sdim    CCValAssign &VA = RVLocs[i];
1499276479Sdim    if (!VA.isRegLoc())
1500276479Sdim      continue;
1501276479Sdim    // Copy the result values into the output registers.
1502276479Sdim    Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Flag);
1503276479Sdim
1504193323Sed    // guarantee that all emitted copies are
1505193323Sed    // stuck together, avoiding something bad
1506193323Sed    Flag = Chain.getValue(1);
1507249423Sdim    RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
1508193323Sed  }
1509193323Sed
1510249423Sdim  RetOps[0] = Chain;  // Update chain.
1511249423Sdim
1512249423Sdim  // Add the flag if we have it.
1513193323Sed  if (Flag.getNode())
1514249423Sdim    RetOps.push_back(Flag);
1515249423Sdim
1516276479Sdim  return DAG.getNode(XCoreISD::RETSP, dl, MVT::Other, RetOps);
1517193323Sed}
1518193323Sed
1519193323Sed//===----------------------------------------------------------------------===//
1520193323Sed//  Other Lowering Code
1521193323Sed//===----------------------------------------------------------------------===//
1522193323Sed
1523193323SedMachineBasicBlock *
1524309124SdimXCoreTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
1525207618Srdivacky                                                 MachineBasicBlock *BB) const {
1526288943Sdim  const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
1527309124Sdim  DebugLoc dl = MI.getDebugLoc();
1528309124Sdim  assert((MI.getOpcode() == XCore::SELECT_CC) &&
1529193323Sed         "Unexpected instr type to insert");
1530219077Sdim
1531193323Sed  // To "insert" a SELECT_CC instruction, we actually have to insert the diamond
1532193323Sed  // control-flow pattern.  The incoming instruction knows the destination vreg
1533193323Sed  // to set, the condition code register to branch on, the true/false values to
1534193323Sed  // select between, and a branch opcode to use.
1535193323Sed  const BasicBlock *LLVM_BB = BB->getBasicBlock();
1536296417Sdim  MachineFunction::iterator It = ++BB->getIterator();
1537219077Sdim
1538193323Sed  //  thisMBB:
1539193323Sed  //  ...
1540193323Sed  //   TrueVal = ...
1541193323Sed  //   cmpTY ccX, r1, r2
1542193323Sed  //   bCC copy1MBB
1543193323Sed  //   fallthrough --> copy0MBB
1544193323Sed  MachineBasicBlock *thisMBB = BB;
1545193323Sed  MachineFunction *F = BB->getParent();
1546193323Sed  MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
1547193323Sed  MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
1548193323Sed  F->insert(It, copy0MBB);
1549193323Sed  F->insert(It, sinkMBB);
1550210299Sed
1551210299Sed  // Transfer the remainder of BB and its successor edges to sinkMBB.
1552210299Sed  sinkMBB->splice(sinkMBB->begin(), BB,
1553276479Sdim                  std::next(MachineBasicBlock::iterator(MI)), BB->end());
1554210299Sed  sinkMBB->transferSuccessorsAndUpdatePHIs(BB);
1555210299Sed
1556193323Sed  // Next, add the true and fallthrough blocks as its successors.
1557193323Sed  BB->addSuccessor(copy0MBB);
1558193323Sed  BB->addSuccessor(sinkMBB);
1559219077Sdim
1560210299Sed  BuildMI(BB, dl, TII.get(XCore::BRFT_lru6))
1561309124Sdim      .addReg(MI.getOperand(1).getReg())
1562309124Sdim      .addMBB(sinkMBB);
1563210299Sed
1564193323Sed  //  copy0MBB:
1565193323Sed  //   %FalseValue = ...
1566193323Sed  //   # fallthrough to sinkMBB
1567193323Sed  BB = copy0MBB;
1568219077Sdim
1569193323Sed  // Update machine-CFG edges
1570193323Sed  BB->addSuccessor(sinkMBB);
1571219077Sdim
1572193323Sed  //  sinkMBB:
1573193323Sed  //   %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ]
1574193323Sed  //  ...
1575193323Sed  BB = sinkMBB;
1576309124Sdim  BuildMI(*BB, BB->begin(), dl, TII.get(XCore::PHI), MI.getOperand(0).getReg())
1577309124Sdim      .addReg(MI.getOperand(3).getReg())
1578309124Sdim      .addMBB(copy0MBB)
1579309124Sdim      .addReg(MI.getOperand(2).getReg())
1580309124Sdim      .addMBB(thisMBB);
1581219077Sdim
1582309124Sdim  MI.eraseFromParent(); // The pseudo instruction is gone now.
1583193323Sed  return BB;
1584193323Sed}
1585193323Sed
1586193323Sed//===----------------------------------------------------------------------===//
1587198090Srdivacky// Target Optimization Hooks
1588198090Srdivacky//===----------------------------------------------------------------------===//
1589198090Srdivacky
1590198090SrdivackySDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N,
1591198090Srdivacky                                             DAGCombinerInfo &DCI) const {
1592198090Srdivacky  SelectionDAG &DAG = DCI.DAG;
1593261991Sdim  SDLoc dl(N);
1594198090Srdivacky  switch (N->getOpcode()) {
1595198090Srdivacky  default: break;
1596276479Sdim  case ISD::INTRINSIC_VOID:
1597276479Sdim    switch (cast<ConstantSDNode>(N->getOperand(1))->getZExtValue()) {
1598276479Sdim    case Intrinsic::xcore_outt:
1599276479Sdim    case Intrinsic::xcore_outct:
1600276479Sdim    case Intrinsic::xcore_chkct: {
1601276479Sdim      SDValue OutVal = N->getOperand(3);
1602276479Sdim      // These instructions ignore the high bits.
1603276479Sdim      if (OutVal.hasOneUse()) {
1604276479Sdim        unsigned BitWidth = OutVal.getValueSizeInBits();
1605276479Sdim        APInt DemandedMask = APInt::getLowBitsSet(BitWidth, 8);
1606321369Sdim        KnownBits Known;
1607276479Sdim        TargetLowering::TargetLoweringOpt TLO(DAG, !DCI.isBeforeLegalize(),
1608276479Sdim                                              !DCI.isBeforeLegalizeOps());
1609276479Sdim        const TargetLowering &TLI = DAG.getTargetLoweringInfo();
1610321369Sdim        if (TLI.ShrinkDemandedConstant(OutVal, DemandedMask, TLO) ||
1611321369Sdim            TLI.SimplifyDemandedBits(OutVal, DemandedMask, Known, TLO))
1612276479Sdim          DCI.CommitTargetLoweringOpt(TLO);
1613276479Sdim      }
1614276479Sdim      break;
1615276479Sdim    }
1616276479Sdim    case Intrinsic::xcore_setpt: {
1617276479Sdim      SDValue Time = N->getOperand(3);
1618276479Sdim      // This instruction ignores the high bits.
1619276479Sdim      if (Time.hasOneUse()) {
1620276479Sdim        unsigned BitWidth = Time.getValueSizeInBits();
1621276479Sdim        APInt DemandedMask = APInt::getLowBitsSet(BitWidth, 16);
1622321369Sdim        KnownBits Known;
1623276479Sdim        TargetLowering::TargetLoweringOpt TLO(DAG, !DCI.isBeforeLegalize(),
1624276479Sdim                                              !DCI.isBeforeLegalizeOps());
1625276479Sdim        const TargetLowering &TLI = DAG.getTargetLoweringInfo();
1626321369Sdim        if (TLI.ShrinkDemandedConstant(Time, DemandedMask, TLO) ||
1627321369Sdim            TLI.SimplifyDemandedBits(Time, DemandedMask, Known, TLO))
1628276479Sdim          DCI.CommitTargetLoweringOpt(TLO);
1629276479Sdim      }
1630276479Sdim      break;
1631276479Sdim    }
1632276479Sdim    }
1633276479Sdim    break;
1634204961Srdivacky  case XCoreISD::LADD: {
1635204961Srdivacky    SDValue N0 = N->getOperand(0);
1636204961Srdivacky    SDValue N1 = N->getOperand(1);
1637204961Srdivacky    SDValue N2 = N->getOperand(2);
1638204961Srdivacky    ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
1639204961Srdivacky    ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
1640204961Srdivacky    EVT VT = N0.getValueType();
1641204961Srdivacky
1642204961Srdivacky    // canonicalize constant to RHS
1643204961Srdivacky    if (N0C && !N1C)
1644204961Srdivacky      return DAG.getNode(XCoreISD::LADD, dl, DAG.getVTList(VT, VT), N1, N0, N2);
1645204961Srdivacky
1646204961Srdivacky    // fold (ladd 0, 0, x) -> 0, x & 1
1647204961Srdivacky    if (N0C && N0C->isNullValue() && N1C && N1C->isNullValue()) {
1648288943Sdim      SDValue Carry = DAG.getConstant(0, dl, VT);
1649204961Srdivacky      SDValue Result = DAG.getNode(ISD::AND, dl, VT, N2,
1650288943Sdim                                   DAG.getConstant(1, dl, VT));
1651249423Sdim      SDValue Ops[] = { Result, Carry };
1652276479Sdim      return DAG.getMergeValues(Ops, dl);
1653204961Srdivacky    }
1654204961Srdivacky
1655204961Srdivacky    // fold (ladd x, 0, y) -> 0, add x, y iff carry is unused and y has only the
1656204961Srdivacky    // low bit set
1657249423Sdim    if (N1C && N1C->isNullValue() && N->hasNUsesOfValue(0, 1)) {
1658204961Srdivacky      APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(),
1659204961Srdivacky                                         VT.getSizeInBits() - 1);
1660344779Sdim      KnownBits Known = DAG.computeKnownBits(N2);
1661321369Sdim      if ((Known.Zero & Mask) == Mask) {
1662288943Sdim        SDValue Carry = DAG.getConstant(0, dl, VT);
1663204961Srdivacky        SDValue Result = DAG.getNode(ISD::ADD, dl, VT, N0, N2);
1664249423Sdim        SDValue Ops[] = { Result, Carry };
1665276479Sdim        return DAG.getMergeValues(Ops, dl);
1666204961Srdivacky      }
1667204961Srdivacky    }
1668204961Srdivacky  }
1669204961Srdivacky  break;
1670204961Srdivacky  case XCoreISD::LSUB: {
1671204961Srdivacky    SDValue N0 = N->getOperand(0);
1672204961Srdivacky    SDValue N1 = N->getOperand(1);
1673204961Srdivacky    SDValue N2 = N->getOperand(2);
1674204961Srdivacky    ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
1675204961Srdivacky    ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
1676204961Srdivacky    EVT VT = N0.getValueType();
1677204961Srdivacky
1678204961Srdivacky    // fold (lsub 0, 0, x) -> x, -x iff x has only the low bit set
1679219077Sdim    if (N0C && N0C->isNullValue() && N1C && N1C->isNullValue()) {
1680204961Srdivacky      APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(),
1681204961Srdivacky                                         VT.getSizeInBits() - 1);
1682344779Sdim      KnownBits Known = DAG.computeKnownBits(N2);
1683321369Sdim      if ((Known.Zero & Mask) == Mask) {
1684204961Srdivacky        SDValue Borrow = N2;
1685204961Srdivacky        SDValue Result = DAG.getNode(ISD::SUB, dl, VT,
1686288943Sdim                                     DAG.getConstant(0, dl, VT), N2);
1687249423Sdim        SDValue Ops[] = { Result, Borrow };
1688276479Sdim        return DAG.getMergeValues(Ops, dl);
1689204961Srdivacky      }
1690204961Srdivacky    }
1691204961Srdivacky
1692204961Srdivacky    // fold (lsub x, 0, y) -> 0, sub x, y iff borrow is unused and y has only the
1693204961Srdivacky    // low bit set
1694249423Sdim    if (N1C && N1C->isNullValue() && N->hasNUsesOfValue(0, 1)) {
1695204961Srdivacky      APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(),
1696204961Srdivacky                                         VT.getSizeInBits() - 1);
1697344779Sdim      KnownBits Known = DAG.computeKnownBits(N2);
1698321369Sdim      if ((Known.Zero & Mask) == Mask) {
1699288943Sdim        SDValue Borrow = DAG.getConstant(0, dl, VT);
1700204961Srdivacky        SDValue Result = DAG.getNode(ISD::SUB, dl, VT, N0, N2);
1701249423Sdim        SDValue Ops[] = { Result, Borrow };
1702276479Sdim        return DAG.getMergeValues(Ops, dl);
1703204961Srdivacky      }
1704204961Srdivacky    }
1705204961Srdivacky  }
1706204961Srdivacky  break;
1707205218Srdivacky  case XCoreISD::LMUL: {
1708205218Srdivacky    SDValue N0 = N->getOperand(0);
1709205218Srdivacky    SDValue N1 = N->getOperand(1);
1710205218Srdivacky    SDValue N2 = N->getOperand(2);
1711205218Srdivacky    SDValue N3 = N->getOperand(3);
1712205218Srdivacky    ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
1713205218Srdivacky    ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
1714205218Srdivacky    EVT VT = N0.getValueType();
1715205218Srdivacky    // Canonicalize multiplicative constant to RHS. If both multiplicative
1716205218Srdivacky    // operands are constant canonicalize smallest to RHS.
1717205218Srdivacky    if ((N0C && !N1C) ||
1718205218Srdivacky        (N0C && N1C && N0C->getZExtValue() < N1C->getZExtValue()))
1719226633Sdim      return DAG.getNode(XCoreISD::LMUL, dl, DAG.getVTList(VT, VT),
1720226633Sdim                         N1, N0, N2, N3);
1721205218Srdivacky
1722205218Srdivacky    // lmul(x, 0, a, b)
1723205218Srdivacky    if (N1C && N1C->isNullValue()) {
1724205218Srdivacky      // If the high result is unused fold to add(a, b)
1725205218Srdivacky      if (N->hasNUsesOfValue(0, 0)) {
1726205218Srdivacky        SDValue Lo = DAG.getNode(ISD::ADD, dl, VT, N2, N3);
1727249423Sdim        SDValue Ops[] = { Lo, Lo };
1728276479Sdim        return DAG.getMergeValues(Ops, dl);
1729205218Srdivacky      }
1730205218Srdivacky      // Otherwise fold to ladd(a, b, 0)
1731249423Sdim      SDValue Result =
1732249423Sdim        DAG.getNode(XCoreISD::LADD, dl, DAG.getVTList(VT, VT), N2, N3, N1);
1733249423Sdim      SDValue Carry(Result.getNode(), 1);
1734249423Sdim      SDValue Ops[] = { Carry, Result };
1735276479Sdim      return DAG.getMergeValues(Ops, dl);
1736205218Srdivacky    }
1737205218Srdivacky  }
1738205218Srdivacky  break;
1739204961Srdivacky  case ISD::ADD: {
1740205218Srdivacky    // Fold 32 bit expressions such as add(add(mul(x,y),a),b) ->
1741205218Srdivacky    // lmul(x, y, a, b). The high result of lmul will be ignored.
1742204961Srdivacky    // This is only profitable if the intermediate results are unused
1743204961Srdivacky    // elsewhere.
1744204961Srdivacky    SDValue Mul0, Mul1, Addend0, Addend1;
1745205218Srdivacky    if (N->getValueType(0) == MVT::i32 &&
1746205218Srdivacky        isADDADDMUL(SDValue(N, 0), Mul0, Mul1, Addend0, Addend1, true)) {
1747204961Srdivacky      SDValue Ignored = DAG.getNode(XCoreISD::LMUL, dl,
1748204961Srdivacky                                    DAG.getVTList(MVT::i32, MVT::i32), Mul0,
1749204961Srdivacky                                    Mul1, Addend0, Addend1);
1750204961Srdivacky      SDValue Result(Ignored.getNode(), 1);
1751204961Srdivacky      return Result;
1752204961Srdivacky    }
1753205218Srdivacky    APInt HighMask = APInt::getHighBitsSet(64, 32);
1754205218Srdivacky    // Fold 64 bit expression such as add(add(mul(x,y),a),b) ->
1755205218Srdivacky    // lmul(x, y, a, b) if all operands are zero-extended. We do this
1756205218Srdivacky    // before type legalization as it is messy to match the operands after
1757205218Srdivacky    // that.
1758205218Srdivacky    if (N->getValueType(0) == MVT::i64 &&
1759205218Srdivacky        isADDADDMUL(SDValue(N, 0), Mul0, Mul1, Addend0, Addend1, false) &&
1760205218Srdivacky        DAG.MaskedValueIsZero(Mul0, HighMask) &&
1761205218Srdivacky        DAG.MaskedValueIsZero(Mul1, HighMask) &&
1762205218Srdivacky        DAG.MaskedValueIsZero(Addend0, HighMask) &&
1763205218Srdivacky        DAG.MaskedValueIsZero(Addend1, HighMask)) {
1764205218Srdivacky      SDValue Mul0L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
1765288943Sdim                                  Mul0, DAG.getConstant(0, dl, MVT::i32));
1766205218Srdivacky      SDValue Mul1L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
1767288943Sdim                                  Mul1, DAG.getConstant(0, dl, MVT::i32));
1768205218Srdivacky      SDValue Addend0L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
1769288943Sdim                                     Addend0, DAG.getConstant(0, dl, MVT::i32));
1770205218Srdivacky      SDValue Addend1L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
1771288943Sdim                                     Addend1, DAG.getConstant(0, dl, MVT::i32));
1772205218Srdivacky      SDValue Hi = DAG.getNode(XCoreISD::LMUL, dl,
1773205218Srdivacky                               DAG.getVTList(MVT::i32, MVT::i32), Mul0L, Mul1L,
1774205218Srdivacky                               Addend0L, Addend1L);
1775205218Srdivacky      SDValue Lo(Hi.getNode(), 1);
1776205218Srdivacky      return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);
1777205218Srdivacky    }
1778204961Srdivacky  }
1779204961Srdivacky  break;
1780198090Srdivacky  case ISD::STORE: {
1781198090Srdivacky    // Replace unaligned store of unaligned load with memmove.
1782353358Sdim    StoreSDNode *ST = cast<StoreSDNode>(N);
1783198090Srdivacky    if (!DCI.isBeforeLegalize() ||
1784360784Sdim        allowsMemoryAccessForAlignment(*DAG.getContext(), DAG.getDataLayout(),
1785360784Sdim                                       ST->getMemoryVT(),
1786360784Sdim                                       *ST->getMemOperand()) ||
1787198090Srdivacky        ST->isVolatile() || ST->isIndexed()) {
1788198090Srdivacky      break;
1789198090Srdivacky    }
1790198090Srdivacky    SDValue Chain = ST->getChain();
1791198090Srdivacky
1792198090Srdivacky    unsigned StoreBits = ST->getMemoryVT().getStoreSizeInBits();
1793296417Sdim    assert((StoreBits % 8) == 0 &&
1794296417Sdim           "Store size in bits must be a multiple of 8");
1795198090Srdivacky    unsigned Alignment = ST->getAlignment();
1796198090Srdivacky
1797198090Srdivacky    if (LoadSDNode *LD = dyn_cast<LoadSDNode>(ST->getValue())) {
1798198090Srdivacky      if (LD->hasNUsesOfValue(1, 0) && ST->getMemoryVT() == LD->getMemoryVT() &&
1799198090Srdivacky        LD->getAlignment() == Alignment &&
1800198090Srdivacky        !LD->isVolatile() && !LD->isIndexed() &&
1801198090Srdivacky        Chain.reachesChainWithoutSideEffects(SDValue(LD, 1))) {
1802288943Sdim        bool isTail = isInTailCallPosition(DAG, ST, Chain);
1803198090Srdivacky        return DAG.getMemmove(Chain, dl, ST->getBasePtr(),
1804198090Srdivacky                              LD->getBasePtr(),
1805288943Sdim                              DAG.getConstant(StoreBits/8, dl, MVT::i32),
1806288943Sdim                              Alignment, false, isTail, ST->getPointerInfo(),
1807218893Sdim                              LD->getPointerInfo());
1808198090Srdivacky      }
1809198090Srdivacky    }
1810198090Srdivacky    break;
1811198090Srdivacky  }
1812198090Srdivacky  }
1813198090Srdivacky  return SDValue();
1814198090Srdivacky}
1815198090Srdivacky
1816276479Sdimvoid XCoreTargetLowering::computeKnownBitsForTargetNode(const SDValue Op,
1817321369Sdim                                                        KnownBits &Known,
1818321369Sdim                                                        const APInt &DemandedElts,
1819276479Sdim                                                        const SelectionDAG &DAG,
1820276479Sdim                                                        unsigned Depth) const {
1821321369Sdim  Known.resetAll();
1822204961Srdivacky  switch (Op.getOpcode()) {
1823204961Srdivacky  default: break;
1824204961Srdivacky  case XCoreISD::LADD:
1825204961Srdivacky  case XCoreISD::LSUB:
1826249423Sdim    if (Op.getResNo() == 1) {
1827204961Srdivacky      // Top bits of carry / borrow are clear.
1828321369Sdim      Known.Zero = APInt::getHighBitsSet(Known.getBitWidth(),
1829321369Sdim                                         Known.getBitWidth() - 1);
1830204961Srdivacky    }
1831204961Srdivacky    break;
1832276479Sdim  case ISD::INTRINSIC_W_CHAIN:
1833276479Sdim    {
1834276479Sdim      unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue();
1835276479Sdim      switch (IntNo) {
1836276479Sdim      case Intrinsic::xcore_getts:
1837276479Sdim        // High bits are known to be zero.
1838321369Sdim        Known.Zero = APInt::getHighBitsSet(Known.getBitWidth(),
1839321369Sdim                                           Known.getBitWidth() - 16);
1840276479Sdim        break;
1841276479Sdim      case Intrinsic::xcore_int:
1842276479Sdim      case Intrinsic::xcore_inct:
1843276479Sdim        // High bits are known to be zero.
1844321369Sdim        Known.Zero = APInt::getHighBitsSet(Known.getBitWidth(),
1845321369Sdim                                           Known.getBitWidth() - 8);
1846276479Sdim        break;
1847276479Sdim      case Intrinsic::xcore_testct:
1848276479Sdim        // Result is either 0 or 1.
1849321369Sdim        Known.Zero = APInt::getHighBitsSet(Known.getBitWidth(),
1850321369Sdim                                           Known.getBitWidth() - 1);
1851276479Sdim        break;
1852276479Sdim      case Intrinsic::xcore_testwct:
1853276479Sdim        // Result is in the range 0 - 4.
1854321369Sdim        Known.Zero = APInt::getHighBitsSet(Known.getBitWidth(),
1855321369Sdim                                           Known.getBitWidth() - 3);
1856276479Sdim        break;
1857276479Sdim      }
1858276479Sdim    }
1859276479Sdim    break;
1860204961Srdivacky  }
1861204961Srdivacky}
1862204961Srdivacky
1863198090Srdivacky//===----------------------------------------------------------------------===//
1864193323Sed//  Addressing mode description hooks
1865193323Sed//===----------------------------------------------------------------------===//
1866193323Sed
1867193323Sedstatic inline bool isImmUs(int64_t val)
1868193323Sed{
1869193323Sed  return (val >= 0 && val <= 11);
1870193323Sed}
1871193323Sed
1872193323Sedstatic inline bool isImmUs2(int64_t val)
1873193323Sed{
1874193323Sed  return (val%2 == 0 && isImmUs(val/2));
1875193323Sed}
1876193323Sed
1877193323Sedstatic inline bool isImmUs4(int64_t val)
1878193323Sed{
1879193323Sed  return (val%4 == 0 && isImmUs(val/4));
1880193323Sed}
1881193323Sed
1882193323Sed/// isLegalAddressingMode - Return true if the addressing mode represented
1883193323Sed/// by AM is legal for this target, for a load/store of the specified type.
1884288943Sdimbool XCoreTargetLowering::isLegalAddressingMode(const DataLayout &DL,
1885288943Sdim                                                const AddrMode &AM, Type *Ty,
1886327952Sdim                                                unsigned AS,
1887327952Sdim                                                Instruction *I) const {
1888198090Srdivacky  if (Ty->getTypeID() == Type::VoidTyID)
1889204642Srdivacky    return AM.Scale == 0 && isImmUs(AM.BaseOffs) && isImmUs4(AM.BaseOffs);
1890198090Srdivacky
1891288943Sdim  unsigned Size = DL.getTypeAllocSize(Ty);
1892193323Sed  if (AM.BaseGV) {
1893198090Srdivacky    return Size >= 4 && !AM.HasBaseReg && AM.Scale == 0 &&
1894193323Sed                 AM.BaseOffs%4 == 0;
1895193323Sed  }
1896219077Sdim
1897198090Srdivacky  switch (Size) {
1898198090Srdivacky  case 1:
1899193323Sed    // reg + imm
1900193323Sed    if (AM.Scale == 0) {
1901193323Sed      return isImmUs(AM.BaseOffs);
1902193323Sed    }
1903198090Srdivacky    // reg + reg
1904193323Sed    return AM.Scale == 1 && AM.BaseOffs == 0;
1905198090Srdivacky  case 2:
1906198090Srdivacky  case 3:
1907193323Sed    // reg + imm
1908193323Sed    if (AM.Scale == 0) {
1909193323Sed      return isImmUs2(AM.BaseOffs);
1910193323Sed    }
1911198090Srdivacky    // reg + reg<<1
1912193323Sed    return AM.Scale == 2 && AM.BaseOffs == 0;
1913198090Srdivacky  default:
1914193323Sed    // reg + imm
1915193323Sed    if (AM.Scale == 0) {
1916193323Sed      return isImmUs4(AM.BaseOffs);
1917193323Sed    }
1918193323Sed    // reg + reg<<2
1919193323Sed    return AM.Scale == 4 && AM.BaseOffs == 0;
1920193323Sed  }
1921193323Sed}
1922193323Sed
1923193323Sed//===----------------------------------------------------------------------===//
1924193323Sed//                           XCore Inline Assembly Support
1925193323Sed//===----------------------------------------------------------------------===//
1926193323Sed
1927288943Sdimstd::pair<unsigned, const TargetRegisterClass *>
1928288943SdimXCoreTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
1929288943Sdim                                                  StringRef Constraint,
1930288943Sdim                                                  MVT VT) const {
1931224145Sdim  if (Constraint.size() == 1) {
1932224145Sdim    switch (Constraint[0]) {
1933193323Sed    default : break;
1934193323Sed    case 'r':
1935239462Sdim      return std::make_pair(0U, &XCore::GRRegsRegClass);
1936224145Sdim    }
1937193323Sed  }
1938224145Sdim  // Use the default implementation in TargetLowering to convert the register
1939224145Sdim  // constraint into a member of a register class.
1940288943Sdim  return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
1941193323Sed}
1942