LLVM 23.0.0git
VEISelLowering.cpp
Go to the documentation of this file.
1//===-- VEISelLowering.cpp - VE 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 interfaces that VE uses to lower LLVM code into a
10// selection DAG.
11//
12//===----------------------------------------------------------------------===//
13
14#include "VEISelLowering.h"
16#include "VECustomDAG.h"
17#include "VEInstrBuilder.h"
19#include "VERegisterInfo.h"
20#include "VESelectionDAGInfo.h"
21#include "VETargetMachine.h"
33#include "llvm/IR/Function.h"
34#include "llvm/IR/IRBuilder.h"
35#include "llvm/IR/Module.h"
37using namespace llvm;
38
39#define DEBUG_TYPE "ve-lower"
40
41//===----------------------------------------------------------------------===//
42// Calling Convention Implementation
43//===----------------------------------------------------------------------===//
44
45#define GET_CALLING_CONV_IMPL
46#include "VEGenCallingConv.inc"
47
49 switch (CallConv) {
50 default:
51 return RetCC_VE_C;
53 return RetCC_VE_Fast;
54 }
55}
56
57CCAssignFn *getParamCC(CallingConv::ID CallConv, bool IsVarArg) {
58 if (IsVarArg)
59 return CC_VE2;
60 switch (CallConv) {
61 default:
62 return CC_VE_C;
64 return CC_VE_Fast;
65 }
66}
67
69 CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
70 const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,
71 const Type *RetTy) const {
72 CCAssignFn *RetCC = getReturnCC(CallConv);
74 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
75 return CCInfo.CheckReturn(Outs, RetCC);
76}
77
78static const MVT AllVectorVTs[] = {MVT::v256i32, MVT::v512i32, MVT::v256i64,
79 MVT::v256f32, MVT::v512f32, MVT::v256f64};
80
81static const MVT AllMaskVTs[] = {MVT::v256i1, MVT::v512i1};
82
83static const MVT AllPackedVTs[] = {MVT::v512i32, MVT::v512f32};
84
85void VETargetLowering::initRegisterClasses() {
86 // Set up the register classes.
87 addRegisterClass(MVT::i32, &VE::I32RegClass);
88 addRegisterClass(MVT::i64, &VE::I64RegClass);
89 addRegisterClass(MVT::f32, &VE::F32RegClass);
90 addRegisterClass(MVT::f64, &VE::I64RegClass);
91 addRegisterClass(MVT::f128, &VE::F128RegClass);
92
93 if (Subtarget->enableVPU()) {
94 for (MVT VecVT : AllVectorVTs)
95 addRegisterClass(VecVT, &VE::V64RegClass);
96 addRegisterClass(MVT::v256i1, &VE::VMRegClass);
97 addRegisterClass(MVT::v512i1, &VE::VM512RegClass);
98 }
99}
100
101void VETargetLowering::initSPUActions() {
102 const auto &TM = getTargetMachine();
103 /// Load & Store {
104
105 // VE doesn't have i1 sign extending load.
106 for (MVT VT : MVT::integer_valuetypes()) {
110 setTruncStoreAction(VT, MVT::i1, Expand);
111 }
112
113 // VE doesn't have floating point extload/truncstore, so expand them.
114 for (MVT FPVT : MVT::fp_valuetypes()) {
115 for (MVT OtherFPVT : MVT::fp_valuetypes()) {
116 setLoadExtAction(ISD::EXTLOAD, FPVT, OtherFPVT, Expand);
117 setTruncStoreAction(FPVT, OtherFPVT, Expand);
118 }
119 }
120
121 // VE doesn't have fp128 load/store, so expand them in custom lower.
124
125 /// } Load & Store
126
127 // Custom legalize address nodes into LO/HI parts.
128 MVT PtrVT = MVT::getIntegerVT(TM.getPointerSizeInBits(0));
134
135 /// VAARG handling {
137 // VAARG needs to be lowered to access with 8 bytes alignment.
139 // Use the default implementation.
142 /// } VAARG handling
143
144 /// Stack {
147
148 // Use the default implementation.
151 /// } Stack
152
153 /// Branch {
154
155 // VE doesn't have BRCOND
157
158 // BR_JT is not implemented yet.
160
161 /// } Branch
162
163 /// Int Ops {
164 for (MVT IntVT : {MVT::i32, MVT::i64}) {
165 // VE has no REM or DIVREM operations.
170
171 // VE has no SHL_PARTS/SRA_PARTS/SRL_PARTS operations.
175
176 // VE has no MULHU/S or U/SMUL_LOHI operations.
177 // TODO: Use MPD instruction to implement SMUL_LOHI for i32 type.
182
183 // VE has no CTTZ, ROTL, ROTR operations.
187
188 // VE has 64 bits instruction which works as i64 BSWAP operation. This
189 // instruction works fine as i32 BSWAP operation with an additional
190 // parameter. Use isel patterns to lower BSWAP.
192
193 // VE has only 64 bits instructions which work as i64 BITREVERSE/CTLZ/CTPOP
194 // operations. Use isel patterns for i64, promote for i32.
195 LegalizeAction Act = (IntVT == MVT::i32) ? Promote : Legal;
197 setOperationAction(ISD::CTLZ, IntVT, Act);
199 setOperationAction(ISD::CTPOP, IntVT, Act);
200
201 // VE has only 64 bits instructions which work as i64 AND/OR/XOR operations.
202 // Use isel patterns for i64, promote for i32.
203 setOperationAction(ISD::AND, IntVT, Act);
204 setOperationAction(ISD::OR, IntVT, Act);
205 setOperationAction(ISD::XOR, IntVT, Act);
206
207 // Legal smax and smin
210 }
211 /// } Int Ops
212
213 /// Conversion {
214 // VE doesn't have instructions for fp<->uint, so expand them by llvm
215 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote); // use i64
216 setOperationAction(ISD::UINT_TO_FP, MVT::i32, Promote); // use i64
219
220 // fp16 not supported
221 for (MVT FPVT : MVT::fp_valuetypes()) {
224 }
225 /// } Conversion
226
227 /// Floating-point Ops {
228 /// Note: Floating-point operations are fneg, fadd, fsub, fmul, fdiv, frem,
229 /// and fcmp.
230
231 // VE doesn't have following floating point operations.
232 for (MVT VT : MVT::fp_valuetypes()) {
235 }
236
237 // VE doesn't have fdiv of f128.
239
240 for (MVT FPVT : {MVT::f32, MVT::f64}) {
241 // f32 and f64 uses ConstantFP. f128 uses ConstantPool.
243 }
244 /// } Floating-point Ops
245
246 /// Floating-point math functions {
247
248 // VE doesn't have following floating point math functions.
249 for (MVT VT : MVT::fp_valuetypes()) {
257 }
258
259 // VE has single and double FMINNUM and FMAXNUM
260 for (MVT VT : {MVT::f32, MVT::f64}) {
262 }
263
264 /// } Floating-point math functions
265
266 /// Atomic instructions {
267
271
272 // Use custom inserter for ATOMIC_FENCE.
274
275 // Other atomic instructions.
276 for (MVT VT : MVT::integer_valuetypes()) {
277 // Support i8/i16 atomic swap.
279
280 // FIXME: Support "atmam" instructions.
285
286 // VE doesn't have follwing instructions.
295 }
296
297 /// } Atomic instructions
298
299 /// SJLJ instructions {
303 /// } SJLJ instructions
304
305 // Intrinsic instructions
307}
308
309void VETargetLowering::initVPUActions() {
310 for (MVT LegalMaskVT : AllMaskVTs)
312
313 for (unsigned Opc : {ISD::AND, ISD::OR, ISD::XOR})
314 setOperationAction(Opc, MVT::v512i1, Custom);
315
316 for (MVT LegalVecVT : AllVectorVTs) {
320 // Translate all vector instructions with legal element types to VVP_*
321 // nodes.
322 // TODO We will custom-widen into VVP_* nodes in the future. While we are
323 // buildling the infrastructure for this, we only do this for legal vector
324 // VTs.
325#define HANDLE_VP_TO_VVP(VP_OPC, VVP_NAME) \
326 setOperationAction(ISD::VP_OPC, LegalVecVT, Custom);
327#define ADD_VVP_OP(VVP_NAME, ISD_NAME) \
328 setOperationAction(ISD::ISD_NAME, LegalVecVT, Custom);
329 setOperationAction(ISD::EXPERIMENTAL_VP_STRIDED_LOAD, LegalVecVT, Custom);
330 setOperationAction(ISD::EXPERIMENTAL_VP_STRIDED_STORE, LegalVecVT, Custom);
331#include "VVPNodes.def"
332 }
333
334 for (MVT LegalPackedVT : AllPackedVTs) {
337 }
338
339 // vNt32, vNt64 ops (legal element types)
340 for (MVT VT : MVT::vector_valuetypes()) {
341 MVT ElemVT = VT.getVectorElementType();
342 unsigned ElemBits = ElemVT.getScalarSizeInBits();
343 if (ElemBits != 32 && ElemBits != 64)
344 continue;
345
346 for (unsigned MemOpc : {ISD::MLOAD, ISD::MSTORE, ISD::LOAD, ISD::STORE})
347 setOperationAction(MemOpc, VT, Custom);
348
349 const ISD::NodeType IntReductionOCs[] = {
353
354 for (unsigned IntRedOpc : IntReductionOCs)
355 setOperationAction(IntRedOpc, VT, Custom);
356 }
357
358 // v256i1 and v512i1 ops
359 for (MVT MaskVT : AllMaskVTs) {
360 // Custom lower mask ops
363 }
364}
365
368 bool IsVarArg,
370 const SmallVectorImpl<SDValue> &OutVals,
371 const SDLoc &DL, SelectionDAG &DAG) const {
372 // CCValAssign - represent the assignment of the return value to locations.
374
375 // CCState - Info about the registers and stack slot.
376 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
377 *DAG.getContext());
378
379 // Analyze return values.
380 CCInfo.AnalyzeReturn(Outs, getReturnCC(CallConv));
381
382 SDValue Glue;
383 SmallVector<SDValue, 4> RetOps(1, Chain);
384
385 // Copy the result values into the output registers.
386 for (unsigned i = 0; i != RVLocs.size(); ++i) {
387 CCValAssign &VA = RVLocs[i];
388 assert(VA.isRegLoc() && "Can only return in registers!");
389 assert(!VA.needsCustom() && "Unexpected custom lowering");
390 SDValue OutVal = OutVals[i];
391
392 // Integer return values must be sign or zero extended by the callee.
393 switch (VA.getLocInfo()) {
395 break;
397 OutVal = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), OutVal);
398 break;
400 OutVal = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), OutVal);
401 break;
403 OutVal = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), OutVal);
404 break;
405 case CCValAssign::BCvt: {
406 // Convert a float return value to i64 with padding.
407 // 63 31 0
408 // +------+------+
409 // | float| 0 |
410 // +------+------+
411 assert(VA.getLocVT() == MVT::i64);
412 assert(VA.getValVT() == MVT::f32);
414 DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, MVT::i64), 0);
415 SDValue Sub_f32 = DAG.getTargetConstant(VE::sub_f32, DL, MVT::i32);
416 OutVal = SDValue(DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, DL,
417 MVT::i64, Undef, OutVal, Sub_f32),
418 0);
419 break;
420 }
421 default:
422 llvm_unreachable("Unknown loc info!");
423 }
424
425 Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVal, Glue);
426
427 // Guarantee that all emitted copies are stuck together with flags.
428 Glue = Chain.getValue(1);
429 RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
430 }
431
432 RetOps[0] = Chain; // Update chain.
433
434 // Add the glue if we have it.
435 if (Glue.getNode())
436 RetOps.push_back(Glue);
437
438 return DAG.getNode(VEISD::RET_GLUE, DL, MVT::Other, RetOps);
439}
440
442 SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
443 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
444 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
446
447 // Get the base offset of the incoming arguments stack space.
448 unsigned ArgsBaseOffset = Subtarget->getRsaSize();
449 // Get the size of the preserved arguments area
450 unsigned ArgsPreserved = 64;
451
452 // Analyze arguments according to CC_VE.
454 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
455 *DAG.getContext());
456 // Allocate the preserved area first.
457 CCInfo.AllocateStack(ArgsPreserved, Align(8));
458 // We already allocated the preserved area, so the stack offset computed
459 // by CC_VE would be correct now.
460 CCInfo.AnalyzeFormalArguments(Ins, getParamCC(CallConv, false));
461
462 for (const CCValAssign &VA : ArgLocs) {
463 assert(!VA.needsCustom() && "Unexpected custom lowering");
464 if (VA.isRegLoc()) {
465 // This argument is passed in a register.
466 // All integer register arguments are promoted by the caller to i64.
467
468 // Create a virtual register for the promoted live-in value.
469 Register VReg =
470 MF.addLiveIn(VA.getLocReg(), getRegClassFor(VA.getLocVT()));
471 SDValue Arg = DAG.getCopyFromReg(Chain, DL, VReg, VA.getLocVT());
472
473 // The caller promoted the argument, so insert an Assert?ext SDNode so we
474 // won't promote the value again in this function.
475 switch (VA.getLocInfo()) {
477 Arg = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), Arg,
478 DAG.getValueType(VA.getValVT()));
479 break;
481 Arg = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), Arg,
482 DAG.getValueType(VA.getValVT()));
483 break;
484 case CCValAssign::BCvt: {
485 // Extract a float argument from i64 with padding.
486 // 63 31 0
487 // +------+------+
488 // | float| 0 |
489 // +------+------+
490 assert(VA.getLocVT() == MVT::i64);
491 assert(VA.getValVT() == MVT::f32);
492 SDValue Sub_f32 = DAG.getTargetConstant(VE::sub_f32, DL, MVT::i32);
493 Arg = SDValue(DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL,
494 MVT::f32, Arg, Sub_f32),
495 0);
496 break;
497 }
498 default:
499 break;
500 }
501
502 // Truncate the register down to the argument type.
503 if (VA.isExtInLoc())
504 Arg = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Arg);
505
506 InVals.push_back(Arg);
507 continue;
508 }
509
510 // The registers are exhausted. This argument was passed on the stack.
511 assert(VA.isMemLoc());
512 // The CC_VE_Full/Half functions compute stack offsets relative to the
513 // beginning of the arguments area at %fp + the size of reserved area.
514 unsigned Offset = VA.getLocMemOffset() + ArgsBaseOffset;
515 unsigned ValSize = VA.getValVT().getSizeInBits() / 8;
516
517 // Adjust offset for a float argument by adding 4 since the argument is
518 // stored in 8 bytes buffer with offset like below. LLVM generates
519 // 4 bytes load instruction, so need to adjust offset here. This
520 // adjustment is required in only LowerFormalArguments. In LowerCall,
521 // a float argument is converted to i64 first, and stored as 8 bytes
522 // data, which is required by ABI, so no need for adjustment.
523 // 0 4
524 // +------+------+
525 // | empty| float|
526 // +------+------+
527 if (VA.getValVT() == MVT::f32)
528 Offset += 4;
529
530 int FI = MF.getFrameInfo().CreateFixedObject(ValSize, Offset, true);
531 InVals.push_back(
532 DAG.getLoad(VA.getValVT(), DL, Chain,
535 }
536
537 if (!IsVarArg)
538 return Chain;
539
540 // This function takes variable arguments, some of which may have been passed
541 // in registers %s0-%s8.
542 //
543 // The va_start intrinsic needs to know the offset to the first variable
544 // argument.
545 // TODO: need to calculate offset correctly once we support f128.
546 unsigned ArgOffset = ArgLocs.size() * 8;
548 // Skip the reserved area at the top of stack.
549 FuncInfo->setVarArgsFrameOffset(ArgOffset + ArgsBaseOffset);
550
551 return Chain;
552}
553
554// FIXME? Maybe this could be a TableGen attribute on some registers and
555// this table could be generated automatically from RegInfo.
557 const MachineFunction &MF) const {
559 .Case("sp", VE::SX11) // Stack pointer
560 .Case("fp", VE::SX9) // Frame pointer
561 .Case("sl", VE::SX8) // Stack limit
562 .Case("lr", VE::SX10) // Link register
563 .Case("tp", VE::SX14) // Thread pointer
564 .Case("outer", VE::SX12) // Outer regiser
565 .Case("info", VE::SX17) // Info area register
566 .Case("got", VE::SX15) // Global offset table register
567 .Case("plt", VE::SX16) // Procedure linkage table register
568 .Default(Register());
569 return Reg;
570}
571
572//===----------------------------------------------------------------------===//
573// TargetLowering Implementation
574//===----------------------------------------------------------------------===//
575
577 SmallVectorImpl<SDValue> &InVals) const {
578 SelectionDAG &DAG = CLI.DAG;
579 SDLoc DL = CLI.DL;
580 SDValue Chain = CLI.Chain;
581 auto PtrVT = getPointerTy(DAG.getDataLayout());
582
583 // VE target does not yet support tail call optimization.
584 CLI.IsTailCall = false;
585
586 // Get the base offset of the outgoing arguments stack space.
587 unsigned ArgsBaseOffset = Subtarget->getRsaSize();
588 // Get the size of the preserved arguments area
589 unsigned ArgsPreserved = 8 * 8u;
590
591 // Analyze operands of the call, assigning locations to each operand.
593 CCState CCInfo(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(), ArgLocs,
594 *DAG.getContext());
595 // Allocate the preserved area first.
596 CCInfo.AllocateStack(ArgsPreserved, Align(8));
597 // We already allocated the preserved area, so the stack offset computed
598 // by CC_VE would be correct now.
599 CCInfo.AnalyzeCallOperands(CLI.Outs, getParamCC(CLI.CallConv, false));
600
601 // VE requires to use both register and stack for varargs or no-prototyped
602 // functions.
603 bool UseBoth = CLI.IsVarArg;
604
605 // Analyze operands again if it is required to store BOTH.
607 CCState CCInfo2(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(),
608 ArgLocs2, *DAG.getContext());
609 if (UseBoth)
610 CCInfo2.AnalyzeCallOperands(CLI.Outs, getParamCC(CLI.CallConv, true));
611
612 // Get the size of the outgoing arguments stack space requirement.
613 unsigned ArgsSize = CCInfo.getStackSize();
614
615 // Keep stack frames 16-byte aligned.
616 ArgsSize = alignTo(ArgsSize, 16);
617
618 // Adjust the stack pointer to make room for the arguments.
619 // FIXME: Use hasReservedCallFrame to avoid %sp adjustments around all calls
620 // with more than 6 arguments.
621 Chain = DAG.getCALLSEQ_START(Chain, ArgsSize, 0, DL);
622
623 // Collect the set of registers to pass to the function and their values.
624 // This will be emitted as a sequence of CopyToReg nodes glued to the call
625 // instruction.
627
628 // Collect chains from all the memory opeations that copy arguments to the
629 // stack. They must follow the stack pointer adjustment above and precede the
630 // call instruction itself.
631 SmallVector<SDValue, 8> MemOpChains;
632
633 // VE needs to get address of callee function in a register
634 // So, prepare to copy it to SX12 here.
635
636 // If the callee is a GlobalAddress node (quite common, every direct call is)
637 // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
638 // Likewise ExternalSymbol -> TargetExternalSymbol.
639 SDValue Callee = CLI.Callee;
640
641 bool IsPICCall = isPositionIndependent();
642
643 // PC-relative references to external symbols should go through $stub.
644 // If so, we need to prepare GlobalBaseReg first.
645 const TargetMachine &TM = DAG.getTarget();
646 const GlobalValue *GV = nullptr;
647 auto *CalleeG = dyn_cast<GlobalAddressSDNode>(Callee);
648 if (CalleeG)
649 GV = CalleeG->getGlobal();
650 bool Local = TM.shouldAssumeDSOLocal(GV);
651 bool UsePlt = !Local;
653
654 // Turn GlobalAddress/ExternalSymbol node into a value node
655 // containing the address of them here.
656 if (CalleeG) {
657 if (IsPICCall) {
658 if (UsePlt)
659 Subtarget->getInstrInfo()->getGlobalBaseReg(&MF);
660 Callee = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, 0);
661 Callee = DAG.getNode(VEISD::GETFUNPLT, DL, PtrVT, Callee);
662 } else {
663 Callee = makeHiLoPair(Callee, VE::S_HI32, VE::S_LO32, DAG);
664 }
666 if (IsPICCall) {
667 if (UsePlt)
668 Subtarget->getInstrInfo()->getGlobalBaseReg(&MF);
669 Callee = DAG.getTargetExternalSymbol(E->getSymbol(), PtrVT, 0);
670 Callee = DAG.getNode(VEISD::GETFUNPLT, DL, PtrVT, Callee);
671 } else {
672 Callee = makeHiLoPair(Callee, VE::S_HI32, VE::S_LO32, DAG);
673 }
674 }
675
676 RegsToPass.push_back(std::make_pair(VE::SX12, Callee));
677
678 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
679 CCValAssign &VA = ArgLocs[i];
680 SDValue Arg = CLI.OutVals[i];
681
682 // Promote the value if needed.
683 switch (VA.getLocInfo()) {
684 default:
685 llvm_unreachable("Unknown location info!");
687 break;
689 Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), Arg);
690 break;
692 Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Arg);
693 break;
695 Arg = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Arg);
696 break;
697 case CCValAssign::BCvt: {
698 // Convert a float argument to i64 with padding.
699 // 63 31 0
700 // +------+------+
701 // | float| 0 |
702 // +------+------+
703 assert(VA.getLocVT() == MVT::i64);
704 assert(VA.getValVT() == MVT::f32);
706 DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, MVT::i64), 0);
707 SDValue Sub_f32 = DAG.getTargetConstant(VE::sub_f32, DL, MVT::i32);
708 Arg = SDValue(DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, DL,
709 MVT::i64, Undef, Arg, Sub_f32),
710 0);
711 break;
712 }
713 }
714
715 if (VA.isRegLoc()) {
716 RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
717 if (!UseBoth)
718 continue;
719 VA = ArgLocs2[i];
720 }
721
722 assert(VA.isMemLoc());
723
724 // Create a store off the stack pointer for this argument.
725 SDValue StackPtr = DAG.getRegister(VE::SX11, PtrVT);
726 // The argument area starts at %fp/%sp + the size of reserved area.
727 SDValue PtrOff =
728 DAG.getIntPtrConstant(VA.getLocMemOffset() + ArgsBaseOffset, DL);
729 PtrOff = DAG.getNode(ISD::ADD, DL, PtrVT, StackPtr, PtrOff);
730 MemOpChains.push_back(
731 DAG.getStore(Chain, DL, Arg, PtrOff, MachinePointerInfo()));
732 }
733
734 // Emit all stores, make sure they occur before the call.
735 if (!MemOpChains.empty())
736 Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains);
737
738 // Build a sequence of CopyToReg nodes glued together with token chain and
739 // glue operands which copy the outgoing args into registers. The InGlue is
740 // necessary since all emitted instructions must be stuck together in order
741 // to pass the live physical registers.
742 SDValue InGlue;
743 for (const auto &[Reg, N] : RegsToPass) {
744 Chain = DAG.getCopyToReg(Chain, DL, Reg, N, InGlue);
745 InGlue = Chain.getValue(1);
746 }
747
748 // Build the operands for the call instruction itself.
750 Ops.push_back(Chain);
751 for (const auto &[Reg, N] : RegsToPass)
752 Ops.push_back(DAG.getRegister(Reg, N.getValueType()));
753
754 // Add a register mask operand representing the call-preserved registers.
755 const VERegisterInfo *TRI = Subtarget->getRegisterInfo();
756 const uint32_t *Mask =
757 TRI->getCallPreservedMask(DAG.getMachineFunction(), CLI.CallConv);
758 assert(Mask && "Missing call preserved mask for calling convention");
759 Ops.push_back(DAG.getRegisterMask(Mask));
760
761 // Make sure the CopyToReg nodes are glued to the call instruction which
762 // consumes the registers.
763 if (InGlue.getNode())
764 Ops.push_back(InGlue);
765
766 // Now the call itself.
767 SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
768 Chain = DAG.getNode(VEISD::CALL, DL, NodeTys, Ops);
769 InGlue = Chain.getValue(1);
770
771 // Revert the stack pointer immediately after the call.
772 Chain = DAG.getCALLSEQ_END(Chain, ArgsSize, 0, InGlue, DL);
773 InGlue = Chain.getValue(1);
774
775 // Now extract the return values. This is more or less the same as
776 // LowerFormalArguments.
777
778 // Assign locations to each value returned by this call.
780 CCState RVInfo(CLI.CallConv, CLI.IsVarArg, DAG.getMachineFunction(), RVLocs,
781 *DAG.getContext());
782
783 // Set inreg flag manually for codegen generated library calls that
784 // return float.
785 if (CLI.Ins.size() == 1 && CLI.Ins[0].VT == MVT::f32 && !CLI.CB)
786 CLI.Ins[0].Flags.setInReg();
787
788 RVInfo.AnalyzeCallResult(CLI.Ins, getReturnCC(CLI.CallConv));
789
790 // Copy all of the result registers out of their specified physreg.
791 for (unsigned i = 0; i != RVLocs.size(); ++i) {
792 CCValAssign &VA = RVLocs[i];
793 assert(!VA.needsCustom() && "Unexpected custom lowering");
794 Register Reg = VA.getLocReg();
795
796 // When returning 'inreg {i32, i32 }', two consecutive i32 arguments can
797 // reside in the same register in the high and low bits. Reuse the
798 // CopyFromReg previous node to avoid duplicate copies.
799 SDValue RV;
800 if (RegisterSDNode *SrcReg = dyn_cast<RegisterSDNode>(Chain.getOperand(1)))
801 if (SrcReg->getReg() == Reg && Chain->getOpcode() == ISD::CopyFromReg)
802 RV = Chain.getValue(0);
803
804 // But usually we'll create a new CopyFromReg for a different register.
805 if (!RV.getNode()) {
806 RV = DAG.getCopyFromReg(Chain, DL, Reg, RVLocs[i].getLocVT(), InGlue);
807 Chain = RV.getValue(1);
808 InGlue = Chain.getValue(2);
809 }
810
811 // The callee promoted the return value, so insert an Assert?ext SDNode so
812 // we won't promote the value again in this function.
813 switch (VA.getLocInfo()) {
815 RV = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), RV,
816 DAG.getValueType(VA.getValVT()));
817 break;
819 RV = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), RV,
820 DAG.getValueType(VA.getValVT()));
821 break;
822 case CCValAssign::BCvt: {
823 // Extract a float return value from i64 with padding.
824 // 63 31 0
825 // +------+------+
826 // | float| 0 |
827 // +------+------+
828 assert(VA.getLocVT() == MVT::i64);
829 assert(VA.getValVT() == MVT::f32);
830 SDValue Sub_f32 = DAG.getTargetConstant(VE::sub_f32, DL, MVT::i32);
831 RV = SDValue(DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL,
832 MVT::f32, RV, Sub_f32),
833 0);
834 break;
835 }
836 default:
837 break;
838 }
839
840 // Truncate the register down to the return value type.
841 if (VA.isExtInLoc())
842 RV = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), RV);
843
844 InVals.push_back(RV);
845 }
846
847 return Chain;
848}
849
851 const GlobalAddressSDNode *GA) const {
852 // VE uses 64 bit addressing, so we need multiple instructions to generate
853 // an address. Folding address with offset increases the number of
854 // instructions, so that we disable it here. Offsets will be folded in
855 // the DAG combine later if it worth to do so.
856 return false;
857}
858
859/// isFPImmLegal - Returns true if the target can instruction select the
860/// specified FP immediate natively. If false, the legalizer will
861/// materialize the FP immediate as a load from a constant pool.
863 bool ForCodeSize) const {
864 return VT == MVT::f32 || VT == MVT::f64;
865}
866
867/// Determine if the target supports unaligned memory accesses.
868///
869/// This function returns true if the target allows unaligned memory accesses
870/// of the specified type in the given address space. If true, it also returns
871/// whether the unaligned memory access is "fast" in the last argument by
872/// reference. This is used, for example, in situations where an array
873/// copy/move/set is converted to a sequence of store operations. Its use
874/// helps to ensure that such replacements don't generate code that causes an
875/// alignment error (trap) on the target machine.
877 unsigned AddrSpace,
878 Align A,
880 unsigned *Fast) const {
881 if (Fast) {
882 // It's fast anytime on VE
883 *Fast = 1;
884 }
885 return true;
886}
887
889 const VESubtarget &STI)
890 : TargetLowering(TM, STI), Subtarget(&STI) {
891 // Instructions which use registers as conditionals examine all the
892 // bits (as does the pseudo SELECT_CC expansion). I don't think it
893 // matters much whether it's ZeroOrOneBooleanContent, or
894 // ZeroOrNegativeOneBooleanContent, so, arbitrarily choose the
895 // former.
898
899 initRegisterClasses();
900 initSPUActions();
901 initVPUActions();
902
904
905 // We have target-specific dag combine patterns for the following nodes:
909
910 // Set function alignment to 16 bytes
912
913 // VE stores all argument by 8 bytes alignment
915
916 computeRegisterProperties(Subtarget->getRegisterInfo());
917}
918
920 LLVMContext &Context, EVT VT) const {
921 if (VT.isVector())
922 return VT.changeVectorElementType(Context, MVT::i1);
923 return MVT::i32;
924}
925
926// Convert to a target node and set target flags.
928 SelectionDAG &DAG) const {
930 return DAG.getTargetGlobalAddress(GA->getGlobal(), SDLoc(GA),
931 GA->getValueType(0), GA->getOffset(), TF);
932
934 return DAG.getTargetBlockAddress(BA->getBlockAddress(), Op.getValueType(),
935 0, TF);
936
938 return DAG.getTargetConstantPool(CP->getConstVal(), CP->getValueType(0),
939 CP->getAlign(), CP->getOffset(), TF);
940
942 return DAG.getTargetExternalSymbol(ES->getSymbol(), ES->getValueType(0),
943 TF);
944
946 return DAG.getTargetJumpTable(JT->getIndex(), JT->getValueType(0), TF);
947
948 llvm_unreachable("Unhandled address SDNode");
949}
950
951// Split Op into high and low parts according to HiTF and LoTF.
952// Return an ADD node combining the parts.
953SDValue VETargetLowering::makeHiLoPair(SDValue Op, unsigned HiTF, unsigned LoTF,
954 SelectionDAG &DAG) const {
955 SDLoc DL(Op);
956 EVT VT = Op.getValueType();
957 SDValue Hi = DAG.getNode(VEISD::Hi, DL, VT, withTargetFlags(Op, HiTF, DAG));
958 SDValue Lo = DAG.getNode(VEISD::Lo, DL, VT, withTargetFlags(Op, LoTF, DAG));
959 return DAG.getNode(ISD::ADD, DL, VT, Hi, Lo);
960}
961
962// Build SDNodes for producing an address from a GlobalAddress, ConstantPool,
963// or ExternalSymbol SDNode.
965 SDLoc DL(Op);
966 EVT PtrVT = Op.getValueType();
967
968 // Handle PIC mode first. VE needs a got load for every variable!
969 if (isPositionIndependent()) {
970 auto GlobalN = dyn_cast<GlobalAddressSDNode>(Op);
971
973 (GlobalN && GlobalN->getGlobal()->hasLocalLinkage())) {
974 // Create following instructions for local linkage PIC code.
975 // lea %reg, label@gotoff_lo
976 // and %reg, %reg, (32)0
977 // lea.sl %reg, label@gotoff_hi(%reg, %got)
978 SDValue HiLo =
980 SDValue GlobalBase = DAG.getNode(VEISD::GLOBAL_BASE_REG, DL, PtrVT);
981 return DAG.getNode(ISD::ADD, DL, PtrVT, GlobalBase, HiLo);
982 }
983 // Create following instructions for not local linkage PIC code.
984 // lea %reg, label@got_lo
985 // and %reg, %reg, (32)0
986 // lea.sl %reg, label@got_hi(%reg)
987 // ld %reg, (%reg, %got)
989 SDValue GlobalBase = DAG.getNode(VEISD::GLOBAL_BASE_REG, DL, PtrVT);
990 SDValue AbsAddr = DAG.getNode(ISD::ADD, DL, PtrVT, GlobalBase, HiLo);
991 return DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), AbsAddr,
993 }
994
995 // This is one of the absolute code models.
996 switch (getTargetMachine().getCodeModel()) {
997 default:
998 llvm_unreachable("Unsupported absolute code model");
999 case CodeModel::Small:
1000 case CodeModel::Medium:
1001 case CodeModel::Large:
1002 // abs64.
1003 return makeHiLoPair(Op, VE::S_HI32, VE::S_LO32, DAG);
1004 }
1005}
1006
1007/// Custom Lower {
1008
1009// The mappings for emitLeading/TrailingFence for VE is designed by following
1010// http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html
1012 Instruction *Inst,
1013 AtomicOrdering Ord) const {
1014 switch (Ord) {
1017 llvm_unreachable("Invalid fence: unordered/non-atomic");
1020 return nullptr; // Nothing to do
1023 return Builder.CreateFence(AtomicOrdering::Release);
1025 if (!Inst->hasAtomicStore())
1026 return nullptr; // Nothing to do
1027 return Builder.CreateFence(AtomicOrdering::SequentiallyConsistent);
1028 }
1029 llvm_unreachable("Unknown fence ordering in emitLeadingFence");
1030}
1031
1033 Instruction *Inst,
1034 AtomicOrdering Ord) const {
1035 switch (Ord) {
1038 llvm_unreachable("Invalid fence: unordered/not-atomic");
1041 return nullptr; // Nothing to do
1044 return Builder.CreateFence(AtomicOrdering::Acquire);
1046 return Builder.CreateFence(AtomicOrdering::SequentiallyConsistent);
1047 }
1048 llvm_unreachable("Unknown fence ordering in emitTrailingFence");
1049}
1050
1052 SelectionDAG &DAG) const {
1053 SDLoc DL(Op);
1054 AtomicOrdering FenceOrdering =
1055 static_cast<AtomicOrdering>(Op.getConstantOperandVal(1));
1056 SyncScope::ID FenceSSID =
1057 static_cast<SyncScope::ID>(Op.getConstantOperandVal(2));
1058
1059 // VE uses Release consistency, so need a fence instruction if it is a
1060 // cross-thread fence.
1061 if (FenceSSID == SyncScope::System) {
1062 switch (FenceOrdering) {
1066 // No need to generate fencem instruction here.
1067 break;
1069 // Generate "fencem 2" as acquire fence.
1070 return SDValue(DAG.getMachineNode(VE::FENCEM, DL, MVT::Other,
1071 DAG.getTargetConstant(2, DL, MVT::i32),
1072 Op.getOperand(0)),
1073 0);
1075 // Generate "fencem 1" as release fence.
1076 return SDValue(DAG.getMachineNode(VE::FENCEM, DL, MVT::Other,
1077 DAG.getTargetConstant(1, DL, MVT::i32),
1078 Op.getOperand(0)),
1079 0);
1082 // Generate "fencem 3" as acq_rel and seq_cst fence.
1083 // FIXME: "fencem 3" doesn't wait for PCIe deveices accesses,
1084 // so seq_cst may require more instruction for them.
1085 return SDValue(DAG.getMachineNode(VE::FENCEM, DL, MVT::Other,
1086 DAG.getTargetConstant(3, DL, MVT::i32),
1087 Op.getOperand(0)),
1088 0);
1089 }
1090 }
1091
1092 // MEMBARRIER is a compiler barrier; it codegens to a no-op.
1093 return DAG.getNode(ISD::MEMBARRIER, DL, MVT::Other, Op.getOperand(0));
1094}
1095
1098 // We have TS1AM implementation for i8/i16/i32/i64, so use it.
1099 if (AI->getOperation() == AtomicRMWInst::Xchg) {
1101 }
1102 // FIXME: Support "ATMAM" instruction for LOAD_ADD/SUB/AND/OR.
1103
1104 // Otherwise, expand it using compare and exchange instruction to not call
1105 // __sync_fetch_and_* functions.
1107}
1108
1110 SDValue &Bits) {
1111 SDLoc DL(Op);
1113 SDValue Ptr = N->getOperand(1);
1114 SDValue Val = N->getOperand(2);
1115 EVT PtrVT = Ptr.getValueType();
1116 bool Byte = N->getMemoryVT() == MVT::i8;
1117 // Remainder = AND Ptr, 3
1118 // Flag = 1 << Remainder ; If Byte is true (1 byte swap flag)
1119 // Flag = 3 << Remainder ; If Byte is false (2 bytes swap flag)
1120 // Bits = Remainder << 3
1121 // NewVal = Val << Bits
1122 SDValue Const3 = DAG.getConstant(3, DL, PtrVT);
1123 SDValue Remainder = DAG.getNode(ISD::AND, DL, PtrVT, {Ptr, Const3});
1124 SDValue Mask = Byte ? DAG.getConstant(1, DL, MVT::i32)
1125 : DAG.getConstant(3, DL, MVT::i32);
1126 Flag = DAG.getNode(ISD::SHL, DL, MVT::i32, {Mask, Remainder});
1127 Bits = DAG.getNode(ISD::SHL, DL, PtrVT, {Remainder, Const3});
1128 return DAG.getNode(ISD::SHL, DL, Val.getValueType(), {Val, Bits});
1129}
1130
1132 SDValue Bits) {
1133 SDLoc DL(Op);
1134 EVT VT = Data.getValueType();
1135 bool Byte = cast<AtomicSDNode>(Op)->getMemoryVT() == MVT::i8;
1136 // NewData = Data >> Bits
1137 // Result = NewData & 0xff ; If Byte is true (1 byte)
1138 // Result = NewData & 0xffff ; If Byte is false (2 bytes)
1139
1140 SDValue NewData = DAG.getNode(ISD::SRL, DL, VT, Data, Bits);
1141 return DAG.getNode(ISD::AND, DL, VT,
1142 {NewData, DAG.getConstant(Byte ? 0xff : 0xffff, DL, VT)});
1143}
1144
1146 SelectionDAG &DAG) const {
1147 SDLoc DL(Op);
1149
1150 if (N->getMemoryVT() == MVT::i8) {
1151 // For i8, use "ts1am"
1152 // Input:
1153 // ATOMIC_SWAP Ptr, Val, Order
1154 //
1155 // Output:
1156 // Remainder = AND Ptr, 3
1157 // Flag = 1 << Remainder ; 1 byte swap flag for TS1AM inst.
1158 // Bits = Remainder << 3
1159 // NewVal = Val << Bits
1160 //
1161 // Aligned = AND Ptr, -4
1162 // Data = TS1AM Aligned, Flag, NewVal
1163 //
1164 // NewData = Data >> Bits
1165 // Result = NewData & 0xff ; 1 byte result
1166 SDValue Flag;
1167 SDValue Bits;
1168 SDValue NewVal = prepareTS1AM(Op, DAG, Flag, Bits);
1169
1170 SDValue Ptr = N->getOperand(1);
1172 DAG.getNode(ISD::AND, DL, Ptr.getValueType(),
1173 {Ptr, DAG.getSignedConstant(-4, DL, MVT::i64)});
1174 SDValue TS1AM = DAG.getAtomic(VEISD::TS1AM, DL, N->getMemoryVT(),
1175 DAG.getVTList(Op.getNode()->getValueType(0),
1176 Op.getNode()->getValueType(1)),
1177 {N->getChain(), Aligned, Flag, NewVal},
1178 N->getMemOperand());
1179
1180 SDValue Result = finalizeTS1AM(Op, DAG, TS1AM, Bits);
1181 SDValue Chain = TS1AM.getValue(1);
1182 return DAG.getMergeValues({Result, Chain}, DL);
1183 }
1184 if (N->getMemoryVT() == MVT::i16) {
1185 // For i16, use "ts1am"
1186 SDValue Flag;
1187 SDValue Bits;
1188 SDValue NewVal = prepareTS1AM(Op, DAG, Flag, Bits);
1189
1190 SDValue Ptr = N->getOperand(1);
1192 DAG.getNode(ISD::AND, DL, Ptr.getValueType(),
1193 {Ptr, DAG.getSignedConstant(-4, DL, MVT::i64)});
1194 SDValue TS1AM = DAG.getAtomic(VEISD::TS1AM, DL, N->getMemoryVT(),
1195 DAG.getVTList(Op.getNode()->getValueType(0),
1196 Op.getNode()->getValueType(1)),
1197 {N->getChain(), Aligned, Flag, NewVal},
1198 N->getMemOperand());
1199
1200 SDValue Result = finalizeTS1AM(Op, DAG, TS1AM, Bits);
1201 SDValue Chain = TS1AM.getValue(1);
1202 return DAG.getMergeValues({Result, Chain}, DL);
1203 }
1204 // Otherwise, let llvm legalize it.
1205 return Op;
1206}
1207
1212
1217
1222
1223SDValue
1225 SelectionDAG &DAG) const {
1226 SDLoc DL(Op);
1227
1228 // Generate the following code:
1229 // t1: ch,glue = callseq_start t0, 0, 0
1230 // t2: i64,ch,glue = VEISD::GETTLSADDR t1, label, t1:1
1231 // t3: ch,glue = callseq_end t2, 0, 0, t2:2
1232 // t4: i64,ch,glue = CopyFromReg t3, Register:i64 $sx0, t3:1
1233 SDValue Label = withTargetFlags(Op, 0, DAG);
1234 EVT PtrVT = Op.getValueType();
1235
1236 // Lowering the machine isd will make sure everything is in the right
1237 // location.
1238 SDValue Chain = DAG.getEntryNode();
1239 SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
1240 const uint32_t *Mask = Subtarget->getRegisterInfo()->getCallPreservedMask(
1242 Chain = DAG.getCALLSEQ_START(Chain, 64, 0, DL);
1243 SDValue Args[] = {Chain, Label, DAG.getRegisterMask(Mask), Chain.getValue(1)};
1244 Chain = DAG.getNode(VEISD::GETTLSADDR, DL, NodeTys, Args);
1245 Chain = DAG.getCALLSEQ_END(Chain, 64, 0, Chain.getValue(1), DL);
1246 Chain = DAG.getCopyFromReg(Chain, DL, VE::SX0, PtrVT, Chain.getValue(1));
1247
1248 // GETTLSADDR will be codegen'ed as call. Inform MFI that function has calls.
1250 MFI.setHasCalls(true);
1251
1252 // Also generate code to prepare a GOT register if it is PIC.
1253 if (isPositionIndependent()) {
1255 Subtarget->getInstrInfo()->getGlobalBaseReg(&MF);
1256 }
1257
1258 return Chain;
1259}
1260
1262 SelectionDAG &DAG) const {
1263 // The current implementation of nld (2.26) doesn't allow local exec model
1264 // code described in VE-tls_v1.1.pdf (*1) as its input. Instead, we always
1265 // generate the general dynamic model code sequence.
1266 //
1267 // *1: https://www.nec.com/en/global/prod/hpc/aurora/document/VE-tls_v1.1.pdf
1268 return lowerToTLSGeneralDynamicModel(Op, DAG);
1269}
1270
1274
1275// Lower a f128 load into two f64 loads.
1277 SDLoc DL(Op);
1278 LoadSDNode *LdNode = dyn_cast<LoadSDNode>(Op.getNode());
1279 assert(LdNode && LdNode->getOffset().isUndef() && "Unexpected node type");
1280 Align Alignment = LdNode->getAlign();
1281 if (Alignment > 8)
1282 Alignment = Align(8);
1283
1284 SDValue Lo64 =
1285 DAG.getLoad(MVT::f64, DL, LdNode->getChain(), LdNode->getBasePtr(),
1286 LdNode->getPointerInfo(), Alignment,
1289 EVT AddrVT = LdNode->getBasePtr().getValueType();
1290 SDValue HiPtr = DAG.getNode(ISD::ADD, DL, AddrVT, LdNode->getBasePtr(),
1291 DAG.getConstant(8, DL, AddrVT));
1292 SDValue Hi64 =
1293 DAG.getLoad(MVT::f64, DL, LdNode->getChain(), HiPtr,
1294 LdNode->getPointerInfo(), Alignment,
1297
1298 SDValue SubRegEven = DAG.getTargetConstant(VE::sub_even, DL, MVT::i32);
1299 SDValue SubRegOdd = DAG.getTargetConstant(VE::sub_odd, DL, MVT::i32);
1300
1301 // VE stores Hi64 to 8(addr) and Lo64 to 0(addr)
1302 SDNode *InFP128 =
1303 DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, MVT::f128);
1304 InFP128 = DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, DL, MVT::f128,
1305 SDValue(InFP128, 0), Hi64, SubRegEven);
1306 InFP128 = DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, DL, MVT::f128,
1307 SDValue(InFP128, 0), Lo64, SubRegOdd);
1308 SDValue OutChains[2] = {SDValue(Lo64.getNode(), 1),
1309 SDValue(Hi64.getNode(), 1)};
1310 SDValue OutChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains);
1311 SDValue Ops[2] = {SDValue(InFP128, 0), OutChain};
1312 return DAG.getMergeValues(Ops, DL);
1313}
1314
1315// Lower a vXi1 load into following instructions
1316// LDrii %1, (,%addr)
1317// LVMxir %vm, 0, %1
1318// LDrii %2, 8(,%addr)
1319// LVMxir %vm, 0, %2
1320// ...
1322 SDLoc DL(Op);
1323 LoadSDNode *LdNode = dyn_cast<LoadSDNode>(Op.getNode());
1324 assert(LdNode && LdNode->getOffset().isUndef() && "Unexpected node type");
1325
1326 SDValue BasePtr = LdNode->getBasePtr();
1327 Align Alignment = LdNode->getAlign();
1328 if (Alignment > 8)
1329 Alignment = Align(8);
1330
1331 EVT AddrVT = BasePtr.getValueType();
1332 EVT MemVT = LdNode->getMemoryVT();
1333 if (MemVT == MVT::v256i1 || MemVT == MVT::v4i64) {
1334 SDValue OutChains[4];
1335 SDNode *VM = DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, MemVT);
1336 for (int i = 0; i < 4; ++i) {
1337 // Generate load dag and prepare chains.
1338 SDValue Addr = DAG.getNode(ISD::ADD, DL, AddrVT, BasePtr,
1339 DAG.getConstant(8 * i, DL, AddrVT));
1340 SDValue Val =
1341 DAG.getLoad(MVT::i64, DL, LdNode->getChain(), Addr,
1342 LdNode->getPointerInfo(), Alignment,
1345 OutChains[i] = SDValue(Val.getNode(), 1);
1346
1347 VM = DAG.getMachineNode(VE::LVMir_m, DL, MVT::i64,
1348 DAG.getTargetConstant(i, DL, MVT::i64), Val,
1349 SDValue(VM, 0));
1350 }
1351 SDValue OutChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains);
1352 SDValue Ops[2] = {SDValue(VM, 0), OutChain};
1353 return DAG.getMergeValues(Ops, DL);
1354 } else if (MemVT == MVT::v512i1 || MemVT == MVT::v8i64) {
1355 SDValue OutChains[8];
1356 SDNode *VM = DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, MemVT);
1357 for (int i = 0; i < 8; ++i) {
1358 // Generate load dag and prepare chains.
1359 SDValue Addr = DAG.getNode(ISD::ADD, DL, AddrVT, BasePtr,
1360 DAG.getConstant(8 * i, DL, AddrVT));
1361 SDValue Val =
1362 DAG.getLoad(MVT::i64, DL, LdNode->getChain(), Addr,
1363 LdNode->getPointerInfo(), Alignment,
1366 OutChains[i] = SDValue(Val.getNode(), 1);
1367
1368 VM = DAG.getMachineNode(VE::LVMyir_y, DL, MVT::i64,
1369 DAG.getTargetConstant(i, DL, MVT::i64), Val,
1370 SDValue(VM, 0));
1371 }
1372 SDValue OutChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains);
1373 SDValue Ops[2] = {SDValue(VM, 0), OutChain};
1374 return DAG.getMergeValues(Ops, DL);
1375 } else {
1376 // Otherwise, ask llvm to expand it.
1377 return SDValue();
1378 }
1379}
1380
1382 LoadSDNode *LdNode = cast<LoadSDNode>(Op.getNode());
1383 EVT MemVT = LdNode->getMemoryVT();
1384
1385 // If VPU is enabled, always expand non-mask vector loads to VVP
1386 if (Subtarget->enableVPU() && MemVT.isVector() && !isMaskType(MemVT))
1387 return lowerToVVP(Op, DAG);
1388
1389 SDValue BasePtr = LdNode->getBasePtr();
1390 if (isa<FrameIndexSDNode>(BasePtr.getNode())) {
1391 // Do not expand store instruction with frame index here because of
1392 // dependency problems. We expand it later in eliminateFrameIndex().
1393 return Op;
1394 }
1395
1396 if (MemVT == MVT::f128)
1397 return lowerLoadF128(Op, DAG);
1398 if (isMaskType(MemVT))
1399 return lowerLoadI1(Op, DAG);
1400
1401 return Op;
1402}
1403
1404// Lower a f128 store into two f64 stores.
1406 SDLoc DL(Op);
1407 StoreSDNode *StNode = dyn_cast<StoreSDNode>(Op.getNode());
1408 assert(StNode && StNode->getOffset().isUndef() && "Unexpected node type");
1409
1410 SDValue SubRegEven = DAG.getTargetConstant(VE::sub_even, DL, MVT::i32);
1411 SDValue SubRegOdd = DAG.getTargetConstant(VE::sub_odd, DL, MVT::i32);
1412
1413 SDNode *Hi64 = DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL, MVT::i64,
1414 StNode->getValue(), SubRegEven);
1415 SDNode *Lo64 = DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL, MVT::i64,
1416 StNode->getValue(), SubRegOdd);
1417
1418 Align Alignment = StNode->getAlign();
1419 if (Alignment > 8)
1420 Alignment = Align(8);
1421
1422 // VE stores Hi64 to 8(addr) and Lo64 to 0(addr)
1423 SDValue OutChains[2];
1424 OutChains[0] =
1425 DAG.getStore(StNode->getChain(), DL, SDValue(Lo64, 0),
1426 StNode->getBasePtr(), MachinePointerInfo(), Alignment,
1429 EVT AddrVT = StNode->getBasePtr().getValueType();
1430 SDValue HiPtr = DAG.getNode(ISD::ADD, DL, AddrVT, StNode->getBasePtr(),
1431 DAG.getConstant(8, DL, AddrVT));
1432 OutChains[1] =
1433 DAG.getStore(StNode->getChain(), DL, SDValue(Hi64, 0), HiPtr,
1434 MachinePointerInfo(), Alignment,
1437 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains);
1438}
1439
1440// Lower a vXi1 store into following instructions
1441// SVMi %1, %vm, 0
1442// STrii %1, (,%addr)
1443// SVMi %2, %vm, 1
1444// STrii %2, 8(,%addr)
1445// ...
1447 SDLoc DL(Op);
1448 StoreSDNode *StNode = dyn_cast<StoreSDNode>(Op.getNode());
1449 assert(StNode && StNode->getOffset().isUndef() && "Unexpected node type");
1450
1451 SDValue BasePtr = StNode->getBasePtr();
1452 Align Alignment = StNode->getAlign();
1453 if (Alignment > 8)
1454 Alignment = Align(8);
1455 EVT AddrVT = BasePtr.getValueType();
1456 EVT MemVT = StNode->getMemoryVT();
1457 if (MemVT == MVT::v256i1 || MemVT == MVT::v4i64) {
1458 SDValue OutChains[4];
1459 for (int i = 0; i < 4; ++i) {
1460 SDNode *V =
1461 DAG.getMachineNode(VE::SVMmi, DL, MVT::i64, StNode->getValue(),
1462 DAG.getTargetConstant(i, DL, MVT::i64));
1463 SDValue Addr = DAG.getNode(ISD::ADD, DL, AddrVT, BasePtr,
1464 DAG.getConstant(8 * i, DL, AddrVT));
1465 OutChains[i] =
1466 DAG.getStore(StNode->getChain(), DL, SDValue(V, 0), Addr,
1467 MachinePointerInfo(), Alignment,
1470 }
1471 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains);
1472 } else if (MemVT == MVT::v512i1 || MemVT == MVT::v8i64) {
1473 SDValue OutChains[8];
1474 for (int i = 0; i < 8; ++i) {
1475 SDNode *V =
1476 DAG.getMachineNode(VE::SVMyi, DL, MVT::i64, StNode->getValue(),
1477 DAG.getTargetConstant(i, DL, MVT::i64));
1478 SDValue Addr = DAG.getNode(ISD::ADD, DL, AddrVT, BasePtr,
1479 DAG.getConstant(8 * i, DL, AddrVT));
1480 OutChains[i] =
1481 DAG.getStore(StNode->getChain(), DL, SDValue(V, 0), Addr,
1482 MachinePointerInfo(), Alignment,
1485 }
1486 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains);
1487 } else {
1488 // Otherwise, ask llvm to expand it.
1489 return SDValue();
1490 }
1491}
1492
1494 StoreSDNode *StNode = cast<StoreSDNode>(Op.getNode());
1495 assert(StNode && StNode->getOffset().isUndef() && "Unexpected node type");
1496 EVT MemVT = StNode->getMemoryVT();
1497
1498 // If VPU is enabled, always expand non-mask vector stores to VVP
1499 if (Subtarget->enableVPU() && MemVT.isVector() && !isMaskType(MemVT))
1500 return lowerToVVP(Op, DAG);
1501
1502 SDValue BasePtr = StNode->getBasePtr();
1503 if (isa<FrameIndexSDNode>(BasePtr.getNode())) {
1504 // Do not expand store instruction with frame index here because of
1505 // dependency problems. We expand it later in eliminateFrameIndex().
1506 return Op;
1507 }
1508
1509 if (MemVT == MVT::f128)
1510 return lowerStoreF128(Op, DAG);
1511 if (isMaskType(MemVT))
1512 return lowerStoreI1(Op, DAG);
1513
1514 // Otherwise, ask llvm to expand it.
1515 return SDValue();
1516}
1517
1521 auto PtrVT = getPointerTy(DAG.getDataLayout());
1522
1523 // Need frame address to find the address of VarArgsFrameIndex.
1525
1526 // vastart just stores the address of the VarArgsFrameIndex slot into the
1527 // memory location argument.
1528 SDLoc DL(Op);
1529 SDValue Offset =
1530 DAG.getNode(ISD::ADD, DL, PtrVT, DAG.getRegister(VE::SX9, PtrVT),
1531 DAG.getIntPtrConstant(FuncInfo->getVarArgsFrameOffset(), DL));
1532 const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
1533 return DAG.getStore(Op.getOperand(0), DL, Offset, Op.getOperand(1),
1534 MachinePointerInfo(SV));
1535}
1536
1538 SDNode *Node = Op.getNode();
1539 EVT VT = Node->getValueType(0);
1540 SDValue InChain = Node->getOperand(0);
1541 SDValue VAListPtr = Node->getOperand(1);
1542 EVT PtrVT = VAListPtr.getValueType();
1543 const Value *SV = cast<SrcValueSDNode>(Node->getOperand(2))->getValue();
1544 SDLoc DL(Node);
1545 SDValue VAList =
1546 DAG.getLoad(PtrVT, DL, InChain, VAListPtr, MachinePointerInfo(SV));
1547 SDValue Chain = VAList.getValue(1);
1548 SDValue NextPtr;
1549
1550 if (VT == MVT::f128) {
1551 // VE f128 values must be stored with 16 bytes alignment. We don't
1552 // know the actual alignment of VAList, so we take alignment of it
1553 // dynamically.
1554 int Align = 16;
1555 VAList = DAG.getNode(ISD::ADD, DL, PtrVT, VAList,
1556 DAG.getConstant(Align - 1, DL, PtrVT));
1557 VAList = DAG.getNode(ISD::AND, DL, PtrVT, VAList,
1558 DAG.getSignedConstant(-Align, DL, PtrVT));
1559 // Increment the pointer, VAList, by 16 to the next vaarg.
1560 NextPtr =
1561 DAG.getNode(ISD::ADD, DL, PtrVT, VAList, DAG.getIntPtrConstant(16, DL));
1562 } else if (VT == MVT::f32) {
1563 // float --> need special handling like below.
1564 // 0 4
1565 // +------+------+
1566 // | empty| float|
1567 // +------+------+
1568 // Increment the pointer, VAList, by 8 to the next vaarg.
1569 NextPtr =
1570 DAG.getNode(ISD::ADD, DL, PtrVT, VAList, DAG.getIntPtrConstant(8, DL));
1571 // Then, adjust VAList.
1572 unsigned InternalOffset = 4;
1573 VAList = DAG.getNode(ISD::ADD, DL, PtrVT, VAList,
1574 DAG.getConstant(InternalOffset, DL, PtrVT));
1575 } else {
1576 // Increment the pointer, VAList, by 8 to the next vaarg.
1577 NextPtr =
1578 DAG.getNode(ISD::ADD, DL, PtrVT, VAList, DAG.getIntPtrConstant(8, DL));
1579 }
1580
1581 // Store the incremented VAList to the legalized pointer.
1582 InChain = DAG.getStore(Chain, DL, NextPtr, VAListPtr, MachinePointerInfo(SV));
1583
1584 // Load the actual argument out of the pointer VAList.
1585 // We can't count on greater alignment than the word size.
1586 return DAG.getLoad(
1587 VT, DL, InChain, VAList, MachinePointerInfo(),
1588 Align(std::min(PtrVT.getSizeInBits(), VT.getSizeInBits()) / 8));
1589}
1590
1592 SelectionDAG &DAG) const {
1593 // Generate following code.
1594 // (void)__llvm_grow_stack(size);
1595 // ret = GETSTACKTOP; // pseudo instruction
1596 SDLoc DL(Op);
1597
1598 // Get the inputs.
1599 SDNode *Node = Op.getNode();
1600 SDValue Chain = Op.getOperand(0);
1601 SDValue Size = Op.getOperand(1);
1602 MaybeAlign Alignment(Op.getConstantOperandVal(2));
1603 EVT VT = Node->getValueType(0);
1604
1605 // Chain the dynamic stack allocation so that it doesn't modify the stack
1606 // pointer when other instructions are using the stack.
1607 Chain = DAG.getCALLSEQ_START(Chain, 0, 0, DL);
1608
1609 const TargetFrameLowering &TFI = *Subtarget->getFrameLowering();
1610 Align StackAlign = TFI.getStackAlign();
1611 bool NeedsAlign = Alignment.valueOrOne() > StackAlign;
1612
1613 // Prepare arguments
1615 Args.emplace_back(Size, Size.getValueType().getTypeForEVT(*DAG.getContext()));
1616 if (NeedsAlign) {
1617 SDValue Align = DAG.getConstant(~(Alignment->value() - 1ULL), DL, VT);
1618 Args.emplace_back(Align,
1619 Align.getValueType().getTypeForEVT(*DAG.getContext()));
1620 }
1621 Type *RetTy = Type::getVoidTy(*DAG.getContext());
1622
1623 EVT PtrVT = Op.getValueType();
1624 SDValue Callee;
1625 if (NeedsAlign) {
1626 Callee = DAG.getTargetExternalSymbol("__ve_grow_stack_align", PtrVT, 0);
1627 } else {
1628 Callee = DAG.getTargetExternalSymbol("__ve_grow_stack", PtrVT, 0);
1629 }
1630
1632 CLI.setDebugLoc(DL)
1633 .setChain(Chain)
1634 .setCallee(CallingConv::PreserveAll, RetTy, Callee, std::move(Args))
1635 .setDiscardResult(true);
1636 std::pair<SDValue, SDValue> pair = LowerCallTo(CLI);
1637 Chain = pair.second;
1638 SDValue Result = DAG.getNode(VEISD::GETSTACKTOP, DL, VT, Chain);
1639 if (NeedsAlign) {
1640 Result = DAG.getNode(ISD::ADD, DL, VT, Result,
1641 DAG.getConstant((Alignment->value() - 1ULL), DL, VT));
1642 Result = DAG.getNode(ISD::AND, DL, VT, Result,
1643 DAG.getConstant(~(Alignment->value() - 1ULL), DL, VT));
1644 }
1645 // Chain = Result.getValue(1);
1646 Chain = DAG.getCALLSEQ_END(Chain, 0, 0, SDValue(), DL);
1647
1648 SDValue Ops[2] = {Result, Chain};
1649 return DAG.getMergeValues(Ops, DL);
1650}
1651
1653 SelectionDAG &DAG) const {
1654 SDLoc DL(Op);
1655 return DAG.getNode(VEISD::EH_SJLJ_LONGJMP, DL, MVT::Other, Op.getOperand(0),
1656 Op.getOperand(1));
1657}
1658
1660 SelectionDAG &DAG) const {
1661 SDLoc DL(Op);
1662 return DAG.getNode(VEISD::EH_SJLJ_SETJMP, DL,
1663 DAG.getVTList(MVT::i32, MVT::Other), Op.getOperand(0),
1664 Op.getOperand(1));
1665}
1666
1668 SelectionDAG &DAG) const {
1669 SDLoc DL(Op);
1670 return DAG.getNode(VEISD::EH_SJLJ_SETUP_DISPATCH, DL, MVT::Other,
1671 Op.getOperand(0));
1672}
1673
1675 const VETargetLowering &TLI,
1676 const VESubtarget *Subtarget) {
1677 SDLoc DL(Op);
1679 EVT PtrVT = TLI.getPointerTy(MF.getDataLayout());
1680
1681 MachineFrameInfo &MFI = MF.getFrameInfo();
1682 MFI.setFrameAddressIsTaken(true);
1683
1684 unsigned Depth = Op.getConstantOperandVal(0);
1685 const VERegisterInfo *RegInfo = Subtarget->getRegisterInfo();
1686 Register FrameReg = RegInfo->getFrameRegister(MF);
1687 SDValue FrameAddr =
1688 DAG.getCopyFromReg(DAG.getEntryNode(), DL, FrameReg, PtrVT);
1689 while (Depth--)
1690 FrameAddr = DAG.getLoad(Op.getValueType(), DL, DAG.getEntryNode(),
1691 FrameAddr, MachinePointerInfo());
1692 return FrameAddr;
1693}
1694
1696 const VETargetLowering &TLI,
1697 const VESubtarget *Subtarget) {
1699 MachineFrameInfo &MFI = MF.getFrameInfo();
1700 MFI.setReturnAddressIsTaken(true);
1701
1702 SDValue FrameAddr = lowerFRAMEADDR(Op, DAG, TLI, Subtarget);
1703
1704 SDLoc DL(Op);
1705 EVT VT = Op.getValueType();
1706 SDValue Offset = DAG.getConstant(8, DL, VT);
1707 return DAG.getLoad(VT, DL, DAG.getEntryNode(),
1708 DAG.getNode(ISD::ADD, DL, VT, FrameAddr, Offset),
1710}
1711
1713 SelectionDAG &DAG) const {
1714 SDLoc DL(Op);
1715 unsigned IntNo = Op.getConstantOperandVal(0);
1716 switch (IntNo) {
1717 default: // Don't custom lower most intrinsics.
1718 return SDValue();
1719 case Intrinsic::eh_sjlj_lsda: {
1721 MVT VT = Op.getSimpleValueType();
1722 const VETargetMachine *TM =
1723 static_cast<const VETargetMachine *>(&DAG.getTarget());
1724
1725 // Create GCC_except_tableXX string. The real symbol for that will be
1726 // generated in EHStreamer::emitExceptionTable() later. So, we just
1727 // borrow it's name here.
1728 TM->getStrList()->push_back(std::string(
1729 (Twine("GCC_except_table") + Twine(MF.getFunctionNumber())).str()));
1730 SDValue Addr =
1731 DAG.getTargetExternalSymbol(TM->getStrList()->back().c_str(), VT, 0);
1732 if (isPositionIndependent()) {
1734 SDValue GlobalBase = DAG.getNode(VEISD::GLOBAL_BASE_REG, DL, VT);
1735 return DAG.getNode(ISD::ADD, DL, VT, GlobalBase, Addr);
1736 }
1737 return makeHiLoPair(Addr, VE::S_HI32, VE::S_LO32, DAG);
1738 }
1739 }
1740}
1741
1742static bool getUniqueInsertion(SDNode *N, unsigned &UniqueIdx) {
1744 return false;
1745 const auto *BVN = cast<BuildVectorSDNode>(N);
1746
1747 // Find first non-undef insertion.
1748 unsigned Idx;
1749 for (Idx = 0; Idx < BVN->getNumOperands(); ++Idx) {
1750 auto ElemV = BVN->getOperand(Idx);
1751 if (!ElemV->isUndef())
1752 break;
1753 }
1754 // Catch the (hypothetical) all-undef case.
1755 if (Idx == BVN->getNumOperands())
1756 return false;
1757 // Remember insertion.
1758 UniqueIdx = Idx++;
1759 // Verify that all other insertions are undef.
1760 for (; Idx < BVN->getNumOperands(); ++Idx) {
1761 auto ElemV = BVN->getOperand(Idx);
1762 if (!ElemV->isUndef())
1763 return false;
1764 }
1765 return true;
1766}
1767
1769 if (auto *BuildVec = dyn_cast<BuildVectorSDNode>(N)) {
1770 return BuildVec->getSplatValue();
1771 }
1772 return SDValue();
1773}
1774
1776 SelectionDAG &DAG) const {
1777 VECustomDAG CDAG(DAG, Op);
1778 MVT ResultVT = Op.getSimpleValueType();
1779
1780 // If there is just one element, expand to INSERT_VECTOR_ELT.
1781 unsigned UniqueIdx;
1782 if (getUniqueInsertion(Op.getNode(), UniqueIdx)) {
1783 SDValue AccuV = CDAG.getUNDEF(Op.getValueType());
1784 auto ElemV = Op->getOperand(UniqueIdx);
1785 SDValue IdxV = CDAG.getConstant(UniqueIdx, MVT::i64);
1786 return CDAG.getNode(ISD::INSERT_VECTOR_ELT, ResultVT, {AccuV, ElemV, IdxV});
1787 }
1788
1789 // Else emit a broadcast.
1790 if (SDValue ScalarV = getSplatValue(Op.getNode())) {
1791 unsigned NumEls = ResultVT.getVectorNumElements();
1792 auto AVL = CDAG.getConstant(NumEls, MVT::i32);
1793 return CDAG.getBroadcast(ResultVT, ScalarV, AVL);
1794 }
1795
1796 // Expand
1797 return SDValue();
1798}
1799
1802 // Custom legalization on VVP_* and VEC_* opcodes is required to pack-legalize
1803 // these operations (transform nodes such that their AVL parameter refers to
1804 // packs of 64bit, instead of number of elements.
1805
1806 // Packing opcodes are created with a pack-legal AVL (LEGALAVL). No need to
1807 // re-visit them.
1808 if (isPackingSupportOpcode(Op.getOpcode()))
1809 return Legal;
1810
1811 // Custom lower to legalize AVL for packed mode.
1812 if (isVVPOrVEC(Op.getOpcode()))
1813 return Custom;
1814 return Legal;
1815}
1816
1818 LLVM_DEBUG(dbgs() << "::LowerOperation "; Op.dump(&DAG));
1819 unsigned Opcode = Op.getOpcode();
1820
1821 /// Scalar isel.
1822 switch (Opcode) {
1823 case ISD::ATOMIC_FENCE:
1824 return lowerATOMIC_FENCE(Op, DAG);
1825 case ISD::ATOMIC_SWAP:
1826 return lowerATOMIC_SWAP(Op, DAG);
1827 case ISD::BlockAddress:
1828 return lowerBlockAddress(Op, DAG);
1829 case ISD::ConstantPool:
1830 return lowerConstantPool(Op, DAG);
1832 return lowerDYNAMIC_STACKALLOC(Op, DAG);
1834 return lowerEH_SJLJ_LONGJMP(Op, DAG);
1836 return lowerEH_SJLJ_SETJMP(Op, DAG);
1838 return lowerEH_SJLJ_SETUP_DISPATCH(Op, DAG);
1839 case ISD::FRAMEADDR:
1840 return lowerFRAMEADDR(Op, DAG, *this, Subtarget);
1841 case ISD::GlobalAddress:
1842 return lowerGlobalAddress(Op, DAG);
1844 return lowerGlobalTLSAddress(Op, DAG);
1846 return lowerINTRINSIC_WO_CHAIN(Op, DAG);
1847 case ISD::JumpTable:
1848 return lowerJumpTable(Op, DAG);
1849 case ISD::LOAD:
1850 return lowerLOAD(Op, DAG);
1851 case ISD::RETURNADDR:
1852 return lowerRETURNADDR(Op, DAG, *this, Subtarget);
1853 case ISD::BUILD_VECTOR:
1854 return lowerBUILD_VECTOR(Op, DAG);
1855 case ISD::STORE:
1856 return lowerSTORE(Op, DAG);
1857 case ISD::VASTART:
1858 return lowerVASTART(Op, DAG);
1859 case ISD::VAARG:
1860 return lowerVAARG(Op, DAG);
1861
1863 return lowerINSERT_VECTOR_ELT(Op, DAG);
1865 return lowerEXTRACT_VECTOR_ELT(Op, DAG);
1866 }
1867
1868 /// Vector isel.
1869 if (ISD::isVPOpcode(Opcode))
1870 return lowerToVVP(Op, DAG);
1871
1872 switch (Opcode) {
1873 default:
1874 llvm_unreachable("Should not custom lower this!");
1875
1876 // Legalize the AVL of this internal node.
1877 case VEISD::VEC_BROADCAST:
1878#define ADD_VVP_OP(VVP_NAME, ...) case VEISD::VVP_NAME:
1879#include "VVPNodes.def"
1880 // AVL already legalized.
1881 if (getAnnotatedNodeAVL(Op).second)
1882 return Op;
1883 return legalizeInternalVectorOp(Op, DAG);
1884
1885 // Translate into a VEC_*/VVP_* layer operation.
1886 case ISD::MLOAD:
1887 case ISD::MSTORE:
1888#define ADD_VVP_OP(VVP_NAME, ISD_NAME) case ISD::ISD_NAME:
1889#include "VVPNodes.def"
1890 if (isMaskArithmetic(Op) && isPackedVectorType(Op.getValueType()))
1891 return splitMaskArithmetic(Op, DAG);
1892 return lowerToVVP(Op, DAG);
1893 }
1894}
1895/// } Custom Lower
1896
1899 SelectionDAG &DAG) const {
1900 switch (N->getOpcode()) {
1901 case ISD::ATOMIC_SWAP:
1902 // Let LLVM expand atomic swap instruction through LowerOperation.
1903 return;
1904 default:
1905 LLVM_DEBUG(N->dumpr(&DAG));
1906 llvm_unreachable("Do not know how to custom type legalize this operation!");
1907 }
1908}
1909
1910/// JumpTable for VE.
1911///
1912/// VE cannot generate relocatable symbol in jump table. VE cannot
1913/// generate expressions using symbols in both text segment and data
1914/// segment like below.
1915/// .4byte .LBB0_2-.LJTI0_0
1916/// So, we generate offset from the top of function like below as
1917/// a custom label.
1918/// .4byte .LBB0_2-<function name>
1919
1921 // Use custom label for PIC.
1924
1925 // Otherwise, use the normal jump table encoding heuristics.
1927}
1928
1930 const MachineJumpTableInfo *MJTI, const MachineBasicBlock *MBB,
1931 unsigned Uid, MCContext &Ctx) const {
1933
1934 // Generate custom label for PIC like below.
1935 // .4bytes .LBB0_2-<function name>
1936 const auto *Value = MCSymbolRefExpr::create(MBB->getSymbol(), Ctx);
1937 MCSymbol *Sym = Ctx.getOrCreateSymbol(MBB->getParent()->getName().data());
1938 const auto *Base = MCSymbolRefExpr::create(Sym, Ctx);
1939 return MCBinaryExpr::createSub(Value, Base, Ctx);
1940}
1941
1943 SelectionDAG &DAG) const {
1945 SDLoc DL(Table);
1947 assert(Function != nullptr);
1948 auto PtrTy = getPointerTy(DAG.getDataLayout(), Function->getAddressSpace());
1949
1950 // In the jump table, we have following values in PIC mode.
1951 // .4bytes .LBB0_2-<function name>
1952 // We need to add this value and the address of this function to generate
1953 // .LBB0_2 label correctly under PIC mode. So, we want to generate following
1954 // instructions:
1955 // lea %reg, fun@gotoff_lo
1956 // and %reg, %reg, (32)0
1957 // lea.sl %reg, fun@gotoff_hi(%reg, %got)
1958 // In order to do so, we need to genarate correctly marked DAG node using
1959 // makeHiLoPair.
1960 SDValue Op = DAG.getGlobalAddress(Function, DL, PtrTy);
1962 SDValue GlobalBase = DAG.getNode(VEISD::GLOBAL_BASE_REG, DL, PtrTy);
1963 return DAG.getNode(ISD::ADD, DL, PtrTy, GlobalBase, HiLo);
1964}
1965
1968 MachineBasicBlock *TargetBB,
1969 const DebugLoc &DL) const {
1970 MachineFunction *MF = MBB.getParent();
1971 MachineRegisterInfo &MRI = MF->getRegInfo();
1972 const VEInstrInfo *TII = Subtarget->getInstrInfo();
1973
1974 const TargetRegisterClass *RC = &VE::I64RegClass;
1975 Register Tmp1 = MRI.createVirtualRegister(RC);
1976 Register Tmp2 = MRI.createVirtualRegister(RC);
1977 Register Result = MRI.createVirtualRegister(RC);
1978
1979 if (isPositionIndependent()) {
1980 // Create following instructions for local linkage PIC code.
1981 // lea %Tmp1, TargetBB@gotoff_lo
1982 // and %Tmp2, %Tmp1, (32)0
1983 // lea.sl %Result, TargetBB@gotoff_hi(%Tmp2, %s15) ; %s15 is GOT
1984 BuildMI(MBB, I, DL, TII->get(VE::LEAzii), Tmp1)
1985 .addImm(0)
1986 .addImm(0)
1987 .addMBB(TargetBB, VE::S_GOTOFF_LO32);
1988 BuildMI(MBB, I, DL, TII->get(VE::ANDrm), Tmp2)
1989 .addReg(Tmp1, getKillRegState(true))
1990 .addImm(M0(32));
1991 BuildMI(MBB, I, DL, TII->get(VE::LEASLrri), Result)
1992 .addReg(VE::SX15)
1993 .addReg(Tmp2, getKillRegState(true))
1994 .addMBB(TargetBB, VE::S_GOTOFF_HI32);
1995 } else {
1996 // Create following instructions for non-PIC code.
1997 // lea %Tmp1, TargetBB@lo
1998 // and %Tmp2, %Tmp1, (32)0
1999 // lea.sl %Result, TargetBB@hi(%Tmp2)
2000 BuildMI(MBB, I, DL, TII->get(VE::LEAzii), Tmp1)
2001 .addImm(0)
2002 .addImm(0)
2003 .addMBB(TargetBB, VE::S_LO32);
2004 BuildMI(MBB, I, DL, TII->get(VE::ANDrm), Tmp2)
2005 .addReg(Tmp1, getKillRegState(true))
2006 .addImm(M0(32));
2007 BuildMI(MBB, I, DL, TII->get(VE::LEASLrii), Result)
2008 .addReg(Tmp2, getKillRegState(true))
2009 .addImm(0)
2010 .addMBB(TargetBB, VE::S_HI32);
2011 }
2012 return Result;
2013}
2014
2017 StringRef Symbol, const DebugLoc &DL,
2018 bool IsLocal = false,
2019 bool IsCall = false) const {
2020 MachineFunction *MF = MBB.getParent();
2021 MachineRegisterInfo &MRI = MF->getRegInfo();
2022 const VEInstrInfo *TII = Subtarget->getInstrInfo();
2023
2024 const TargetRegisterClass *RC = &VE::I64RegClass;
2025 Register Result = MRI.createVirtualRegister(RC);
2026
2027 if (isPositionIndependent()) {
2028 if (IsCall && !IsLocal) {
2029 // Create following instructions for non-local linkage PIC code function
2030 // calls. These instructions uses IC and magic number -24, so we expand
2031 // them in VEAsmPrinter.cpp from GETFUNPLT pseudo instruction.
2032 // lea %Reg, Symbol@plt_lo(-24)
2033 // and %Reg, %Reg, (32)0
2034 // sic %s16
2035 // lea.sl %Result, Symbol@plt_hi(%Reg, %s16) ; %s16 is PLT
2036 BuildMI(MBB, I, DL, TII->get(VE::GETFUNPLT), Result)
2037 .addExternalSymbol("abort");
2038 } else if (IsLocal) {
2039 Register Tmp1 = MRI.createVirtualRegister(RC);
2040 Register Tmp2 = MRI.createVirtualRegister(RC);
2041 // Create following instructions for local linkage PIC code.
2042 // lea %Tmp1, Symbol@gotoff_lo
2043 // and %Tmp2, %Tmp1, (32)0
2044 // lea.sl %Result, Symbol@gotoff_hi(%Tmp2, %s15) ; %s15 is GOT
2045 BuildMI(MBB, I, DL, TII->get(VE::LEAzii), Tmp1)
2046 .addImm(0)
2047 .addImm(0)
2048 .addExternalSymbol(Symbol.data(), VE::S_GOTOFF_LO32);
2049 BuildMI(MBB, I, DL, TII->get(VE::ANDrm), Tmp2)
2050 .addReg(Tmp1, getKillRegState(true))
2051 .addImm(M0(32));
2052 BuildMI(MBB, I, DL, TII->get(VE::LEASLrri), Result)
2053 .addReg(VE::SX15)
2054 .addReg(Tmp2, getKillRegState(true))
2055 .addExternalSymbol(Symbol.data(), VE::S_GOTOFF_HI32);
2056 } else {
2057 Register Tmp1 = MRI.createVirtualRegister(RC);
2058 Register Tmp2 = MRI.createVirtualRegister(RC);
2059 // Create following instructions for not local linkage PIC code.
2060 // lea %Tmp1, Symbol@got_lo
2061 // and %Tmp2, %Tmp1, (32)0
2062 // lea.sl %Tmp3, Symbol@gotoff_hi(%Tmp2, %s15) ; %s15 is GOT
2063 // ld %Result, 0(%Tmp3)
2064 Register Tmp3 = MRI.createVirtualRegister(RC);
2065 BuildMI(MBB, I, DL, TII->get(VE::LEAzii), Tmp1)
2066 .addImm(0)
2067 .addImm(0)
2068 .addExternalSymbol(Symbol.data(), VE::S_GOT_LO32);
2069 BuildMI(MBB, I, DL, TII->get(VE::ANDrm), Tmp2)
2070 .addReg(Tmp1, getKillRegState(true))
2071 .addImm(M0(32));
2072 BuildMI(MBB, I, DL, TII->get(VE::LEASLrri), Tmp3)
2073 .addReg(VE::SX15)
2074 .addReg(Tmp2, getKillRegState(true))
2075 .addExternalSymbol(Symbol.data(), VE::S_GOT_HI32);
2076 BuildMI(MBB, I, DL, TII->get(VE::LDrii), Result)
2077 .addReg(Tmp3, getKillRegState(true))
2078 .addImm(0)
2079 .addImm(0);
2080 }
2081 } else {
2082 Register Tmp1 = MRI.createVirtualRegister(RC);
2083 Register Tmp2 = MRI.createVirtualRegister(RC);
2084 // Create following instructions for non-PIC code.
2085 // lea %Tmp1, Symbol@lo
2086 // and %Tmp2, %Tmp1, (32)0
2087 // lea.sl %Result, Symbol@hi(%Tmp2)
2088 BuildMI(MBB, I, DL, TII->get(VE::LEAzii), Tmp1)
2089 .addImm(0)
2090 .addImm(0)
2091 .addExternalSymbol(Symbol.data(), VE::S_LO32);
2092 BuildMI(MBB, I, DL, TII->get(VE::ANDrm), Tmp2)
2093 .addReg(Tmp1, getKillRegState(true))
2094 .addImm(M0(32));
2095 BuildMI(MBB, I, DL, TII->get(VE::LEASLrii), Result)
2096 .addReg(Tmp2, getKillRegState(true))
2097 .addImm(0)
2098 .addExternalSymbol(Symbol.data(), VE::S_HI32);
2099 }
2100 return Result;
2101}
2102
2105 MachineBasicBlock *DispatchBB,
2106 int FI, int Offset) const {
2107 DebugLoc DL = MI.getDebugLoc();
2108 const VEInstrInfo *TII = Subtarget->getInstrInfo();
2109
2110 Register LabelReg =
2112
2113 // Store an address of DispatchBB to a given jmpbuf[1] where has next IC
2114 // referenced by longjmp (throw) later.
2115 MachineInstrBuilder MIB = BuildMI(*MBB, MI, DL, TII->get(VE::STrii));
2116 addFrameReference(MIB, FI, Offset); // jmpbuf[1]
2117 MIB.addReg(LabelReg, getKillRegState(true));
2118}
2119
2122 MachineBasicBlock *MBB) const {
2123 DebugLoc DL = MI.getDebugLoc();
2124 MachineFunction *MF = MBB->getParent();
2125 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
2126 const TargetRegisterInfo *TRI = Subtarget->getRegisterInfo();
2127 MachineRegisterInfo &MRI = MF->getRegInfo();
2128
2129 const BasicBlock *BB = MBB->getBasicBlock();
2130 MachineFunction::iterator I = ++MBB->getIterator();
2131
2132 // Memory Reference.
2133 SmallVector<MachineMemOperand *, 2> MMOs(MI.memoperands());
2134 Register BufReg = MI.getOperand(1).getReg();
2135
2136 Register DstReg;
2137
2138 DstReg = MI.getOperand(0).getReg();
2139 const TargetRegisterClass *RC = MRI.getRegClass(DstReg);
2140 assert(TRI->isTypeLegalForClass(*RC, MVT::i32) && "Invalid destination!");
2141 (void)TRI;
2142 Register MainDestReg = MRI.createVirtualRegister(RC);
2143 Register RestoreDestReg = MRI.createVirtualRegister(RC);
2144
2145 // For `v = call @llvm.eh.sjlj.setjmp(buf)`, we generate following
2146 // instructions. SP/FP must be saved in jmpbuf before `llvm.eh.sjlj.setjmp`.
2147 //
2148 // ThisMBB:
2149 // buf[3] = %s17 iff %s17 is used as BP
2150 // buf[1] = RestoreMBB as IC after longjmp
2151 // # SjLjSetup RestoreMBB
2152 //
2153 // MainMBB:
2154 // v_main = 0
2155 //
2156 // SinkMBB:
2157 // v = phi(v_main, MainMBB, v_restore, RestoreMBB)
2158 // ...
2159 //
2160 // RestoreMBB:
2161 // %s17 = buf[3] = iff %s17 is used as BP
2162 // v_restore = 1
2163 // goto SinkMBB
2164
2165 MachineBasicBlock *ThisMBB = MBB;
2166 MachineBasicBlock *MainMBB = MF->CreateMachineBasicBlock(BB);
2167 MachineBasicBlock *SinkMBB = MF->CreateMachineBasicBlock(BB);
2168 MachineBasicBlock *RestoreMBB = MF->CreateMachineBasicBlock(BB);
2169 MF->insert(I, MainMBB);
2170 MF->insert(I, SinkMBB);
2171 MF->push_back(RestoreMBB);
2172 RestoreMBB->setMachineBlockAddressTaken();
2173
2174 // Transfer the remainder of BB and its successor edges to SinkMBB.
2175 SinkMBB->splice(SinkMBB->begin(), MBB,
2176 std::next(MachineBasicBlock::iterator(MI)), MBB->end());
2178
2179 // ThisMBB:
2180 Register LabelReg =
2182
2183 // Store BP in buf[3] iff this function is using BP.
2184 const VEFrameLowering *TFI = Subtarget->getFrameLowering();
2185 if (TFI->hasBP(*MF)) {
2186 MachineInstrBuilder MIB = BuildMI(*MBB, MI, DL, TII->get(VE::STrii));
2187 MIB.addReg(BufReg);
2188 MIB.addImm(0);
2189 MIB.addImm(24);
2190 MIB.addReg(VE::SX17);
2191 MIB.setMemRefs(MMOs);
2192 }
2193
2194 // Store IP in buf[1].
2195 MachineInstrBuilder MIB = BuildMI(*MBB, MI, DL, TII->get(VE::STrii));
2196 MIB.add(MI.getOperand(1)); // we can preserve the kill flags here.
2197 MIB.addImm(0);
2198 MIB.addImm(8);
2199 MIB.addReg(LabelReg, getKillRegState(true));
2200 MIB.setMemRefs(MMOs);
2201
2202 // SP/FP are already stored in jmpbuf before `llvm.eh.sjlj.setjmp`.
2203
2204 // Insert setup.
2205 MIB =
2206 BuildMI(*ThisMBB, MI, DL, TII->get(VE::EH_SjLj_Setup)).addMBB(RestoreMBB);
2207
2208 const VERegisterInfo *RegInfo = Subtarget->getRegisterInfo();
2209 MIB.addRegMask(RegInfo->getNoPreservedMask());
2210 ThisMBB->addSuccessor(MainMBB);
2211 ThisMBB->addSuccessor(RestoreMBB);
2212
2213 // MainMBB:
2214 BuildMI(MainMBB, DL, TII->get(VE::LEAzii), MainDestReg)
2215 .addImm(0)
2216 .addImm(0)
2217 .addImm(0);
2218 MainMBB->addSuccessor(SinkMBB);
2219
2220 // SinkMBB:
2221 BuildMI(*SinkMBB, SinkMBB->begin(), DL, TII->get(VE::PHI), DstReg)
2222 .addReg(MainDestReg)
2223 .addMBB(MainMBB)
2224 .addReg(RestoreDestReg)
2225 .addMBB(RestoreMBB);
2226
2227 // RestoreMBB:
2228 // Restore BP from buf[3] iff this function is using BP. The address of
2229 // buf is in SX10.
2230 // FIXME: Better to not use SX10 here
2231 if (TFI->hasBP(*MF)) {
2233 BuildMI(RestoreMBB, DL, TII->get(VE::LDrii), VE::SX17);
2234 MIB.addReg(VE::SX10);
2235 MIB.addImm(0);
2236 MIB.addImm(24);
2237 MIB.setMemRefs(MMOs);
2238 }
2239 BuildMI(RestoreMBB, DL, TII->get(VE::LEAzii), RestoreDestReg)
2240 .addImm(0)
2241 .addImm(0)
2242 .addImm(1);
2243 BuildMI(RestoreMBB, DL, TII->get(VE::BRCFLa_t)).addMBB(SinkMBB);
2244 RestoreMBB->addSuccessor(SinkMBB);
2245
2246 MI.eraseFromParent();
2247 return SinkMBB;
2248}
2249
2252 MachineBasicBlock *MBB) const {
2253 DebugLoc DL = MI.getDebugLoc();
2254 MachineFunction *MF = MBB->getParent();
2255 const TargetInstrInfo *TII = Subtarget->getInstrInfo();
2256 MachineRegisterInfo &MRI = MF->getRegInfo();
2257
2258 // Memory Reference.
2259 SmallVector<MachineMemOperand *, 2> MMOs(MI.memoperands());
2260 Register BufReg = MI.getOperand(0).getReg();
2261
2262 Register Tmp = MRI.createVirtualRegister(&VE::I64RegClass);
2263 // Since FP is only updated here but NOT referenced, it's treated as GPR.
2264 Register FP = VE::SX9;
2265 Register SP = VE::SX11;
2266
2268
2269 MachineBasicBlock *ThisMBB = MBB;
2270
2271 // For `call @llvm.eh.sjlj.longjmp(buf)`, we generate following instructions.
2272 //
2273 // ThisMBB:
2274 // %fp = load buf[0]
2275 // %jmp = load buf[1]
2276 // %s10 = buf ; Store an address of buf to SX10 for RestoreMBB
2277 // %sp = load buf[2] ; generated by llvm.eh.sjlj.setjmp.
2278 // jmp %jmp
2279
2280 // Reload FP.
2281 MIB = BuildMI(*ThisMBB, MI, DL, TII->get(VE::LDrii), FP);
2282 MIB.addReg(BufReg);
2283 MIB.addImm(0);
2284 MIB.addImm(0);
2285 MIB.setMemRefs(MMOs);
2286
2287 // Reload IP.
2288 MIB = BuildMI(*ThisMBB, MI, DL, TII->get(VE::LDrii), Tmp);
2289 MIB.addReg(BufReg);
2290 MIB.addImm(0);
2291 MIB.addImm(8);
2292 MIB.setMemRefs(MMOs);
2293
2294 // Copy BufReg to SX10 for later use in setjmp.
2295 // FIXME: Better to not use SX10 here
2296 BuildMI(*ThisMBB, MI, DL, TII->get(VE::ORri), VE::SX10)
2297 .addReg(BufReg)
2298 .addImm(0);
2299
2300 // Reload SP.
2301 MIB = BuildMI(*ThisMBB, MI, DL, TII->get(VE::LDrii), SP);
2302 MIB.add(MI.getOperand(0)); // we can preserve the kill flags here.
2303 MIB.addImm(0);
2304 MIB.addImm(16);
2305 MIB.setMemRefs(MMOs);
2306
2307 // Jump.
2308 BuildMI(*ThisMBB, MI, DL, TII->get(VE::BCFLari_t))
2309 .addReg(Tmp, getKillRegState(true))
2310 .addImm(0);
2311
2312 MI.eraseFromParent();
2313 return ThisMBB;
2314}
2315
2318 MachineBasicBlock *BB) const {
2319 DebugLoc DL = MI.getDebugLoc();
2320 MachineFunction *MF = BB->getParent();
2321 MachineFrameInfo &MFI = MF->getFrameInfo();
2322 MachineRegisterInfo &MRI = MF->getRegInfo();
2323 const VEInstrInfo *TII = Subtarget->getInstrInfo();
2324 int FI = MFI.getFunctionContextIndex();
2325
2326 // Get a mapping of the call site numbers to all of the landing pads they're
2327 // associated with.
2329 unsigned MaxCSNum = 0;
2330 for (auto &MBB : *MF) {
2331 if (!MBB.isEHPad())
2332 continue;
2333
2334 MCSymbol *Sym = nullptr;
2335 for (const auto &MI : MBB) {
2336 if (MI.isDebugInstr())
2337 continue;
2338
2339 assert(MI.isEHLabel() && "expected EH_LABEL");
2340 Sym = MI.getOperand(0).getMCSymbol();
2341 break;
2342 }
2343
2344 if (!MF->hasCallSiteLandingPad(Sym))
2345 continue;
2346
2347 for (unsigned CSI : MF->getCallSiteLandingPad(Sym)) {
2348 CallSiteNumToLPad[CSI].push_back(&MBB);
2349 MaxCSNum = std::max(MaxCSNum, CSI);
2350 }
2351 }
2352
2353 // Get an ordered list of the machine basic blocks for the jump table.
2354 std::vector<MachineBasicBlock *> LPadList;
2356 LPadList.reserve(CallSiteNumToLPad.size());
2357
2358 for (unsigned CSI = 1; CSI <= MaxCSNum; ++CSI) {
2359 for (auto &LP : CallSiteNumToLPad[CSI]) {
2360 LPadList.push_back(LP);
2361 InvokeBBs.insert_range(LP->predecessors());
2362 }
2363 }
2364
2365 assert(!LPadList.empty() &&
2366 "No landing pad destinations for the dispatch jump table!");
2367
2368 // The %fn_context is allocated like below (from --print-after=sjljehprepare):
2369 // %fn_context = alloca { i8*, i64, [4 x i64], i8*, i8*, [5 x i8*] }
2370 //
2371 // This `[5 x i8*]` is jmpbuf, so jmpbuf[1] is FI+72.
2372 // First `i64` is callsite, so callsite is FI+8.
2373 static const int OffsetIC = 72;
2374 static const int OffsetCS = 8;
2375
2376 // Create the MBBs for the dispatch code like following:
2377 //
2378 // ThisMBB:
2379 // Prepare DispatchBB address and store it to buf[1].
2380 // ...
2381 //
2382 // DispatchBB:
2383 // %s15 = GETGOT iff isPositionIndependent
2384 // %callsite = load callsite
2385 // brgt.l.t #size of callsites, %callsite, DispContBB
2386 //
2387 // TrapBB:
2388 // Call abort.
2389 //
2390 // DispContBB:
2391 // %breg = address of jump table
2392 // %pc = load and calculate next pc from %breg and %callsite
2393 // jmp %pc
2394
2395 // Shove the dispatch's address into the return slot in the function context.
2396 MachineBasicBlock *DispatchBB = MF->CreateMachineBasicBlock();
2397 DispatchBB->setIsEHPad(true);
2398
2399 // Trap BB will causes trap like `assert(0)`.
2401 DispatchBB->addSuccessor(TrapBB);
2402
2403 MachineBasicBlock *DispContBB = MF->CreateMachineBasicBlock();
2404 DispatchBB->addSuccessor(DispContBB);
2405
2406 // Insert MBBs.
2407 MF->push_back(DispatchBB);
2408 MF->push_back(DispContBB);
2409 MF->push_back(TrapBB);
2410
2411 // Insert code to call abort in the TrapBB.
2412 Register Abort = prepareSymbol(*TrapBB, TrapBB->end(), "abort", DL,
2413 /* Local */ false, /* Call */ true);
2414 BuildMI(TrapBB, DL, TII->get(VE::BSICrii), VE::SX10)
2415 .addReg(Abort, getKillRegState(true))
2416 .addImm(0)
2417 .addImm(0);
2418
2419 // Insert code into the entry block that creates and registers the function
2420 // context.
2421 setupEntryBlockForSjLj(MI, BB, DispatchBB, FI, OffsetIC);
2422
2423 // Create the jump table and associated information
2424 unsigned JTE = getJumpTableEncoding();
2426 unsigned MJTI = JTI->createJumpTableIndex(LPadList);
2427
2428 const VERegisterInfo &RI = TII->getRegisterInfo();
2429 // Add a register mask with no preserved registers. This results in all
2430 // registers being marked as clobbered.
2431 BuildMI(DispatchBB, DL, TII->get(VE::NOP))
2433
2434 if (isPositionIndependent()) {
2435 // Force to generate GETGOT, since current implementation doesn't store GOT
2436 // register.
2437 BuildMI(DispatchBB, DL, TII->get(VE::GETGOT), VE::SX15);
2438 }
2439
2440 // IReg is used as an index in a memory operand and therefore can't be SP
2441 const TargetRegisterClass *RC = &VE::I64RegClass;
2442 Register IReg = MRI.createVirtualRegister(RC);
2443 addFrameReference(BuildMI(DispatchBB, DL, TII->get(VE::LDLZXrii), IReg), FI,
2444 OffsetCS);
2445 if (LPadList.size() < 64) {
2446 BuildMI(DispatchBB, DL, TII->get(VE::BRCFLir_t))
2448 .addImm(LPadList.size())
2449 .addReg(IReg)
2450 .addMBB(TrapBB);
2451 } else {
2452 assert(LPadList.size() <= 0x7FFFFFFF && "Too large Landing Pad!");
2453 Register TmpReg = MRI.createVirtualRegister(RC);
2454 BuildMI(DispatchBB, DL, TII->get(VE::LEAzii), TmpReg)
2455 .addImm(0)
2456 .addImm(0)
2457 .addImm(LPadList.size());
2458 BuildMI(DispatchBB, DL, TII->get(VE::BRCFLrr_t))
2460 .addReg(TmpReg, getKillRegState(true))
2461 .addReg(IReg)
2462 .addMBB(TrapBB);
2463 }
2464
2465 Register BReg = MRI.createVirtualRegister(RC);
2466 Register Tmp1 = MRI.createVirtualRegister(RC);
2467 Register Tmp2 = MRI.createVirtualRegister(RC);
2468
2469 if (isPositionIndependent()) {
2470 // Create following instructions for local linkage PIC code.
2471 // lea %Tmp1, .LJTI0_0@gotoff_lo
2472 // and %Tmp2, %Tmp1, (32)0
2473 // lea.sl %BReg, .LJTI0_0@gotoff_hi(%Tmp2, %s15) ; %s15 is GOT
2474 BuildMI(DispContBB, DL, TII->get(VE::LEAzii), Tmp1)
2475 .addImm(0)
2476 .addImm(0)
2478 BuildMI(DispContBB, DL, TII->get(VE::ANDrm), Tmp2)
2479 .addReg(Tmp1, getKillRegState(true))
2480 .addImm(M0(32));
2481 BuildMI(DispContBB, DL, TII->get(VE::LEASLrri), BReg)
2482 .addReg(VE::SX15)
2483 .addReg(Tmp2, getKillRegState(true))
2485 } else {
2486 // Create following instructions for non-PIC code.
2487 // lea %Tmp1, .LJTI0_0@lo
2488 // and %Tmp2, %Tmp1, (32)0
2489 // lea.sl %BReg, .LJTI0_0@hi(%Tmp2)
2490 BuildMI(DispContBB, DL, TII->get(VE::LEAzii), Tmp1)
2491 .addImm(0)
2492 .addImm(0)
2494 BuildMI(DispContBB, DL, TII->get(VE::ANDrm), Tmp2)
2495 .addReg(Tmp1, getKillRegState(true))
2496 .addImm(M0(32));
2497 BuildMI(DispContBB, DL, TII->get(VE::LEASLrii), BReg)
2498 .addReg(Tmp2, getKillRegState(true))
2499 .addImm(0)
2501 }
2502
2503 switch (JTE) {
2505 // Generate simple block address code for no-PIC model.
2506 // sll %Tmp1, %IReg, 3
2507 // lds %TReg, 0(%Tmp1, %BReg)
2508 // bcfla %TReg
2509
2510 Register TReg = MRI.createVirtualRegister(RC);
2511 Register Tmp1 = MRI.createVirtualRegister(RC);
2512
2513 BuildMI(DispContBB, DL, TII->get(VE::SLLri), Tmp1)
2514 .addReg(IReg, getKillRegState(true))
2515 .addImm(3);
2516 BuildMI(DispContBB, DL, TII->get(VE::LDrri), TReg)
2517 .addReg(BReg, getKillRegState(true))
2518 .addReg(Tmp1, getKillRegState(true))
2519 .addImm(0);
2520 BuildMI(DispContBB, DL, TII->get(VE::BCFLari_t))
2521 .addReg(TReg, getKillRegState(true))
2522 .addImm(0);
2523 break;
2524 }
2526 // Generate block address code using differences from the function pointer
2527 // for PIC model.
2528 // sll %Tmp1, %IReg, 2
2529 // ldl.zx %OReg, 0(%Tmp1, %BReg)
2530 // Prepare function address in BReg2.
2531 // adds.l %TReg, %BReg2, %OReg
2532 // bcfla %TReg
2533
2535 Register OReg = MRI.createVirtualRegister(RC);
2536 Register TReg = MRI.createVirtualRegister(RC);
2537 Register Tmp1 = MRI.createVirtualRegister(RC);
2538
2539 BuildMI(DispContBB, DL, TII->get(VE::SLLri), Tmp1)
2540 .addReg(IReg, getKillRegState(true))
2541 .addImm(2);
2542 BuildMI(DispContBB, DL, TII->get(VE::LDLZXrri), OReg)
2543 .addReg(BReg, getKillRegState(true))
2544 .addReg(Tmp1, getKillRegState(true))
2545 .addImm(0);
2546 Register BReg2 =
2547 prepareSymbol(*DispContBB, DispContBB->end(),
2548 DispContBB->getParent()->getName(), DL, /* Local */ true);
2549 BuildMI(DispContBB, DL, TII->get(VE::ADDSLrr), TReg)
2550 .addReg(OReg, getKillRegState(true))
2551 .addReg(BReg2, getKillRegState(true));
2552 BuildMI(DispContBB, DL, TII->get(VE::BCFLari_t))
2553 .addReg(TReg, getKillRegState(true))
2554 .addImm(0);
2555 break;
2556 }
2557 default:
2558 llvm_unreachable("Unexpected jump table encoding");
2559 }
2560
2561 // Add the jump table entries as successors to the MBB.
2563 for (auto &LP : LPadList)
2564 if (SeenMBBs.insert(LP).second)
2565 DispContBB->addSuccessor(LP);
2566
2567 // N.B. the order the invoke BBs are processed in doesn't matter here.
2569 const MCPhysReg *SavedRegs = MF->getRegInfo().getCalleeSavedRegs();
2570 for (MachineBasicBlock *MBB : InvokeBBs) {
2571 // Remove the landing pad successor from the invoke block and replace it
2572 // with the new dispatch block.
2573 // Keep a copy of Successors since it's modified inside the loop.
2574 SmallVector<MachineBasicBlock *, 8> Successors(MBB->succ_rbegin(),
2575 MBB->succ_rend());
2576 // FIXME: Avoid quadratic complexity.
2577 for (auto *MBBS : Successors) {
2578 if (MBBS->isEHPad()) {
2579 MBB->removeSuccessor(MBBS);
2580 MBBLPads.push_back(MBBS);
2581 }
2582 }
2583
2584 MBB->addSuccessor(DispatchBB);
2585
2586 // Find the invoke call and mark all of the callee-saved registers as
2587 // 'implicit defined' so that they're spilled. This prevents code from
2588 // moving instructions to before the EH block, where they will never be
2589 // executed.
2590 for (auto &II : reverse(*MBB)) {
2591 if (!II.isCall())
2592 continue;
2593
2594 DenseSet<Register> DefRegs;
2595 for (auto &MOp : II.operands())
2596 if (MOp.isReg())
2597 DefRegs.insert(MOp.getReg());
2598
2599 MachineInstrBuilder MIB(*MF, &II);
2600 for (unsigned RI = 0; SavedRegs[RI]; ++RI) {
2601 Register Reg = SavedRegs[RI];
2602 if (!DefRegs.contains(Reg))
2604 }
2605
2606 break;
2607 }
2608 }
2609
2610 // Mark all former landing pads as non-landing pads. The dispatch is the only
2611 // landing pad now.
2612 for (auto &LP : MBBLPads)
2613 LP->setIsEHPad(false);
2614
2615 // The instruction is gone now.
2616 MI.eraseFromParent();
2617 return BB;
2618}
2619
2622 MachineBasicBlock *BB) const {
2623 switch (MI.getOpcode()) {
2624 default:
2625 llvm_unreachable("Unknown Custom Instruction!");
2626 case VE::EH_SjLj_LongJmp:
2627 return emitEHSjLjLongJmp(MI, BB);
2628 case VE::EH_SjLj_SetJmp:
2629 return emitEHSjLjSetJmp(MI, BB);
2630 case VE::EH_SjLj_Setup_Dispatch:
2631 return emitSjLjDispatchBlock(MI, BB);
2632 }
2633}
2634
2635static bool isSimm7(SDValue V) {
2636 EVT VT = V.getValueType();
2637 if (VT.isVector())
2638 return false;
2639
2640 if (VT.isInteger()) {
2642 return isInt<7>(C->getSExtValue());
2643 } else if (VT.isFloatingPoint()) {
2645 if (VT == MVT::f32 || VT == MVT::f64) {
2646 const APInt &Imm = C->getValueAPF().bitcastToAPInt();
2647 uint64_t Val = Imm.getSExtValue();
2648 if (Imm.getBitWidth() == 32)
2649 Val <<= 32; // Immediate value of float place at higher bits on VE.
2650 return isInt<7>(Val);
2651 }
2652 }
2653 }
2654 return false;
2655}
2656
2657static bool isMImm(SDValue V) {
2658 EVT VT = V.getValueType();
2659 if (VT.isVector())
2660 return false;
2661
2662 if (VT.isInteger()) {
2664 return isMImmVal(getImmVal(C));
2665 } else if (VT.isFloatingPoint()) {
2667 if (VT == MVT::f32) {
2668 // Float value places at higher bits, so ignore lower 32 bits.
2669 return isMImm32Val(getFpImmVal(C) >> 32);
2670 } else if (VT == MVT::f64) {
2671 return isMImmVal(getFpImmVal(C));
2672 }
2673 }
2674 }
2675 return false;
2676}
2677
2678static unsigned decideComp(EVT SrcVT, ISD::CondCode CC) {
2679 if (SrcVT.isFloatingPoint()) {
2680 if (SrcVT == MVT::f128)
2681 return VEISD::CMPQ;
2682 return VEISD::CMPF;
2683 }
2684 return isSignedIntSetCC(CC) ? VEISD::CMPI : VEISD::CMPU;
2685}
2686
2687static EVT decideCompType(EVT SrcVT) {
2688 if (SrcVT == MVT::f128)
2689 return MVT::f64;
2690 return SrcVT;
2691}
2692
2694 bool WithCMov) {
2695 if (SrcVT.isFloatingPoint()) {
2696 // For the case of floating point setcc, only unordered comparison
2697 // or general comparison with -enable-no-nans-fp-math option reach
2698 // here, so it is safe even if values are NaN. Only f128 doesn't
2699 // safe since VE uses f64 result of f128 comparison.
2700 return SrcVT != MVT::f128;
2701 }
2702 if (isIntEqualitySetCC(CC)) {
2703 // For the case of equal or not equal, it is safe without comparison with 0.
2704 return true;
2705 }
2706 if (WithCMov) {
2707 // For the case of integer setcc with cmov, all signed comparison with 0
2708 // are safe.
2709 return isSignedIntSetCC(CC);
2710 }
2711 // For the case of integer setcc, only signed 64 bits comparison is safe.
2712 // For unsigned, "CMPU 0x80000000, 0" has to be greater than 0, but it becomes
2713 // less than 0 witout CMPU. For 32 bits, other half of 32 bits are
2714 // uncoditional, so it is not safe too without CMPI..
2715 return isSignedIntSetCC(CC) && SrcVT == MVT::i64;
2716}
2717
2719 ISD::CondCode CC, bool WithCMov,
2720 const SDLoc &DL, SelectionDAG &DAG) {
2721 // Compare values. If RHS is 0 and it is safe to calculate without
2722 // comparison, we don't generate an instruction for comparison.
2723 EVT CompVT = decideCompType(VT);
2724 if (CompVT == VT && safeWithoutCompWithNull(VT, CC, WithCMov) &&
2726 return LHS;
2727 }
2728 return DAG.getNode(decideComp(VT, CC), DL, CompVT, LHS, RHS);
2729}
2730
2732 DAGCombinerInfo &DCI) const {
2733 assert(N->getOpcode() == ISD::SELECT &&
2734 "Should be called with a SELECT node");
2736 SDValue Cond = N->getOperand(0);
2737 SDValue True = N->getOperand(1);
2738 SDValue False = N->getOperand(2);
2739
2740 // We handle only scalar SELECT.
2741 EVT VT = N->getValueType(0);
2742 if (VT.isVector())
2743 return SDValue();
2744
2745 // Peform combineSelect after leagalize DAG.
2746 if (!DCI.isAfterLegalizeDAG())
2747 return SDValue();
2748
2749 EVT VT0 = Cond.getValueType();
2750 if (isMImm(True)) {
2751 // VE's condition move can handle MImm in True clause, so nothing to do.
2752 } else if (isMImm(False)) {
2753 // VE's condition move can handle MImm in True clause, so swap True and
2754 // False clauses if False has MImm value. And, update condition code.
2755 std::swap(True, False);
2756 CC = getSetCCInverse(CC, VT0);
2757 }
2758
2759 SDLoc DL(N);
2760 SelectionDAG &DAG = DCI.DAG;
2761 VECC::CondCode VECCVal;
2762 if (VT0.isFloatingPoint()) {
2763 VECCVal = fpCondCode2Fcc(CC);
2764 } else {
2765 VECCVal = intCondCode2Icc(CC);
2766 }
2767 SDValue Ops[] = {Cond, True, False,
2768 DAG.getConstant(VECCVal, DL, MVT::i32)};
2769 return DAG.getNode(VEISD::CMOV, DL, VT, Ops);
2770}
2771
2773 DAGCombinerInfo &DCI) const {
2774 assert(N->getOpcode() == ISD::SELECT_CC &&
2775 "Should be called with a SELECT_CC node");
2776 ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(4))->get();
2777 SDValue LHS = N->getOperand(0);
2778 SDValue RHS = N->getOperand(1);
2779 SDValue True = N->getOperand(2);
2780 SDValue False = N->getOperand(3);
2781
2782 // We handle only scalar SELECT_CC.
2783 EVT VT = N->getValueType(0);
2784 if (VT.isVector())
2785 return SDValue();
2786
2787 // Peform combineSelectCC after leagalize DAG.
2788 if (!DCI.isAfterLegalizeDAG())
2789 return SDValue();
2790
2791 // We handle only i32/i64/f32/f64/f128 comparisons.
2792 EVT LHSVT = LHS.getValueType();
2793 assert(LHSVT == RHS.getValueType());
2794 switch (LHSVT.getSimpleVT().SimpleTy) {
2795 case MVT::i32:
2796 case MVT::i64:
2797 case MVT::f32:
2798 case MVT::f64:
2799 case MVT::f128:
2800 break;
2801 default:
2802 // Return SDValue to let llvm handle other types.
2803 return SDValue();
2804 }
2805
2806 if (isMImm(RHS)) {
2807 // VE's comparison can handle MImm in RHS, so nothing to do.
2808 } else if (isSimm7(RHS)) {
2809 // VE's comparison can handle Simm7 in LHS, so swap LHS and RHS, and
2810 // update condition code.
2811 std::swap(LHS, RHS);
2812 CC = getSetCCSwappedOperands(CC);
2813 }
2814 if (isMImm(True)) {
2815 // VE's condition move can handle MImm in True clause, so nothing to do.
2816 } else if (isMImm(False)) {
2817 // VE's condition move can handle MImm in True clause, so swap True and
2818 // False clauses if False has MImm value. And, update condition code.
2819 std::swap(True, False);
2820 CC = getSetCCInverse(CC, LHSVT);
2821 }
2822
2823 SDLoc DL(N);
2824 SelectionDAG &DAG = DCI.DAG;
2825
2826 bool WithCMov = true;
2827 SDValue CompNode = generateComparison(LHSVT, LHS, RHS, CC, WithCMov, DL, DAG);
2828
2829 VECC::CondCode VECCVal;
2830 if (LHSVT.isFloatingPoint()) {
2831 VECCVal = fpCondCode2Fcc(CC);
2832 } else {
2833 VECCVal = intCondCode2Icc(CC);
2834 }
2835 SDValue Ops[] = {CompNode, True, False,
2836 DAG.getConstant(VECCVal, DL, MVT::i32)};
2837 return DAG.getNode(VEISD::CMOV, DL, VT, Ops);
2838}
2839
2840static bool isI32InsnAllUses(const SDNode *User, const SDNode *N);
2841static bool isI32Insn(const SDNode *User, const SDNode *N) {
2842 switch (User->getOpcode()) {
2843 default:
2844 return false;
2845 case ISD::ADD:
2846 case ISD::SUB:
2847 case ISD::MUL:
2848 case ISD::SDIV:
2849 case ISD::UDIV:
2850 case ISD::SETCC:
2851 case ISD::SMIN:
2852 case ISD::SMAX:
2853 case ISD::SHL:
2854 case ISD::SRA:
2855 case ISD::BSWAP:
2856 case ISD::SINT_TO_FP:
2857 case ISD::UINT_TO_FP:
2858 case ISD::BR_CC:
2859 case ISD::BITCAST:
2861 case ISD::ATOMIC_SWAP:
2862 case VEISD::CMPU:
2863 case VEISD::CMPI:
2864 return true;
2865 case ISD::SRL:
2866 if (N->getOperand(0).getOpcode() != ISD::SRL)
2867 return true;
2868 // (srl (trunc (srl ...))) may be optimized by combining srl, so
2869 // doesn't optimize trunc now.
2870 return false;
2871 case ISD::SELECT_CC:
2872 if (User->getOperand(2).getNode() != N &&
2873 User->getOperand(3).getNode() != N)
2874 return true;
2875 return isI32InsnAllUses(User, N);
2876 case VEISD::CMOV:
2877 // CMOV in (cmov (trunc ...), true, false, int-comparison) is safe.
2878 // However, trunc in true or false clauses is not safe.
2879 if (User->getOperand(1).getNode() != N &&
2880 User->getOperand(2).getNode() != N &&
2882 VECC::CondCode VECCVal =
2883 static_cast<VECC::CondCode>(User->getConstantOperandVal(3));
2884 return isIntVECondCode(VECCVal);
2885 }
2886 [[fallthrough]];
2887 case ISD::AND:
2888 case ISD::OR:
2889 case ISD::XOR:
2890 case ISD::SELECT:
2891 case ISD::CopyToReg:
2892 // Check all use of selections, bit operations, and copies. If all of them
2893 // are safe, optimize truncate to extract_subreg.
2894 return isI32InsnAllUses(User, N);
2895 }
2896}
2897
2898static bool isI32InsnAllUses(const SDNode *User, const SDNode *N) {
2899 // Check all use of User node. If all of them are safe, optimize
2900 // truncate to extract_subreg.
2901 for (const SDNode *U : User->users()) {
2902 switch (U->getOpcode()) {
2903 default:
2904 // If the use is an instruction which treats the source operand as i32,
2905 // it is safe to avoid truncate here.
2906 if (isI32Insn(U, N))
2907 continue;
2908 break;
2909 case ISD::ANY_EXTEND:
2910 case ISD::SIGN_EXTEND:
2911 case ISD::ZERO_EXTEND: {
2912 // Special optimizations to the combination of ext and trunc.
2913 // (ext ... (select ... (trunc ...))) is safe to avoid truncate here
2914 // since this truncate instruction clears higher 32 bits which is filled
2915 // by one of ext instructions later.
2916 assert(N->getValueType(0) == MVT::i32 &&
2917 "find truncate to not i32 integer");
2918 if (User->getOpcode() == ISD::SELECT_CC ||
2919 User->getOpcode() == ISD::SELECT || User->getOpcode() == VEISD::CMOV)
2920 continue;
2921 break;
2922 }
2923 }
2924 return false;
2925 }
2926 return true;
2927}
2928
2929// Optimize TRUNCATE in DAG combining. Optimizing it in CUSTOM lower is
2930// sometime too early. Optimizing it in DAG pattern matching in VEInstrInfo.td
2931// is sometime too late. So, doing it at here.
2933 DAGCombinerInfo &DCI) const {
2934 assert(N->getOpcode() == ISD::TRUNCATE &&
2935 "Should be called with a TRUNCATE node");
2936
2937 SelectionDAG &DAG = DCI.DAG;
2938 SDLoc DL(N);
2939 EVT VT = N->getValueType(0);
2940
2941 // We prefer to do this when all types are legal.
2942 if (!DCI.isAfterLegalizeDAG())
2943 return SDValue();
2944
2945 // Skip combine TRUNCATE atm if the operand of TRUNCATE might be a constant.
2946 if (N->getOperand(0)->getOpcode() == ISD::SELECT_CC &&
2947 isa<ConstantSDNode>(N->getOperand(0)->getOperand(0)) &&
2948 isa<ConstantSDNode>(N->getOperand(0)->getOperand(1)))
2949 return SDValue();
2950
2951 // Check all use of this TRUNCATE.
2952 for (const SDNode *User : N->users()) {
2953 // Make sure that we're not going to replace TRUNCATE for non i32
2954 // instructions.
2955 //
2956 // FIXME: Although we could sometimes handle this, and it does occur in
2957 // practice that one of the condition inputs to the select is also one of
2958 // the outputs, we currently can't deal with this.
2959 if (isI32Insn(User, N))
2960 continue;
2961
2962 return SDValue();
2963 }
2964
2965 SDValue SubI32 = DAG.getTargetConstant(VE::sub_i32, DL, MVT::i32);
2966 return SDValue(DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL, VT,
2967 N->getOperand(0), SubI32),
2968 0);
2969}
2970
2972 DAGCombinerInfo &DCI) const {
2973 switch (N->getOpcode()) {
2974 default:
2975 break;
2976 case ISD::SELECT:
2977 return combineSelect(N, DCI);
2978 case ISD::SELECT_CC:
2979 return combineSelectCC(N, DCI);
2980 case ISD::TRUNCATE:
2981 return combineTRUNCATE(N, DCI);
2982 }
2983
2984 return SDValue();
2985}
2986
2987//===----------------------------------------------------------------------===//
2988// VE Inline Assembly Support
2989//===----------------------------------------------------------------------===//
2990
2993 if (Constraint.size() == 1) {
2994 switch (Constraint[0]) {
2995 default:
2996 break;
2997 case 'v': // vector registers
2998 return C_RegisterClass;
2999 }
3000 }
3001 return TargetLowering::getConstraintType(Constraint);
3002}
3003
3004std::pair<unsigned, const TargetRegisterClass *>
3006 StringRef Constraint,
3007 MVT VT) const {
3008 const TargetRegisterClass *RC = nullptr;
3009 if (Constraint.size() == 1) {
3010 switch (Constraint[0]) {
3011 default:
3012 return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
3013 case 'r':
3014 RC = &VE::I64RegClass;
3015 break;
3016 case 'v':
3017 RC = &VE::V64RegClass;
3018 break;
3019 }
3020 return std::make_pair(0U, RC);
3021 }
3022
3023 return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
3024}
3025
3026//===----------------------------------------------------------------------===//
3027// VE Target Optimization Support
3028//===----------------------------------------------------------------------===//
3029
3031 // Specify 8 for PIC model to relieve the impact of PIC load instructions.
3032 if (isJumpTableRelative())
3033 return 8;
3034
3036}
3037
3039 EVT VT = Y.getValueType();
3040
3041 // VE doesn't have vector and not instruction.
3042 if (VT.isVector())
3043 return false;
3044
3045 // VE allows different immediate values for X and Y where ~X & Y.
3046 // Only simm7 works for X, and only mimm works for Y on VE. However, this
3047 // function is used to check whether an immediate value is OK for and-not
3048 // instruction as both X and Y. Generating additional instruction to
3049 // retrieve an immediate value is no good since the purpose of this
3050 // function is to convert a series of 3 instructions to another series of
3051 // 3 instructions with better parallelism. Therefore, we return false
3052 // for all immediate values now.
3053 // FIXME: Change hasAndNot function to have two operands to make it work
3054 // correctly with Aurora VE.
3056 return false;
3057
3058 // It's ok for generic registers.
3059 return true;
3060}
3061
3063 SelectionDAG &DAG) const {
3064 assert(Op.getOpcode() == ISD::EXTRACT_VECTOR_ELT && "Unknown opcode!");
3065 MVT VT = Op.getOperand(0).getSimpleValueType();
3066
3067 // Special treatment for packed V64 types.
3068 assert(VT == MVT::v512i32 || VT == MVT::v512f32);
3069 (void)VT;
3070 // Example of codes:
3071 // %packed_v = extractelt %vr, %idx / 2
3072 // %v = %packed_v >> (%idx % 2 * 32)
3073 // %res = %v & 0xffffffff
3074
3075 SDValue Vec = Op.getOperand(0);
3076 SDValue Idx = Op.getOperand(1);
3077 SDLoc DL(Op);
3078 SDValue Result = Op;
3079 if (false /* Idx->isConstant() */) {
3080 // TODO: optimized implementation using constant values
3081 } else {
3082 SDValue Const1 = DAG.getConstant(1, DL, MVT::i64);
3083 SDValue HalfIdx = DAG.getNode(ISD::SRL, DL, MVT::i64, {Idx, Const1});
3084 SDValue PackedElt =
3085 SDValue(DAG.getMachineNode(VE::LVSvr, DL, MVT::i64, {Vec, HalfIdx}), 0);
3086 SDValue AndIdx = DAG.getNode(ISD::AND, DL, MVT::i64, {Idx, Const1});
3087 SDValue Shift = DAG.getNode(ISD::XOR, DL, MVT::i64, {AndIdx, Const1});
3088 SDValue Const5 = DAG.getConstant(5, DL, MVT::i64);
3089 Shift = DAG.getNode(ISD::SHL, DL, MVT::i64, {Shift, Const5});
3090 PackedElt = DAG.getNode(ISD::SRL, DL, MVT::i64, {PackedElt, Shift});
3091 SDValue Mask = DAG.getConstant(0xFFFFFFFFL, DL, MVT::i64);
3092 PackedElt = DAG.getNode(ISD::AND, DL, MVT::i64, {PackedElt, Mask});
3093 SDValue SubI32 = DAG.getTargetConstant(VE::sub_i32, DL, MVT::i32);
3094 Result = SDValue(DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL,
3095 MVT::i32, PackedElt, SubI32),
3096 0);
3097
3098 if (Op.getSimpleValueType() == MVT::f32) {
3099 Result = DAG.getBitcast(MVT::f32, Result);
3100 } else {
3101 assert(Op.getSimpleValueType() == MVT::i32);
3102 }
3103 }
3104 return Result;
3105}
3106
3108 SelectionDAG &DAG) const {
3109 assert(Op.getOpcode() == ISD::INSERT_VECTOR_ELT && "Unknown opcode!");
3110 MVT VT = Op.getOperand(0).getSimpleValueType();
3111
3112 // Special treatment for packed V64 types.
3113 assert(VT == MVT::v512i32 || VT == MVT::v512f32);
3114 (void)VT;
3115 // The v512i32 and v512f32 starts from upper bits (0..31). This "upper
3116 // bits" required `val << 32` from C implementation's point of view.
3117 //
3118 // Example of codes:
3119 // %packed_elt = extractelt %vr, (%idx >> 1)
3120 // %shift = ((%idx & 1) ^ 1) << 5
3121 // %packed_elt &= 0xffffffff00000000 >> shift
3122 // %packed_elt |= (zext %val) << shift
3123 // %vr = insertelt %vr, %packed_elt, (%idx >> 1)
3124
3125 SDLoc DL(Op);
3126 SDValue Vec = Op.getOperand(0);
3127 SDValue Val = Op.getOperand(1);
3128 SDValue Idx = Op.getOperand(2);
3129 if (Idx.getSimpleValueType() == MVT::i32)
3130 Idx = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, Idx);
3131 if (Val.getSimpleValueType() == MVT::f32)
3132 Val = DAG.getBitcast(MVT::i32, Val);
3133 assert(Val.getSimpleValueType() == MVT::i32);
3134 Val = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i64, Val);
3135
3136 SDValue Result = Op;
3137 if (false /* Idx->isConstant()*/) {
3138 // TODO: optimized implementation using constant values
3139 } else {
3140 SDValue Const1 = DAG.getConstant(1, DL, MVT::i64);
3141 SDValue HalfIdx = DAG.getNode(ISD::SRL, DL, MVT::i64, {Idx, Const1});
3142 SDValue PackedElt =
3143 SDValue(DAG.getMachineNode(VE::LVSvr, DL, MVT::i64, {Vec, HalfIdx}), 0);
3144 SDValue AndIdx = DAG.getNode(ISD::AND, DL, MVT::i64, {Idx, Const1});
3145 SDValue Shift = DAG.getNode(ISD::XOR, DL, MVT::i64, {AndIdx, Const1});
3146 SDValue Const5 = DAG.getConstant(5, DL, MVT::i64);
3147 Shift = DAG.getNode(ISD::SHL, DL, MVT::i64, {Shift, Const5});
3148 SDValue Mask = DAG.getConstant(0xFFFFFFFF00000000L, DL, MVT::i64);
3149 Mask = DAG.getNode(ISD::SRL, DL, MVT::i64, {Mask, Shift});
3150 PackedElt = DAG.getNode(ISD::AND, DL, MVT::i64, {PackedElt, Mask});
3151 Val = DAG.getNode(ISD::SHL, DL, MVT::i64, {Val, Shift});
3152 PackedElt = DAG.getNode(ISD::OR, DL, MVT::i64, {PackedElt, Val});
3153 Result =
3154 SDValue(DAG.getMachineNode(VE::LSVrr_v, DL, Vec.getSimpleValueType(),
3155 {HalfIdx, PackedElt, Vec}),
3156 0);
3157 }
3158 return Result;
3159}
return SDValue()
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis Results
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define RegName(no)
#define I(x, y, z)
Definition MD5.cpp:57
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
uint64_t IntrinsicInst * II
static CodeModel::Model getCodeModel(const PPCSubtarget &S, const TargetMachine &TM, const MachineOperand &MO)
const SmallVectorImpl< MachineOperand > & Cond
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
#define LLVM_DEBUG(...)
Definition Debug.h:119
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static unsigned decideComp(EVT SrcVT, ISD::CondCode CC)
static bool isSimm7(SDValue V)
CCAssignFn * getParamCC(CallingConv::ID CallConv, bool IsVarArg)
static SDValue lowerLoadF128(SDValue Op, SelectionDAG &DAG)
static bool isMImm(SDValue V)
static SDValue prepareTS1AM(SDValue Op, SelectionDAG &DAG, SDValue &Flag, SDValue &Bits)
CCAssignFn * getReturnCC(CallingConv::ID CallConv)
static bool safeWithoutCompWithNull(EVT SrcVT, ISD::CondCode CC, bool WithCMov)
static bool isI32InsnAllUses(const SDNode *User, const SDNode *N)
static SDValue lowerLoadI1(SDValue Op, SelectionDAG &DAG)
static SDValue generateComparison(EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode CC, bool WithCMov, const SDLoc &DL, SelectionDAG &DAG)
static EVT decideCompType(EVT SrcVT)
static bool isI32Insn(const SDNode *User, const SDNode *N)
static SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG, const VETargetLowering &TLI, const VESubtarget *Subtarget)
static const MVT AllMaskVTs[]
static bool getUniqueInsertion(SDNode *N, unsigned &UniqueIdx)
static SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG, const VETargetLowering &TLI, const VESubtarget *Subtarget)
static const MVT AllVectorVTs[]
static const MVT AllPackedVTs[]
static SDValue finalizeTS1AM(SDValue Op, SelectionDAG &DAG, SDValue Data, SDValue Bits)
static SDValue lowerStoreF128(SDValue Op, SelectionDAG &DAG)
static SDValue lowerStoreI1(SDValue Op, SelectionDAG &DAG)
Value * RHS
Value * LHS
Class for arbitrary precision integers.
Definition APInt.h:78
an instruction that atomically reads a memory location, combines it with another value,...
BinOp getOperation() const
This is an SDNode representing atomic operations.
LLVM Basic Block Representation.
Definition BasicBlock.h:62
CCState - This class holds information needed while lowering arguments and return values.
LLVM_ABI void AnalyzeCallResult(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeCallResult - Analyze the return values of a call, incorporating info about the passed values i...
LLVM_ABI bool CheckReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
CheckReturn - Analyze the return values of a function, returning true if the return can be performed ...
LLVM_ABI void AnalyzeReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeReturn - Analyze the returned values of a return, incorporating info about the result values i...
int64_t AllocateStack(unsigned Size, Align Alignment)
AllocateStack - Allocate a chunk of stack space with the specified size and alignment.
LLVM_ABI void AnalyzeCallOperands(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeCallOperands - Analyze the outgoing arguments to a call, incorporating info about the passed v...
uint64_t getStackSize() const
Returns the size of the currently allocated portion of the stack.
LLVM_ABI void AnalyzeFormalArguments(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeFormalArguments - Analyze an array of argument values, incorporating info about the formals in...
CCValAssign - Represent assignment of one arg/retval to a location.
Register getLocReg() const
LocInfo getLocInfo() const
bool needsCustom() const
bool isExtInLoc() const
int64_t getLocMemOffset() const
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
A debug info location.
Definition DebugLoc.h:126
unsigned size() const
Definition DenseMap.h:172
Implements a dense probed hash-table based set.
Definition DenseSet.h:281
unsigned getAddressSpace() const
Common base class shared among various IRBuilders.
Definition IRBuilder.h:114
LLVM_ABI bool hasAtomicStore() const LLVM_READONLY
Return true if this atomic instruction stores to memory.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
const SDValue & getOffset() const
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:427
Context object for machine code objects.
Definition MCContext.h:83
Base class for the full range of assembler expressions which are needed for parsing.
Definition MCExpr.h:34
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:213
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
Machine Value Type.
SimpleValueType SimpleTy
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
static auto integer_valuetypes()
static auto vector_valuetypes()
static MVT getIntegerVT(unsigned BitWidth)
static auto fp_valuetypes()
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI 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 '...
MachineInstrBundleIterator< MachineInstr > iterator
void setMachineBlockAddressTaken()
Set this block to indicate that its address is used as something other than the target of a terminato...
void setIsEHPad(bool V=true)
Indicates the block is a landing pad.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
void setFrameAddressIsTaken(bool T)
void setReturnAddressIsTaken(bool s)
int getFunctionContextIndex() const
Return the index for the function context object.
unsigned getFunctionNumber() const
getFunctionNumber - Return a unique ID for the current function.
MachineJumpTableInfo * getOrCreateJumpTableInfo(unsigned JTEntryKind)
getOrCreateJumpTableInfo - Get the JumpTableInfo for this function, if it does already exist,...
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
bool hasCallSiteLandingPad(MCSymbol *Sym)
Return true if the landing pad Eh symbol has an associated call site.
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
SmallVectorImpl< unsigned > & getCallSiteLandingPad(MCSymbol *Sym)
Get the call site indexes for a landing pad EH symbol.
const MachineInstrBuilder & setMemRefs(ArrayRef< MachineMemOperand * > MMOs) const
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addRegMask(const uint32_t *Mask) const
const MachineInstrBuilder & addJumpTableIndex(unsigned Idx, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
LLVM_ABI unsigned createJumpTableIndex(const std::vector< MachineBasicBlock * > &DestBBs)
createJumpTableIndex - Create a new jump table.
@ EK_Custom32
EK_Custom32 - Each entry is a 32-bit value that is custom lowered by the TargetLowering::LowerCustomJ...
@ EK_BlockAddress
EK_BlockAddress - Each entry is a plain address of block, e.g.: .word LBB123.
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 TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLVM_ABI const MCPhysReg * getCalleeSavedRegs() const
Returns list of callee saved registers.
Align getAlign() const
bool isVolatile() const
const MachinePointerInfo & getPointerInfo() const
const SDValue & getChain() const
EVT getMemoryVT() const
Return the type of the in-memory value.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
bool isUndef() const
SDNode * getNode() const
get the SDNode which holds the desired result
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOperand(unsigned i) const
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI 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,...
LLVM_ABI SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Val, MachineMemOperand *MMO)
Gets a node for an atomic op, produces result (if relevant) and chain and takes 2 operands.
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
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).
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI SDValue getGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, bool isTargetGA=false, unsigned TargetFlags=0)
LLVM_ABI 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.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
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 ...
const TargetMachine & getTarget() const
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getValueType(EVT)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
SDValue getTargetBlockAddress(const BlockAddress *BA, EVT VT, int64_t Offset=0, unsigned TargetFlags=0)
MachineFunction & getMachineFunction() const
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVMContext * getContext() const
LLVM_ABI 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)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
void insert_range(Range &&R)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class is used to represent ISD::STORE nodes.
const SDValue & getBasePtr() const
const SDValue & getOffset() const
const SDValue & getValue() const
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
Information about stack frame layout on the target.
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
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...
LegalizeAction
This enum indicates whether operations are valid for a target, and if not, what action should be used...
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
void setMinStackArgumentAlignment(Align Alignment)
Set the minimum stack alignment of an argument.
virtual unsigned getMinimumJumpTableEntries() const
Return lower limit for number of blocks in a jump table.
const TargetMachine & getTargetMachine() const
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
void setSupportsUnalignedAtomics(bool UnalignedSupported)
Sets whether unaligned atomic operations are supported.
virtual bool isJumpTableRelative() const
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 setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
void setMinCmpXchgSizeInBits(unsigned SizeInBits)
Sets the minimum cmpxchg or ll/sc size supported by the backend.
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
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
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
bool isPositionIndependent() const
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
TargetLowering(const TargetLowering &)=delete
virtual unsigned getJumpTableEncoding() const
Return the entry encoding for a jump table in the current function.
Primary interface to the complete machine description for the target machine.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
Definition Type.cpp:282
Value * getOperand(unsigned i) const
Definition User.h:207
SDValue getBroadcast(EVT ResultVT, SDValue Scalar, SDValue AVL) const
SDValue getNode(unsigned OC, SDVTList VTL, ArrayRef< SDValue > OpV, std::optional< SDNodeFlags > Flags=std::nullopt) const
getNode {
SDValue getUNDEF(EVT VT) const
SDValue getConstant(uint64_t Val, EVT VT, bool IsTarget=false, bool IsOpaque=false) const
bool hasBP(const MachineFunction &MF) const
const VERegisterInfo * getRegisterInfo() const override
Definition VESubtarget.h:56
SDValue splitMaskArithmetic(SDValue Op, SelectionDAG &DAG) const
SDValue lowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const
std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override
Given a physical register constraint (e.g.
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
SDValue lowerToVVP(SDValue Op, SelectionDAG &DAG) const
} Custom Inserter
SDValue lowerJumpTable(SDValue Op, SelectionDAG &DAG) const
SDValue getPICJumpTableRelocBase(SDValue Table, SelectionDAG &DAG) const override
Returns relocation base for the given PIC jumptable.
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
getSetCCResultType - Return the ISD::SETCC ValueType
TargetLoweringBase::AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *AI) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
SDValue lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const
bool hasAndNot(SDValue Y) const override
Return true if the target has a bitwise and-not operation: X = ~A & B This can be used to simplify se...
SDValue lowerVAARG(SDValue Op, SelectionDAG &DAG) const
SDValue combineSelect(SDNode *N, DAGCombinerInfo &DCI) const
bool isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize) const override
isFPImmLegal - Returns true if the target can instruction select the specified FP immediate natively.
VETargetLowering(const TargetMachine &TM, const VESubtarget &STI)
Instruction * emitLeadingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
Custom Lower {.
SDValue lowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG) const
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
This callback is invoked for operations that are unsupported by the target, which are registered to u...
SDValue lowerLOAD(SDValue Op, SelectionDAG &DAG) const
MachineBasicBlock * emitEHSjLjLongJmp(MachineInstr &MI, MachineBasicBlock *MBB) const
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
} VVPLowering
SDValue lowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const
SDValue combineSelectCC(SDNode *N, DAGCombinerInfo &DCI) const
SDValue lowerEH_SJLJ_SETUP_DISPATCH(SDValue Op, SelectionDAG &DAG) const
unsigned getMinimumJumpTableEntries() const override
} Inline Assembly
SDValue lowerEH_SJLJ_SETJMP(SDValue Op, SelectionDAG &DAG) const
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SDLoc &dl, SelectionDAG &DAG) const override
This hook must be implemented to lower outgoing return values, described by the Outs array,...
MachineBasicBlock * emitSjLjDispatchBlock(MachineInstr &MI, MachineBasicBlock *BB) const
Instruction * emitTrailingFence(IRBuilderBase &Builder, Instruction *Inst, AtomicOrdering Ord) const override
Register prepareMBB(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MachineBasicBlock *TargetBB, const DebugLoc &DL) const
void setupEntryBlockForSjLj(MachineInstr &MI, MachineBasicBlock *MBB, MachineBasicBlock *DispatchBB, int FI, int Offset) const
SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const override
Custom Inserter {.
MachineBasicBlock * emitEHSjLjSetJmp(MachineInstr &MI, MachineBasicBlock *MBB) const
bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AS, Align A, MachineMemOperand::Flags Flags, unsigned *Fast) const override
Returns true if the target allows unaligned memory accesses of the specified type.
SDValue lowerEH_SJLJ_LONGJMP(SDValue Op, SelectionDAG &DAG) const
SDValue lowerSTORE(SDValue Op, SelectionDAG &DAG) const
TargetLoweringBase::LegalizeAction getCustomOperationAction(SDNode &) const override
Custom Lower {.
SDValue makeAddress(SDValue Op, SelectionDAG &DAG) const
SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const
SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const
SDValue legalizeInternalVectorOp(SDValue Op, SelectionDAG &DAG) const
Register prepareSymbol(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, StringRef Symbol, const DebugLoc &DL, bool IsLocal, bool IsCall) const
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &dl, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower the incoming (formal) arguments, described by the Ins array,...
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
} Custom Lower
SDValue lowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const
SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower calls into the specified DAG.
SDValue withTargetFlags(SDValue Op, unsigned TF, SelectionDAG &DAG) const
} Custom DAGCombine
SDValue combineTRUNCATE(SDNode *N, DAGCombinerInfo &DCI) const
const MCExpr * LowerCustomJumpTableEntry(const MachineJumpTableInfo *MJTI, const MachineBasicBlock *MBB, unsigned Uid, MCContext &Ctx) const override
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg, const SmallVectorImpl< ISD::OutputArg > &ArgsFlags, LLVMContext &Context, const Type *RetTy) const override
This hook should be implemented to check whether the return values described by the Outs array can fi...
SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const
unsigned getJumpTableEncoding() const override
JumpTable for VE.
SDValue lowerATOMIC_SWAP(SDValue Op, SelectionDAG &DAG) const
SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const
Register getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const override
Return the register ID of the name passed in.
SDValue makeHiLoPair(SDValue Op, unsigned HiTF, unsigned LoTF, SelectionDAG &DAG) const
ConstraintType getConstraintType(StringRef Constraint) const override
Inline Assembly {.
SDValue lowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const
SDValue lowerToTLSGeneralDynamicModel(SDValue Op, SelectionDAG &DAG) const
std::list< std::string > * getStrList() const
LLVM Value Representation.
Definition Value.h:75
iterator_range< user_iterator > users()
Definition Value.h:426
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:209
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
Definition DenseSet.h:182
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ PreserveAll
Used for runtime calls that preserves (almost) all registers.
Definition CallingConv.h:66
@ 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
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
Definition ISDOpcodes.h:41
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
Definition ISDOpcodes.h:829
@ STACKRESTORE
STACKRESTORE has two operands, an input chain and a pointer to restore to it returns an output chain.
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
@ MLOAD
Masked load and store - consecutive vector load and store operations with additional mask operand tha...
@ EH_SJLJ_LONGJMP
OUTCHAIN = EH_SJLJ_LONGJMP(INCHAIN, buffer) This corresponds to the eh.sjlj.longjmp intrinsic.
Definition ISDOpcodes.h:168
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
Definition ISDOpcodes.h:275
@ BSWAP
Byte Swap and Counting operators.
Definition ISDOpcodes.h:789
@ VAEND
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE.
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:264
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition ISDOpcodes.h:863
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
Definition ISDOpcodes.h:520
@ EH_SJLJ_SETUP_DISPATCH
OUTCHAIN = EH_SJLJ_SETUP_DISPATCH(INCHAIN) The target initializes the dispatch table here.
Definition ISDOpcodes.h:172
@ GlobalAddress
Definition ISDOpcodes.h:88
@ ATOMIC_CMP_SWAP_WITH_SUCCESS
Val, Success, OUTCHAIN = ATOMIC_CMP_SWAP_WITH_SUCCESS(INCHAIN, ptr, cmp, swap) N.b.
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
Definition ISDOpcodes.h:890
@ MEMBARRIER
MEMBARRIER - Compiler barrier only; generate a no-op.
@ ATOMIC_FENCE
OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) This corresponds to the fence instruction.
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
Definition ISDOpcodes.h:280
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ GlobalTLSAddress
Definition ISDOpcodes.h:89
@ CTLZ_ZERO_POISON
Definition ISDOpcodes.h:798
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:854
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BR_CC
BR_CC - Conditional branch.
@ BR_JT
BR_JT - Jumptable branch.
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition ISDOpcodes.h:806
@ VACOPY
VACOPY - VACOPY has 5 operands: an input chain, a destination pointer, a source pointer,...
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
Definition ISDOpcodes.h:230
@ VECREDUCE_ADD
Integer reductions may have a result type larger than the vector element type.
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
Definition ISDOpcodes.h:706
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:771
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition ISDOpcodes.h:578
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
Definition ISDOpcodes.h:224
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:860
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition ISDOpcodes.h:821
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ DYNAMIC_STACKALLOC
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary.
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition ISDOpcodes.h:729
@ FRAMEADDR
FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and llvm.returnaddress on the DAG.
Definition ISDOpcodes.h:110
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:741
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
Definition ISDOpcodes.h:205
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
Definition ISDOpcodes.h:567
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
Definition ISDOpcodes.h:53
@ ATOMIC_SWAP
Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN,...
@ EH_SJLJ_SETJMP
RESULT, OUTCHAIN = EH_SJLJ_SETJMP(INCHAIN, buffer) This corresponds to the eh.sjlj....
Definition ISDOpcodes.h:162
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:866
@ VAARG
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
@ BRCOND
BRCOND - Conditional branch.
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
Definition ISDOpcodes.h:843
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
Definition ISDOpcodes.h:62
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
Definition ISDOpcodes.h:536
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
Definition ISDOpcodes.h:558
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LLVM_ABI bool isVPOpcode(unsigned Opcode)
Whether this is a vector-predicated Opcode.
@ System
Synchronized with respect to all concurrently executing threads.
Definition LLVMContext.h:58
CondCode
Definition VE.h:43
@ CC_ILE
Definition VE.h:50
@ S_GOTOFF_LO32
Definition VEMCAsmInfo.h:48
@ S_GOTOFF_HI32
Definition VEMCAsmInfo.h:47
This is an optimization pass for GlobalISel generic memory operations.
static uint64_t getFpImmVal(const ConstantFPSDNode *N)
getFpImmVal - get immediate representation of floating point value
bool isPackedVectorType(EVT SomeVT)
@ Offset
Definition DWP.cpp:573
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:165
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
@ Dead
Unused definition.
@ Undef
Value of the register doesn't matter.
constexpr RegState getKillRegState(bool B)
static bool isIntVECondCode(VECC::CondCode CC)
Definition VE.h:151
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change.
static uint64_t getImmVal(const ConstantSDNode *N)
getImmVal - get immediate representation of integer value
static const MachineInstrBuilder & addFrameReference(const MachineInstrBuilder &MIB, int FI, int Offset=0, bool mem=true)
addFrameReference - This function is used to add a reference to the base of an abstract object on the...
LLVM_ABI Value * getSplatValue(const Value *V)
Get splat value if the input is a splat vector or return nullptr.
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
bool isMaskArithmetic(SDValue Op)
static VECC::CondCode fpCondCode2Fcc(ISD::CondCode CC)
Convert a DAG floating point condition code to a VE FCC condition.
bool isMaskType(EVT SomeVT)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
AtomicOrdering
Atomic ordering for LLVM's memory model.
bool isVVPOrVEC(unsigned Opcode)
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Definition MCRegister.h:21
bool isPackingSupportOpcode(unsigned Opc)
std::pair< SDValue, bool > getAnnotatedNodeAVL(SDValue Op)
DWARFExpression::Operation Op
unsigned M0(unsigned Val)
Definition VE.h:376
static VECC::CondCode intCondCode2Icc(ISD::CondCode CC)
Convert a DAG integer condition code to a VE ICC condition.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
LLVM_ABI bool isNullFPConstant(SDValue V)
Returns true if V is an FP constant with a value of positive zero.
static bool isMImmVal(uint64_t Val)
Definition VE.h:332
static bool isMImm32Val(uint32_t Val)
Definition VE.h:345
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:862
#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:35
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
Definition ValueTypes.h:155
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition ValueTypes.h:396
EVT changeVectorElementType(LLVMContext &Context, EVT EltVT) const
Return a VT for a vector type whose attributes match ourselves with the exception of the element type...
Definition ValueTypes.h:98
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
Definition ValueTypes.h:339
bool isVector() const
Return true if this is a vector value type.
Definition ValueTypes.h:176
bool isInteger() const
Return true if this is an integer or a vector integer type.
Definition ValueTypes.h:160
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Definition Alignment.h:106
Align valueOrOne() const
For convenience, returns a valid alignment or 1 if undefined.
Definition Alignment.h:130
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
This structure contains all information that is necessary for lowering calls.
SmallVector< ISD::InputArg, 32 > Ins
CallLoweringInfo & setDiscardResult(bool Value=true)
CallLoweringInfo & setDebugLoc(const SDLoc &dl)
SmallVector< ISD::OutputArg, 32 > Outs
CallLoweringInfo & setChain(SDValue InChain)
CallLoweringInfo & setCallee(CallingConv::ID CC, Type *ResultType, SDValue Target, ArgListTy &&ArgsList, AttributeSet ResultAttrs={})
const uint32_t * getNoPreservedMask() const override