1 //===-- XCoreISelLowering.cpp - XCore DAG Lowering Implementation ---------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the XCoreTargetLowering class.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "XCoreISelLowering.h"
14 #include "XCore.h"
15 #include "XCoreMachineFunctionInfo.h"
16 #include "XCoreSubtarget.h"
17 #include "XCoreTargetMachine.h"
18 #include "XCoreTargetObjectFile.h"
19 #include "llvm/CodeGen/CallingConvLower.h"
20 #include "llvm/CodeGen/MachineFrameInfo.h"
21 #include "llvm/CodeGen/MachineFunction.h"
22 #include "llvm/CodeGen/MachineInstrBuilder.h"
23 #include "llvm/CodeGen/MachineJumpTableInfo.h"
24 #include "llvm/CodeGen/MachineRegisterInfo.h"
25 #include "llvm/CodeGen/SelectionDAGISel.h"
26 #include "llvm/CodeGen/ValueTypes.h"
27 #include "llvm/IR/CallingConv.h"
28 #include "llvm/IR/Constants.h"
29 #include "llvm/IR/DerivedTypes.h"
30 #include "llvm/IR/Function.h"
31 #include "llvm/IR/GlobalAlias.h"
32 #include "llvm/IR/GlobalVariable.h"
33 #include "llvm/IR/Intrinsics.h"
34 #include "llvm/IR/IntrinsicsXCore.h"
35 #include "llvm/Support/Debug.h"
36 #include "llvm/Support/ErrorHandling.h"
37 #include "llvm/Support/KnownBits.h"
38 #include "llvm/Support/raw_ostream.h"
39 #include <algorithm>
40
41 using namespace llvm;
42
43 #define DEBUG_TYPE "xcore-lower"
44
45 const char *XCoreTargetLowering::
getTargetNodeName(unsigned Opcode) const46 getTargetNodeName(unsigned Opcode) const
47 {
48 switch ((XCoreISD::NodeType)Opcode)
49 {
50 case XCoreISD::FIRST_NUMBER : break;
51 case XCoreISD::BL : return "XCoreISD::BL";
52 case XCoreISD::PCRelativeWrapper : return "XCoreISD::PCRelativeWrapper";
53 case XCoreISD::DPRelativeWrapper : return "XCoreISD::DPRelativeWrapper";
54 case XCoreISD::CPRelativeWrapper : return "XCoreISD::CPRelativeWrapper";
55 case XCoreISD::LDWSP : return "XCoreISD::LDWSP";
56 case XCoreISD::STWSP : return "XCoreISD::STWSP";
57 case XCoreISD::RETSP : return "XCoreISD::RETSP";
58 case XCoreISD::LADD : return "XCoreISD::LADD";
59 case XCoreISD::LSUB : return "XCoreISD::LSUB";
60 case XCoreISD::LMUL : return "XCoreISD::LMUL";
61 case XCoreISD::MACCU : return "XCoreISD::MACCU";
62 case XCoreISD::MACCS : return "XCoreISD::MACCS";
63 case XCoreISD::CRC8 : return "XCoreISD::CRC8";
64 case XCoreISD::BR_JT : return "XCoreISD::BR_JT";
65 case XCoreISD::BR_JT32 : return "XCoreISD::BR_JT32";
66 case XCoreISD::FRAME_TO_ARGS_OFFSET : return "XCoreISD::FRAME_TO_ARGS_OFFSET";
67 case XCoreISD::EH_RETURN : return "XCoreISD::EH_RETURN";
68 case XCoreISD::MEMBARRIER : return "XCoreISD::MEMBARRIER";
69 }
70 return nullptr;
71 }
72
XCoreTargetLowering(const TargetMachine & TM,const XCoreSubtarget & Subtarget)73 XCoreTargetLowering::XCoreTargetLowering(const TargetMachine &TM,
74 const XCoreSubtarget &Subtarget)
75 : TargetLowering(TM), TM(TM), Subtarget(Subtarget) {
76
77 // Set up the register classes.
78 addRegisterClass(MVT::i32, &XCore::GRRegsRegClass);
79
80 // Compute derived properties from the register classes
81 computeRegisterProperties(Subtarget.getRegisterInfo());
82
83 setStackPointerRegisterToSaveRestore(XCore::SP);
84
85 setSchedulingPreference(Sched::Source);
86
87 // Use i32 for setcc operations results (slt, sgt, ...).
88 setBooleanContents(ZeroOrOneBooleanContent);
89 setBooleanVectorContents(ZeroOrOneBooleanContent); // FIXME: Is this correct?
90
91 // XCore does not have the NodeTypes below.
92 setOperationAction(ISD::BR_CC, MVT::i32, Expand);
93 setOperationAction(ISD::SELECT_CC, MVT::i32, Expand);
94
95 // 64bit
96 setOperationAction(ISD::ADD, MVT::i64, Custom);
97 setOperationAction(ISD::SUB, MVT::i64, Custom);
98 setOperationAction(ISD::SMUL_LOHI, MVT::i32, Custom);
99 setOperationAction(ISD::UMUL_LOHI, MVT::i32, Custom);
100 setOperationAction(ISD::MULHS, MVT::i32, Expand);
101 setOperationAction(ISD::MULHU, MVT::i32, Expand);
102 setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
103 setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
104 setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);
105
106 // Bit Manipulation
107 setOperationAction(ISD::CTPOP, MVT::i32, Expand);
108 setOperationAction(ISD::ROTL , MVT::i32, Expand);
109 setOperationAction(ISD::ROTR , MVT::i32, Expand);
110 setOperationAction(ISD::BITREVERSE , MVT::i32, Legal);
111
112 setOperationAction(ISD::TRAP, MVT::Other, Legal);
113
114 // Jump tables.
115 setOperationAction(ISD::BR_JT, MVT::Other, Custom);
116
117 setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
118 setOperationAction(ISD::BlockAddress, MVT::i32 , Custom);
119
120 // Conversion of i64 -> double produces constantpool nodes
121 setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
122
123 // Loads
124 for (MVT VT : MVT::integer_valuetypes()) {
125 setLoadExtAction(ISD::EXTLOAD, VT, MVT::i1, Promote);
126 setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i1, Promote);
127 setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote);
128
129 setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i8, Expand);
130 setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i16, Expand);
131 }
132
133 // Custom expand misaligned loads / stores.
134 setOperationAction(ISD::LOAD, MVT::i32, Custom);
135 setOperationAction(ISD::STORE, MVT::i32, Custom);
136
137 // Varargs
138 setOperationAction(ISD::VAEND, MVT::Other, Expand);
139 setOperationAction(ISD::VACOPY, MVT::Other, Expand);
140 setOperationAction(ISD::VAARG, MVT::Other, Custom);
141 setOperationAction(ISD::VASTART, MVT::Other, Custom);
142
143 // Dynamic stack
144 setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
145 setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
146 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand);
147
148 // Exception handling
149 setOperationAction(ISD::EH_RETURN, MVT::Other, Custom);
150 setOperationAction(ISD::FRAME_TO_ARGS_OFFSET, MVT::i32, Custom);
151
152 // Atomic operations
153 // We request a fence for ATOMIC_* instructions, to reduce them to Monotonic.
154 // As we are always Sequential Consistent, an ATOMIC_FENCE becomes a no OP.
155 setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom);
156 setOperationAction(ISD::ATOMIC_LOAD, MVT::i32, Custom);
157 setOperationAction(ISD::ATOMIC_STORE, MVT::i32, Custom);
158
159 // TRAMPOLINE is custom lowered.
160 setOperationAction(ISD::INIT_TRAMPOLINE, MVT::Other, Custom);
161 setOperationAction(ISD::ADJUST_TRAMPOLINE, MVT::Other, Custom);
162
163 // We want to custom lower some of our intrinsics.
164 setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
165
166 MaxStoresPerMemset = MaxStoresPerMemsetOptSize = 4;
167 MaxStoresPerMemmove = MaxStoresPerMemmoveOptSize
168 = MaxStoresPerMemcpy = MaxStoresPerMemcpyOptSize = 2;
169
170 // We have target-specific dag combine patterns for the following nodes:
171 setTargetDAGCombine(ISD::STORE);
172 setTargetDAGCombine(ISD::ADD);
173 setTargetDAGCombine(ISD::INTRINSIC_VOID);
174 setTargetDAGCombine(ISD::INTRINSIC_W_CHAIN);
175
176 setMinFunctionAlignment(Align(2));
177 setPrefFunctionAlignment(Align(4));
178 }
179
isZExtFree(SDValue Val,EVT VT2) const180 bool XCoreTargetLowering::isZExtFree(SDValue Val, EVT VT2) const {
181 if (Val.getOpcode() != ISD::LOAD)
182 return false;
183
184 EVT VT1 = Val.getValueType();
185 if (!VT1.isSimple() || !VT1.isInteger() ||
186 !VT2.isSimple() || !VT2.isInteger())
187 return false;
188
189 switch (VT1.getSimpleVT().SimpleTy) {
190 default: break;
191 case MVT::i8:
192 return true;
193 }
194
195 return false;
196 }
197
198 SDValue XCoreTargetLowering::
LowerOperation(SDValue Op,SelectionDAG & DAG) const199 LowerOperation(SDValue Op, SelectionDAG &DAG) const {
200 switch (Op.getOpcode())
201 {
202 case ISD::EH_RETURN: return LowerEH_RETURN(Op, DAG);
203 case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
204 case ISD::BlockAddress: return LowerBlockAddress(Op, DAG);
205 case ISD::ConstantPool: return LowerConstantPool(Op, DAG);
206 case ISD::BR_JT: return LowerBR_JT(Op, DAG);
207 case ISD::LOAD: return LowerLOAD(Op, DAG);
208 case ISD::STORE: return LowerSTORE(Op, DAG);
209 case ISD::VAARG: return LowerVAARG(Op, DAG);
210 case ISD::VASTART: return LowerVASTART(Op, DAG);
211 case ISD::SMUL_LOHI: return LowerSMUL_LOHI(Op, DAG);
212 case ISD::UMUL_LOHI: return LowerUMUL_LOHI(Op, DAG);
213 // FIXME: Remove these when LegalizeDAGTypes lands.
214 case ISD::ADD:
215 case ISD::SUB: return ExpandADDSUB(Op.getNode(), DAG);
216 case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
217 case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG);
218 case ISD::FRAME_TO_ARGS_OFFSET: return LowerFRAME_TO_ARGS_OFFSET(Op, DAG);
219 case ISD::INIT_TRAMPOLINE: return LowerINIT_TRAMPOLINE(Op, DAG);
220 case ISD::ADJUST_TRAMPOLINE: return LowerADJUST_TRAMPOLINE(Op, DAG);
221 case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG);
222 case ISD::ATOMIC_FENCE: return LowerATOMIC_FENCE(Op, DAG);
223 case ISD::ATOMIC_LOAD: return LowerATOMIC_LOAD(Op, DAG);
224 case ISD::ATOMIC_STORE: return LowerATOMIC_STORE(Op, DAG);
225 default:
226 llvm_unreachable("unimplemented operand");
227 }
228 }
229
230 /// ReplaceNodeResults - Replace the results of node with an illegal result
231 /// type with new values built out of custom code.
ReplaceNodeResults(SDNode * N,SmallVectorImpl<SDValue> & Results,SelectionDAG & DAG) const232 void XCoreTargetLowering::ReplaceNodeResults(SDNode *N,
233 SmallVectorImpl<SDValue>&Results,
234 SelectionDAG &DAG) const {
235 switch (N->getOpcode()) {
236 default:
237 llvm_unreachable("Don't know how to custom expand this!");
238 case ISD::ADD:
239 case ISD::SUB:
240 Results.push_back(ExpandADDSUB(N, DAG));
241 return;
242 }
243 }
244
245 //===----------------------------------------------------------------------===//
246 // Misc Lower Operation implementation
247 //===----------------------------------------------------------------------===//
248
getGlobalAddressWrapper(SDValue GA,const GlobalValue * GV,SelectionDAG & DAG) const249 SDValue XCoreTargetLowering::getGlobalAddressWrapper(SDValue GA,
250 const GlobalValue *GV,
251 SelectionDAG &DAG) const {
252 // FIXME there is no actual debug info here
253 SDLoc dl(GA);
254
255 if (GV->getValueType()->isFunctionTy())
256 return DAG.getNode(XCoreISD::PCRelativeWrapper, dl, MVT::i32, GA);
257
258 const auto *GVar = dyn_cast<GlobalVariable>(GV);
259 if ((GV->hasSection() && GV->getSection().startswith(".cp.")) ||
260 (GVar && GVar->isConstant() && GV->hasLocalLinkage()))
261 return DAG.getNode(XCoreISD::CPRelativeWrapper, dl, MVT::i32, GA);
262
263 return DAG.getNode(XCoreISD::DPRelativeWrapper, dl, MVT::i32, GA);
264 }
265
IsSmallObject(const GlobalValue * GV,const XCoreTargetLowering & XTL)266 static bool IsSmallObject(const GlobalValue *GV, const XCoreTargetLowering &XTL) {
267 if (XTL.getTargetMachine().getCodeModel() == CodeModel::Small)
268 return true;
269
270 Type *ObjType = GV->getValueType();
271 if (!ObjType->isSized())
272 return false;
273
274 auto &DL = GV->getParent()->getDataLayout();
275 unsigned ObjSize = DL.getTypeAllocSize(ObjType);
276 return ObjSize < CodeModelLargeSize && ObjSize != 0;
277 }
278
279 SDValue XCoreTargetLowering::
LowerGlobalAddress(SDValue Op,SelectionDAG & DAG) const280 LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const
281 {
282 const GlobalAddressSDNode *GN = cast<GlobalAddressSDNode>(Op);
283 const GlobalValue *GV = GN->getGlobal();
284 SDLoc DL(GN);
285 int64_t Offset = GN->getOffset();
286 if (IsSmallObject(GV, *this)) {
287 // We can only fold positive offsets that are a multiple of the word size.
288 int64_t FoldedOffset = std::max(Offset & ~3, (int64_t)0);
289 SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, FoldedOffset);
290 GA = getGlobalAddressWrapper(GA, GV, DAG);
291 // Handle the rest of the offset.
292 if (Offset != FoldedOffset) {
293 SDValue Remaining = DAG.getConstant(Offset - FoldedOffset, DL, MVT::i32);
294 GA = DAG.getNode(ISD::ADD, DL, MVT::i32, GA, Remaining);
295 }
296 return GA;
297 } else {
298 // Ideally we would not fold in offset with an index <= 11.
299 Type *Ty = Type::getInt8PtrTy(*DAG.getContext());
300 Constant *GA = ConstantExpr::getBitCast(const_cast<GlobalValue*>(GV), Ty);
301 Ty = Type::getInt32Ty(*DAG.getContext());
302 Constant *Idx = ConstantInt::get(Ty, Offset);
303 Constant *GAI = ConstantExpr::getGetElementPtr(
304 Type::getInt8Ty(*DAG.getContext()), GA, Idx);
305 SDValue CP = DAG.getConstantPool(GAI, MVT::i32);
306 return DAG.getLoad(getPointerTy(DAG.getDataLayout()), DL,
307 DAG.getEntryNode(), CP, MachinePointerInfo());
308 }
309 }
310
311 SDValue XCoreTargetLowering::
LowerBlockAddress(SDValue Op,SelectionDAG & DAG) const312 LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const
313 {
314 SDLoc DL(Op);
315 auto PtrVT = getPointerTy(DAG.getDataLayout());
316 const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress();
317 SDValue Result = DAG.getTargetBlockAddress(BA, PtrVT);
318
319 return DAG.getNode(XCoreISD::PCRelativeWrapper, DL, PtrVT, Result);
320 }
321
322 SDValue XCoreTargetLowering::
LowerConstantPool(SDValue Op,SelectionDAG & DAG) const323 LowerConstantPool(SDValue Op, SelectionDAG &DAG) const
324 {
325 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
326 // FIXME there isn't really debug info here
327 SDLoc dl(CP);
328 EVT PtrVT = Op.getValueType();
329 SDValue Res;
330 if (CP->isMachineConstantPoolEntry()) {
331 Res = DAG.getTargetConstantPool(CP->getMachineCPVal(), PtrVT,
332 CP->getAlign(), CP->getOffset());
333 } else {
334 Res = DAG.getTargetConstantPool(CP->getConstVal(), PtrVT, CP->getAlign(),
335 CP->getOffset());
336 }
337 return DAG.getNode(XCoreISD::CPRelativeWrapper, dl, MVT::i32, Res);
338 }
339
getJumpTableEncoding() const340 unsigned XCoreTargetLowering::getJumpTableEncoding() const {
341 return MachineJumpTableInfo::EK_Inline;
342 }
343
344 SDValue XCoreTargetLowering::
LowerBR_JT(SDValue Op,SelectionDAG & DAG) const345 LowerBR_JT(SDValue Op, SelectionDAG &DAG) const
346 {
347 SDValue Chain = Op.getOperand(0);
348 SDValue Table = Op.getOperand(1);
349 SDValue Index = Op.getOperand(2);
350 SDLoc dl(Op);
351 JumpTableSDNode *JT = cast<JumpTableSDNode>(Table);
352 unsigned JTI = JT->getIndex();
353 MachineFunction &MF = DAG.getMachineFunction();
354 const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo();
355 SDValue TargetJT = DAG.getTargetJumpTable(JT->getIndex(), MVT::i32);
356
357 unsigned NumEntries = MJTI->getJumpTables()[JTI].MBBs.size();
358 if (NumEntries <= 32) {
359 return DAG.getNode(XCoreISD::BR_JT, dl, MVT::Other, Chain, TargetJT, Index);
360 }
361 assert((NumEntries >> 31) == 0);
362 SDValue ScaledIndex = DAG.getNode(ISD::SHL, dl, MVT::i32, Index,
363 DAG.getConstant(1, dl, MVT::i32));
364 return DAG.getNode(XCoreISD::BR_JT32, dl, MVT::Other, Chain, TargetJT,
365 ScaledIndex);
366 }
367
lowerLoadWordFromAlignedBasePlusOffset(const SDLoc & DL,SDValue Chain,SDValue Base,int64_t Offset,SelectionDAG & DAG) const368 SDValue XCoreTargetLowering::lowerLoadWordFromAlignedBasePlusOffset(
369 const SDLoc &DL, SDValue Chain, SDValue Base, int64_t Offset,
370 SelectionDAG &DAG) const {
371 auto PtrVT = getPointerTy(DAG.getDataLayout());
372 if ((Offset & 0x3) == 0) {
373 return DAG.getLoad(PtrVT, DL, Chain, Base, MachinePointerInfo());
374 }
375 // Lower to pair of consecutive word aligned loads plus some bit shifting.
376 int32_t HighOffset = alignTo(Offset, 4);
377 int32_t LowOffset = HighOffset - 4;
378 SDValue LowAddr, HighAddr;
379 if (GlobalAddressSDNode *GASD =
380 dyn_cast<GlobalAddressSDNode>(Base.getNode())) {
381 LowAddr = DAG.getGlobalAddress(GASD->getGlobal(), DL, Base.getValueType(),
382 LowOffset);
383 HighAddr = DAG.getGlobalAddress(GASD->getGlobal(), DL, Base.getValueType(),
384 HighOffset);
385 } else {
386 LowAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, Base,
387 DAG.getConstant(LowOffset, DL, MVT::i32));
388 HighAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, Base,
389 DAG.getConstant(HighOffset, DL, MVT::i32));
390 }
391 SDValue LowShift = DAG.getConstant((Offset - LowOffset) * 8, DL, MVT::i32);
392 SDValue HighShift = DAG.getConstant((HighOffset - Offset) * 8, DL, MVT::i32);
393
394 SDValue Low = DAG.getLoad(PtrVT, DL, Chain, LowAddr, MachinePointerInfo());
395 SDValue High = DAG.getLoad(PtrVT, DL, Chain, HighAddr, MachinePointerInfo());
396 SDValue LowShifted = DAG.getNode(ISD::SRL, DL, MVT::i32, Low, LowShift);
397 SDValue HighShifted = DAG.getNode(ISD::SHL, DL, MVT::i32, High, HighShift);
398 SDValue Result = DAG.getNode(ISD::OR, DL, MVT::i32, LowShifted, HighShifted);
399 Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Low.getValue(1),
400 High.getValue(1));
401 SDValue Ops[] = { Result, Chain };
402 return DAG.getMergeValues(Ops, DL);
403 }
404
isWordAligned(SDValue Value,SelectionDAG & DAG)405 static bool isWordAligned(SDValue Value, SelectionDAG &DAG)
406 {
407 KnownBits Known = DAG.computeKnownBits(Value);
408 return Known.countMinTrailingZeros() >= 2;
409 }
410
LowerLOAD(SDValue Op,SelectionDAG & DAG) const411 SDValue XCoreTargetLowering::LowerLOAD(SDValue Op, SelectionDAG &DAG) const {
412 const TargetLowering &TLI = DAG.getTargetLoweringInfo();
413 LLVMContext &Context = *DAG.getContext();
414 LoadSDNode *LD = cast<LoadSDNode>(Op);
415 assert(LD->getExtensionType() == ISD::NON_EXTLOAD &&
416 "Unexpected extension type");
417 assert(LD->getMemoryVT() == MVT::i32 && "Unexpected load EVT");
418
419 if (allowsMemoryAccessForAlignment(Context, DAG.getDataLayout(),
420 LD->getMemoryVT(), *LD->getMemOperand()))
421 return SDValue();
422
423 SDValue Chain = LD->getChain();
424 SDValue BasePtr = LD->getBasePtr();
425 SDLoc DL(Op);
426
427 if (!LD->isVolatile()) {
428 const GlobalValue *GV;
429 int64_t Offset = 0;
430 if (DAG.isBaseWithConstantOffset(BasePtr) &&
431 isWordAligned(BasePtr->getOperand(0), DAG)) {
432 SDValue NewBasePtr = BasePtr->getOperand(0);
433 Offset = cast<ConstantSDNode>(BasePtr->getOperand(1))->getSExtValue();
434 return lowerLoadWordFromAlignedBasePlusOffset(DL, Chain, NewBasePtr,
435 Offset, DAG);
436 }
437 if (TLI.isGAPlusOffset(BasePtr.getNode(), GV, Offset) &&
438 GV->getPointerAlignment(DAG.getDataLayout()) >= 4) {
439 SDValue NewBasePtr = DAG.getGlobalAddress(GV, DL,
440 BasePtr->getValueType(0));
441 return lowerLoadWordFromAlignedBasePlusOffset(DL, Chain, NewBasePtr,
442 Offset, DAG);
443 }
444 }
445
446 if (LD->getAlignment() == 2) {
447 SDValue Low =
448 DAG.getExtLoad(ISD::ZEXTLOAD, DL, MVT::i32, Chain, BasePtr,
449 LD->getPointerInfo(), MVT::i16,
450 /* Alignment = */ 2, LD->getMemOperand()->getFlags());
451 SDValue HighAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, BasePtr,
452 DAG.getConstant(2, DL, MVT::i32));
453 SDValue High =
454 DAG.getExtLoad(ISD::EXTLOAD, DL, MVT::i32, Chain, HighAddr,
455 LD->getPointerInfo().getWithOffset(2), MVT::i16,
456 /* Alignment = */ 2, LD->getMemOperand()->getFlags());
457 SDValue HighShifted = DAG.getNode(ISD::SHL, DL, MVT::i32, High,
458 DAG.getConstant(16, DL, MVT::i32));
459 SDValue Result = DAG.getNode(ISD::OR, DL, MVT::i32, Low, HighShifted);
460 Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Low.getValue(1),
461 High.getValue(1));
462 SDValue Ops[] = { Result, Chain };
463 return DAG.getMergeValues(Ops, DL);
464 }
465
466 // Lower to a call to __misaligned_load(BasePtr).
467 Type *IntPtrTy = DAG.getDataLayout().getIntPtrType(Context);
468 TargetLowering::ArgListTy Args;
469 TargetLowering::ArgListEntry Entry;
470
471 Entry.Ty = IntPtrTy;
472 Entry.Node = BasePtr;
473 Args.push_back(Entry);
474
475 TargetLowering::CallLoweringInfo CLI(DAG);
476 CLI.setDebugLoc(DL).setChain(Chain).setLibCallee(
477 CallingConv::C, IntPtrTy,
478 DAG.getExternalSymbol("__misaligned_load",
479 getPointerTy(DAG.getDataLayout())),
480 std::move(Args));
481
482 std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI);
483 SDValue Ops[] = { CallResult.first, CallResult.second };
484 return DAG.getMergeValues(Ops, DL);
485 }
486
LowerSTORE(SDValue Op,SelectionDAG & DAG) const487 SDValue XCoreTargetLowering::LowerSTORE(SDValue Op, SelectionDAG &DAG) const {
488 LLVMContext &Context = *DAG.getContext();
489 StoreSDNode *ST = cast<StoreSDNode>(Op);
490 assert(!ST->isTruncatingStore() && "Unexpected store type");
491 assert(ST->getMemoryVT() == MVT::i32 && "Unexpected store EVT");
492
493 if (allowsMemoryAccessForAlignment(Context, DAG.getDataLayout(),
494 ST->getMemoryVT(), *ST->getMemOperand()))
495 return SDValue();
496
497 SDValue Chain = ST->getChain();
498 SDValue BasePtr = ST->getBasePtr();
499 SDValue Value = ST->getValue();
500 SDLoc dl(Op);
501
502 if (ST->getAlignment() == 2) {
503 SDValue Low = Value;
504 SDValue High = DAG.getNode(ISD::SRL, dl, MVT::i32, Value,
505 DAG.getConstant(16, dl, MVT::i32));
506 SDValue StoreLow = DAG.getTruncStore(
507 Chain, dl, Low, BasePtr, ST->getPointerInfo(), MVT::i16,
508 /* Alignment = */ 2, ST->getMemOperand()->getFlags());
509 SDValue HighAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, BasePtr,
510 DAG.getConstant(2, dl, MVT::i32));
511 SDValue StoreHigh = DAG.getTruncStore(
512 Chain, dl, High, HighAddr, ST->getPointerInfo().getWithOffset(2),
513 MVT::i16, /* Alignment = */ 2, ST->getMemOperand()->getFlags());
514 return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, StoreLow, StoreHigh);
515 }
516
517 // Lower to a call to __misaligned_store(BasePtr, Value).
518 Type *IntPtrTy = DAG.getDataLayout().getIntPtrType(Context);
519 TargetLowering::ArgListTy Args;
520 TargetLowering::ArgListEntry Entry;
521
522 Entry.Ty = IntPtrTy;
523 Entry.Node = BasePtr;
524 Args.push_back(Entry);
525
526 Entry.Node = Value;
527 Args.push_back(Entry);
528
529 TargetLowering::CallLoweringInfo CLI(DAG);
530 CLI.setDebugLoc(dl).setChain(Chain).setCallee(
531 CallingConv::C, Type::getVoidTy(Context),
532 DAG.getExternalSymbol("__misaligned_store",
533 getPointerTy(DAG.getDataLayout())),
534 std::move(Args));
535
536 std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI);
537 return CallResult.second;
538 }
539
540 SDValue XCoreTargetLowering::
LowerSMUL_LOHI(SDValue Op,SelectionDAG & DAG) const541 LowerSMUL_LOHI(SDValue Op, SelectionDAG &DAG) const
542 {
543 assert(Op.getValueType() == MVT::i32 && Op.getOpcode() == ISD::SMUL_LOHI &&
544 "Unexpected operand to lower!");
545 SDLoc dl(Op);
546 SDValue LHS = Op.getOperand(0);
547 SDValue RHS = Op.getOperand(1);
548 SDValue Zero = DAG.getConstant(0, dl, MVT::i32);
549 SDValue Hi = DAG.getNode(XCoreISD::MACCS, dl,
550 DAG.getVTList(MVT::i32, MVT::i32), Zero, Zero,
551 LHS, RHS);
552 SDValue Lo(Hi.getNode(), 1);
553 SDValue Ops[] = { Lo, Hi };
554 return DAG.getMergeValues(Ops, dl);
555 }
556
557 SDValue XCoreTargetLowering::
LowerUMUL_LOHI(SDValue Op,SelectionDAG & DAG) const558 LowerUMUL_LOHI(SDValue Op, SelectionDAG &DAG) const
559 {
560 assert(Op.getValueType() == MVT::i32 && Op.getOpcode() == ISD::UMUL_LOHI &&
561 "Unexpected operand to lower!");
562 SDLoc dl(Op);
563 SDValue LHS = Op.getOperand(0);
564 SDValue RHS = Op.getOperand(1);
565 SDValue Zero = DAG.getConstant(0, dl, MVT::i32);
566 SDValue Hi = DAG.getNode(XCoreISD::LMUL, dl,
567 DAG.getVTList(MVT::i32, MVT::i32), LHS, RHS,
568 Zero, Zero);
569 SDValue Lo(Hi.getNode(), 1);
570 SDValue Ops[] = { Lo, Hi };
571 return DAG.getMergeValues(Ops, dl);
572 }
573
574 /// isADDADDMUL - Return whether Op is in a form that is equivalent to
575 /// add(add(mul(x,y),a),b). If requireIntermediatesHaveOneUse is true then
576 /// each intermediate result in the calculation must also have a single use.
577 /// If the Op is in the correct form the constituent parts are written to Mul0,
578 /// Mul1, Addend0 and Addend1.
579 static bool
isADDADDMUL(SDValue Op,SDValue & Mul0,SDValue & Mul1,SDValue & Addend0,SDValue & Addend1,bool requireIntermediatesHaveOneUse)580 isADDADDMUL(SDValue Op, SDValue &Mul0, SDValue &Mul1, SDValue &Addend0,
581 SDValue &Addend1, bool requireIntermediatesHaveOneUse)
582 {
583 if (Op.getOpcode() != ISD::ADD)
584 return false;
585 SDValue N0 = Op.getOperand(0);
586 SDValue N1 = Op.getOperand(1);
587 SDValue AddOp;
588 SDValue OtherOp;
589 if (N0.getOpcode() == ISD::ADD) {
590 AddOp = N0;
591 OtherOp = N1;
592 } else if (N1.getOpcode() == ISD::ADD) {
593 AddOp = N1;
594 OtherOp = N0;
595 } else {
596 return false;
597 }
598 if (requireIntermediatesHaveOneUse && !AddOp.hasOneUse())
599 return false;
600 if (OtherOp.getOpcode() == ISD::MUL) {
601 // add(add(a,b),mul(x,y))
602 if (requireIntermediatesHaveOneUse && !OtherOp.hasOneUse())
603 return false;
604 Mul0 = OtherOp.getOperand(0);
605 Mul1 = OtherOp.getOperand(1);
606 Addend0 = AddOp.getOperand(0);
607 Addend1 = AddOp.getOperand(1);
608 return true;
609 }
610 if (AddOp.getOperand(0).getOpcode() == ISD::MUL) {
611 // add(add(mul(x,y),a),b)
612 if (requireIntermediatesHaveOneUse && !AddOp.getOperand(0).hasOneUse())
613 return false;
614 Mul0 = AddOp.getOperand(0).getOperand(0);
615 Mul1 = AddOp.getOperand(0).getOperand(1);
616 Addend0 = AddOp.getOperand(1);
617 Addend1 = OtherOp;
618 return true;
619 }
620 if (AddOp.getOperand(1).getOpcode() == ISD::MUL) {
621 // add(add(a,mul(x,y)),b)
622 if (requireIntermediatesHaveOneUse && !AddOp.getOperand(1).hasOneUse())
623 return false;
624 Mul0 = AddOp.getOperand(1).getOperand(0);
625 Mul1 = AddOp.getOperand(1).getOperand(1);
626 Addend0 = AddOp.getOperand(0);
627 Addend1 = OtherOp;
628 return true;
629 }
630 return false;
631 }
632
633 SDValue XCoreTargetLowering::
TryExpandADDWithMul(SDNode * N,SelectionDAG & DAG) const634 TryExpandADDWithMul(SDNode *N, SelectionDAG &DAG) const
635 {
636 SDValue Mul;
637 SDValue Other;
638 if (N->getOperand(0).getOpcode() == ISD::MUL) {
639 Mul = N->getOperand(0);
640 Other = N->getOperand(1);
641 } else if (N->getOperand(1).getOpcode() == ISD::MUL) {
642 Mul = N->getOperand(1);
643 Other = N->getOperand(0);
644 } else {
645 return SDValue();
646 }
647 SDLoc dl(N);
648 SDValue LL, RL, AddendL, AddendH;
649 LL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
650 Mul.getOperand(0), DAG.getConstant(0, dl, MVT::i32));
651 RL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
652 Mul.getOperand(1), DAG.getConstant(0, dl, MVT::i32));
653 AddendL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
654 Other, DAG.getConstant(0, dl, MVT::i32));
655 AddendH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
656 Other, DAG.getConstant(1, dl, MVT::i32));
657 APInt HighMask = APInt::getHighBitsSet(64, 32);
658 unsigned LHSSB = DAG.ComputeNumSignBits(Mul.getOperand(0));
659 unsigned RHSSB = DAG.ComputeNumSignBits(Mul.getOperand(1));
660 if (DAG.MaskedValueIsZero(Mul.getOperand(0), HighMask) &&
661 DAG.MaskedValueIsZero(Mul.getOperand(1), HighMask)) {
662 // The inputs are both zero-extended.
663 SDValue Hi = DAG.getNode(XCoreISD::MACCU, dl,
664 DAG.getVTList(MVT::i32, MVT::i32), AddendH,
665 AddendL, LL, RL);
666 SDValue Lo(Hi.getNode(), 1);
667 return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);
668 }
669 if (LHSSB > 32 && RHSSB > 32) {
670 // The inputs are both sign-extended.
671 SDValue Hi = DAG.getNode(XCoreISD::MACCS, dl,
672 DAG.getVTList(MVT::i32, MVT::i32), AddendH,
673 AddendL, LL, RL);
674 SDValue Lo(Hi.getNode(), 1);
675 return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);
676 }
677 SDValue LH, RH;
678 LH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
679 Mul.getOperand(0), DAG.getConstant(1, dl, MVT::i32));
680 RH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
681 Mul.getOperand(1), DAG.getConstant(1, dl, MVT::i32));
682 SDValue Hi = DAG.getNode(XCoreISD::MACCU, dl,
683 DAG.getVTList(MVT::i32, MVT::i32), AddendH,
684 AddendL, LL, RL);
685 SDValue Lo(Hi.getNode(), 1);
686 RH = DAG.getNode(ISD::MUL, dl, MVT::i32, LL, RH);
687 LH = DAG.getNode(ISD::MUL, dl, MVT::i32, LH, RL);
688 Hi = DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, RH);
689 Hi = DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, LH);
690 return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);
691 }
692
693 SDValue XCoreTargetLowering::
ExpandADDSUB(SDNode * N,SelectionDAG & DAG) const694 ExpandADDSUB(SDNode *N, SelectionDAG &DAG) const
695 {
696 assert(N->getValueType(0) == MVT::i64 &&
697 (N->getOpcode() == ISD::ADD || N->getOpcode() == ISD::SUB) &&
698 "Unknown operand to lower!");
699
700 if (N->getOpcode() == ISD::ADD)
701 if (SDValue Result = TryExpandADDWithMul(N, DAG))
702 return Result;
703
704 SDLoc dl(N);
705
706 // Extract components
707 SDValue LHSL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
708 N->getOperand(0),
709 DAG.getConstant(0, dl, MVT::i32));
710 SDValue LHSH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
711 N->getOperand(0),
712 DAG.getConstant(1, dl, MVT::i32));
713 SDValue RHSL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
714 N->getOperand(1),
715 DAG.getConstant(0, dl, MVT::i32));
716 SDValue RHSH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
717 N->getOperand(1),
718 DAG.getConstant(1, dl, MVT::i32));
719
720 // Expand
721 unsigned Opcode = (N->getOpcode() == ISD::ADD) ? XCoreISD::LADD :
722 XCoreISD::LSUB;
723 SDValue Zero = DAG.getConstant(0, dl, MVT::i32);
724 SDValue Lo = DAG.getNode(Opcode, dl, DAG.getVTList(MVT::i32, MVT::i32),
725 LHSL, RHSL, Zero);
726 SDValue Carry(Lo.getNode(), 1);
727
728 SDValue Hi = DAG.getNode(Opcode, dl, DAG.getVTList(MVT::i32, MVT::i32),
729 LHSH, RHSH, Carry);
730 SDValue Ignored(Hi.getNode(), 1);
731 // Merge the pieces
732 return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);
733 }
734
735 SDValue XCoreTargetLowering::
LowerVAARG(SDValue Op,SelectionDAG & DAG) const736 LowerVAARG(SDValue Op, SelectionDAG &DAG) const
737 {
738 // Whist llvm does not support aggregate varargs we can ignore
739 // the possibility of the ValueType being an implicit byVal vararg.
740 SDNode *Node = Op.getNode();
741 EVT VT = Node->getValueType(0); // not an aggregate
742 SDValue InChain = Node->getOperand(0);
743 SDValue VAListPtr = Node->getOperand(1);
744 EVT PtrVT = VAListPtr.getValueType();
745 const Value *SV = cast<SrcValueSDNode>(Node->getOperand(2))->getValue();
746 SDLoc dl(Node);
747 SDValue VAList =
748 DAG.getLoad(PtrVT, dl, InChain, VAListPtr, MachinePointerInfo(SV));
749 // Increment the pointer, VAList, to the next vararg
750 SDValue nextPtr = DAG.getNode(ISD::ADD, dl, PtrVT, VAList,
751 DAG.getIntPtrConstant(VT.getSizeInBits() / 8,
752 dl));
753 // Store the incremented VAList to the legalized pointer
754 InChain = DAG.getStore(VAList.getValue(1), dl, nextPtr, VAListPtr,
755 MachinePointerInfo(SV));
756 // Load the actual argument out of the pointer VAList
757 return DAG.getLoad(VT, dl, InChain, VAList, MachinePointerInfo());
758 }
759
760 SDValue XCoreTargetLowering::
LowerVASTART(SDValue Op,SelectionDAG & DAG) const761 LowerVASTART(SDValue Op, SelectionDAG &DAG) const
762 {
763 SDLoc dl(Op);
764 // vastart stores the address of the VarArgsFrameIndex slot into the
765 // memory location argument
766 MachineFunction &MF = DAG.getMachineFunction();
767 XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
768 SDValue Addr = DAG.getFrameIndex(XFI->getVarArgsFrameIndex(), MVT::i32);
769 return DAG.getStore(Op.getOperand(0), dl, Addr, Op.getOperand(1),
770 MachinePointerInfo());
771 }
772
LowerFRAMEADDR(SDValue Op,SelectionDAG & DAG) const773 SDValue XCoreTargetLowering::LowerFRAMEADDR(SDValue Op,
774 SelectionDAG &DAG) const {
775 // This nodes represent llvm.frameaddress on the DAG.
776 // It takes one operand, the index of the frame address to return.
777 // An index of zero corresponds to the current function's frame address.
778 // An index of one to the parent's frame address, and so on.
779 // Depths > 0 not supported yet!
780 if (cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() > 0)
781 return SDValue();
782
783 MachineFunction &MF = DAG.getMachineFunction();
784 const TargetRegisterInfo *RegInfo = Subtarget.getRegisterInfo();
785 return DAG.getCopyFromReg(DAG.getEntryNode(), SDLoc(Op),
786 RegInfo->getFrameRegister(MF), MVT::i32);
787 }
788
789 SDValue XCoreTargetLowering::
LowerRETURNADDR(SDValue Op,SelectionDAG & DAG) const790 LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const {
791 // This nodes represent llvm.returnaddress on the DAG.
792 // It takes one operand, the index of the return address to return.
793 // An index of zero corresponds to the current function's return address.
794 // An index of one to the parent's return address, and so on.
795 // Depths > 0 not supported yet!
796 if (cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() > 0)
797 return SDValue();
798
799 MachineFunction &MF = DAG.getMachineFunction();
800 XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
801 int FI = XFI->createLRSpillSlot(MF);
802 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
803 return DAG.getLoad(getPointerTy(DAG.getDataLayout()), SDLoc(Op),
804 DAG.getEntryNode(), FIN,
805 MachinePointerInfo::getFixedStack(MF, FI));
806 }
807
808 SDValue XCoreTargetLowering::
LowerFRAME_TO_ARGS_OFFSET(SDValue Op,SelectionDAG & DAG) const809 LowerFRAME_TO_ARGS_OFFSET(SDValue Op, SelectionDAG &DAG) const {
810 // This node represents offset from frame pointer to first on-stack argument.
811 // This is needed for correct stack adjustment during unwind.
812 // However, we don't know the offset until after the frame has be finalised.
813 // This is done during the XCoreFTAOElim pass.
814 return DAG.getNode(XCoreISD::FRAME_TO_ARGS_OFFSET, SDLoc(Op), MVT::i32);
815 }
816
817 SDValue XCoreTargetLowering::
LowerEH_RETURN(SDValue Op,SelectionDAG & DAG) const818 LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const {
819 // OUTCHAIN = EH_RETURN(INCHAIN, OFFSET, HANDLER)
820 // This node represents 'eh_return' gcc dwarf builtin, which is used to
821 // return from exception. The general meaning is: adjust stack by OFFSET and
822 // pass execution to HANDLER.
823 MachineFunction &MF = DAG.getMachineFunction();
824 SDValue Chain = Op.getOperand(0);
825 SDValue Offset = Op.getOperand(1);
826 SDValue Handler = Op.getOperand(2);
827 SDLoc dl(Op);
828
829 // Absolute SP = (FP + FrameToArgs) + Offset
830 const TargetRegisterInfo *RegInfo = Subtarget.getRegisterInfo();
831 SDValue Stack = DAG.getCopyFromReg(DAG.getEntryNode(), dl,
832 RegInfo->getFrameRegister(MF), MVT::i32);
833 SDValue FrameToArgs = DAG.getNode(XCoreISD::FRAME_TO_ARGS_OFFSET, dl,
834 MVT::i32);
835 Stack = DAG.getNode(ISD::ADD, dl, MVT::i32, Stack, FrameToArgs);
836 Stack = DAG.getNode(ISD::ADD, dl, MVT::i32, Stack, Offset);
837
838 // R0=ExceptionPointerRegister R1=ExceptionSelectorRegister
839 // which leaves 2 caller saved registers, R2 & R3 for us to use.
840 unsigned StackReg = XCore::R2;
841 unsigned HandlerReg = XCore::R3;
842
843 SDValue OutChains[] = {
844 DAG.getCopyToReg(Chain, dl, StackReg, Stack),
845 DAG.getCopyToReg(Chain, dl, HandlerReg, Handler)
846 };
847
848 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);
849
850 return DAG.getNode(XCoreISD::EH_RETURN, dl, MVT::Other, Chain,
851 DAG.getRegister(StackReg, MVT::i32),
852 DAG.getRegister(HandlerReg, MVT::i32));
853
854 }
855
856 SDValue XCoreTargetLowering::
LowerADJUST_TRAMPOLINE(SDValue Op,SelectionDAG & DAG) const857 LowerADJUST_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const {
858 return Op.getOperand(0);
859 }
860
861 SDValue XCoreTargetLowering::
LowerINIT_TRAMPOLINE(SDValue Op,SelectionDAG & DAG) const862 LowerINIT_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const {
863 SDValue Chain = Op.getOperand(0);
864 SDValue Trmp = Op.getOperand(1); // trampoline
865 SDValue FPtr = Op.getOperand(2); // nested function
866 SDValue Nest = Op.getOperand(3); // 'nest' parameter value
867
868 const Value *TrmpAddr = cast<SrcValueSDNode>(Op.getOperand(4))->getValue();
869
870 // .align 4
871 // LDAPF_u10 r11, nest
872 // LDW_2rus r11, r11[0]
873 // STWSP_ru6 r11, sp[0]
874 // LDAPF_u10 r11, fptr
875 // LDW_2rus r11, r11[0]
876 // BAU_1r r11
877 // nest:
878 // .word nest
879 // fptr:
880 // .word fptr
881 SDValue OutChains[5];
882
883 SDValue Addr = Trmp;
884
885 SDLoc dl(Op);
886 OutChains[0] =
887 DAG.getStore(Chain, dl, DAG.getConstant(0x0a3cd805, dl, MVT::i32), Addr,
888 MachinePointerInfo(TrmpAddr));
889
890 Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp,
891 DAG.getConstant(4, dl, MVT::i32));
892 OutChains[1] =
893 DAG.getStore(Chain, dl, DAG.getConstant(0xd80456c0, dl, MVT::i32), Addr,
894 MachinePointerInfo(TrmpAddr, 4));
895
896 Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp,
897 DAG.getConstant(8, dl, MVT::i32));
898 OutChains[2] =
899 DAG.getStore(Chain, dl, DAG.getConstant(0x27fb0a3c, dl, MVT::i32), Addr,
900 MachinePointerInfo(TrmpAddr, 8));
901
902 Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp,
903 DAG.getConstant(12, dl, MVT::i32));
904 OutChains[3] =
905 DAG.getStore(Chain, dl, Nest, Addr, MachinePointerInfo(TrmpAddr, 12));
906
907 Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp,
908 DAG.getConstant(16, dl, MVT::i32));
909 OutChains[4] =
910 DAG.getStore(Chain, dl, FPtr, Addr, MachinePointerInfo(TrmpAddr, 16));
911
912 return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);
913 }
914
915 SDValue XCoreTargetLowering::
LowerINTRINSIC_WO_CHAIN(SDValue Op,SelectionDAG & DAG) const916 LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const {
917 SDLoc DL(Op);
918 unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
919 switch (IntNo) {
920 case Intrinsic::xcore_crc8:
921 EVT VT = Op.getValueType();
922 SDValue Data =
923 DAG.getNode(XCoreISD::CRC8, DL, DAG.getVTList(VT, VT),
924 Op.getOperand(1), Op.getOperand(2) , Op.getOperand(3));
925 SDValue Crc(Data.getNode(), 1);
926 SDValue Results[] = { Crc, Data };
927 return DAG.getMergeValues(Results, DL);
928 }
929 return SDValue();
930 }
931
932 SDValue XCoreTargetLowering::
LowerATOMIC_FENCE(SDValue Op,SelectionDAG & DAG) const933 LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG) const {
934 SDLoc DL(Op);
935 return DAG.getNode(XCoreISD::MEMBARRIER, DL, MVT::Other, Op.getOperand(0));
936 }
937
938 SDValue XCoreTargetLowering::
LowerATOMIC_LOAD(SDValue Op,SelectionDAG & DAG) const939 LowerATOMIC_LOAD(SDValue Op, SelectionDAG &DAG) const {
940 AtomicSDNode *N = cast<AtomicSDNode>(Op);
941 assert(N->getOpcode() == ISD::ATOMIC_LOAD && "Bad Atomic OP");
942 assert((N->getOrdering() == AtomicOrdering::Unordered ||
943 N->getOrdering() == AtomicOrdering::Monotonic) &&
944 "setInsertFencesForAtomic(true) expects unordered / monotonic");
945 if (N->getMemoryVT() == MVT::i32) {
946 if (N->getAlignment() < 4)
947 report_fatal_error("atomic load must be aligned");
948 return DAG.getLoad(getPointerTy(DAG.getDataLayout()), SDLoc(Op),
949 N->getChain(), N->getBasePtr(), N->getPointerInfo(),
950 N->getAlignment(), N->getMemOperand()->getFlags(),
951 N->getAAInfo(), N->getRanges());
952 }
953 if (N->getMemoryVT() == MVT::i16) {
954 if (N->getAlignment() < 2)
955 report_fatal_error("atomic load must be aligned");
956 return DAG.getExtLoad(ISD::EXTLOAD, SDLoc(Op), MVT::i32, N->getChain(),
957 N->getBasePtr(), N->getPointerInfo(), MVT::i16,
958 N->getAlignment(), N->getMemOperand()->getFlags(),
959 N->getAAInfo());
960 }
961 if (N->getMemoryVT() == MVT::i8)
962 return DAG.getExtLoad(ISD::EXTLOAD, SDLoc(Op), MVT::i32, N->getChain(),
963 N->getBasePtr(), N->getPointerInfo(), MVT::i8,
964 N->getAlignment(), N->getMemOperand()->getFlags(),
965 N->getAAInfo());
966 return SDValue();
967 }
968
969 SDValue XCoreTargetLowering::
LowerATOMIC_STORE(SDValue Op,SelectionDAG & DAG) const970 LowerATOMIC_STORE(SDValue Op, SelectionDAG &DAG) const {
971 AtomicSDNode *N = cast<AtomicSDNode>(Op);
972 assert(N->getOpcode() == ISD::ATOMIC_STORE && "Bad Atomic OP");
973 assert((N->getOrdering() == AtomicOrdering::Unordered ||
974 N->getOrdering() == AtomicOrdering::Monotonic) &&
975 "setInsertFencesForAtomic(true) expects unordered / monotonic");
976 if (N->getMemoryVT() == MVT::i32) {
977 if (N->getAlignment() < 4)
978 report_fatal_error("atomic store must be aligned");
979 return DAG.getStore(N->getChain(), SDLoc(Op), N->getVal(), N->getBasePtr(),
980 N->getPointerInfo(), N->getAlignment(),
981 N->getMemOperand()->getFlags(), N->getAAInfo());
982 }
983 if (N->getMemoryVT() == MVT::i16) {
984 if (N->getAlignment() < 2)
985 report_fatal_error("atomic store must be aligned");
986 return DAG.getTruncStore(N->getChain(), SDLoc(Op), N->getVal(),
987 N->getBasePtr(), N->getPointerInfo(), MVT::i16,
988 N->getAlignment(), N->getMemOperand()->getFlags(),
989 N->getAAInfo());
990 }
991 if (N->getMemoryVT() == MVT::i8)
992 return DAG.getTruncStore(N->getChain(), SDLoc(Op), N->getVal(),
993 N->getBasePtr(), N->getPointerInfo(), MVT::i8,
994 N->getAlignment(), N->getMemOperand()->getFlags(),
995 N->getAAInfo());
996 return SDValue();
997 }
998
999 MachineMemOperand::Flags
getTargetMMOFlags(const Instruction & I) const1000 XCoreTargetLowering::getTargetMMOFlags(const Instruction &I) const {
1001 // Because of how we convert atomic_load and atomic_store to normal loads and
1002 // stores in the DAG, we need to ensure that the MMOs are marked volatile
1003 // since DAGCombine hasn't been updated to account for atomic, but non
1004 // volatile loads. (See D57601)
1005 if (auto *SI = dyn_cast<StoreInst>(&I))
1006 if (SI->isAtomic())
1007 return MachineMemOperand::MOVolatile;
1008 if (auto *LI = dyn_cast<LoadInst>(&I))
1009 if (LI->isAtomic())
1010 return MachineMemOperand::MOVolatile;
1011 if (auto *AI = dyn_cast<AtomicRMWInst>(&I))
1012 if (AI->isAtomic())
1013 return MachineMemOperand::MOVolatile;
1014 if (auto *AI = dyn_cast<AtomicCmpXchgInst>(&I))
1015 if (AI->isAtomic())
1016 return MachineMemOperand::MOVolatile;
1017 return MachineMemOperand::MONone;
1018 }
1019
1020 //===----------------------------------------------------------------------===//
1021 // Calling Convention Implementation
1022 //===----------------------------------------------------------------------===//
1023
1024 #include "XCoreGenCallingConv.inc"
1025
1026 //===----------------------------------------------------------------------===//
1027 // Call Calling Convention Implementation
1028 //===----------------------------------------------------------------------===//
1029
1030 /// XCore call implementation
1031 SDValue
LowerCall(TargetLowering::CallLoweringInfo & CLI,SmallVectorImpl<SDValue> & InVals) const1032 XCoreTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
1033 SmallVectorImpl<SDValue> &InVals) const {
1034 SelectionDAG &DAG = CLI.DAG;
1035 SDLoc &dl = CLI.DL;
1036 SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
1037 SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
1038 SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
1039 SDValue Chain = CLI.Chain;
1040 SDValue Callee = CLI.Callee;
1041 bool &isTailCall = CLI.IsTailCall;
1042 CallingConv::ID CallConv = CLI.CallConv;
1043 bool isVarArg = CLI.IsVarArg;
1044
1045 // XCore target does not yet support tail call optimization.
1046 isTailCall = false;
1047
1048 // For now, only CallingConv::C implemented
1049 switch (CallConv)
1050 {
1051 default:
1052 report_fatal_error("Unsupported calling convention");
1053 case CallingConv::Fast:
1054 case CallingConv::C:
1055 return LowerCCCCallTo(Chain, Callee, CallConv, isVarArg, isTailCall,
1056 Outs, OutVals, Ins, dl, DAG, InVals);
1057 }
1058 }
1059
1060 /// LowerCallResult - Lower the result values of a call into the
1061 /// appropriate copies out of appropriate physical registers / memory locations.
LowerCallResult(SDValue Chain,SDValue InFlag,const SmallVectorImpl<CCValAssign> & RVLocs,const SDLoc & dl,SelectionDAG & DAG,SmallVectorImpl<SDValue> & InVals)1062 static SDValue LowerCallResult(SDValue Chain, SDValue InFlag,
1063 const SmallVectorImpl<CCValAssign> &RVLocs,
1064 const SDLoc &dl, SelectionDAG &DAG,
1065 SmallVectorImpl<SDValue> &InVals) {
1066 SmallVector<std::pair<int, unsigned>, 4> ResultMemLocs;
1067 // Copy results out of physical registers.
1068 for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
1069 const CCValAssign &VA = RVLocs[i];
1070 if (VA.isRegLoc()) {
1071 Chain = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getValVT(),
1072 InFlag).getValue(1);
1073 InFlag = Chain.getValue(2);
1074 InVals.push_back(Chain.getValue(0));
1075 } else {
1076 assert(VA.isMemLoc());
1077 ResultMemLocs.push_back(std::make_pair(VA.getLocMemOffset(),
1078 InVals.size()));
1079 // Reserve space for this result.
1080 InVals.push_back(SDValue());
1081 }
1082 }
1083
1084 // Copy results out of memory.
1085 SmallVector<SDValue, 4> MemOpChains;
1086 for (unsigned i = 0, e = ResultMemLocs.size(); i != e; ++i) {
1087 int offset = ResultMemLocs[i].first;
1088 unsigned index = ResultMemLocs[i].second;
1089 SDVTList VTs = DAG.getVTList(MVT::i32, MVT::Other);
1090 SDValue Ops[] = { Chain, DAG.getConstant(offset / 4, dl, MVT::i32) };
1091 SDValue load = DAG.getNode(XCoreISD::LDWSP, dl, VTs, Ops);
1092 InVals[index] = load;
1093 MemOpChains.push_back(load.getValue(1));
1094 }
1095
1096 // Transform all loads nodes into one single node because
1097 // all load nodes are independent of each other.
1098 if (!MemOpChains.empty())
1099 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
1100
1101 return Chain;
1102 }
1103
1104 /// LowerCCCCallTo - functions arguments are copied from virtual
1105 /// regs to (physical regs)/(stack frame), CALLSEQ_START and
1106 /// CALLSEQ_END are emitted.
1107 /// TODO: isTailCall, sret.
LowerCCCCallTo(SDValue Chain,SDValue Callee,CallingConv::ID CallConv,bool isVarArg,bool isTailCall,const SmallVectorImpl<ISD::OutputArg> & Outs,const SmallVectorImpl<SDValue> & OutVals,const SmallVectorImpl<ISD::InputArg> & Ins,const SDLoc & dl,SelectionDAG & DAG,SmallVectorImpl<SDValue> & InVals) const1108 SDValue XCoreTargetLowering::LowerCCCCallTo(
1109 SDValue Chain, SDValue Callee, CallingConv::ID CallConv, bool isVarArg,
1110 bool isTailCall, const SmallVectorImpl<ISD::OutputArg> &Outs,
1111 const SmallVectorImpl<SDValue> &OutVals,
1112 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
1113 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
1114
1115 // Analyze operands of the call, assigning locations to each operand.
1116 SmallVector<CCValAssign, 16> ArgLocs;
1117 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
1118 *DAG.getContext());
1119
1120 // The ABI dictates there should be one stack slot available to the callee
1121 // on function entry (for saving lr).
1122 CCInfo.AllocateStack(4, Align(4));
1123
1124 CCInfo.AnalyzeCallOperands(Outs, CC_XCore);
1125
1126 SmallVector<CCValAssign, 16> RVLocs;
1127 // Analyze return values to determine the number of bytes of stack required.
1128 CCState RetCCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
1129 *DAG.getContext());
1130 RetCCInfo.AllocateStack(CCInfo.getNextStackOffset(), Align(4));
1131 RetCCInfo.AnalyzeCallResult(Ins, RetCC_XCore);
1132
1133 // Get a count of how many bytes are to be pushed on the stack.
1134 unsigned NumBytes = RetCCInfo.getNextStackOffset();
1135 auto PtrVT = getPointerTy(DAG.getDataLayout());
1136
1137 Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, dl);
1138
1139 SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass;
1140 SmallVector<SDValue, 12> MemOpChains;
1141
1142 // Walk the register/memloc assignments, inserting copies/loads.
1143 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
1144 CCValAssign &VA = ArgLocs[i];
1145 SDValue Arg = OutVals[i];
1146
1147 // Promote the value if needed.
1148 switch (VA.getLocInfo()) {
1149 default: llvm_unreachable("Unknown loc info!");
1150 case CCValAssign::Full: break;
1151 case CCValAssign::SExt:
1152 Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);
1153 break;
1154 case CCValAssign::ZExt:
1155 Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);
1156 break;
1157 case CCValAssign::AExt:
1158 Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);
1159 break;
1160 }
1161
1162 // Arguments that can be passed on register must be kept at
1163 // RegsToPass vector
1164 if (VA.isRegLoc()) {
1165 RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
1166 } else {
1167 assert(VA.isMemLoc());
1168
1169 int Offset = VA.getLocMemOffset();
1170
1171 MemOpChains.push_back(DAG.getNode(XCoreISD::STWSP, dl, MVT::Other,
1172 Chain, Arg,
1173 DAG.getConstant(Offset/4, dl,
1174 MVT::i32)));
1175 }
1176 }
1177
1178 // Transform all store nodes into one single node because
1179 // all store nodes are independent of each other.
1180 if (!MemOpChains.empty())
1181 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
1182
1183 // Build a sequence of copy-to-reg nodes chained together with token
1184 // chain and flag operands which copy the outgoing args into registers.
1185 // The InFlag in necessary since all emitted instructions must be
1186 // stuck together.
1187 SDValue InFlag;
1188 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1189 Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
1190 RegsToPass[i].second, InFlag);
1191 InFlag = Chain.getValue(1);
1192 }
1193
1194 // If the callee is a GlobalAddress node (quite common, every direct call is)
1195 // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
1196 // Likewise ExternalSymbol -> TargetExternalSymbol.
1197 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
1198 Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32);
1199 else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
1200 Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32);
1201
1202 // XCoreBranchLink = #chain, #target_address, #opt_in_flags...
1203 // = Chain, Callee, Reg#1, Reg#2, ...
1204 //
1205 // Returns a chain & a flag for retval copy to use.
1206 SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
1207 SmallVector<SDValue, 8> Ops;
1208 Ops.push_back(Chain);
1209 Ops.push_back(Callee);
1210
1211 // Add argument registers to the end of the list so that they are
1212 // known live into the call.
1213 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
1214 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
1215 RegsToPass[i].second.getValueType()));
1216
1217 if (InFlag.getNode())
1218 Ops.push_back(InFlag);
1219
1220 Chain = DAG.getNode(XCoreISD::BL, dl, NodeTys, Ops);
1221 InFlag = Chain.getValue(1);
1222
1223 // Create the CALLSEQ_END node.
1224 Chain = DAG.getCALLSEQ_END(Chain, DAG.getConstant(NumBytes, dl, PtrVT, true),
1225 DAG.getConstant(0, dl, PtrVT, true), InFlag, dl);
1226 InFlag = Chain.getValue(1);
1227
1228 // Handle result values, copying them out of physregs into vregs that we
1229 // return.
1230 return LowerCallResult(Chain, InFlag, RVLocs, dl, DAG, InVals);
1231 }
1232
1233 //===----------------------------------------------------------------------===//
1234 // Formal Arguments Calling Convention Implementation
1235 //===----------------------------------------------------------------------===//
1236
1237 namespace {
1238 struct ArgDataPair { SDValue SDV; ISD::ArgFlagsTy Flags; };
1239 }
1240
1241 /// XCore formal arguments implementation
LowerFormalArguments(SDValue Chain,CallingConv::ID CallConv,bool isVarArg,const SmallVectorImpl<ISD::InputArg> & Ins,const SDLoc & dl,SelectionDAG & DAG,SmallVectorImpl<SDValue> & InVals) const1242 SDValue XCoreTargetLowering::LowerFormalArguments(
1243 SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
1244 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
1245 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
1246 switch (CallConv)
1247 {
1248 default:
1249 report_fatal_error("Unsupported calling convention");
1250 case CallingConv::C:
1251 case CallingConv::Fast:
1252 return LowerCCCArguments(Chain, CallConv, isVarArg,
1253 Ins, dl, DAG, InVals);
1254 }
1255 }
1256
1257 /// LowerCCCArguments - transform physical registers into
1258 /// virtual registers and generate load operations for
1259 /// arguments places on the stack.
1260 /// TODO: sret
LowerCCCArguments(SDValue Chain,CallingConv::ID CallConv,bool isVarArg,const SmallVectorImpl<ISD::InputArg> & Ins,const SDLoc & dl,SelectionDAG & DAG,SmallVectorImpl<SDValue> & InVals) const1261 SDValue XCoreTargetLowering::LowerCCCArguments(
1262 SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
1263 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
1264 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
1265 MachineFunction &MF = DAG.getMachineFunction();
1266 MachineFrameInfo &MFI = MF.getFrameInfo();
1267 MachineRegisterInfo &RegInfo = MF.getRegInfo();
1268 XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
1269
1270 // Assign locations to all of the incoming arguments.
1271 SmallVector<CCValAssign, 16> ArgLocs;
1272 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
1273 *DAG.getContext());
1274
1275 CCInfo.AnalyzeFormalArguments(Ins, CC_XCore);
1276
1277 unsigned StackSlotSize = XCoreFrameLowering::stackSlotSize();
1278
1279 unsigned LRSaveSize = StackSlotSize;
1280
1281 if (!isVarArg)
1282 XFI->setReturnStackOffset(CCInfo.getNextStackOffset() + LRSaveSize);
1283
1284 // All getCopyFromReg ops must precede any getMemcpys to prevent the
1285 // scheduler clobbering a register before it has been copied.
1286 // The stages are:
1287 // 1. CopyFromReg (and load) arg & vararg registers.
1288 // 2. Chain CopyFromReg nodes into a TokenFactor.
1289 // 3. Memcpy 'byVal' args & push final InVals.
1290 // 4. Chain mem ops nodes into a TokenFactor.
1291 SmallVector<SDValue, 4> CFRegNode;
1292 SmallVector<ArgDataPair, 4> ArgData;
1293 SmallVector<SDValue, 4> MemOps;
1294
1295 // 1a. CopyFromReg (and load) arg registers.
1296 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
1297
1298 CCValAssign &VA = ArgLocs[i];
1299 SDValue ArgIn;
1300
1301 if (VA.isRegLoc()) {
1302 // Arguments passed in registers
1303 EVT RegVT = VA.getLocVT();
1304 switch (RegVT.getSimpleVT().SimpleTy) {
1305 default:
1306 {
1307 #ifndef NDEBUG
1308 errs() << "LowerFormalArguments Unhandled argument type: "
1309 << RegVT.getEVTString() << "\n";
1310 #endif
1311 llvm_unreachable(nullptr);
1312 }
1313 case MVT::i32:
1314 Register VReg = RegInfo.createVirtualRegister(&XCore::GRRegsRegClass);
1315 RegInfo.addLiveIn(VA.getLocReg(), VReg);
1316 ArgIn = DAG.getCopyFromReg(Chain, dl, VReg, RegVT);
1317 CFRegNode.push_back(ArgIn.getValue(ArgIn->getNumValues() - 1));
1318 }
1319 } else {
1320 // sanity check
1321 assert(VA.isMemLoc());
1322 // Load the argument to a virtual register
1323 unsigned ObjSize = VA.getLocVT().getSizeInBits()/8;
1324 if (ObjSize > StackSlotSize) {
1325 errs() << "LowerFormalArguments Unhandled argument type: "
1326 << EVT(VA.getLocVT()).getEVTString()
1327 << "\n";
1328 }
1329 // Create the frame index object for this incoming parameter...
1330 int FI = MFI.CreateFixedObject(ObjSize,
1331 LRSaveSize + VA.getLocMemOffset(),
1332 true);
1333
1334 // Create the SelectionDAG nodes corresponding to a load
1335 //from this parameter
1336 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
1337 ArgIn = DAG.getLoad(VA.getLocVT(), dl, Chain, FIN,
1338 MachinePointerInfo::getFixedStack(MF, FI));
1339 }
1340 const ArgDataPair ADP = { ArgIn, Ins[i].Flags };
1341 ArgData.push_back(ADP);
1342 }
1343
1344 // 1b. CopyFromReg vararg registers.
1345 if (isVarArg) {
1346 // Argument registers
1347 static const MCPhysReg ArgRegs[] = {
1348 XCore::R0, XCore::R1, XCore::R2, XCore::R3
1349 };
1350 XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
1351 unsigned FirstVAReg = CCInfo.getFirstUnallocated(ArgRegs);
1352 if (FirstVAReg < array_lengthof(ArgRegs)) {
1353 int offset = 0;
1354 // Save remaining registers, storing higher register numbers at a higher
1355 // address
1356 for (int i = array_lengthof(ArgRegs) - 1; i >= (int)FirstVAReg; --i) {
1357 // Create a stack slot
1358 int FI = MFI.CreateFixedObject(4, offset, true);
1359 if (i == (int)FirstVAReg) {
1360 XFI->setVarArgsFrameIndex(FI);
1361 }
1362 offset -= StackSlotSize;
1363 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
1364 // Move argument from phys reg -> virt reg
1365 Register VReg = RegInfo.createVirtualRegister(&XCore::GRRegsRegClass);
1366 RegInfo.addLiveIn(ArgRegs[i], VReg);
1367 SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
1368 CFRegNode.push_back(Val.getValue(Val->getNumValues() - 1));
1369 // Move argument from virt reg -> stack
1370 SDValue Store =
1371 DAG.getStore(Val.getValue(1), dl, Val, FIN, MachinePointerInfo());
1372 MemOps.push_back(Store);
1373 }
1374 } else {
1375 // This will point to the next argument passed via stack.
1376 XFI->setVarArgsFrameIndex(
1377 MFI.CreateFixedObject(4, LRSaveSize + CCInfo.getNextStackOffset(),
1378 true));
1379 }
1380 }
1381
1382 // 2. chain CopyFromReg nodes into a TokenFactor.
1383 if (!CFRegNode.empty())
1384 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, CFRegNode);
1385
1386 // 3. Memcpy 'byVal' args & push final InVals.
1387 // Aggregates passed "byVal" need to be copied by the callee.
1388 // The callee will use a pointer to this copy, rather than the original
1389 // pointer.
1390 for (SmallVectorImpl<ArgDataPair>::const_iterator ArgDI = ArgData.begin(),
1391 ArgDE = ArgData.end();
1392 ArgDI != ArgDE; ++ArgDI) {
1393 if (ArgDI->Flags.isByVal() && ArgDI->Flags.getByValSize()) {
1394 unsigned Size = ArgDI->Flags.getByValSize();
1395 Align Alignment =
1396 std::max(Align(StackSlotSize), ArgDI->Flags.getNonZeroByValAlign());
1397 // Create a new object on the stack and copy the pointee into it.
1398 int FI = MFI.CreateStackObject(Size, Alignment, false);
1399 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
1400 InVals.push_back(FIN);
1401 MemOps.push_back(DAG.getMemcpy(
1402 Chain, dl, FIN, ArgDI->SDV, DAG.getConstant(Size, dl, MVT::i32),
1403 Alignment, false, false, false, MachinePointerInfo(),
1404 MachinePointerInfo()));
1405 } else {
1406 InVals.push_back(ArgDI->SDV);
1407 }
1408 }
1409
1410 // 4, chain mem ops nodes into a TokenFactor.
1411 if (!MemOps.empty()) {
1412 MemOps.push_back(Chain);
1413 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOps);
1414 }
1415
1416 return Chain;
1417 }
1418
1419 //===----------------------------------------------------------------------===//
1420 // Return Value Calling Convention Implementation
1421 //===----------------------------------------------------------------------===//
1422
1423 bool XCoreTargetLowering::
CanLowerReturn(CallingConv::ID CallConv,MachineFunction & MF,bool isVarArg,const SmallVectorImpl<ISD::OutputArg> & Outs,LLVMContext & Context) const1424 CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
1425 bool isVarArg,
1426 const SmallVectorImpl<ISD::OutputArg> &Outs,
1427 LLVMContext &Context) const {
1428 SmallVector<CCValAssign, 16> RVLocs;
1429 CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context);
1430 if (!CCInfo.CheckReturn(Outs, RetCC_XCore))
1431 return false;
1432 if (CCInfo.getNextStackOffset() != 0 && isVarArg)
1433 return false;
1434 return true;
1435 }
1436
1437 SDValue
LowerReturn(SDValue Chain,CallingConv::ID CallConv,bool isVarArg,const SmallVectorImpl<ISD::OutputArg> & Outs,const SmallVectorImpl<SDValue> & OutVals,const SDLoc & dl,SelectionDAG & DAG) const1438 XCoreTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
1439 bool isVarArg,
1440 const SmallVectorImpl<ISD::OutputArg> &Outs,
1441 const SmallVectorImpl<SDValue> &OutVals,
1442 const SDLoc &dl, SelectionDAG &DAG) const {
1443
1444 XCoreFunctionInfo *XFI =
1445 DAG.getMachineFunction().getInfo<XCoreFunctionInfo>();
1446 MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
1447
1448 // CCValAssign - represent the assignment of
1449 // the return value to a location
1450 SmallVector<CCValAssign, 16> RVLocs;
1451
1452 // CCState - Info about the registers and stack slot.
1453 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
1454 *DAG.getContext());
1455
1456 // Analyze return values.
1457 if (!isVarArg)
1458 CCInfo.AllocateStack(XFI->getReturnStackOffset(), Align(4));
1459
1460 CCInfo.AnalyzeReturn(Outs, RetCC_XCore);
1461
1462 SDValue Flag;
1463 SmallVector<SDValue, 4> RetOps(1, Chain);
1464
1465 // Return on XCore is always a "retsp 0"
1466 RetOps.push_back(DAG.getConstant(0, dl, MVT::i32));
1467
1468 SmallVector<SDValue, 4> MemOpChains;
1469 // Handle return values that must be copied to memory.
1470 for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
1471 CCValAssign &VA = RVLocs[i];
1472 if (VA.isRegLoc())
1473 continue;
1474 assert(VA.isMemLoc());
1475 if (isVarArg) {
1476 report_fatal_error("Can't return value from vararg function in memory");
1477 }
1478
1479 int Offset = VA.getLocMemOffset();
1480 unsigned ObjSize = VA.getLocVT().getSizeInBits() / 8;
1481 // Create the frame index object for the memory location.
1482 int FI = MFI.CreateFixedObject(ObjSize, Offset, false);
1483
1484 // Create a SelectionDAG node corresponding to a store
1485 // to this memory location.
1486 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
1487 MemOpChains.push_back(DAG.getStore(
1488 Chain, dl, OutVals[i], FIN,
1489 MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI)));
1490 }
1491
1492 // Transform all store nodes into one single node because
1493 // all stores are independent of each other.
1494 if (!MemOpChains.empty())
1495 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
1496
1497 // Now handle return values copied to registers.
1498 for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
1499 CCValAssign &VA = RVLocs[i];
1500 if (!VA.isRegLoc())
1501 continue;
1502 // Copy the result values into the output registers.
1503 Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Flag);
1504
1505 // guarantee that all emitted copies are
1506 // stuck together, avoiding something bad
1507 Flag = Chain.getValue(1);
1508 RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
1509 }
1510
1511 RetOps[0] = Chain; // Update chain.
1512
1513 // Add the flag if we have it.
1514 if (Flag.getNode())
1515 RetOps.push_back(Flag);
1516
1517 return DAG.getNode(XCoreISD::RETSP, dl, MVT::Other, RetOps);
1518 }
1519
1520 //===----------------------------------------------------------------------===//
1521 // Other Lowering Code
1522 //===----------------------------------------------------------------------===//
1523
1524 MachineBasicBlock *
EmitInstrWithCustomInserter(MachineInstr & MI,MachineBasicBlock * BB) const1525 XCoreTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
1526 MachineBasicBlock *BB) const {
1527 const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
1528 DebugLoc dl = MI.getDebugLoc();
1529 assert((MI.getOpcode() == XCore::SELECT_CC) &&
1530 "Unexpected instr type to insert");
1531
1532 // To "insert" a SELECT_CC instruction, we actually have to insert the diamond
1533 // control-flow pattern. The incoming instruction knows the destination vreg
1534 // to set, the condition code register to branch on, the true/false values to
1535 // select between, and a branch opcode to use.
1536 const BasicBlock *LLVM_BB = BB->getBasicBlock();
1537 MachineFunction::iterator It = ++BB->getIterator();
1538
1539 // thisMBB:
1540 // ...
1541 // TrueVal = ...
1542 // cmpTY ccX, r1, r2
1543 // bCC copy1MBB
1544 // fallthrough --> copy0MBB
1545 MachineBasicBlock *thisMBB = BB;
1546 MachineFunction *F = BB->getParent();
1547 MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
1548 MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
1549 F->insert(It, copy0MBB);
1550 F->insert(It, sinkMBB);
1551
1552 // Transfer the remainder of BB and its successor edges to sinkMBB.
1553 sinkMBB->splice(sinkMBB->begin(), BB,
1554 std::next(MachineBasicBlock::iterator(MI)), BB->end());
1555 sinkMBB->transferSuccessorsAndUpdatePHIs(BB);
1556
1557 // Next, add the true and fallthrough blocks as its successors.
1558 BB->addSuccessor(copy0MBB);
1559 BB->addSuccessor(sinkMBB);
1560
1561 BuildMI(BB, dl, TII.get(XCore::BRFT_lru6))
1562 .addReg(MI.getOperand(1).getReg())
1563 .addMBB(sinkMBB);
1564
1565 // copy0MBB:
1566 // %FalseValue = ...
1567 // # fallthrough to sinkMBB
1568 BB = copy0MBB;
1569
1570 // Update machine-CFG edges
1571 BB->addSuccessor(sinkMBB);
1572
1573 // sinkMBB:
1574 // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ]
1575 // ...
1576 BB = sinkMBB;
1577 BuildMI(*BB, BB->begin(), dl, TII.get(XCore::PHI), MI.getOperand(0).getReg())
1578 .addReg(MI.getOperand(3).getReg())
1579 .addMBB(copy0MBB)
1580 .addReg(MI.getOperand(2).getReg())
1581 .addMBB(thisMBB);
1582
1583 MI.eraseFromParent(); // The pseudo instruction is gone now.
1584 return BB;
1585 }
1586
1587 //===----------------------------------------------------------------------===//
1588 // Target Optimization Hooks
1589 //===----------------------------------------------------------------------===//
1590
PerformDAGCombine(SDNode * N,DAGCombinerInfo & DCI) const1591 SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N,
1592 DAGCombinerInfo &DCI) const {
1593 SelectionDAG &DAG = DCI.DAG;
1594 SDLoc dl(N);
1595 switch (N->getOpcode()) {
1596 default: break;
1597 case ISD::INTRINSIC_VOID:
1598 switch (cast<ConstantSDNode>(N->getOperand(1))->getZExtValue()) {
1599 case Intrinsic::xcore_outt:
1600 case Intrinsic::xcore_outct:
1601 case Intrinsic::xcore_chkct: {
1602 SDValue OutVal = N->getOperand(3);
1603 // These instructions ignore the high bits.
1604 if (OutVal.hasOneUse()) {
1605 unsigned BitWidth = OutVal.getValueSizeInBits();
1606 APInt DemandedMask = APInt::getLowBitsSet(BitWidth, 8);
1607 KnownBits Known;
1608 TargetLowering::TargetLoweringOpt TLO(DAG, !DCI.isBeforeLegalize(),
1609 !DCI.isBeforeLegalizeOps());
1610 const TargetLowering &TLI = DAG.getTargetLoweringInfo();
1611 if (TLI.ShrinkDemandedConstant(OutVal, DemandedMask, TLO) ||
1612 TLI.SimplifyDemandedBits(OutVal, DemandedMask, Known, TLO))
1613 DCI.CommitTargetLoweringOpt(TLO);
1614 }
1615 break;
1616 }
1617 case Intrinsic::xcore_setpt: {
1618 SDValue Time = N->getOperand(3);
1619 // This instruction ignores the high bits.
1620 if (Time.hasOneUse()) {
1621 unsigned BitWidth = Time.getValueSizeInBits();
1622 APInt DemandedMask = APInt::getLowBitsSet(BitWidth, 16);
1623 KnownBits Known;
1624 TargetLowering::TargetLoweringOpt TLO(DAG, !DCI.isBeforeLegalize(),
1625 !DCI.isBeforeLegalizeOps());
1626 const TargetLowering &TLI = DAG.getTargetLoweringInfo();
1627 if (TLI.ShrinkDemandedConstant(Time, DemandedMask, TLO) ||
1628 TLI.SimplifyDemandedBits(Time, DemandedMask, Known, TLO))
1629 DCI.CommitTargetLoweringOpt(TLO);
1630 }
1631 break;
1632 }
1633 }
1634 break;
1635 case XCoreISD::LADD: {
1636 SDValue N0 = N->getOperand(0);
1637 SDValue N1 = N->getOperand(1);
1638 SDValue N2 = N->getOperand(2);
1639 ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
1640 ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
1641 EVT VT = N0.getValueType();
1642
1643 // canonicalize constant to RHS
1644 if (N0C && !N1C)
1645 return DAG.getNode(XCoreISD::LADD, dl, DAG.getVTList(VT, VT), N1, N0, N2);
1646
1647 // fold (ladd 0, 0, x) -> 0, x & 1
1648 if (N0C && N0C->isNullValue() && N1C && N1C->isNullValue()) {
1649 SDValue Carry = DAG.getConstant(0, dl, VT);
1650 SDValue Result = DAG.getNode(ISD::AND, dl, VT, N2,
1651 DAG.getConstant(1, dl, VT));
1652 SDValue Ops[] = { Result, Carry };
1653 return DAG.getMergeValues(Ops, dl);
1654 }
1655
1656 // fold (ladd x, 0, y) -> 0, add x, y iff carry is unused and y has only the
1657 // low bit set
1658 if (N1C && N1C->isNullValue() && N->hasNUsesOfValue(0, 1)) {
1659 APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(),
1660 VT.getSizeInBits() - 1);
1661 KnownBits Known = DAG.computeKnownBits(N2);
1662 if ((Known.Zero & Mask) == Mask) {
1663 SDValue Carry = DAG.getConstant(0, dl, VT);
1664 SDValue Result = DAG.getNode(ISD::ADD, dl, VT, N0, N2);
1665 SDValue Ops[] = { Result, Carry };
1666 return DAG.getMergeValues(Ops, dl);
1667 }
1668 }
1669 }
1670 break;
1671 case XCoreISD::LSUB: {
1672 SDValue N0 = N->getOperand(0);
1673 SDValue N1 = N->getOperand(1);
1674 SDValue N2 = N->getOperand(2);
1675 ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
1676 ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
1677 EVT VT = N0.getValueType();
1678
1679 // fold (lsub 0, 0, x) -> x, -x iff x has only the low bit set
1680 if (N0C && N0C->isNullValue() && N1C && N1C->isNullValue()) {
1681 APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(),
1682 VT.getSizeInBits() - 1);
1683 KnownBits Known = DAG.computeKnownBits(N2);
1684 if ((Known.Zero & Mask) == Mask) {
1685 SDValue Borrow = N2;
1686 SDValue Result = DAG.getNode(ISD::SUB, dl, VT,
1687 DAG.getConstant(0, dl, VT), N2);
1688 SDValue Ops[] = { Result, Borrow };
1689 return DAG.getMergeValues(Ops, dl);
1690 }
1691 }
1692
1693 // fold (lsub x, 0, y) -> 0, sub x, y iff borrow is unused and y has only the
1694 // low bit set
1695 if (N1C && N1C->isNullValue() && N->hasNUsesOfValue(0, 1)) {
1696 APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(),
1697 VT.getSizeInBits() - 1);
1698 KnownBits Known = DAG.computeKnownBits(N2);
1699 if ((Known.Zero & Mask) == Mask) {
1700 SDValue Borrow = DAG.getConstant(0, dl, VT);
1701 SDValue Result = DAG.getNode(ISD::SUB, dl, VT, N0, N2);
1702 SDValue Ops[] = { Result, Borrow };
1703 return DAG.getMergeValues(Ops, dl);
1704 }
1705 }
1706 }
1707 break;
1708 case XCoreISD::LMUL: {
1709 SDValue N0 = N->getOperand(0);
1710 SDValue N1 = N->getOperand(1);
1711 SDValue N2 = N->getOperand(2);
1712 SDValue N3 = N->getOperand(3);
1713 ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
1714 ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
1715 EVT VT = N0.getValueType();
1716 // Canonicalize multiplicative constant to RHS. If both multiplicative
1717 // operands are constant canonicalize smallest to RHS.
1718 if ((N0C && !N1C) ||
1719 (N0C && N1C && N0C->getZExtValue() < N1C->getZExtValue()))
1720 return DAG.getNode(XCoreISD::LMUL, dl, DAG.getVTList(VT, VT),
1721 N1, N0, N2, N3);
1722
1723 // lmul(x, 0, a, b)
1724 if (N1C && N1C->isNullValue()) {
1725 // If the high result is unused fold to add(a, b)
1726 if (N->hasNUsesOfValue(0, 0)) {
1727 SDValue Lo = DAG.getNode(ISD::ADD, dl, VT, N2, N3);
1728 SDValue Ops[] = { Lo, Lo };
1729 return DAG.getMergeValues(Ops, dl);
1730 }
1731 // Otherwise fold to ladd(a, b, 0)
1732 SDValue Result =
1733 DAG.getNode(XCoreISD::LADD, dl, DAG.getVTList(VT, VT), N2, N3, N1);
1734 SDValue Carry(Result.getNode(), 1);
1735 SDValue Ops[] = { Carry, Result };
1736 return DAG.getMergeValues(Ops, dl);
1737 }
1738 }
1739 break;
1740 case ISD::ADD: {
1741 // Fold 32 bit expressions such as add(add(mul(x,y),a),b) ->
1742 // lmul(x, y, a, b). The high result of lmul will be ignored.
1743 // This is only profitable if the intermediate results are unused
1744 // elsewhere.
1745 SDValue Mul0, Mul1, Addend0, Addend1;
1746 if (N->getValueType(0) == MVT::i32 &&
1747 isADDADDMUL(SDValue(N, 0), Mul0, Mul1, Addend0, Addend1, true)) {
1748 SDValue Ignored = DAG.getNode(XCoreISD::LMUL, dl,
1749 DAG.getVTList(MVT::i32, MVT::i32), Mul0,
1750 Mul1, Addend0, Addend1);
1751 SDValue Result(Ignored.getNode(), 1);
1752 return Result;
1753 }
1754 APInt HighMask = APInt::getHighBitsSet(64, 32);
1755 // Fold 64 bit expression such as add(add(mul(x,y),a),b) ->
1756 // lmul(x, y, a, b) if all operands are zero-extended. We do this
1757 // before type legalization as it is messy to match the operands after
1758 // that.
1759 if (N->getValueType(0) == MVT::i64 &&
1760 isADDADDMUL(SDValue(N, 0), Mul0, Mul1, Addend0, Addend1, false) &&
1761 DAG.MaskedValueIsZero(Mul0, HighMask) &&
1762 DAG.MaskedValueIsZero(Mul1, HighMask) &&
1763 DAG.MaskedValueIsZero(Addend0, HighMask) &&
1764 DAG.MaskedValueIsZero(Addend1, HighMask)) {
1765 SDValue Mul0L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
1766 Mul0, DAG.getConstant(0, dl, MVT::i32));
1767 SDValue Mul1L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
1768 Mul1, DAG.getConstant(0, dl, MVT::i32));
1769 SDValue Addend0L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
1770 Addend0, DAG.getConstant(0, dl, MVT::i32));
1771 SDValue Addend1L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
1772 Addend1, DAG.getConstant(0, dl, MVT::i32));
1773 SDValue Hi = DAG.getNode(XCoreISD::LMUL, dl,
1774 DAG.getVTList(MVT::i32, MVT::i32), Mul0L, Mul1L,
1775 Addend0L, Addend1L);
1776 SDValue Lo(Hi.getNode(), 1);
1777 return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);
1778 }
1779 }
1780 break;
1781 case ISD::STORE: {
1782 // Replace unaligned store of unaligned load with memmove.
1783 StoreSDNode *ST = cast<StoreSDNode>(N);
1784 if (!DCI.isBeforeLegalize() ||
1785 allowsMemoryAccessForAlignment(*DAG.getContext(), DAG.getDataLayout(),
1786 ST->getMemoryVT(),
1787 *ST->getMemOperand()) ||
1788 ST->isVolatile() || ST->isIndexed()) {
1789 break;
1790 }
1791 SDValue Chain = ST->getChain();
1792
1793 unsigned StoreBits = ST->getMemoryVT().getStoreSizeInBits();
1794 assert((StoreBits % 8) == 0 &&
1795 "Store size in bits must be a multiple of 8");
1796 unsigned Alignment = ST->getAlignment();
1797
1798 if (LoadSDNode *LD = dyn_cast<LoadSDNode>(ST->getValue())) {
1799 if (LD->hasNUsesOfValue(1, 0) && ST->getMemoryVT() == LD->getMemoryVT() &&
1800 LD->getAlignment() == Alignment &&
1801 !LD->isVolatile() && !LD->isIndexed() &&
1802 Chain.reachesChainWithoutSideEffects(SDValue(LD, 1))) {
1803 bool isTail = isInTailCallPosition(DAG, ST, Chain);
1804 return DAG.getMemmove(Chain, dl, ST->getBasePtr(), LD->getBasePtr(),
1805 DAG.getConstant(StoreBits / 8, dl, MVT::i32),
1806 Align(Alignment), false, isTail,
1807 ST->getPointerInfo(), LD->getPointerInfo());
1808 }
1809 }
1810 break;
1811 }
1812 }
1813 return SDValue();
1814 }
1815
computeKnownBitsForTargetNode(const SDValue Op,KnownBits & Known,const APInt & DemandedElts,const SelectionDAG & DAG,unsigned Depth) const1816 void XCoreTargetLowering::computeKnownBitsForTargetNode(const SDValue Op,
1817 KnownBits &Known,
1818 const APInt &DemandedElts,
1819 const SelectionDAG &DAG,
1820 unsigned Depth) const {
1821 Known.resetAll();
1822 switch (Op.getOpcode()) {
1823 default: break;
1824 case XCoreISD::LADD:
1825 case XCoreISD::LSUB:
1826 if (Op.getResNo() == 1) {
1827 // Top bits of carry / borrow are clear.
1828 Known.Zero = APInt::getHighBitsSet(Known.getBitWidth(),
1829 Known.getBitWidth() - 1);
1830 }
1831 break;
1832 case ISD::INTRINSIC_W_CHAIN:
1833 {
1834 unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue();
1835 switch (IntNo) {
1836 case Intrinsic::xcore_getts:
1837 // High bits are known to be zero.
1838 Known.Zero = APInt::getHighBitsSet(Known.getBitWidth(),
1839 Known.getBitWidth() - 16);
1840 break;
1841 case Intrinsic::xcore_int:
1842 case Intrinsic::xcore_inct:
1843 // High bits are known to be zero.
1844 Known.Zero = APInt::getHighBitsSet(Known.getBitWidth(),
1845 Known.getBitWidth() - 8);
1846 break;
1847 case Intrinsic::xcore_testct:
1848 // Result is either 0 or 1.
1849 Known.Zero = APInt::getHighBitsSet(Known.getBitWidth(),
1850 Known.getBitWidth() - 1);
1851 break;
1852 case Intrinsic::xcore_testwct:
1853 // Result is in the range 0 - 4.
1854 Known.Zero = APInt::getHighBitsSet(Known.getBitWidth(),
1855 Known.getBitWidth() - 3);
1856 break;
1857 }
1858 }
1859 break;
1860 }
1861 }
1862
1863 //===----------------------------------------------------------------------===//
1864 // Addressing mode description hooks
1865 //===----------------------------------------------------------------------===//
1866
isImmUs(int64_t val)1867 static inline bool isImmUs(int64_t val)
1868 {
1869 return (val >= 0 && val <= 11);
1870 }
1871
isImmUs2(int64_t val)1872 static inline bool isImmUs2(int64_t val)
1873 {
1874 return (val%2 == 0 && isImmUs(val/2));
1875 }
1876
isImmUs4(int64_t val)1877 static inline bool isImmUs4(int64_t val)
1878 {
1879 return (val%4 == 0 && isImmUs(val/4));
1880 }
1881
1882 /// isLegalAddressingMode - Return true if the addressing mode represented
1883 /// by AM is legal for this target, for a load/store of the specified type.
isLegalAddressingMode(const DataLayout & DL,const AddrMode & AM,Type * Ty,unsigned AS,Instruction * I) const1884 bool XCoreTargetLowering::isLegalAddressingMode(const DataLayout &DL,
1885 const AddrMode &AM, Type *Ty,
1886 unsigned AS,
1887 Instruction *I) const {
1888 if (Ty->getTypeID() == Type::VoidTyID)
1889 return AM.Scale == 0 && isImmUs(AM.BaseOffs) && isImmUs4(AM.BaseOffs);
1890
1891 unsigned Size = DL.getTypeAllocSize(Ty);
1892 if (AM.BaseGV) {
1893 return Size >= 4 && !AM.HasBaseReg && AM.Scale == 0 &&
1894 AM.BaseOffs%4 == 0;
1895 }
1896
1897 switch (Size) {
1898 case 1:
1899 // reg + imm
1900 if (AM.Scale == 0) {
1901 return isImmUs(AM.BaseOffs);
1902 }
1903 // reg + reg
1904 return AM.Scale == 1 && AM.BaseOffs == 0;
1905 case 2:
1906 case 3:
1907 // reg + imm
1908 if (AM.Scale == 0) {
1909 return isImmUs2(AM.BaseOffs);
1910 }
1911 // reg + reg<<1
1912 return AM.Scale == 2 && AM.BaseOffs == 0;
1913 default:
1914 // reg + imm
1915 if (AM.Scale == 0) {
1916 return isImmUs4(AM.BaseOffs);
1917 }
1918 // reg + reg<<2
1919 return AM.Scale == 4 && AM.BaseOffs == 0;
1920 }
1921 }
1922
1923 //===----------------------------------------------------------------------===//
1924 // XCore Inline Assembly Support
1925 //===----------------------------------------------------------------------===//
1926
1927 std::pair<unsigned, const TargetRegisterClass *>
getRegForInlineAsmConstraint(const TargetRegisterInfo * TRI,StringRef Constraint,MVT VT) const1928 XCoreTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
1929 StringRef Constraint,
1930 MVT VT) const {
1931 if (Constraint.size() == 1) {
1932 switch (Constraint[0]) {
1933 default : break;
1934 case 'r':
1935 return std::make_pair(0U, &XCore::GRRegsRegClass);
1936 }
1937 }
1938 // Use the default implementation in TargetLowering to convert the register
1939 // constraint into a member of a register class.
1940 return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
1941 }
1942