LLVM 17.0.0git
XCoreISelLowering.cpp
Go to the documentation of this file.
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"
16#include "XCoreSubtarget.h"
17#include "XCoreTargetMachine.h"
26#include "llvm/IR/CallingConv.h"
27#include "llvm/IR/Constants.h"
29#include "llvm/IR/Function.h"
30#include "llvm/IR/GlobalAlias.h"
32#include "llvm/IR/Intrinsics.h"
33#include "llvm/IR/IntrinsicsXCore.h"
34#include "llvm/Support/Debug.h"
38#include <algorithm>
39
40using namespace llvm;
41
42#define DEBUG_TYPE "xcore-lower"
43
45getTargetNodeName(unsigned Opcode) const
46{
47 switch ((XCoreISD::NodeType)Opcode)
48 {
49 case XCoreISD::FIRST_NUMBER : break;
50 case XCoreISD::BL : return "XCoreISD::BL";
51 case XCoreISD::PCRelativeWrapper : return "XCoreISD::PCRelativeWrapper";
52 case XCoreISD::DPRelativeWrapper : return "XCoreISD::DPRelativeWrapper";
53 case XCoreISD::CPRelativeWrapper : return "XCoreISD::CPRelativeWrapper";
54 case XCoreISD::LDWSP : return "XCoreISD::LDWSP";
55 case XCoreISD::STWSP : return "XCoreISD::STWSP";
56 case XCoreISD::RETSP : return "XCoreISD::RETSP";
57 case XCoreISD::LADD : return "XCoreISD::LADD";
58 case XCoreISD::LSUB : return "XCoreISD::LSUB";
59 case XCoreISD::LMUL : return "XCoreISD::LMUL";
60 case XCoreISD::MACCU : return "XCoreISD::MACCU";
61 case XCoreISD::MACCS : return "XCoreISD::MACCS";
62 case XCoreISD::CRC8 : return "XCoreISD::CRC8";
63 case XCoreISD::BR_JT : return "XCoreISD::BR_JT";
64 case XCoreISD::BR_JT32 : return "XCoreISD::BR_JT32";
65 case XCoreISD::FRAME_TO_ARGS_OFFSET : return "XCoreISD::FRAME_TO_ARGS_OFFSET";
66 case XCoreISD::EH_RETURN : return "XCoreISD::EH_RETURN";
67 }
68 return nullptr;
69}
70
72 const XCoreSubtarget &Subtarget)
73 : TargetLowering(TM), TM(TM), Subtarget(Subtarget) {
74
75 // Set up the register classes.
76 addRegisterClass(MVT::i32, &XCore::GRRegsRegClass);
77
78 // Compute derived properties from the register classes
80
82
84
85 // Use i32 for setcc operations results (slt, sgt, ...).
87 setBooleanVectorContents(ZeroOrOneBooleanContent); // FIXME: Is this correct?
88
89 // XCore does not have the NodeTypes below.
92
93 // 64bit
103
104 // Bit Manipulation
109
111
112 // Jump tables.
114
117
118 // Conversion of i64 -> double produces constantpool nodes
120
121 // Loads
122 for (MVT VT : MVT::integer_valuetypes()) {
126
129 }
130
131 // Custom expand misaligned loads / stores.
134
135 // Varargs
140
141 // Dynamic stack
145
146 // Exception handling
149
150 // Atomic operations
151 // We request a fence for ATOMIC_* instructions, to reduce them to Monotonic.
152 // As we are always Sequential Consistent, an ATOMIC_FENCE becomes a no OP.
156
157 // TRAMPOLINE is custom lowered.
160
161 // We want to custom lower some of our intrinsics.
163
167
168 // We have target-specific dag combine patterns for the following nodes:
171
174}
175
177 if (Val.getOpcode() != ISD::LOAD)
178 return false;
179
180 EVT VT1 = Val.getValueType();
181 if (!VT1.isSimple() || !VT1.isInteger() ||
182 !VT2.isSimple() || !VT2.isInteger())
183 return false;
184
185 switch (VT1.getSimpleVT().SimpleTy) {
186 default: break;
187 case MVT::i8:
188 return true;
189 }
190
191 return false;
192}
193
195LowerOperation(SDValue Op, SelectionDAG &DAG) const {
196 switch (Op.getOpcode())
197 {
198 case ISD::EH_RETURN: return LowerEH_RETURN(Op, DAG);
199 case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
200 case ISD::BlockAddress: return LowerBlockAddress(Op, DAG);
201 case ISD::ConstantPool: return LowerConstantPool(Op, DAG);
202 case ISD::BR_JT: return LowerBR_JT(Op, DAG);
203 case ISD::LOAD: return LowerLOAD(Op, DAG);
204 case ISD::STORE: return LowerSTORE(Op, DAG);
205 case ISD::VAARG: return LowerVAARG(Op, DAG);
206 case ISD::VASTART: return LowerVASTART(Op, DAG);
207 case ISD::SMUL_LOHI: return LowerSMUL_LOHI(Op, DAG);
208 case ISD::UMUL_LOHI: return LowerUMUL_LOHI(Op, DAG);
209 // FIXME: Remove these when LegalizeDAGTypes lands.
210 case ISD::ADD:
211 case ISD::SUB: return ExpandADDSUB(Op.getNode(), DAG);
212 case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
213 case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG);
214 case ISD::FRAME_TO_ARGS_OFFSET: return LowerFRAME_TO_ARGS_OFFSET(Op, DAG);
215 case ISD::INIT_TRAMPOLINE: return LowerINIT_TRAMPOLINE(Op, DAG);
216 case ISD::ADJUST_TRAMPOLINE: return LowerADJUST_TRAMPOLINE(Op, DAG);
217 case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG);
218 case ISD::ATOMIC_FENCE: return LowerATOMIC_FENCE(Op, DAG);
219 case ISD::ATOMIC_LOAD: return LowerATOMIC_LOAD(Op, DAG);
220 case ISD::ATOMIC_STORE: return LowerATOMIC_STORE(Op, DAG);
221 default:
222 llvm_unreachable("unimplemented operand");
223 }
224}
225
226/// ReplaceNodeResults - Replace the results of node with an illegal result
227/// type with new values built out of custom code.
230 SelectionDAG &DAG) const {
231 switch (N->getOpcode()) {
232 default:
233 llvm_unreachable("Don't know how to custom expand this!");
234 case ISD::ADD:
235 case ISD::SUB:
236 Results.push_back(ExpandADDSUB(N, DAG));
237 return;
238 }
239}
240
241//===----------------------------------------------------------------------===//
242// Misc Lower Operation implementation
243//===----------------------------------------------------------------------===//
244
245SDValue XCoreTargetLowering::getGlobalAddressWrapper(SDValue GA,
246 const GlobalValue *GV,
247 SelectionDAG &DAG) const {
248 // FIXME there is no actual debug info here
249 SDLoc dl(GA);
250
251 if (GV->getValueType()->isFunctionTy())
252 return DAG.getNode(XCoreISD::PCRelativeWrapper, dl, MVT::i32, GA);
253
254 const auto *GVar = dyn_cast<GlobalVariable>(GV);
255 if ((GV->hasSection() && GV->getSection().startswith(".cp.")) ||
256 (GVar && GVar->isConstant() && GV->hasLocalLinkage()))
257 return DAG.getNode(XCoreISD::CPRelativeWrapper, dl, MVT::i32, GA);
258
259 return DAG.getNode(XCoreISD::DPRelativeWrapper, dl, MVT::i32, GA);
260}
261
262static bool IsSmallObject(const GlobalValue *GV, const XCoreTargetLowering &XTL) {
264 return true;
265
266 Type *ObjType = GV->getValueType();
267 if (!ObjType->isSized())
268 return false;
269
270 auto &DL = GV->getParent()->getDataLayout();
271 unsigned ObjSize = DL.getTypeAllocSize(ObjType);
272 return ObjSize < CodeModelLargeSize && ObjSize != 0;
273}
274
275SDValue XCoreTargetLowering::
276LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const
277{
278 const GlobalAddressSDNode *GN = cast<GlobalAddressSDNode>(Op);
279 const GlobalValue *GV = GN->getGlobal();
280 SDLoc DL(GN);
281 int64_t Offset = GN->getOffset();
282 if (IsSmallObject(GV, *this)) {
283 // We can only fold positive offsets that are a multiple of the word size.
284 int64_t FoldedOffset = std::max(Offset & ~3, (int64_t)0);
285 SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, FoldedOffset);
286 GA = getGlobalAddressWrapper(GA, GV, DAG);
287 // Handle the rest of the offset.
288 if (Offset != FoldedOffset) {
289 SDValue Remaining = DAG.getConstant(Offset - FoldedOffset, DL, MVT::i32);
290 GA = DAG.getNode(ISD::ADD, DL, MVT::i32, GA, Remaining);
291 }
292 return GA;
293 } else {
294 // Ideally we would not fold in offset with an index <= 11.
295 Type *Ty = Type::getInt8PtrTy(*DAG.getContext());
296 Constant *GA = ConstantExpr::getBitCast(const_cast<GlobalValue*>(GV), Ty);
297 Ty = Type::getInt32Ty(*DAG.getContext());
300 Type::getInt8Ty(*DAG.getContext()), GA, Idx);
302 return DAG.getLoad(getPointerTy(DAG.getDataLayout()), DL,
303 DAG.getEntryNode(), CP, MachinePointerInfo());
304 }
305}
306
307SDValue XCoreTargetLowering::
308LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const
309{
310 SDLoc DL(Op);
311 auto PtrVT = getPointerTy(DAG.getDataLayout());
312 const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress();
313 SDValue Result = DAG.getTargetBlockAddress(BA, PtrVT);
314
315 return DAG.getNode(XCoreISD::PCRelativeWrapper, DL, PtrVT, Result);
316}
317
318SDValue XCoreTargetLowering::
319LowerConstantPool(SDValue Op, SelectionDAG &DAG) const
320{
321 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
322 // FIXME there isn't really debug info here
323 SDLoc dl(CP);
324 EVT PtrVT = Op.getValueType();
325 SDValue Res;
326 if (CP->isMachineConstantPoolEntry()) {
327 Res = DAG.getTargetConstantPool(CP->getMachineCPVal(), PtrVT,
328 CP->getAlign(), CP->getOffset());
329 } else {
330 Res = DAG.getTargetConstantPool(CP->getConstVal(), PtrVT, CP->getAlign(),
331 CP->getOffset());
332 }
333 return DAG.getNode(XCoreISD::CPRelativeWrapper, dl, MVT::i32, Res);
334}
335
338}
339
340SDValue XCoreTargetLowering::
341LowerBR_JT(SDValue Op, SelectionDAG &DAG) const
342{
343 SDValue Chain = Op.getOperand(0);
344 SDValue Table = Op.getOperand(1);
345 SDValue Index = Op.getOperand(2);
346 SDLoc dl(Op);
347 JumpTableSDNode *JT = cast<JumpTableSDNode>(Table);
348 unsigned JTI = JT->getIndex();
350 const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo();
351 SDValue TargetJT = DAG.getTargetJumpTable(JT->getIndex(), MVT::i32);
352
353 unsigned NumEntries = MJTI->getJumpTables()[JTI].MBBs.size();
354 if (NumEntries <= 32) {
355 return DAG.getNode(XCoreISD::BR_JT, dl, MVT::Other, Chain, TargetJT, Index);
356 }
357 assert((NumEntries >> 31) == 0);
358 SDValue ScaledIndex = DAG.getNode(ISD::SHL, dl, MVT::i32, Index,
359 DAG.getConstant(1, dl, MVT::i32));
360 return DAG.getNode(XCoreISD::BR_JT32, dl, MVT::Other, Chain, TargetJT,
361 ScaledIndex);
362}
363
364SDValue XCoreTargetLowering::lowerLoadWordFromAlignedBasePlusOffset(
365 const SDLoc &DL, SDValue Chain, SDValue Base, int64_t Offset,
366 SelectionDAG &DAG) const {
367 auto PtrVT = getPointerTy(DAG.getDataLayout());
368 if ((Offset & 0x3) == 0) {
369 return DAG.getLoad(PtrVT, DL, Chain, Base, MachinePointerInfo());
370 }
371 // Lower to pair of consecutive word aligned loads plus some bit shifting.
372 int32_t HighOffset = alignTo(Offset, 4);
373 int32_t LowOffset = HighOffset - 4;
374 SDValue LowAddr, HighAddr;
375 if (GlobalAddressSDNode *GASD =
376 dyn_cast<GlobalAddressSDNode>(Base.getNode())) {
377 LowAddr = DAG.getGlobalAddress(GASD->getGlobal(), DL, Base.getValueType(),
378 LowOffset);
379 HighAddr = DAG.getGlobalAddress(GASD->getGlobal(), DL, Base.getValueType(),
380 HighOffset);
381 } else {
382 LowAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, Base,
383 DAG.getConstant(LowOffset, DL, MVT::i32));
384 HighAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, Base,
385 DAG.getConstant(HighOffset, DL, MVT::i32));
386 }
387 SDValue LowShift = DAG.getConstant((Offset - LowOffset) * 8, DL, MVT::i32);
388 SDValue HighShift = DAG.getConstant((HighOffset - Offset) * 8, DL, MVT::i32);
389
390 SDValue Low = DAG.getLoad(PtrVT, DL, Chain, LowAddr, MachinePointerInfo());
391 SDValue High = DAG.getLoad(PtrVT, DL, Chain, HighAddr, MachinePointerInfo());
392 SDValue LowShifted = DAG.getNode(ISD::SRL, DL, MVT::i32, Low, LowShift);
393 SDValue HighShifted = DAG.getNode(ISD::SHL, DL, MVT::i32, High, HighShift);
394 SDValue Result = DAG.getNode(ISD::OR, DL, MVT::i32, LowShifted, HighShifted);
395 Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Low.getValue(1),
396 High.getValue(1));
397 SDValue Ops[] = { Result, Chain };
398 return DAG.getMergeValues(Ops, DL);
399}
400
402{
403 KnownBits Known = DAG.computeKnownBits(Value);
404 return Known.countMinTrailingZeros() >= 2;
405}
406
407SDValue XCoreTargetLowering::LowerLOAD(SDValue Op, SelectionDAG &DAG) const {
408 const TargetLowering &TLI = DAG.getTargetLoweringInfo();
410 LoadSDNode *LD = cast<LoadSDNode>(Op);
411 assert(LD->getExtensionType() == ISD::NON_EXTLOAD &&
412 "Unexpected extension type");
413 assert(LD->getMemoryVT() == MVT::i32 && "Unexpected load EVT");
414
416 LD->getMemoryVT(), *LD->getMemOperand()))
417 return SDValue();
418
419 SDValue Chain = LD->getChain();
420 SDValue BasePtr = LD->getBasePtr();
421 SDLoc DL(Op);
422
423 if (!LD->isVolatile()) {
424 const GlobalValue *GV;
425 int64_t Offset = 0;
426 if (DAG.isBaseWithConstantOffset(BasePtr) &&
427 isWordAligned(BasePtr->getOperand(0), DAG)) {
428 SDValue NewBasePtr = BasePtr->getOperand(0);
429 Offset = cast<ConstantSDNode>(BasePtr->getOperand(1))->getSExtValue();
430 return lowerLoadWordFromAlignedBasePlusOffset(DL, Chain, NewBasePtr,
431 Offset, DAG);
432 }
433 if (TLI.isGAPlusOffset(BasePtr.getNode(), GV, Offset) &&
434 GV->getPointerAlignment(DAG.getDataLayout()) >= 4) {
435 SDValue NewBasePtr = DAG.getGlobalAddress(GV, DL,
436 BasePtr->getValueType(0));
437 return lowerLoadWordFromAlignedBasePlusOffset(DL, Chain, NewBasePtr,
438 Offset, DAG);
439 }
440 }
441
442 if (LD->getAlign() == Align(2)) {
443 SDValue Low = DAG.getExtLoad(ISD::ZEXTLOAD, DL, MVT::i32, Chain, BasePtr,
444 LD->getPointerInfo(), MVT::i16, Align(2),
445 LD->getMemOperand()->getFlags());
446 SDValue HighAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, BasePtr,
447 DAG.getConstant(2, DL, MVT::i32));
448 SDValue High =
449 DAG.getExtLoad(ISD::EXTLOAD, DL, MVT::i32, Chain, HighAddr,
450 LD->getPointerInfo().getWithOffset(2), MVT::i16,
451 Align(2), LD->getMemOperand()->getFlags());
452 SDValue HighShifted = DAG.getNode(ISD::SHL, DL, MVT::i32, High,
453 DAG.getConstant(16, DL, MVT::i32));
454 SDValue Result = DAG.getNode(ISD::OR, DL, MVT::i32, Low, HighShifted);
455 Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Low.getValue(1),
456 High.getValue(1));
457 SDValue Ops[] = { Result, Chain };
458 return DAG.getMergeValues(Ops, DL);
459 }
460
461 // Lower to a call to __misaligned_load(BasePtr).
462 Type *IntPtrTy = DAG.getDataLayout().getIntPtrType(Context);
465
466 Entry.Ty = IntPtrTy;
467 Entry.Node = BasePtr;
468 Args.push_back(Entry);
469
471 CLI.setDebugLoc(DL).setChain(Chain).setLibCallee(
472 CallingConv::C, IntPtrTy,
473 DAG.getExternalSymbol("__misaligned_load",
475 std::move(Args));
476
477 std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI);
478 SDValue Ops[] = { CallResult.first, CallResult.second };
479 return DAG.getMergeValues(Ops, DL);
480}
481
482SDValue XCoreTargetLowering::LowerSTORE(SDValue Op, SelectionDAG &DAG) const {
484 StoreSDNode *ST = cast<StoreSDNode>(Op);
485 assert(!ST->isTruncatingStore() && "Unexpected store type");
486 assert(ST->getMemoryVT() == MVT::i32 && "Unexpected store EVT");
487
489 ST->getMemoryVT(), *ST->getMemOperand()))
490 return SDValue();
491
492 SDValue Chain = ST->getChain();
493 SDValue BasePtr = ST->getBasePtr();
494 SDValue Value = ST->getValue();
495 SDLoc dl(Op);
496
497 if (ST->getAlign() == Align(2)) {
498 SDValue Low = Value;
500 DAG.getConstant(16, dl, MVT::i32));
501 SDValue StoreLow =
502 DAG.getTruncStore(Chain, dl, Low, BasePtr, ST->getPointerInfo(),
503 MVT::i16, Align(2), ST->getMemOperand()->getFlags());
504 SDValue HighAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, BasePtr,
505 DAG.getConstant(2, dl, MVT::i32));
506 SDValue StoreHigh = DAG.getTruncStore(
507 Chain, dl, High, HighAddr, ST->getPointerInfo().getWithOffset(2),
508 MVT::i16, Align(2), ST->getMemOperand()->getFlags());
509 return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, StoreLow, StoreHigh);
510 }
511
512 // Lower to a call to __misaligned_store(BasePtr, Value).
513 Type *IntPtrTy = DAG.getDataLayout().getIntPtrType(Context);
516
517 Entry.Ty = IntPtrTy;
518 Entry.Node = BasePtr;
519 Args.push_back(Entry);
520
521 Entry.Node = Value;
522 Args.push_back(Entry);
523
525 CLI.setDebugLoc(dl).setChain(Chain).setCallee(
527 DAG.getExternalSymbol("__misaligned_store",
529 std::move(Args));
530
531 std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI);
532 return CallResult.second;
533}
534
535SDValue XCoreTargetLowering::
536LowerSMUL_LOHI(SDValue Op, SelectionDAG &DAG) const
537{
538 assert(Op.getValueType() == MVT::i32 && Op.getOpcode() == ISD::SMUL_LOHI &&
539 "Unexpected operand to lower!");
540 SDLoc dl(Op);
541 SDValue LHS = Op.getOperand(0);
542 SDValue RHS = Op.getOperand(1);
543 SDValue Zero = DAG.getConstant(0, dl, MVT::i32);
545 DAG.getVTList(MVT::i32, MVT::i32), Zero, Zero,
546 LHS, RHS);
547 SDValue Lo(Hi.getNode(), 1);
548 SDValue Ops[] = { Lo, Hi };
549 return DAG.getMergeValues(Ops, dl);
550}
551
552SDValue XCoreTargetLowering::
553LowerUMUL_LOHI(SDValue Op, SelectionDAG &DAG) const
554{
555 assert(Op.getValueType() == MVT::i32 && Op.getOpcode() == ISD::UMUL_LOHI &&
556 "Unexpected operand to lower!");
557 SDLoc dl(Op);
558 SDValue LHS = Op.getOperand(0);
559 SDValue RHS = Op.getOperand(1);
560 SDValue Zero = DAG.getConstant(0, dl, MVT::i32);
562 DAG.getVTList(MVT::i32, MVT::i32), LHS, RHS,
563 Zero, Zero);
564 SDValue Lo(Hi.getNode(), 1);
565 SDValue Ops[] = { Lo, Hi };
566 return DAG.getMergeValues(Ops, dl);
567}
568
569/// isADDADDMUL - Return whether Op is in a form that is equivalent to
570/// add(add(mul(x,y),a),b). If requireIntermediatesHaveOneUse is true then
571/// each intermediate result in the calculation must also have a single use.
572/// If the Op is in the correct form the constituent parts are written to Mul0,
573/// Mul1, Addend0 and Addend1.
574static bool
575isADDADDMUL(SDValue Op, SDValue &Mul0, SDValue &Mul1, SDValue &Addend0,
576 SDValue &Addend1, bool requireIntermediatesHaveOneUse)
577{
578 if (Op.getOpcode() != ISD::ADD)
579 return false;
580 SDValue N0 = Op.getOperand(0);
581 SDValue N1 = Op.getOperand(1);
582 SDValue AddOp;
583 SDValue OtherOp;
584 if (N0.getOpcode() == ISD::ADD) {
585 AddOp = N0;
586 OtherOp = N1;
587 } else if (N1.getOpcode() == ISD::ADD) {
588 AddOp = N1;
589 OtherOp = N0;
590 } else {
591 return false;
592 }
593 if (requireIntermediatesHaveOneUse && !AddOp.hasOneUse())
594 return false;
595 if (OtherOp.getOpcode() == ISD::MUL) {
596 // add(add(a,b),mul(x,y))
597 if (requireIntermediatesHaveOneUse && !OtherOp.hasOneUse())
598 return false;
599 Mul0 = OtherOp.getOperand(0);
600 Mul1 = OtherOp.getOperand(1);
601 Addend0 = AddOp.getOperand(0);
602 Addend1 = AddOp.getOperand(1);
603 return true;
604 }
605 if (AddOp.getOperand(0).getOpcode() == ISD::MUL) {
606 // add(add(mul(x,y),a),b)
607 if (requireIntermediatesHaveOneUse && !AddOp.getOperand(0).hasOneUse())
608 return false;
609 Mul0 = AddOp.getOperand(0).getOperand(0);
610 Mul1 = AddOp.getOperand(0).getOperand(1);
611 Addend0 = AddOp.getOperand(1);
612 Addend1 = OtherOp;
613 return true;
614 }
615 if (AddOp.getOperand(1).getOpcode() == ISD::MUL) {
616 // add(add(a,mul(x,y)),b)
617 if (requireIntermediatesHaveOneUse && !AddOp.getOperand(1).hasOneUse())
618 return false;
619 Mul0 = AddOp.getOperand(1).getOperand(0);
620 Mul1 = AddOp.getOperand(1).getOperand(1);
621 Addend0 = AddOp.getOperand(0);
622 Addend1 = OtherOp;
623 return true;
624 }
625 return false;
626}
627
628SDValue XCoreTargetLowering::
629TryExpandADDWithMul(SDNode *N, SelectionDAG &DAG) const
630{
631 SDValue Mul;
633 if (N->getOperand(0).getOpcode() == ISD::MUL) {
634 Mul = N->getOperand(0);
635 Other = N->getOperand(1);
636 } else if (N->getOperand(1).getOpcode() == ISD::MUL) {
637 Mul = N->getOperand(1);
638 Other = N->getOperand(0);
639 } else {
640 return SDValue();
641 }
642 SDLoc dl(N);
643 SDValue LL, RL, AddendL, AddendH;
645 Mul.getOperand(0), DAG.getConstant(0, dl, MVT::i32));
647 Mul.getOperand(1), DAG.getConstant(0, dl, MVT::i32));
648 AddendL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
649 Other, DAG.getConstant(0, dl, MVT::i32));
650 AddendH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
651 Other, DAG.getConstant(1, dl, MVT::i32));
652 APInt HighMask = APInt::getHighBitsSet(64, 32);
653 unsigned LHSSB = DAG.ComputeNumSignBits(Mul.getOperand(0));
654 unsigned RHSSB = DAG.ComputeNumSignBits(Mul.getOperand(1));
655 if (DAG.MaskedValueIsZero(Mul.getOperand(0), HighMask) &&
656 DAG.MaskedValueIsZero(Mul.getOperand(1), HighMask)) {
657 // The inputs are both zero-extended.
659 DAG.getVTList(MVT::i32, MVT::i32), AddendH,
660 AddendL, LL, RL);
661 SDValue Lo(Hi.getNode(), 1);
662 return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);
663 }
664 if (LHSSB > 32 && RHSSB > 32) {
665 // The inputs are both sign-extended.
667 DAG.getVTList(MVT::i32, MVT::i32), AddendH,
668 AddendL, LL, RL);
669 SDValue Lo(Hi.getNode(), 1);
670 return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);
671 }
672 SDValue LH, RH;
674 Mul.getOperand(0), DAG.getConstant(1, dl, MVT::i32));
676 Mul.getOperand(1), DAG.getConstant(1, dl, MVT::i32));
678 DAG.getVTList(MVT::i32, MVT::i32), AddendH,
679 AddendL, LL, RL);
680 SDValue Lo(Hi.getNode(), 1);
681 RH = DAG.getNode(ISD::MUL, dl, MVT::i32, LL, RH);
682 LH = DAG.getNode(ISD::MUL, dl, MVT::i32, LH, RL);
683 Hi = DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, RH);
684 Hi = DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, LH);
685 return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);
686}
687
688SDValue XCoreTargetLowering::
689ExpandADDSUB(SDNode *N, SelectionDAG &DAG) const
690{
691 assert(N->getValueType(0) == MVT::i64 &&
692 (N->getOpcode() == ISD::ADD || N->getOpcode() == ISD::SUB) &&
693 "Unknown operand to lower!");
694
695 if (N->getOpcode() == ISD::ADD)
696 if (SDValue Result = TryExpandADDWithMul(N, DAG))
697 return Result;
698
699 SDLoc dl(N);
700
701 // Extract components
703 N->getOperand(0),
704 DAG.getConstant(0, dl, MVT::i32));
706 N->getOperand(0),
707 DAG.getConstant(1, dl, MVT::i32));
709 N->getOperand(1),
710 DAG.getConstant(0, dl, MVT::i32));
712 N->getOperand(1),
713 DAG.getConstant(1, dl, MVT::i32));
714
715 // Expand
716 unsigned Opcode = (N->getOpcode() == ISD::ADD) ? XCoreISD::LADD :
718 SDValue Zero = DAG.getConstant(0, dl, MVT::i32);
719 SDValue Lo = DAG.getNode(Opcode, dl, DAG.getVTList(MVT::i32, MVT::i32),
720 LHSL, RHSL, Zero);
721 SDValue Carry(Lo.getNode(), 1);
722
723 SDValue Hi = DAG.getNode(Opcode, dl, DAG.getVTList(MVT::i32, MVT::i32),
724 LHSH, RHSH, Carry);
725 SDValue Ignored(Hi.getNode(), 1);
726 // Merge the pieces
727 return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);
728}
729
730SDValue XCoreTargetLowering::
731LowerVAARG(SDValue Op, SelectionDAG &DAG) const
732{
733 // Whist llvm does not support aggregate varargs we can ignore
734 // the possibility of the ValueType being an implicit byVal vararg.
735 SDNode *Node = Op.getNode();
736 EVT VT = Node->getValueType(0); // not an aggregate
737 SDValue InChain = Node->getOperand(0);
738 SDValue VAListPtr = Node->getOperand(1);
739 EVT PtrVT = VAListPtr.getValueType();
740 const Value *SV = cast<SrcValueSDNode>(Node->getOperand(2))->getValue();
741 SDLoc dl(Node);
742 SDValue VAList =
743 DAG.getLoad(PtrVT, dl, InChain, VAListPtr, MachinePointerInfo(SV));
744 // Increment the pointer, VAList, to the next vararg
745 SDValue nextPtr = DAG.getNode(ISD::ADD, dl, PtrVT, VAList,
746 DAG.getIntPtrConstant(VT.getSizeInBits() / 8,
747 dl));
748 // Store the incremented VAList to the legalized pointer
749 InChain = DAG.getStore(VAList.getValue(1), dl, nextPtr, VAListPtr,
751 // Load the actual argument out of the pointer VAList
752 return DAG.getLoad(VT, dl, InChain, VAList, MachinePointerInfo());
753}
754
755SDValue XCoreTargetLowering::
756LowerVASTART(SDValue Op, SelectionDAG &DAG) const
757{
758 SDLoc dl(Op);
759 // vastart stores the address of the VarArgsFrameIndex slot into the
760 // memory location argument
764 return DAG.getStore(Op.getOperand(0), dl, Addr, Op.getOperand(1),
766}
767
768SDValue XCoreTargetLowering::LowerFRAMEADDR(SDValue Op,
769 SelectionDAG &DAG) const {
770 // This nodes represent llvm.frameaddress on the DAG.
771 // It takes one operand, the index of the frame address to return.
772 // An index of zero corresponds to the current function's frame address.
773 // An index of one to the parent's frame address, and so on.
774 // Depths > 0 not supported yet!
775 if (cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() > 0)
776 return SDValue();
777
779 const TargetRegisterInfo *RegInfo = Subtarget.getRegisterInfo();
780 return DAG.getCopyFromReg(DAG.getEntryNode(), SDLoc(Op),
781 RegInfo->getFrameRegister(MF), MVT::i32);
782}
783
784SDValue XCoreTargetLowering::
785LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const {
786 // This nodes represent llvm.returnaddress on the DAG.
787 // It takes one operand, the index of the return address to return.
788 // An index of zero corresponds to the current function's return address.
789 // An index of one to the parent's return address, and so on.
790 // Depths > 0 not supported yet!
791 if (cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() > 0)
792 return SDValue();
793
796 int FI = XFI->createLRSpillSlot(MF);
797 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
798 return DAG.getLoad(getPointerTy(DAG.getDataLayout()), SDLoc(Op),
799 DAG.getEntryNode(), FIN,
801}
802
803SDValue XCoreTargetLowering::
804LowerFRAME_TO_ARGS_OFFSET(SDValue Op, SelectionDAG &DAG) const {
805 // This node represents offset from frame pointer to first on-stack argument.
806 // This is needed for correct stack adjustment during unwind.
807 // However, we don't know the offset until after the frame has be finalised.
808 // This is done during the XCoreFTAOElim pass.
810}
811
812SDValue XCoreTargetLowering::
813LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const {
814 // OUTCHAIN = EH_RETURN(INCHAIN, OFFSET, HANDLER)
815 // This node represents 'eh_return' gcc dwarf builtin, which is used to
816 // return from exception. The general meaning is: adjust stack by OFFSET and
817 // pass execution to HANDLER.
819 SDValue Chain = Op.getOperand(0);
820 SDValue Offset = Op.getOperand(1);
821 SDValue Handler = Op.getOperand(2);
822 SDLoc dl(Op);
823
824 // Absolute SP = (FP + FrameToArgs) + Offset
825 const TargetRegisterInfo *RegInfo = Subtarget.getRegisterInfo();
827 RegInfo->getFrameRegister(MF), MVT::i32);
828 SDValue FrameToArgs = DAG.getNode(XCoreISD::FRAME_TO_ARGS_OFFSET, dl,
829 MVT::i32);
830 Stack = DAG.getNode(ISD::ADD, dl, MVT::i32, Stack, FrameToArgs);
831 Stack = DAG.getNode(ISD::ADD, dl, MVT::i32, Stack, Offset);
832
833 // R0=ExceptionPointerRegister R1=ExceptionSelectorRegister
834 // which leaves 2 caller saved registers, R2 & R3 for us to use.
835 unsigned StackReg = XCore::R2;
836 unsigned HandlerReg = XCore::R3;
837
838 SDValue OutChains[] = {
839 DAG.getCopyToReg(Chain, dl, StackReg, Stack),
840 DAG.getCopyToReg(Chain, dl, HandlerReg, Handler)
841 };
842
843 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);
844
845 return DAG.getNode(XCoreISD::EH_RETURN, dl, MVT::Other, Chain,
846 DAG.getRegister(StackReg, MVT::i32),
847 DAG.getRegister(HandlerReg, MVT::i32));
848
849}
850
851SDValue XCoreTargetLowering::
852LowerADJUST_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const {
853 return Op.getOperand(0);
854}
855
856SDValue XCoreTargetLowering::
857LowerINIT_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const {
858 SDValue Chain = Op.getOperand(0);
859 SDValue Trmp = Op.getOperand(1); // trampoline
860 SDValue FPtr = Op.getOperand(2); // nested function
861 SDValue Nest = Op.getOperand(3); // 'nest' parameter value
862
863 const Value *TrmpAddr = cast<SrcValueSDNode>(Op.getOperand(4))->getValue();
864
865 // .align 4
866 // LDAPF_u10 r11, nest
867 // LDW_2rus r11, r11[0]
868 // STWSP_ru6 r11, sp[0]
869 // LDAPF_u10 r11, fptr
870 // LDW_2rus r11, r11[0]
871 // BAU_1r r11
872 // nest:
873 // .word nest
874 // fptr:
875 // .word fptr
876 SDValue OutChains[5];
877
878 SDValue Addr = Trmp;
879
880 SDLoc dl(Op);
881 OutChains[0] =
882 DAG.getStore(Chain, dl, DAG.getConstant(0x0a3cd805, dl, MVT::i32), Addr,
883 MachinePointerInfo(TrmpAddr));
884
885 Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp,
886 DAG.getConstant(4, dl, MVT::i32));
887 OutChains[1] =
888 DAG.getStore(Chain, dl, DAG.getConstant(0xd80456c0, dl, MVT::i32), Addr,
889 MachinePointerInfo(TrmpAddr, 4));
890
891 Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp,
892 DAG.getConstant(8, dl, MVT::i32));
893 OutChains[2] =
894 DAG.getStore(Chain, dl, DAG.getConstant(0x27fb0a3c, dl, MVT::i32), Addr,
895 MachinePointerInfo(TrmpAddr, 8));
896
897 Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp,
898 DAG.getConstant(12, dl, MVT::i32));
899 OutChains[3] =
900 DAG.getStore(Chain, dl, Nest, Addr, MachinePointerInfo(TrmpAddr, 12));
901
902 Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp,
903 DAG.getConstant(16, dl, MVT::i32));
904 OutChains[4] =
905 DAG.getStore(Chain, dl, FPtr, Addr, MachinePointerInfo(TrmpAddr, 16));
906
907 return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);
908}
909
910SDValue XCoreTargetLowering::
911LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const {
912 SDLoc DL(Op);
913 unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
914 switch (IntNo) {
915 case Intrinsic::xcore_crc8:
916 EVT VT = Op.getValueType();
917 SDValue Data =
918 DAG.getNode(XCoreISD::CRC8, DL, DAG.getVTList(VT, VT),
919 Op.getOperand(1), Op.getOperand(2) , Op.getOperand(3));
920 SDValue Crc(Data.getNode(), 1);
921 SDValue Results[] = { Crc, Data };
922 return DAG.getMergeValues(Results, DL);
923 }
924 return SDValue();
925}
926
927SDValue XCoreTargetLowering::
928LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG) const {
929 SDLoc DL(Op);
930 return DAG.getNode(ISD::MEMBARRIER, DL, MVT::Other, Op.getOperand(0));
931}
932
933SDValue XCoreTargetLowering::
934LowerATOMIC_LOAD(SDValue Op, SelectionDAG &DAG) const {
935 AtomicSDNode *N = cast<AtomicSDNode>(Op);
936 assert(N->getOpcode() == ISD::ATOMIC_LOAD && "Bad Atomic OP");
937 assert((N->getSuccessOrdering() == AtomicOrdering::Unordered ||
938 N->getSuccessOrdering() == AtomicOrdering::Monotonic) &&
939 "setInsertFencesForAtomic(true) expects unordered / monotonic");
940 if (N->getMemoryVT() == MVT::i32) {
941 if (N->getAlign() < Align(4))
942 report_fatal_error("atomic load must be aligned");
943 return DAG.getLoad(getPointerTy(DAG.getDataLayout()), SDLoc(Op),
944 N->getChain(), N->getBasePtr(), N->getPointerInfo(),
945 N->getAlign(), N->getMemOperand()->getFlags(),
946 N->getAAInfo(), N->getRanges());
947 }
948 if (N->getMemoryVT() == MVT::i16) {
949 if (N->getAlign() < Align(2))
950 report_fatal_error("atomic load must be aligned");
951 return DAG.getExtLoad(ISD::EXTLOAD, SDLoc(Op), MVT::i32, N->getChain(),
952 N->getBasePtr(), N->getPointerInfo(), MVT::i16,
953 N->getAlign(), N->getMemOperand()->getFlags(),
954 N->getAAInfo());
955 }
956 if (N->getMemoryVT() == MVT::i8)
957 return DAG.getExtLoad(ISD::EXTLOAD, SDLoc(Op), MVT::i32, N->getChain(),
958 N->getBasePtr(), N->getPointerInfo(), MVT::i8,
959 N->getAlign(), N->getMemOperand()->getFlags(),
960 N->getAAInfo());
961 return SDValue();
962}
963
964SDValue XCoreTargetLowering::
965LowerATOMIC_STORE(SDValue Op, SelectionDAG &DAG) const {
966 AtomicSDNode *N = cast<AtomicSDNode>(Op);
967 assert(N->getOpcode() == ISD::ATOMIC_STORE && "Bad Atomic OP");
968 assert((N->getSuccessOrdering() == AtomicOrdering::Unordered ||
969 N->getSuccessOrdering() == AtomicOrdering::Monotonic) &&
970 "setInsertFencesForAtomic(true) expects unordered / monotonic");
971 if (N->getMemoryVT() == MVT::i32) {
972 if (N->getAlign() < Align(4))
973 report_fatal_error("atomic store must be aligned");
974 return DAG.getStore(N->getChain(), SDLoc(Op), N->getVal(), N->getBasePtr(),
975 N->getPointerInfo(), N->getAlign(),
976 N->getMemOperand()->getFlags(), N->getAAInfo());
977 }
978 if (N->getMemoryVT() == MVT::i16) {
979 if (N->getAlign() < Align(2))
980 report_fatal_error("atomic store must be aligned");
981 return DAG.getTruncStore(N->getChain(), SDLoc(Op), N->getVal(),
982 N->getBasePtr(), N->getPointerInfo(), MVT::i16,
983 N->getAlign(), N->getMemOperand()->getFlags(),
984 N->getAAInfo());
985 }
986 if (N->getMemoryVT() == MVT::i8)
987 return DAG.getTruncStore(N->getChain(), SDLoc(Op), N->getVal(),
988 N->getBasePtr(), N->getPointerInfo(), MVT::i8,
989 N->getAlign(), N->getMemOperand()->getFlags(),
990 N->getAAInfo());
991 return SDValue();
992}
993
995XCoreTargetLowering::getTargetMMOFlags(const Instruction &I) const {
996 // Because of how we convert atomic_load and atomic_store to normal loads and
997 // stores in the DAG, we need to ensure that the MMOs are marked volatile
998 // since DAGCombine hasn't been updated to account for atomic, but non
999 // volatile loads. (See D57601)
1000 if (auto *SI = dyn_cast<StoreInst>(&I))
1001 if (SI->isAtomic())
1003 if (auto *LI = dyn_cast<LoadInst>(&I))
1004 if (LI->isAtomic())
1006 if (auto *AI = dyn_cast<AtomicRMWInst>(&I))
1007 if (AI->isAtomic())
1009 if (auto *AI = dyn_cast<AtomicCmpXchgInst>(&I))
1010 if (AI->isAtomic())
1013}
1014
1015//===----------------------------------------------------------------------===//
1016// Calling Convention Implementation
1017//===----------------------------------------------------------------------===//
1018
1019#include "XCoreGenCallingConv.inc"
1020
1021//===----------------------------------------------------------------------===//
1022// Call Calling Convention Implementation
1023//===----------------------------------------------------------------------===//
1024
1025/// XCore call implementation
1026SDValue
1027XCoreTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
1028 SmallVectorImpl<SDValue> &InVals) const {
1029 SelectionDAG &DAG = CLI.DAG;
1030 SDLoc &dl = CLI.DL;
1032 SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
1034 SDValue Chain = CLI.Chain;
1035 SDValue Callee = CLI.Callee;
1036 bool &isTailCall = CLI.IsTailCall;
1037 CallingConv::ID CallConv = CLI.CallConv;
1038 bool isVarArg = CLI.IsVarArg;
1039
1040 // XCore target does not yet support tail call optimization.
1041 isTailCall = false;
1042
1043 // For now, only CallingConv::C implemented
1044 switch (CallConv)
1045 {
1046 default:
1047 report_fatal_error("Unsupported calling convention");
1048 case CallingConv::Fast:
1049 case CallingConv::C:
1050 return LowerCCCCallTo(Chain, Callee, CallConv, isVarArg, isTailCall,
1051 Outs, OutVals, Ins, dl, DAG, InVals);
1052 }
1053}
1054
1055/// LowerCallResult - Lower the result values of a call into the
1056/// appropriate copies out of appropriate physical registers / memory locations.
1058 const SmallVectorImpl<CCValAssign> &RVLocs,
1059 const SDLoc &dl, SelectionDAG &DAG,
1060 SmallVectorImpl<SDValue> &InVals) {
1061 SmallVector<std::pair<int, unsigned>, 4> ResultMemLocs;
1062 // Copy results out of physical registers.
1063 for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
1064 const CCValAssign &VA = RVLocs[i];
1065 if (VA.isRegLoc()) {
1066 Chain = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getValVT(),
1067 InFlag).getValue(1);
1068 InFlag = Chain.getValue(2);
1069 InVals.push_back(Chain.getValue(0));
1070 } else {
1071 assert(VA.isMemLoc());
1072 ResultMemLocs.push_back(std::make_pair(VA.getLocMemOffset(),
1073 InVals.size()));
1074 // Reserve space for this result.
1075 InVals.push_back(SDValue());
1076 }
1077 }
1078
1079 // Copy results out of memory.
1080 SmallVector<SDValue, 4> MemOpChains;
1081 for (unsigned i = 0, e = ResultMemLocs.size(); i != e; ++i) {
1082 int offset = ResultMemLocs[i].first;
1083 unsigned index = ResultMemLocs[i].second;
1085 SDValue Ops[] = { Chain, DAG.getConstant(offset / 4, dl, MVT::i32) };
1086 SDValue load = DAG.getNode(XCoreISD::LDWSP, dl, VTs, Ops);
1087 InVals[index] = load;
1088 MemOpChains.push_back(load.getValue(1));
1089 }
1090
1091 // Transform all loads nodes into one single node because
1092 // all load nodes are independent of each other.
1093 if (!MemOpChains.empty())
1094 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
1095
1096 return Chain;
1097}
1098
1099/// LowerCCCCallTo - functions arguments are copied from virtual
1100/// regs to (physical regs)/(stack frame), CALLSEQ_START and
1101/// CALLSEQ_END are emitted.
1102/// TODO: isTailCall, sret.
1103SDValue XCoreTargetLowering::LowerCCCCallTo(
1104 SDValue Chain, SDValue Callee, CallingConv::ID CallConv, bool isVarArg,
1105 bool isTailCall, const SmallVectorImpl<ISD::OutputArg> &Outs,
1106 const SmallVectorImpl<SDValue> &OutVals,
1107 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
1108 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
1109
1110 // Analyze operands of the call, assigning locations to each operand.
1112 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
1113 *DAG.getContext());
1114
1115 // The ABI dictates there should be one stack slot available to the callee
1116 // on function entry (for saving lr).
1117 CCInfo.AllocateStack(4, Align(4));
1118
1119 CCInfo.AnalyzeCallOperands(Outs, CC_XCore);
1120
1122 // Analyze return values to determine the number of bytes of stack required.
1123 CCState RetCCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
1124 *DAG.getContext());
1125 RetCCInfo.AllocateStack(CCInfo.getNextStackOffset(), Align(4));
1126 RetCCInfo.AnalyzeCallResult(Ins, RetCC_XCore);
1127
1128 // Get a count of how many bytes are to be pushed on the stack.
1129 unsigned NumBytes = RetCCInfo.getNextStackOffset();
1130
1131 Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, dl);
1132
1134 SmallVector<SDValue, 12> MemOpChains;
1135
1136 // Walk the register/memloc assignments, inserting copies/loads.
1137 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
1138 CCValAssign &VA = ArgLocs[i];
1139 SDValue Arg = OutVals[i];
1140
1141 // Promote the value if needed.
1142 switch (VA.getLocInfo()) {
1143 default: llvm_unreachable("Unknown loc info!");
1144 case CCValAssign::Full: break;
1145 case CCValAssign::SExt:
1146 Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);
1147 break;
1148 case CCValAssign::ZExt:
1149 Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);
1150 break;
1151 case CCValAssign::AExt:
1152 Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);
1153 break;
1154 }
1155
1156 // Arguments that can be passed on register must be kept at
1157 // RegsToPass vector
1158 if (VA.isRegLoc()) {
1159 RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
1160 } else {
1161 assert(VA.isMemLoc());
1162
1163 int Offset = VA.getLocMemOffset();
1164
1165 MemOpChains.push_back(DAG.getNode(XCoreISD::STWSP, dl, MVT::Other,
1166 Chain, Arg,
1167 DAG.getConstant(Offset/4, dl,
1168 MVT::i32)));
1169 }
1170 }
1171
1172 // Transform all store nodes into one single node because
1173 // all store nodes are independent of each other.
1174 if (!MemOpChains.empty())
1175 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
1176
1177 // Build a sequence of copy-to-reg nodes chained together with token
1178 // chain and flag operands which copy the outgoing args into registers.
1179 // The InFlag in necessary since all emitted instructions must be
1180 // stuck together.
1181 SDValue InFlag;
1182 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
1183 Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
1184 RegsToPass[i].second, InFlag);
1185 InFlag = Chain.getValue(1);
1186 }
1187
1188 // If the callee is a GlobalAddress node (quite common, every direct call is)
1189 // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
1190 // Likewise ExternalSymbol -> TargetExternalSymbol.
1191 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
1192 Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32);
1193 else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
1194 Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32);
1195
1196 // XCoreBranchLink = #chain, #target_address, #opt_in_flags...
1197 // = Chain, Callee, Reg#1, Reg#2, ...
1198 //
1199 // Returns a chain & a flag for retval copy to use.
1200 SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
1202 Ops.push_back(Chain);
1203 Ops.push_back(Callee);
1204
1205 // Add argument registers to the end of the list so that they are
1206 // known live into the call.
1207 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
1208 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
1209 RegsToPass[i].second.getValueType()));
1210
1211 if (InFlag.getNode())
1212 Ops.push_back(InFlag);
1213
1214 Chain = DAG.getNode(XCoreISD::BL, dl, NodeTys, Ops);
1215 InFlag = Chain.getValue(1);
1216
1217 // Create the CALLSEQ_END node.
1218 Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, InFlag, dl);
1219 InFlag = Chain.getValue(1);
1220
1221 // Handle result values, copying them out of physregs into vregs that we
1222 // return.
1223 return LowerCallResult(Chain, InFlag, RVLocs, dl, DAG, InVals);
1224}
1225
1226//===----------------------------------------------------------------------===//
1227// Formal Arguments Calling Convention Implementation
1228//===----------------------------------------------------------------------===//
1229
1230namespace {
1231 struct ArgDataPair { SDValue SDV; ISD::ArgFlagsTy Flags; };
1232}
1233
1234/// XCore formal arguments implementation
1235SDValue XCoreTargetLowering::LowerFormalArguments(
1236 SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
1237 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
1238 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
1239 switch (CallConv)
1240 {
1241 default:
1242 report_fatal_error("Unsupported calling convention");
1243 case CallingConv::C:
1244 case CallingConv::Fast:
1245 return LowerCCCArguments(Chain, CallConv, isVarArg,
1246 Ins, dl, DAG, InVals);
1247 }
1248}
1249
1250/// LowerCCCArguments - transform physical registers into
1251/// virtual registers and generate load operations for
1252/// arguments places on the stack.
1253/// TODO: sret
1254SDValue XCoreTargetLowering::LowerCCCArguments(
1255 SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
1256 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
1257 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
1259 MachineFrameInfo &MFI = MF.getFrameInfo();
1262
1263 // Assign locations to all of the incoming arguments.
1265 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
1266 *DAG.getContext());
1267
1268 CCInfo.AnalyzeFormalArguments(Ins, CC_XCore);
1269
1270 unsigned StackSlotSize = XCoreFrameLowering::stackSlotSize();
1271
1272 unsigned LRSaveSize = StackSlotSize;
1273
1274 if (!isVarArg)
1275 XFI->setReturnStackOffset(CCInfo.getNextStackOffset() + LRSaveSize);
1276
1277 // All getCopyFromReg ops must precede any getMemcpys to prevent the
1278 // scheduler clobbering a register before it has been copied.
1279 // The stages are:
1280 // 1. CopyFromReg (and load) arg & vararg registers.
1281 // 2. Chain CopyFromReg nodes into a TokenFactor.
1282 // 3. Memcpy 'byVal' args & push final InVals.
1283 // 4. Chain mem ops nodes into a TokenFactor.
1284 SmallVector<SDValue, 4> CFRegNode;
1287
1288 // 1a. CopyFromReg (and load) arg registers.
1289 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
1290
1291 CCValAssign &VA = ArgLocs[i];
1292 SDValue ArgIn;
1293
1294 if (VA.isRegLoc()) {
1295 // Arguments passed in registers
1296 EVT RegVT = VA.getLocVT();
1297 switch (RegVT.getSimpleVT().SimpleTy) {
1298 default:
1299 {
1300#ifndef NDEBUG
1301 errs() << "LowerFormalArguments Unhandled argument type: "
1302 << RegVT << "\n";
1303#endif
1304 llvm_unreachable(nullptr);
1305 }
1306 case MVT::i32:
1307 Register VReg = RegInfo.createVirtualRegister(&XCore::GRRegsRegClass);
1308 RegInfo.addLiveIn(VA.getLocReg(), VReg);
1309 ArgIn = DAG.getCopyFromReg(Chain, dl, VReg, RegVT);
1310 CFRegNode.push_back(ArgIn.getValue(ArgIn->getNumValues() - 1));
1311 }
1312 } else {
1313 // Only arguments passed on the stack should make it here.
1314 assert(VA.isMemLoc());
1315 // Load the argument to a virtual register
1316 unsigned ObjSize = VA.getLocVT().getSizeInBits()/8;
1317 if (ObjSize > StackSlotSize) {
1318 errs() << "LowerFormalArguments Unhandled argument type: "
1319 << VA.getLocVT() << "\n";
1320 }
1321 // Create the frame index object for this incoming parameter...
1322 int FI = MFI.CreateFixedObject(ObjSize,
1323 LRSaveSize + VA.getLocMemOffset(),
1324 true);
1325
1326 // Create the SelectionDAG nodes corresponding to a load
1327 //from this parameter
1328 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
1329 ArgIn = DAG.getLoad(VA.getLocVT(), dl, Chain, FIN,
1331 }
1332 const ArgDataPair ADP = { ArgIn, Ins[i].Flags };
1333 ArgData.push_back(ADP);
1334 }
1335
1336 // 1b. CopyFromReg vararg registers.
1337 if (isVarArg) {
1338 // Argument registers
1339 static const MCPhysReg ArgRegs[] = {
1340 XCore::R0, XCore::R1, XCore::R2, XCore::R3
1341 };
1343 unsigned FirstVAReg = CCInfo.getFirstUnallocated(ArgRegs);
1344 if (FirstVAReg < std::size(ArgRegs)) {
1345 int offset = 0;
1346 // Save remaining registers, storing higher register numbers at a higher
1347 // address
1348 for (int i = std::size(ArgRegs) - 1; i >= (int)FirstVAReg; --i) {
1349 // Create a stack slot
1350 int FI = MFI.CreateFixedObject(4, offset, true);
1351 if (i == (int)FirstVAReg) {
1352 XFI->setVarArgsFrameIndex(FI);
1353 }
1354 offset -= StackSlotSize;
1355 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
1356 // Move argument from phys reg -> virt reg
1357 Register VReg = RegInfo.createVirtualRegister(&XCore::GRRegsRegClass);
1358 RegInfo.addLiveIn(ArgRegs[i], VReg);
1359 SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
1360 CFRegNode.push_back(Val.getValue(Val->getNumValues() - 1));
1361 // Move argument from virt reg -> stack
1362 SDValue Store =
1363 DAG.getStore(Val.getValue(1), dl, Val, FIN, MachinePointerInfo());
1364 MemOps.push_back(Store);
1365 }
1366 } else {
1367 // This will point to the next argument passed via stack.
1369 MFI.CreateFixedObject(4, LRSaveSize + CCInfo.getNextStackOffset(),
1370 true));
1371 }
1372 }
1373
1374 // 2. chain CopyFromReg nodes into a TokenFactor.
1375 if (!CFRegNode.empty())
1376 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, CFRegNode);
1377
1378 // 3. Memcpy 'byVal' args & push final InVals.
1379 // Aggregates passed "byVal" need to be copied by the callee.
1380 // The callee will use a pointer to this copy, rather than the original
1381 // pointer.
1382 for (const ArgDataPair &ArgDI : ArgData) {
1383 if (ArgDI.Flags.isByVal() && ArgDI.Flags.getByValSize()) {
1384 unsigned Size = ArgDI.Flags.getByValSize();
1385 Align Alignment =
1386 std::max(Align(StackSlotSize), ArgDI.Flags.getNonZeroByValAlign());
1387 // Create a new object on the stack and copy the pointee into it.
1388 int FI = MFI.CreateStackObject(Size, Alignment, false);
1389 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
1390 InVals.push_back(FIN);
1391 MemOps.push_back(DAG.getMemcpy(
1392 Chain, dl, FIN, ArgDI.SDV, DAG.getConstant(Size, dl, MVT::i32),
1393 Alignment, false, false, false, MachinePointerInfo(),
1395 } else {
1396 InVals.push_back(ArgDI.SDV);
1397 }
1398 }
1399
1400 // 4, chain mem ops nodes into a TokenFactor.
1401 if (!MemOps.empty()) {
1402 MemOps.push_back(Chain);
1403 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOps);
1404 }
1405
1406 return Chain;
1407}
1408
1409//===----------------------------------------------------------------------===//
1410// Return Value Calling Convention Implementation
1411//===----------------------------------------------------------------------===//
1412
1413bool XCoreTargetLowering::
1414CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
1415 bool isVarArg,
1417 LLVMContext &Context) const {
1419 CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context);
1420 if (!CCInfo.CheckReturn(Outs, RetCC_XCore))
1421 return false;
1422 if (CCInfo.getNextStackOffset() != 0 && isVarArg)
1423 return false;
1424 return true;
1425}
1426
1427SDValue
1428XCoreTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
1429 bool isVarArg,
1431 const SmallVectorImpl<SDValue> &OutVals,
1432 const SDLoc &dl, SelectionDAG &DAG) const {
1433
1434 XCoreFunctionInfo *XFI =
1437
1438 // CCValAssign - represent the assignment of
1439 // the return value to a location
1441
1442 // CCState - Info about the registers and stack slot.
1443 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
1444 *DAG.getContext());
1445
1446 // Analyze return values.
1447 if (!isVarArg)
1448 CCInfo.AllocateStack(XFI->getReturnStackOffset(), Align(4));
1449
1450 CCInfo.AnalyzeReturn(Outs, RetCC_XCore);
1451
1452 SDValue Flag;
1453 SmallVector<SDValue, 4> RetOps(1, Chain);
1454
1455 // Return on XCore is always a "retsp 0"
1456 RetOps.push_back(DAG.getConstant(0, dl, MVT::i32));
1457
1458 SmallVector<SDValue, 4> MemOpChains;
1459 // Handle return values that must be copied to memory.
1460 for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
1461 CCValAssign &VA = RVLocs[i];
1462 if (VA.isRegLoc())
1463 continue;
1464 assert(VA.isMemLoc());
1465 if (isVarArg) {
1466 report_fatal_error("Can't return value from vararg function in memory");
1467 }
1468
1469 int Offset = VA.getLocMemOffset();
1470 unsigned ObjSize = VA.getLocVT().getSizeInBits() / 8;
1471 // Create the frame index object for the memory location.
1472 int FI = MFI.CreateFixedObject(ObjSize, Offset, false);
1473
1474 // Create a SelectionDAG node corresponding to a store
1475 // to this memory location.
1476 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
1477 MemOpChains.push_back(DAG.getStore(
1478 Chain, dl, OutVals[i], FIN,
1480 }
1481
1482 // Transform all store nodes into one single node because
1483 // all stores are independent of each other.
1484 if (!MemOpChains.empty())
1485 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
1486
1487 // Now handle return values copied to registers.
1488 for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
1489 CCValAssign &VA = RVLocs[i];
1490 if (!VA.isRegLoc())
1491 continue;
1492 // Copy the result values into the output registers.
1493 Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Flag);
1494
1495 // guarantee that all emitted copies are
1496 // stuck together, avoiding something bad
1497 Flag = Chain.getValue(1);
1498 RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
1499 }
1500
1501 RetOps[0] = Chain; // Update chain.
1502
1503 // Add the flag if we have it.
1504 if (Flag.getNode())
1505 RetOps.push_back(Flag);
1506
1507 return DAG.getNode(XCoreISD::RETSP, dl, MVT::Other, RetOps);
1508}
1509
1510//===----------------------------------------------------------------------===//
1511// Other Lowering Code
1512//===----------------------------------------------------------------------===//
1513
1516 MachineBasicBlock *BB) const {
1517 const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
1518 DebugLoc dl = MI.getDebugLoc();
1519 assert((MI.getOpcode() == XCore::SELECT_CC) &&
1520 "Unexpected instr type to insert");
1521
1522 // To "insert" a SELECT_CC instruction, we actually have to insert the diamond
1523 // control-flow pattern. The incoming instruction knows the destination vreg
1524 // to set, the condition code register to branch on, the true/false values to
1525 // select between, and a branch opcode to use.
1526 const BasicBlock *LLVM_BB = BB->getBasicBlock();
1528
1529 // thisMBB:
1530 // ...
1531 // TrueVal = ...
1532 // cmpTY ccX, r1, r2
1533 // bCC copy1MBB
1534 // fallthrough --> copy0MBB
1535 MachineBasicBlock *thisMBB = BB;
1536 MachineFunction *F = BB->getParent();
1537 MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
1538 MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
1539 F->insert(It, copy0MBB);
1540 F->insert(It, sinkMBB);
1541
1542 // Transfer the remainder of BB and its successor edges to sinkMBB.
1543 sinkMBB->splice(sinkMBB->begin(), BB,
1544 std::next(MachineBasicBlock::iterator(MI)), BB->end());
1546
1547 // Next, add the true and fallthrough blocks as its successors.
1548 BB->addSuccessor(copy0MBB);
1549 BB->addSuccessor(sinkMBB);
1550
1551 BuildMI(BB, dl, TII.get(XCore::BRFT_lru6))
1552 .addReg(MI.getOperand(1).getReg())
1553 .addMBB(sinkMBB);
1554
1555 // copy0MBB:
1556 // %FalseValue = ...
1557 // # fallthrough to sinkMBB
1558 BB = copy0MBB;
1559
1560 // Update machine-CFG edges
1561 BB->addSuccessor(sinkMBB);
1562
1563 // sinkMBB:
1564 // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ]
1565 // ...
1566 BB = sinkMBB;
1567 BuildMI(*BB, BB->begin(), dl, TII.get(XCore::PHI), MI.getOperand(0).getReg())
1568 .addReg(MI.getOperand(3).getReg())
1569 .addMBB(copy0MBB)
1570 .addReg(MI.getOperand(2).getReg())
1571 .addMBB(thisMBB);
1572
1573 MI.eraseFromParent(); // The pseudo instruction is gone now.
1574 return BB;
1575}
1576
1577//===----------------------------------------------------------------------===//
1578// Target Optimization Hooks
1579//===----------------------------------------------------------------------===//
1580
1581SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N,
1582 DAGCombinerInfo &DCI) const {
1583 SelectionDAG &DAG = DCI.DAG;
1584 SDLoc dl(N);
1585 switch (N->getOpcode()) {
1586 default: break;
1588 switch (cast<ConstantSDNode>(N->getOperand(1))->getZExtValue()) {
1589 case Intrinsic::xcore_outt:
1590 case Intrinsic::xcore_outct:
1591 case Intrinsic::xcore_chkct: {
1592 SDValue OutVal = N->getOperand(3);
1593 // These instructions ignore the high bits.
1594 if (OutVal.hasOneUse()) {
1595 unsigned BitWidth = OutVal.getValueSizeInBits();
1596 APInt DemandedMask = APInt::getLowBitsSet(BitWidth, 8);
1597 KnownBits Known;
1598 TargetLowering::TargetLoweringOpt TLO(DAG, !DCI.isBeforeLegalize(),
1599 !DCI.isBeforeLegalizeOps());
1600 const TargetLowering &TLI = DAG.getTargetLoweringInfo();
1601 if (TLI.ShrinkDemandedConstant(OutVal, DemandedMask, TLO) ||
1602 TLI.SimplifyDemandedBits(OutVal, DemandedMask, Known, TLO))
1603 DCI.CommitTargetLoweringOpt(TLO);
1604 }
1605 break;
1606 }
1607 case Intrinsic::xcore_setpt: {
1608 SDValue Time = N->getOperand(3);
1609 // This instruction ignores the high bits.
1610 if (Time.hasOneUse()) {
1611 unsigned BitWidth = Time.getValueSizeInBits();
1612 APInt DemandedMask = APInt::getLowBitsSet(BitWidth, 16);
1613 KnownBits Known;
1614 TargetLowering::TargetLoweringOpt TLO(DAG, !DCI.isBeforeLegalize(),
1615 !DCI.isBeforeLegalizeOps());
1616 const TargetLowering &TLI = DAG.getTargetLoweringInfo();
1617 if (TLI.ShrinkDemandedConstant(Time, DemandedMask, TLO) ||
1618 TLI.SimplifyDemandedBits(Time, DemandedMask, Known, TLO))
1619 DCI.CommitTargetLoweringOpt(TLO);
1620 }
1621 break;
1622 }
1623 }
1624 break;
1625 case XCoreISD::LADD: {
1626 SDValue N0 = N->getOperand(0);
1627 SDValue N1 = N->getOperand(1);
1628 SDValue N2 = N->getOperand(2);
1629 ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
1630 ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
1631 EVT VT = N0.getValueType();
1632
1633 // canonicalize constant to RHS
1634 if (N0C && !N1C)
1635 return DAG.getNode(XCoreISD::LADD, dl, DAG.getVTList(VT, VT), N1, N0, N2);
1636
1637 // fold (ladd 0, 0, x) -> 0, x & 1
1638 if (N0C && N0C->isZero() && N1C && N1C->isZero()) {
1639 SDValue Carry = DAG.getConstant(0, dl, VT);
1640 SDValue Result = DAG.getNode(ISD::AND, dl, VT, N2,
1641 DAG.getConstant(1, dl, VT));
1642 SDValue Ops[] = { Result, Carry };
1643 return DAG.getMergeValues(Ops, dl);
1644 }
1645
1646 // fold (ladd x, 0, y) -> 0, add x, y iff carry is unused and y has only the
1647 // low bit set
1648 if (N1C && N1C->isZero() && N->hasNUsesOfValue(0, 1)) {
1650 VT.getSizeInBits() - 1);
1651 KnownBits Known = DAG.computeKnownBits(N2);
1652 if ((Known.Zero & Mask) == Mask) {
1653 SDValue Carry = DAG.getConstant(0, dl, VT);
1654 SDValue Result = DAG.getNode(ISD::ADD, dl, VT, N0, N2);
1655 SDValue Ops[] = { Result, Carry };
1656 return DAG.getMergeValues(Ops, dl);
1657 }
1658 }
1659 }
1660 break;
1661 case XCoreISD::LSUB: {
1662 SDValue N0 = N->getOperand(0);
1663 SDValue N1 = N->getOperand(1);
1664 SDValue N2 = N->getOperand(2);
1665 ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
1666 ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
1667 EVT VT = N0.getValueType();
1668
1669 // fold (lsub 0, 0, x) -> x, -x iff x has only the low bit set
1670 if (N0C && N0C->isZero() && N1C && N1C->isZero()) {
1672 VT.getSizeInBits() - 1);
1673 KnownBits Known = DAG.computeKnownBits(N2);
1674 if ((Known.Zero & Mask) == Mask) {
1675 SDValue Borrow = N2;
1676 SDValue Result = DAG.getNode(ISD::SUB, dl, VT,
1677 DAG.getConstant(0, dl, VT), N2);
1678 SDValue Ops[] = { Result, Borrow };
1679 return DAG.getMergeValues(Ops, dl);
1680 }
1681 }
1682
1683 // fold (lsub x, 0, y) -> 0, sub x, y iff borrow is unused and y has only the
1684 // low bit set
1685 if (N1C && N1C->isZero() && N->hasNUsesOfValue(0, 1)) {
1687 VT.getSizeInBits() - 1);
1688 KnownBits Known = DAG.computeKnownBits(N2);
1689 if ((Known.Zero & Mask) == Mask) {
1690 SDValue Borrow = DAG.getConstant(0, dl, VT);
1691 SDValue Result = DAG.getNode(ISD::SUB, dl, VT, N0, N2);
1692 SDValue Ops[] = { Result, Borrow };
1693 return DAG.getMergeValues(Ops, dl);
1694 }
1695 }
1696 }
1697 break;
1698 case XCoreISD::LMUL: {
1699 SDValue N0 = N->getOperand(0);
1700 SDValue N1 = N->getOperand(1);
1701 SDValue N2 = N->getOperand(2);
1702 SDValue N3 = N->getOperand(3);
1703 ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
1704 ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
1705 EVT VT = N0.getValueType();
1706 // Canonicalize multiplicative constant to RHS. If both multiplicative
1707 // operands are constant canonicalize smallest to RHS.
1708 if ((N0C && !N1C) ||
1709 (N0C && N1C && N0C->getZExtValue() < N1C->getZExtValue()))
1710 return DAG.getNode(XCoreISD::LMUL, dl, DAG.getVTList(VT, VT),
1711 N1, N0, N2, N3);
1712
1713 // lmul(x, 0, a, b)
1714 if (N1C && N1C->isZero()) {
1715 // If the high result is unused fold to add(a, b)
1716 if (N->hasNUsesOfValue(0, 0)) {
1717 SDValue Lo = DAG.getNode(ISD::ADD, dl, VT, N2, N3);
1718 SDValue Ops[] = { Lo, Lo };
1719 return DAG.getMergeValues(Ops, dl);
1720 }
1721 // Otherwise fold to ladd(a, b, 0)
1722 SDValue Result =
1723 DAG.getNode(XCoreISD::LADD, dl, DAG.getVTList(VT, VT), N2, N3, N1);
1724 SDValue Carry(Result.getNode(), 1);
1725 SDValue Ops[] = { Carry, Result };
1726 return DAG.getMergeValues(Ops, dl);
1727 }
1728 }
1729 break;
1730 case ISD::ADD: {
1731 // Fold 32 bit expressions such as add(add(mul(x,y),a),b) ->
1732 // lmul(x, y, a, b). The high result of lmul will be ignored.
1733 // This is only profitable if the intermediate results are unused
1734 // elsewhere.
1735 SDValue Mul0, Mul1, Addend0, Addend1;
1736 if (N->getValueType(0) == MVT::i32 &&
1737 isADDADDMUL(SDValue(N, 0), Mul0, Mul1, Addend0, Addend1, true)) {
1738 SDValue Ignored = DAG.getNode(XCoreISD::LMUL, dl,
1739 DAG.getVTList(MVT::i32, MVT::i32), Mul0,
1740 Mul1, Addend0, Addend1);
1741 SDValue Result(Ignored.getNode(), 1);
1742 return Result;
1743 }
1744 APInt HighMask = APInt::getHighBitsSet(64, 32);
1745 // Fold 64 bit expression such as add(add(mul(x,y),a),b) ->
1746 // lmul(x, y, a, b) if all operands are zero-extended. We do this
1747 // before type legalization as it is messy to match the operands after
1748 // that.
1749 if (N->getValueType(0) == MVT::i64 &&
1750 isADDADDMUL(SDValue(N, 0), Mul0, Mul1, Addend0, Addend1, false) &&
1751 DAG.MaskedValueIsZero(Mul0, HighMask) &&
1752 DAG.MaskedValueIsZero(Mul1, HighMask) &&
1753 DAG.MaskedValueIsZero(Addend0, HighMask) &&
1754 DAG.MaskedValueIsZero(Addend1, HighMask)) {
1756 Mul0, DAG.getConstant(0, dl, MVT::i32));
1758 Mul1, DAG.getConstant(0, dl, MVT::i32));
1759 SDValue Addend0L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
1760 Addend0, DAG.getConstant(0, dl, MVT::i32));
1761 SDValue Addend1L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
1762 Addend1, DAG.getConstant(0, dl, MVT::i32));
1763 SDValue Hi = DAG.getNode(XCoreISD::LMUL, dl,
1764 DAG.getVTList(MVT::i32, MVT::i32), Mul0L, Mul1L,
1765 Addend0L, Addend1L);
1766 SDValue Lo(Hi.getNode(), 1);
1767 return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);
1768 }
1769 }
1770 break;
1771 case ISD::STORE: {
1772 // Replace unaligned store of unaligned load with memmove.
1773 StoreSDNode *ST = cast<StoreSDNode>(N);
1774 if (!DCI.isBeforeLegalize() ||
1776 ST->getMemoryVT(),
1777 *ST->getMemOperand()) ||
1778 ST->isVolatile() || ST->isIndexed()) {
1779 break;
1780 }
1781 SDValue Chain = ST->getChain();
1782
1783 unsigned StoreBits = ST->getMemoryVT().getStoreSizeInBits();
1784 assert((StoreBits % 8) == 0 &&
1785 "Store size in bits must be a multiple of 8");
1786 Align Alignment = ST->getAlign();
1787
1788 if (LoadSDNode *LD = dyn_cast<LoadSDNode>(ST->getValue())) {
1789 if (LD->hasNUsesOfValue(1, 0) && ST->getMemoryVT() == LD->getMemoryVT() &&
1790 LD->getAlign() == Alignment &&
1791 !LD->isVolatile() && !LD->isIndexed() &&
1793 bool isTail = isInTailCallPosition(DAG, ST, Chain);
1794 return DAG.getMemmove(Chain, dl, ST->getBasePtr(), LD->getBasePtr(),
1795 DAG.getConstant(StoreBits / 8, dl, MVT::i32),
1796 Alignment, false, isTail,
1797 ST->getPointerInfo(), LD->getPointerInfo());
1798 }
1799 }
1800 break;
1801 }
1802 }
1803 return SDValue();
1804}
1805
1806void XCoreTargetLowering::computeKnownBitsForTargetNode(const SDValue Op,
1807 KnownBits &Known,
1808 const APInt &DemandedElts,
1809 const SelectionDAG &DAG,
1810 unsigned Depth) const {
1811 Known.resetAll();
1812 switch (Op.getOpcode()) {
1813 default: break;
1814 case XCoreISD::LADD:
1815 case XCoreISD::LSUB:
1816 if (Op.getResNo() == 1) {
1817 // Top bits of carry / borrow are clear.
1818 Known.Zero = APInt::getHighBitsSet(Known.getBitWidth(),
1819 Known.getBitWidth() - 1);
1820 }
1821 break;
1823 {
1824 unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue();
1825 switch (IntNo) {
1826 case Intrinsic::xcore_getts:
1827 // High bits are known to be zero.
1828 Known.Zero = APInt::getHighBitsSet(Known.getBitWidth(),
1829 Known.getBitWidth() - 16);
1830 break;
1831 case Intrinsic::xcore_int:
1832 case Intrinsic::xcore_inct:
1833 // High bits are known to be zero.
1834 Known.Zero = APInt::getHighBitsSet(Known.getBitWidth(),
1835 Known.getBitWidth() - 8);
1836 break;
1837 case Intrinsic::xcore_testct:
1838 // Result is either 0 or 1.
1839 Known.Zero = APInt::getHighBitsSet(Known.getBitWidth(),
1840 Known.getBitWidth() - 1);
1841 break;
1842 case Intrinsic::xcore_testwct:
1843 // Result is in the range 0 - 4.
1844 Known.Zero = APInt::getHighBitsSet(Known.getBitWidth(),
1845 Known.getBitWidth() - 3);
1846 break;
1847 }
1848 }
1849 break;
1850 }
1851}
1852
1853//===----------------------------------------------------------------------===//
1854// Addressing mode description hooks
1855//===----------------------------------------------------------------------===//
1856
1857static inline bool isImmUs(int64_t val)
1858{
1859 return (val >= 0 && val <= 11);
1860}
1861
1862static inline bool isImmUs2(int64_t val)
1863{
1864 return (val%2 == 0 && isImmUs(val/2));
1865}
1866
1867static inline bool isImmUs4(int64_t val)
1868{
1869 return (val%4 == 0 && isImmUs(val/4));
1870}
1871
1872/// isLegalAddressingMode - Return true if the addressing mode represented
1873/// by AM is legal for this target, for a load/store of the specified type.
1875 const AddrMode &AM, Type *Ty,
1876 unsigned AS,
1877 Instruction *I) const {
1878 if (Ty->getTypeID() == Type::VoidTyID)
1879 return AM.Scale == 0 && isImmUs(AM.BaseOffs) && isImmUs4(AM.BaseOffs);
1880
1881 unsigned Size = DL.getTypeAllocSize(Ty);
1882 if (AM.BaseGV) {
1883 return Size >= 4 && !AM.HasBaseReg && AM.Scale == 0 &&
1884 AM.BaseOffs%4 == 0;
1885 }
1886
1887 switch (Size) {
1888 case 1:
1889 // reg + imm
1890 if (AM.Scale == 0) {
1891 return isImmUs(AM.BaseOffs);
1892 }
1893 // reg + reg
1894 return AM.Scale == 1 && AM.BaseOffs == 0;
1895 case 2:
1896 case 3:
1897 // reg + imm
1898 if (AM.Scale == 0) {
1899 return isImmUs2(AM.BaseOffs);
1900 }
1901 // reg + reg<<1
1902 return AM.Scale == 2 && AM.BaseOffs == 0;
1903 default:
1904 // reg + imm
1905 if (AM.Scale == 0) {
1906 return isImmUs4(AM.BaseOffs);
1907 }
1908 // reg + reg<<2
1909 return AM.Scale == 4 && AM.BaseOffs == 0;
1910 }
1911}
1912
1913//===----------------------------------------------------------------------===//
1914// XCore Inline Assembly Support
1915//===----------------------------------------------------------------------===//
1916
1917std::pair<unsigned, const TargetRegisterClass *>
1918XCoreTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
1919 StringRef Constraint,
1920 MVT VT) const {
1921 if (Constraint.size() == 1) {
1922 switch (Constraint[0]) {
1923 default : break;
1924 case 'r':
1925 return std::make_pair(0U, &XCore::GRRegsRegClass);
1926 }
1927 }
1928 // Use the default implementation in TargetLowering to convert the register
1929 // constraint into a member of a register class.
1930 return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
1931}
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
amdgpu Simplify well known AMD library false FunctionCallee Callee
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
Function Alias Analysis Results
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
uint64_t Addr
uint64_t Size
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
#define G(x, y, z)
Definition: MD5.cpp:56
unsigned const TargetRegisterInfo * TRI
uint64_t High
LLVMContext & Context
const char LLVMTargetMachineRef TM
@ SI
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
@ Flags
Definition: TextStubV5.cpp:93
Value * RHS
Value * LHS
static bool isImmUs(int64_t val)
static bool isImmUs4(int64_t val)
static bool IsSmallObject(const GlobalValue *GV, const XCoreTargetLowering &XTL)
static bool isWordAligned(SDValue Value, SelectionDAG &DAG)
static bool isADDADDMUL(SDValue Op, SDValue &Mul0, SDValue &Mul1, SDValue &Addend0, SDValue &Addend1, bool requireIntermediatesHaveOneUse)
isADDADDMUL - Return whether Op is in a form that is equivalent to add(add(mul(x,y),...
static bool isImmUs2(int64_t val)
static SDValue LowerCallResult(SDValue Chain, SDValue InFlag, const SmallVectorImpl< CCValAssign > &RVLocs, const SDLoc &dl, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals)
LowerCallResult - Lower the result values of a call into the appropriate copies out of appropriate ph...
Class for arbitrary precision integers.
Definition: APInt.h:75
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
Definition: APInt.h:289
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
Definition: APInt.h:279
This is an SDNode representing atomic operations.
LLVM Basic Block Representation.
Definition: BasicBlock.h:56
The address of a basic block.
Definition: Constants.h:879
CCState - This class holds information needed while lowering arguments and return values.
CCValAssign - Represent assignment of one arg/retval to a location.
bool isRegLoc() const
unsigned getLocMemOffset() const
Register getLocReg() const
LocInfo getLocInfo() const
bool isMemLoc() const
static Constant * getGetElementPtr(Type *Ty, Constant *C, ArrayRef< Constant * > IdxList, bool InBounds=false, std::optional< unsigned > InRangeIndex=std::nullopt, Type *OnlyIfReducedTy=nullptr)
Getelementptr form.
Definition: Constants.h:1232
static Constant * getBitCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
Definition: Constants.cpp:2220
static Constant * get(Type *Ty, uint64_t V, bool IsSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
Definition: Constants.cpp:888
uint64_t getZExtValue() const
This is an important base class in LLVM.
Definition: Constant.h:41
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:110
IntegerType * getIntPtrType(LLVMContext &C, unsigned AddressSpace=0) const
Returns an integer type with size at least as big as that of a pointer in the given address space.
Definition: DataLayout.cpp:861
A debug info location.
Definition: DebugLoc.h:33
const GlobalValue * getGlobal() const
bool hasLocalLinkage() const
Definition: GlobalValue.h:523
StringRef getSection() const
Definition: Globals.cpp:175
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:652
bool hasSection() const
Definition: GlobalValue.h:286
Type * getValueType() const
Definition: GlobalValue.h:292
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:67
This class is used to represent ISD::LOAD nodes.
Machine Value Type.
SimpleValueType SimpleTy
static auto integer_valuetypes()
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
Definition: MachineInstr.h:68
@ EK_Inline
EK_Inline - Jump table entries are emitted inline at their point of use.
const std::vector< MachineJumpTableEntry > & getJumpTables() const
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
Definition: Module.cpp:398
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
bool reachesChainWithoutSideEffects(SDValue Dest, unsigned Depth=2) const
Return true if this operand (which must be a chain) reaches the specified operand without crossing an...
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
unsigned getOpcode() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
Definition: SelectionDAG.h:225
SDValue getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
Definition: SelectionDAG.h:721
SDValue getMemmove(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align Alignment, bool isVol, bool isTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), AAResults *AA=nullptr)
SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
SDValue getConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offs=0, bool isT=false, unsigned TargetFlags=0)
SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
const TargetLowering & getTargetLoweringInfo() const
Definition: SelectionDAG.h:478
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
Definition: SelectionDAG.h:731
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align Alignment, bool isVol, bool AlwaysInline, bool isTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), AAResults *AA=nullptr)
const DataLayout & getDataLayout() const
Definition: SelectionDAG.h:472
SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, bool isTargetGA=false, unsigned TargetFlags=0)
SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
SDValue getRegister(unsigned Reg, EVT VT)
SDValue getExternalSymbol(const char *Sym, EVT VT)
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, unsigned Reg, SDValue N)
Definition: SelectionDAG.h:773
SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
unsigned ComputeNumSignBits(SDValue Op, unsigned Depth=0) const
Return the number of times the sign bit of the register is replicated into the other bits.
SDValue getTargetBlockAddress(const BlockAddress *BA, EVT VT, int64_t Offset=0, unsigned TargetFlags=0)
Definition: SelectionDAG.h:768
bool isBaseWithConstantOffset(SDValue Op) const
Return true if the specified operand is an ISD::ADD with a ConstantSDNode on the right-hand side,...
MachineFunction & getMachineFunction() const
Definition: SelectionDAG.h:469
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, unsigned Reg, EVT VT)
Definition: SelectionDAG.h:799
SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
LLVMContext * getContext() const
Definition: SelectionDAG.h:485
SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
SDValue getTargetConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offset=0, unsigned TargetFlags=0)
Definition: SelectionDAG.h:737
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
Definition: SelectionDAG.h:554
bool empty() const
Definition: SmallVector.h:94
size_t size() const
Definition: SmallVector.h:91
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:577
void push_back(const T &Elt)
Definition: SmallVector.h:416
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
This class is used to represent ISD::STORE nodes.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:137
bool startswith(StringRef Prefix) const
Definition: StringRef.h:261
TargetInstrInfo - Interface to description of machine instruction set.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
unsigned MaxStoresPerMemcpyOptSize
Likewise for functions with the OptSize attribute.
const TargetMachine & getTargetMachine() const
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
unsigned MaxStoresPerMemsetOptSize
Likewise for functions with the OptSize attribute.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
unsigned MaxStoresPerMemmove
Specify maximum number of store instructions per memmove call.
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
unsigned MaxStoresPerMemmoveOptSize
Likewise for functions with the OptSize attribute.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
unsigned MaxStoresPerMemset
Specify maximum number of store instructions per memset call.
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
void setTargetDAGCombine(ArrayRef< ISD::NodeType > NTs)
Targets should invoke this method for each target independent node that they want to provide a custom...
void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified load with extension does not work with the specified type and indicate wh...
std::vector< ArgListEntry > ArgListTy
bool allowsMemoryAccessForAlignment(LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const
This function returns true if the memory access is aligned or if the target allows this specific unal...
unsigned MaxStoresPerMemcpy
Specify maximum number of store instructions per memcpy call.
void setSchedulingPreference(Sched::Preference Pref)
Specify the target scheduling preference.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
bool ShrinkDemandedConstant(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, TargetLoweringOpt &TLO) const
Check to see if the specified operand of the specified instruction is a constant integer.
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedBits, const APInt &DemandedElts, KnownBits &Known, TargetLoweringOpt &TLO, unsigned Depth=0, bool AssumeSingleUse=false) const
Look at Op.
bool isInTailCallPosition(SelectionDAG &DAG, SDNode *Node, SDValue &Chain) const
Check whether a given call node is in tail position within its function.
virtual bool isGAPlusOffset(SDNode *N, const GlobalValue *&GA, int64_t &Offset) const
Returns true (and the GlobalValue and the offset) if the node is a GlobalAddress + offset.
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:78
CodeModel::Model getCodeModel() const
Returns the code model.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
@ VoidTyID
type with no size
Definition: Type.h:63
static Type * getVoidTy(LLVMContext &C)
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
Definition: Type.h:304
static IntegerType * getInt8Ty(LLVMContext &C)
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
bool isFunctionTy() const
True if this is an instance of FunctionType.
Definition: Type.h:249
static IntegerType * getInt32Ty(LLVMContext &C)
TypeID getTypeID() const
Return the type id for the type.
Definition: Type.h:137
LLVM Value Representation.
Definition: Value.h:74
Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
Definition: Value.cpp:918
static int stackSlotSize()
Stack slot size (4 bytes)
XCoreFunctionInfo - This class is derived from MachineFunction private XCore target-specific informat...
void setReturnStackOffset(unsigned value)
int createLRSpillSlot(MachineFunction &MF)
const TargetRegisterInfo * getRegisterInfo() const override
const XCoreInstrInfo * getInstrInfo() const override
bool isZExtFree(SDValue Val, EVT VT2) const override
Return true if zero-extending the specific node Val to type VT2 is free (either because it's implicit...
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
isLegalAddressingMode - Return true if the addressing mode represented by AM is legal for this target...
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
LowerOperation - Provide custom lowering hooks for some operations.
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
ReplaceNodeResults - Replace the results of node with an illegal result type with new values built ou...
unsigned getJumpTableEncoding() const override
Return the entry encoding for a jump table in the current function.
XCoreTargetLowering(const TargetMachine &TM, const XCoreSubtarget &Subtarget)
const char * getTargetNodeName(unsigned Opcode) const override
getTargetNodeName - This method returns the name of a target specific
self_iterator getIterator()
Definition: ilist_node.h:82
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
Definition: BitmaskEnum.h:119
@ Fast
Attempts to make calls as fast as possible (e.g.
Definition: CallingConv.h:41
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
@ STACKRESTORE
STACKRESTORE has two operands, an input chain and a pointer to restore to it returns an output chain.
Definition: ISDOpcodes.h:1069
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
Definition: ISDOpcodes.h:1065
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
Definition: ISDOpcodes.h:250
@ VAEND
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE.
Definition: ISDOpcodes.h:1098
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, ptr, val) This corresponds to "store atomic" instruction.
Definition: ISDOpcodes.h:1178
@ FRAME_TO_ARGS_OFFSET
FRAME_TO_ARGS_OFFSET - This node represents offset from frame pointer to first (possible) on-stack ar...
Definition: ISDOpcodes.h:124
@ ADD
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:239
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
Definition: ISDOpcodes.h:978
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition: ISDOpcodes.h:779
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
Definition: ISDOpcodes.h:199
@ RETURNADDR
Definition: ISDOpcodes.h:95
@ GlobalAddress
Definition: ISDOpcodes.h:78
@ MEMBARRIER
MEMBARRIER - Compiler barrier only; generate a no-op.
Definition: ISDOpcodes.h:1165
@ ATOMIC_FENCE
OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) This corresponds to the fence instruction.
Definition: ISDOpcodes.h:1170
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
Definition: ISDOpcodes.h:229
@ INIT_TRAMPOLINE
INIT_TRAMPOLINE - This corresponds to the init_trampoline intrinsic.
Definition: ISDOpcodes.h:1136
@ EH_RETURN
OUTCHAIN = EH_RETURN(INCHAIN, OFFSET, HANDLER) - This node represents 'eh_return' gcc dwarf builtin,...
Definition: ISDOpcodes.h:135
@ SIGN_EXTEND
Conversion operators.
Definition: ISDOpcodes.h:773
@ BR_CC
BR_CC - Conditional branch.
Definition: ISDOpcodes.h:1020
@ BR_JT
BR_JT - Jumptable branch.
Definition: ISDOpcodes.h:1003
@ ATOMIC_LOAD
Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr) This corresponds to "load atomic" instruction.
Definition: ISDOpcodes.h:1174
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
Definition: ISDOpcodes.h:222
@ VACOPY
VACOPY - VACOPY has 5 operands: an input chain, a destination pointer, a source pointer,...
Definition: ISDOpcodes.h:1094
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
Definition: ISDOpcodes.h:650
@ SHL
Shift and rotation operations.
Definition: ISDOpcodes.h:704
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition: ISDOpcodes.h:776
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition: ISDOpcodes.h:741
@ DYNAMIC_STACKALLOC
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary.
Definition: ISDOpcodes.h:988
@ ConstantPool
Definition: ISDOpcodes.h:82
@ FRAMEADDR
FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and llvm.returnaddress on the DAG.
Definition: ISDOpcodes.h:94
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition: ISDOpcodes.h:679
@ TRAP
TRAP - Trapping instruction.
Definition: ISDOpcodes.h:1145
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
Definition: ISDOpcodes.h:184
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
Definition: ISDOpcodes.h:52
@ VAARG
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
Definition: ISDOpcodes.h:1089
@ BlockAddress
Definition: ISDOpcodes.h:84
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
Definition: ISDOpcodes.h:762
@ ADJUST_TRAMPOLINE
ADJUST_TRAMPOLINE - This corresponds to the adjust_trampoline intrinsic.
Definition: ISDOpcodes.h:1142
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
Definition: ISDOpcodes.h:192
Flag
These should be considered private to the implementation of the MCInstrDesc class.
Definition: MCInstrDesc.h:148
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
@ Offset
Definition: DWP.cpp:406
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
static const unsigned CodeModelLargeSize
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:145
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ Mul
Product of integers.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:155
constexpr unsigned BitWidth
Definition: BitmaskEnum.h:184
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
Extended Value Type.
Definition: ValueTypes.h:34
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
Definition: ValueTypes.h:129
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition: ValueTypes.h:351
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
Definition: ValueTypes.h:299
bool isInteger() const
Return true if this is an integer or a vector integer type.
Definition: ValueTypes.h:144
unsigned countMinTrailingZeros() const
Returns the minimum number of trailing zero bits.
Definition: KnownBits.h:233
unsigned getBitWidth() const
Get the bit width of this value.
Definition: KnownBits.h:40
void resetAll()
Resets the known state of all bits.
Definition: KnownBits.h:66
This class contains a discriminated union of information about pointers in memory operands,...
static MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg If BaseGV is null...
This structure contains all information that is necessary for lowering calls.
SmallVector< ISD::InputArg, 32 > Ins
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
A convenience struct that encapsulates a DAG, and two SDValues for returning information from TargetL...