LLVM 24.0.0git
HexagonISelLowering.cpp
Go to the documentation of this file.
1//===-- HexagonISelLowering.cpp - Hexagon 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 Hexagon uses to lower LLVM code
10// into a selection DAG.
11//
12//===----------------------------------------------------------------------===//
13
14#include "HexagonISelLowering.h"
15#include "Hexagon.h"
17#include "HexagonRegisterInfo.h"
18#include "HexagonSubtarget.h"
21#include "llvm/ADT/APInt.h"
22#include "llvm/ADT/ArrayRef.h"
33#include "llvm/IR/BasicBlock.h"
34#include "llvm/IR/CallingConv.h"
35#include "llvm/IR/DataLayout.h"
39#include "llvm/IR/Function.h"
40#include "llvm/IR/GlobalValue.h"
41#include "llvm/IR/IRBuilder.h"
42#include "llvm/IR/InlineAsm.h"
45#include "llvm/IR/Intrinsics.h"
46#include "llvm/IR/IntrinsicsHexagon.h"
47#include "llvm/IR/Module.h"
48#include "llvm/IR/Type.h"
49#include "llvm/IR/Value.h"
53#include "llvm/Support/Debug.h"
58#include <algorithm>
59#include <cassert>
60#include <cstdint>
61#include <limits>
62#include <utility>
63
64using namespace llvm;
65
66#define DEBUG_TYPE "hexagon-lowering"
67
68static cl::opt<bool> EmitJumpTables("hexagon-emit-jump-tables",
69 cl::init(true), cl::Hidden,
70 cl::desc("Control jump table emission on Hexagon target"));
71
72static cl::opt<bool>
73 EnableHexSDNodeSched("enable-hexagon-sdnode-sched", cl::Hidden,
74 cl::desc("Enable Hexagon SDNode scheduling"));
75
76static cl::opt<int> MinimumJumpTables("minimum-jump-tables", cl::Hidden,
77 cl::init(5),
78 cl::desc("Set minimum jump tables"));
79
80static cl::opt<bool>
81 ConstantLoadsToImm("constant-loads-to-imm", cl::Hidden, cl::init(true),
82 cl::desc("Convert constant loads to immediate values."));
83
84static cl::opt<bool> AlignLoads("hexagon-align-loads",
85 cl::Hidden, cl::init(false),
86 cl::desc("Rewrite unaligned loads as a pair of aligned loads"));
87
88static cl::opt<bool>
89 DisableArgsMinAlignment("hexagon-disable-args-min-alignment", cl::Hidden,
90 cl::init(false),
91 cl::desc("Disable minimum alignment of 1 for "
92 "arguments passed by value on stack"));
93
94// Implement calling convention for Hexagon.
95
96static bool CC_SkipOdd(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
97 CCValAssign::LocInfo &LocInfo,
98 ISD::ArgFlagsTy &ArgFlags, CCState &State) {
99 static const MCPhysReg ArgRegs[] = {
100 Hexagon::R0, Hexagon::R1, Hexagon::R2,
101 Hexagon::R3, Hexagon::R4, Hexagon::R5
102 };
103 const unsigned NumArgRegs = std::size(ArgRegs);
104 unsigned RegNum = State.getFirstUnallocated(ArgRegs);
105
106 // RegNum is an index into ArgRegs: skip a register if RegNum is odd.
107 if (RegNum != NumArgRegs && RegNum % 2 == 1)
108 State.AllocateReg(ArgRegs[RegNum]);
109
110 // Always return false here, as this function only makes sure that the first
111 // unallocated register has an even register number and does not actually
112 // allocate a register for the current argument.
113 return false;
114}
115
116#define GET_CALLING_CONV_IMPL
117#include "HexagonGenCallingConv.inc"
118
120 LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT,
121 unsigned &NumIntermediates, MVT &RegisterVT) const {
122
123 bool isBoolVector = VT.getVectorElementType() == MVT::i1;
124 bool isPowerOf2 = VT.isPow2VectorType();
125 unsigned NumElts = VT.getVectorNumElements();
126
127 // Split vectors of type vXi1 into (X/8) vectors of type v8i1,
128 // where X is divisible by 8.
129 if (isBoolVector && !Subtarget.useHVXOps() && isPowerOf2 && NumElts >= 8) {
130 RegisterVT = MVT::v8i8;
131 IntermediateVT = MVT::v8i1;
132 NumIntermediates = NumElts / 8;
133 return NumIntermediates;
134 }
135
136 // In HVX 64-byte mode, vectors of type vXi1 are split into (X / 64) vectors
137 // of type v64i1, provided that X is divisible by 64.
138 if (isBoolVector && Subtarget.useHVX64BOps() && isPowerOf2 && NumElts >= 64) {
139 RegisterVT = MVT::v64i8;
140 IntermediateVT = MVT::v64i1;
141 NumIntermediates = NumElts / 64;
142 return NumIntermediates;
143 }
144
145 // In HVX 128-byte mode, vectors of type vXi1 are split into (X / 128) vectors
146 // of type v128i1, provided that X is divisible by 128.
147 if (isBoolVector && Subtarget.useHVX128BOps() && isPowerOf2 &&
148 NumElts >= 128) {
149 RegisterVT = MVT::v128i8;
150 IntermediateVT = MVT::v128i1;
151 NumIntermediates = NumElts / 128;
152 return NumIntermediates;
153 }
154
156 Context, CC, VT, IntermediateVT, NumIntermediates, RegisterVT);
157}
158
159std::pair<MVT, unsigned>
161 const HexagonSubtarget &Subtarget, EVT VT) const {
162 assert(VT.getVectorElementType() == MVT::i1);
163
164 const unsigned NumElems = VT.getVectorNumElements();
165
166 if (!VT.isPow2VectorType())
168
169 if (!Subtarget.useHVXOps() && NumElems >= 8)
170 return {MVT::v8i8, NumElems / 8};
171
172 if (Subtarget.useHVX64BOps() && NumElems >= 64)
173 return {MVT::v64i8, NumElems / 64};
174
175 if (Subtarget.useHVX128BOps() && NumElems >= 128)
176 return {MVT::v128i8, NumElems / 128};
177
179}
180
183 EVT VT) const {
184
185 if (VT.isVectorOf(MVT::i1)) {
186 auto [RegisterVT, NumRegisters] =
188 if (RegisterVT != MVT::INVALID_SIMPLE_VALUE_TYPE)
189 return RegisterVT;
190 }
191
193}
194
197 const {
198 unsigned IntNo = Op.getConstantOperandVal(0);
199 SDLoc dl(Op);
200 switch (IntNo) {
201 default:
202 return SDValue(); // Don't custom lower most intrinsics.
203 case Intrinsic::thread_pointer: {
204 EVT PtrVT = getPointerTy(DAG.getDataLayout());
205 return DAG.getNode(HexagonISD::THREAD_POINTER, dl, PtrVT);
206 }
207 }
208}
209
210/// CreateCopyOfByValArgument - Make a copy of an aggregate at address specified
211/// by "Src" to address "Dst" of size "Size". Alignment information is
212/// specified by the specific parameter attribute. The copy will be passed as
213/// a byval function parameter. Sometimes what we are copying is the end of a
214/// larger object, the part that does not fit in registers.
216 SDValue Chain, ISD::ArgFlagsTy Flags,
217 SelectionDAG &DAG, const SDLoc &dl) {
218 SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), dl, MVT::i32);
219 Align Alignment = Flags.getNonZeroByValAlign();
220 return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Alignment, Alignment,
221 /*isVolatile=*/false, /*AlwaysInline=*/false,
222 /*CI=*/nullptr, std::nullopt, MachinePointerInfo(),
224}
225
226bool
228 CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
230 LLVMContext &Context, const Type *RetTy) const {
232 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
233
234 return CCInfo.CheckReturn(Outs, RetCC_Hexagon);
235}
236
237// LowerReturn - Lower ISD::RET. If a struct is larger than 8 bytes and is
238// passed by value, the function prototype is modified to return void and
239// the value is stored in memory pointed by a pointer passed by caller.
242 bool IsVarArg,
244 const SmallVectorImpl<SDValue> &OutVals,
245 const SDLoc &dl, SelectionDAG &DAG) const {
246 // CCValAssign - represent the assignment of the return value to locations.
248
249 // CCState - Info about the registers and stack slot.
250 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
251 *DAG.getContext());
252
253 // Analyze return values of ISD::RET
254 CCInfo.AnalyzeReturn(Outs, RetCC_Hexagon);
255
256 SDValue Glue;
257 SmallVector<SDValue, 4> RetOps(1, Chain);
258
259 // Copy the result values into the output registers.
260 for (unsigned i = 0; i != RVLocs.size(); ++i) {
261 CCValAssign &VA = RVLocs[i];
262 SDValue Val = OutVals[i];
263
264 switch (VA.getLocInfo()) {
265 default:
266 // Loc info must be one of Full, BCvt, SExt, ZExt, or AExt.
267 llvm_unreachable("Unknown loc info!");
269 break;
271 Val = DAG.getBitcast(VA.getLocVT(), Val);
272 break;
274 Val = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Val);
275 break;
277 Val = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Val);
278 break;
280 Val = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Val);
281 break;
282 }
283
284 Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), Val, Glue);
285
286 // Guarantee that all emitted copies are stuck together with flags.
287 Glue = Chain.getValue(1);
288 RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
289 }
290
291 RetOps[0] = Chain; // Update chain.
292
293 // Add the glue if we have it.
294 if (Glue.getNode())
295 RetOps.push_back(Glue);
296
297 return DAG.getNode(HexagonISD::RET_GLUE, dl, MVT::Other, RetOps);
298}
299
301 // If either no tail call or told not to tail call at all, don't.
302 return CI->isTailCall();
303}
304
306 const char* RegName, LLT VT, const MachineFunction &) const {
307 // Just support r19, the linux kernel uses it.
309 .Case("r0", Hexagon::R0)
310 .Case("r1", Hexagon::R1)
311 .Case("r2", Hexagon::R2)
312 .Case("r3", Hexagon::R3)
313 .Case("r4", Hexagon::R4)
314 .Case("r5", Hexagon::R5)
315 .Case("r6", Hexagon::R6)
316 .Case("r7", Hexagon::R7)
317 .Case("r8", Hexagon::R8)
318 .Case("r9", Hexagon::R9)
319 .Case("r10", Hexagon::R10)
320 .Case("r11", Hexagon::R11)
321 .Case("r12", Hexagon::R12)
322 .Case("r13", Hexagon::R13)
323 .Case("r14", Hexagon::R14)
324 .Case("r15", Hexagon::R15)
325 .Case("r16", Hexagon::R16)
326 .Case("r17", Hexagon::R17)
327 .Case("r18", Hexagon::R18)
328 .Case("r19", Hexagon::R19)
329 .Case("r20", Hexagon::R20)
330 .Case("r21", Hexagon::R21)
331 .Case("r22", Hexagon::R22)
332 .Case("r23", Hexagon::R23)
333 .Case("r24", Hexagon::R24)
334 .Case("r25", Hexagon::R25)
335 .Case("r26", Hexagon::R26)
336 .Case("r27", Hexagon::R27)
337 .Case("r28", Hexagon::R28)
338 .Case("r29", Hexagon::R29)
339 .Case("r30", Hexagon::R30)
340 .Case("r31", Hexagon::R31)
341 .Case("r1:0", Hexagon::D0)
342 .Case("r3:2", Hexagon::D1)
343 .Case("r5:4", Hexagon::D2)
344 .Case("r7:6", Hexagon::D3)
345 .Case("r9:8", Hexagon::D4)
346 .Case("r11:10", Hexagon::D5)
347 .Case("r13:12", Hexagon::D6)
348 .Case("r15:14", Hexagon::D7)
349 .Case("r17:16", Hexagon::D8)
350 .Case("r19:18", Hexagon::D9)
351 .Case("r21:20", Hexagon::D10)
352 .Case("r23:22", Hexagon::D11)
353 .Case("r25:24", Hexagon::D12)
354 .Case("r27:26", Hexagon::D13)
355 .Case("r29:28", Hexagon::D14)
356 .Case("r31:30", Hexagon::D15)
357 .Case("sp", Hexagon::R29)
358 .Case("fp", Hexagon::R30)
359 .Case("lr", Hexagon::R31)
360 .Case("p0", Hexagon::P0)
361 .Case("p1", Hexagon::P1)
362 .Case("p2", Hexagon::P2)
363 .Case("p3", Hexagon::P3)
364 .Case("sa0", Hexagon::SA0)
365 .Case("lc0", Hexagon::LC0)
366 .Case("sa1", Hexagon::SA1)
367 .Case("lc1", Hexagon::LC1)
368 .Case("m0", Hexagon::M0)
369 .Case("m1", Hexagon::M1)
370 .Case("usr", Hexagon::USR)
371 .Case("ugp", Hexagon::UGP)
372 .Case("cs0", Hexagon::CS0)
373 .Case("cs1", Hexagon::CS1)
374 .Default(Register());
375 return Reg;
376}
377
378/// LowerCallResult - Lower the result values of an ISD::CALL into the
379/// appropriate copies out of appropriate physical registers. This assumes that
380/// Chain/Glue are the input chain/glue to use, and that TheCall is the call
381/// being lowered. Returns a SDNode with the same number of values as the
382/// ISD::CALL.
384 SDValue Chain, SDValue Glue, CallingConv::ID CallConv, bool IsVarArg,
385 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
387 const SmallVectorImpl<SDValue> &OutVals, SDValue Callee) const {
388 // Assign locations to each value returned by this call.
390
391 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
392 *DAG.getContext());
393
394 CCInfo.AnalyzeCallResult(Ins, RetCC_Hexagon);
395
396 // Copy all of the result registers out of their specified physreg.
397 for (unsigned i = 0; i != RVLocs.size(); ++i) {
398 SDValue RetVal;
399 if (RVLocs[i].getValVT() == MVT::i1) {
400 // Return values of type MVT::i1 require special handling. The reason
401 // is that MVT::i1 is associated with the PredRegs register class, but
402 // values of that type are still returned in R0. Generate an explicit
403 // copy into a predicate register from R0, and treat the value of the
404 // predicate register as the call result.
405 auto &MRI = DAG.getMachineFunction().getRegInfo();
406 SDValue FR0 = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(),
407 MVT::i32, Glue);
408 // FR0 = (Value, Chain, Glue)
409 Register PredR = MRI.createVirtualRegister(&Hexagon::PredRegsRegClass);
410 SDValue TPR = DAG.getCopyToReg(FR0.getValue(1), dl, PredR,
411 FR0.getValue(0), FR0.getValue(2));
412 // TPR = (Chain, Glue)
413 // Don't glue this CopyFromReg, because it copies from a virtual
414 // register. If it is glued to the call, InstrEmitter will add it
415 // as an implicit def to the call (EmitMachineNode).
416 RetVal = DAG.getCopyFromReg(TPR.getValue(0), dl, PredR, MVT::i1);
417 Glue = TPR.getValue(1);
418 Chain = TPR.getValue(0);
419 } else {
420 RetVal = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(),
421 RVLocs[i].getValVT(), Glue);
422 Glue = RetVal.getValue(2);
423 Chain = RetVal.getValue(1);
424 }
425 InVals.push_back(RetVal.getValue(0));
426 }
427
428 return Chain;
429}
430
431/// LowerCall - Functions arguments are copied from virtual regs to
432/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted.
435 SmallVectorImpl<SDValue> &InVals) const {
436 SelectionDAG &DAG = CLI.DAG;
437 SDLoc &dl = CLI.DL;
439 SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
441 SDValue Chain = CLI.Chain;
442 SDValue Callee = CLI.Callee;
443 CallingConv::ID CallConv = CLI.CallConv;
444 bool IsVarArg = CLI.IsVarArg;
445 bool DoesNotReturn = CLI.DoesNotReturn;
446
447 bool IsStructRet = Outs.empty() ? false : Outs[0].Flags.isSRet();
449 MachineFrameInfo &MFI = MF.getFrameInfo();
450 auto PtrVT = getPointerTy(MF.getDataLayout());
451
453 Callee = DAG.getTargetGlobalAddress(GAN->getGlobal(), dl, MVT::i32);
454
455 // Linux ABI treats var-arg calls the same way as regular ones.
456 bool TreatAsVarArg = !Subtarget.isEnvironmentMusl() && IsVarArg;
457
458 // Analyze operands of the call, assigning locations to each operand.
460 CCState CCInfo(CallConv, TreatAsVarArg, MF, ArgLocs, *DAG.getContext());
461
463 CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon_Legacy);
464 else
465 CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon);
466
467 if (CLI.IsTailCall) {
468 bool StructAttrFlag = MF.getFunction().hasStructRetAttr();
469 CLI.IsTailCall = IsEligibleForTailCallOptimization(Callee, CallConv,
470 IsVarArg, IsStructRet, StructAttrFlag, Outs,
471 OutVals, Ins, DAG);
472 for (const CCValAssign &VA : ArgLocs) {
473 if (VA.isMemLoc()) {
474 CLI.IsTailCall = false;
475 break;
476 }
477 }
478 LLVM_DEBUG(dbgs() << (CLI.IsTailCall ? "Eligible for Tail Call\n"
479 : "Argument must be passed on stack. "
480 "Not eligible for Tail Call\n"));
481 }
482 // Get a count of how many bytes are to be pushed on the stack.
483 unsigned NumBytes = CCInfo.getStackSize();
485 SmallVector<SDValue, 8> MemOpChains;
486
487 const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo();
488 SDValue StackPtr =
489 DAG.getCopyFromReg(Chain, dl, HRI.getStackRegister(), PtrVT);
490
491 bool NeedsArgAlign = false;
492 Align LargestAlignSeen;
493 // Walk the register/memloc assignments, inserting copies/loads.
494 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
495 CCValAssign &VA = ArgLocs[i];
496 SDValue Arg = OutVals[i];
497 ISD::ArgFlagsTy Flags = Outs[i].Flags;
498 // Record if we need > 8 byte alignment on an argument.
499 bool ArgAlign = Subtarget.isHVXVectorType(VA.getValVT());
500 NeedsArgAlign |= ArgAlign;
501
502 // Promote the value if needed.
503 switch (VA.getLocInfo()) {
504 default:
505 // Loc info must be one of Full, BCvt, SExt, ZExt, or AExt.
506 llvm_unreachable("Unknown loc info!");
508 break;
510 Arg = DAG.getBitcast(VA.getLocVT(), Arg);
511 break;
513 Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);
514 break;
516 Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);
517 break;
519 Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);
520 break;
521 }
522
523 if (VA.isMemLoc()) {
524 unsigned LocMemOffset = VA.getLocMemOffset();
525 SDValue MemAddr = DAG.getConstant(LocMemOffset, dl,
526 StackPtr.getValueType());
527 MemAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, MemAddr);
528 if (ArgAlign)
529 LargestAlignSeen = std::max(
530 LargestAlignSeen, Align(VA.getLocVT().getStoreSizeInBits() / 8));
531 if (Flags.isByVal()) {
532 // The argument is a struct passed by value. According to LLVM, "Arg"
533 // is a pointer.
534 MemOpChains.push_back(CreateCopyOfByValArgument(Arg, MemAddr, Chain,
535 Flags, DAG, dl));
536 } else {
538 DAG.getMachineFunction(), LocMemOffset);
539 SDValue S = DAG.getStore(Chain, dl, Arg, MemAddr, LocPI);
540 MemOpChains.push_back(S);
541 }
542 continue;
543 }
544
545 // Arguments that can be passed on register must be kept at RegsToPass
546 // vector.
547 if (VA.isRegLoc())
548 RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
549 }
550
551 if (NeedsArgAlign && Subtarget.hasV60Ops()) {
552 LLVM_DEBUG(dbgs() << "Function needs byte stack align due to call args\n");
553 Align VecAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass);
554 LargestAlignSeen = std::max(LargestAlignSeen, VecAlign);
555 MFI.ensureMaxAlignment(LargestAlignSeen);
556 }
557 // Transform all store nodes into one single node because all store
558 // nodes are independent of each other.
559 if (!MemOpChains.empty())
560 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
561
562 SDValue Glue;
563 if (!CLI.IsTailCall) {
564 Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, dl);
565 Glue = Chain.getValue(1);
566 }
567
568 // Build a sequence of copy-to-reg nodes chained together with token
569 // chain and flag operands which copy the outgoing args into registers.
570 // The Glue is necessary since all emitted instructions must be
571 // stuck together.
572 if (!CLI.IsTailCall) {
573 for (const auto &R : RegsToPass) {
574 Chain = DAG.getCopyToReg(Chain, dl, R.first, R.second, Glue);
575 Glue = Chain.getValue(1);
576 }
577 } else {
578 // For tail calls lower the arguments to the 'real' stack slot.
579 //
580 // Force all the incoming stack arguments to be loaded from the stack
581 // before any new outgoing arguments are stored to the stack, because the
582 // outgoing stack slots may alias the incoming argument stack slots, and
583 // the alias isn't otherwise explicit. This is slightly more conservative
584 // than necessary, because it means that each store effectively depends
585 // on every argument instead of just those arguments it would clobber.
586 //
587 // Do not flag preceding copytoreg stuff together with the following stuff.
588 Glue = SDValue();
589 for (const auto &R : RegsToPass) {
590 Chain = DAG.getCopyToReg(Chain, dl, R.first, R.second, Glue);
591 Glue = Chain.getValue(1);
592 }
593 Glue = SDValue();
594 }
595
596 bool LongCalls = MF.getSubtarget<HexagonSubtarget>().useLongCalls();
597 unsigned Flags = LongCalls ? HexagonII::HMOTF_ConstExtended : 0;
598
599 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
600 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
601 // node so that legalize doesn't hack it.
603 Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, PtrVT, 0, Flags);
604 } else if (ExternalSymbolSDNode *S =
606 Callee = DAG.getTargetExternalSymbol(S->getSymbol(), PtrVT, Flags);
607 }
608
609 // Returns a chain & a flag for retval copy to use.
611 Ops.push_back(Chain);
612 Ops.push_back(Callee);
613
614 // Add argument registers to the end of the list so that they are
615 // known live into the call.
616 for (const auto &R : RegsToPass)
617 Ops.push_back(DAG.getRegister(R.first, R.second.getValueType()));
618
619 const uint32_t *Mask = HRI.getCallPreservedMask(MF, CallConv);
620 assert(Mask && "Missing call preserved mask for calling convention");
621 Ops.push_back(DAG.getRegisterMask(Mask));
622
623 if (Glue.getNode())
624 Ops.push_back(Glue);
625
626 if (CLI.IsTailCall) {
627 MFI.setHasTailCall();
628 return DAG.getNode(HexagonISD::TC_RETURN, dl, MVT::Other, Ops);
629 }
630
631 // Set this here because we need to know this for "hasFP" in frame lowering.
632 // The target-independent code calls getFrameRegister before setting it, and
633 // getFrameRegister uses hasFP to determine whether the function has FP.
634 MFI.setHasCalls(true);
635
636 unsigned OpCode = DoesNotReturn ? HexagonISD::CALLnr : HexagonISD::CALL;
637 Chain = DAG.getNode(OpCode, dl, {MVT::Other, MVT::Glue}, Ops);
638 if (CLI.CFIType)
639 Chain.getNode()->setCFIType(CLI.CFIType->getZExtValue());
640 Glue = Chain.getValue(1);
641
642 // Create the CALLSEQ_END node.
643 Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, Glue, dl);
644 Glue = Chain.getValue(1);
645
646 // Handle result values, copying them out of physregs into vregs that we
647 // return.
648 return LowerCallResult(Chain, Glue, CallConv, IsVarArg, Ins, dl, DAG,
649 InVals, OutVals, Callee);
650}
651
652/// Returns true by value, base pointer and offset pointer and addressing
653/// mode by reference if this node can be combined with a load / store to
654/// form a post-indexed load / store.
657 SelectionDAG &DAG) const {
659 if (!LSN)
660 return false;
661 EVT VT = LSN->getMemoryVT();
662 if (!VT.isSimple())
663 return false;
664 bool IsLegalType = VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32 ||
665 VT == MVT::i64 || VT == MVT::f32 || VT == MVT::f64 ||
666 VT == MVT::v2i16 || VT == MVT::v2i32 || VT == MVT::v4i8 ||
667 VT == MVT::v4i16 || VT == MVT::v8i8 ||
668 Subtarget.isHVXVectorType(VT.getSimpleVT());
669 if (!IsLegalType)
670 return false;
671
672 if (Op->getOpcode() != ISD::ADD)
673 return false;
674 Base = Op->getOperand(0);
675 Offset = Op->getOperand(1);
676 if (!isa<ConstantSDNode>(Offset.getNode()))
677 return false;
678 AM = ISD::POST_INC;
679
680 int32_t V = cast<ConstantSDNode>(Offset.getNode())->getSExtValue();
681 return Subtarget.getInstrInfo()->isValidAutoIncImm(VT, V);
682}
683
686 return SDValue();
687 else
688 return Op;
689}
690
694 auto &HMFI = *MF.getInfo<HexagonMachineFunctionInfo>();
695 const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo();
696 unsigned LR = HRI.getRARegister();
697
698 if ((Op.getOpcode() != ISD::INLINEASM &&
699 Op.getOpcode() != ISD::INLINEASM_BR) || HMFI.hasClobberLR())
700 return Op;
701
702 unsigned NumOps = Op.getNumOperands();
703 if (Op.getOperand(NumOps-1).getValueType() == MVT::Glue)
704 --NumOps; // Ignore the flag operand.
705
706 for (unsigned i = InlineAsm::Op_FirstOperand; i != NumOps;) {
707 const InlineAsm::Flag Flags(Op.getConstantOperandVal(i));
708 unsigned NumVals = Flags.getNumOperandRegisters();
709 ++i; // Skip the ID value.
710
711 switch (Flags.getKind()) {
712 default:
713 llvm_unreachable("Bad flags!");
717 i += NumVals;
718 break;
722 for (; NumVals; --NumVals, ++i) {
723 Register Reg = cast<RegisterSDNode>(Op.getOperand(i))->getReg();
724 if (Reg != LR)
725 continue;
726 HMFI.setHasClobberLR(true);
727 return Op;
728 }
729 break;
730 }
731 }
732 }
733
734 return Op;
735}
736
737// Need to transform ISD::PREFETCH into something that doesn't inherit
738// all of the properties of ISD::PREFETCH, specifically SDNPMayLoad and
739// SDNPMayStore.
741 SelectionDAG &DAG) const {
742 SDValue Chain = Op.getOperand(0);
743 SDValue Addr = Op.getOperand(1);
744 // Lower it to DCFETCH($reg, #0). A "pat" will try to merge the offset in,
745 // if the "reg" is fed by an "add".
746 SDLoc DL(Op);
747 SDValue Zero = DAG.getConstant(0, DL, MVT::i32);
748 return DAG.getNode(HexagonISD::DCFETCH, DL, MVT::Other, Chain, Addr, Zero);
749}
750
752 SelectionDAG &DAG) const {
753 SDValue Chain = Op.getOperand(0);
754 unsigned IntNo = Op.getConstantOperandVal(1);
755 // Lower the hexagon_prefetch builtin to DCFETCH, as above.
756 if (IntNo == Intrinsic::hexagon_prefetch) {
757 SDValue Addr = Op.getOperand(2);
758 SDLoc DL(Op);
759 SDValue Zero = DAG.getConstant(0, DL, MVT::i32);
760 return DAG.getNode(HexagonISD::DCFETCH, DL, MVT::Other, Chain, Addr, Zero);
761 }
762 return SDValue();
763}
764
767 SelectionDAG &DAG) const {
768 SDValue Chain = Op.getOperand(0);
769 SDValue Size = Op.getOperand(1);
770 SDValue Align = Op.getOperand(2);
771 SDLoc dl(Op);
772
774 assert(AlignConst && "Non-constant Align in LowerDYNAMIC_STACKALLOC");
775
776 unsigned A = AlignConst->getSExtValue();
777 auto &HFI = *Subtarget.getFrameLowering();
778 // "Zero" means natural stack alignment.
779 if (A == 0)
780 A = HFI.getStackAlign().value();
781
782 LLVM_DEBUG({
783 dbgs () << __func__ << " Align: " << A << " Size: ";
784 Size.getNode()->dump(&DAG);
785 dbgs() << "\n";
786 });
787
788 SDValue AC = DAG.getConstant(A, dl, MVT::i32);
789 SDVTList VTs = DAG.getVTList(MVT::i32, MVT::Other);
790 SDValue AA = DAG.getNode(HexagonISD::ALLOCA, dl, VTs, Chain, Size, AC);
791
793 return AA;
794}
795
797 SelectionDAG &DAG) const {
798 EVT OpVT = Op.getValueType();
799 MVT SimpleVT = OpVT.getSimpleVT();
800 SDLoc DL(Op);
801
802 // Check if any of the inputs are NaN. If so, propagate the NaN
803 // to the output, otherwise return the maximum/minimum of the inputs.
804 // We can safely use ISD::FMINNUM/ISD::FMAXNUM to run
805 // Hexagon's F2_sfmin/F2_sfmax, when no operand is NaN.
806 // Note: We cannot directly compare nodes against NaN node to find NaNs,
807 // because comparing NaN with anything always returns False (except for !=0
808 // which always return True). To work around that, we compare input operands
809 // with themselves under ISD::SETUO, which only returns true if the operand is
810 // NaN.
811
812 SDValue Op1 = Op.getOperand(0);
813 SDValue Op2 = Op.getOperand(1);
814 SDValue isOp1NaN = DAG.getSetCC(DL, MVT::i1, Op1, Op1, ISD::SETUO);
815 SDValue isOp2NaN = DAG.getSetCC(DL, MVT::i1, Op2, Op2, ISD::SETUO);
816
817 switch (Op.getOpcode()) {
818 case ISD::FMAXIMUM: {
819 SDValue FmaxNode = DAG.getNode(ISD::FMAXNUM, DL, SimpleVT, Op1, Op2);
820 SDValue result =
821 DAG.getNode(ISD::SELECT, DL, SimpleVT, isOp2NaN, Op2, FmaxNode);
822 return DAG.getNode(ISD::SELECT, DL, SimpleVT, isOp1NaN, Op1, result);
823 }
824 case ISD::FMINIMUM: {
825 SDValue FminNode = DAG.getNode(ISD::FMINNUM, DL, SimpleVT, Op1, Op2);
826 SDValue result =
827 DAG.getNode(ISD::SELECT, DL, SimpleVT, isOp2NaN, Op2, FminNode);
828 return DAG.getNode(ISD::SELECT, DL, SimpleVT, isOp1NaN, Op1, result);
829 }
830 default:
831 llvm_unreachable("Invalid opcode for LowerFMINFMAX");
832 }
833}
834
836 SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
837 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
838 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
840 MachineFrameInfo &MFI = MF.getFrameInfo();
842
843 // Linux ABI treats var-arg calls the same way as regular ones.
844 bool TreatAsVarArg = !Subtarget.isEnvironmentMusl() && IsVarArg;
845
846 // Assign locations to all of the incoming arguments.
848 CCState CCInfo(CallConv, TreatAsVarArg, MF, ArgLocs, *DAG.getContext());
849
851 CCInfo.AnalyzeFormalArguments(Ins, CC_Hexagon_Legacy);
852 else
853 CCInfo.AnalyzeFormalArguments(Ins, CC_Hexagon);
854
855 // For LLVM, in the case when returning a struct by value (>8byte),
856 // the first argument is a pointer that points to the location on caller's
857 // stack where the return value will be stored. For Hexagon, the location on
858 // caller's stack is passed only when the struct size is smaller than (and
859 // equal to) 8 bytes. If not, no address will be passed into callee and
860 // callee return the result directly through R0/R1.
861 auto NextSingleReg = [] (const TargetRegisterClass &RC, unsigned Reg) {
862 switch (RC.getID()) {
863 case Hexagon::IntRegsRegClassID:
864 return Reg - Hexagon::R0 + 1;
865 case Hexagon::DoubleRegsRegClassID:
866 return (Reg - Hexagon::D0 + 1) * 2;
867 case Hexagon::HvxVRRegClassID:
868 return Reg - Hexagon::V0 + 1;
869 case Hexagon::HvxWRRegClassID:
870 return (Reg - Hexagon::W0 + 1) * 2;
871 }
872 llvm_unreachable("Unexpected register class");
873 };
874
875 auto &HFL = const_cast<HexagonFrameLowering&>(*Subtarget.getFrameLowering());
876 auto &HMFI = *MF.getInfo<HexagonMachineFunctionInfo>();
877 HFL.FirstVarArgSavedReg = 0;
879
880 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
881 CCValAssign &VA = ArgLocs[i];
882 ISD::ArgFlagsTy Flags = Ins[i].Flags;
883 bool ByVal = Flags.isByVal();
884
885 // Arguments passed in registers:
886 // 1. 32- and 64-bit values and HVX vectors are passed directly,
887 // 2. Large structs are passed via an address, and the address is
888 // passed in a register.
889 if (VA.isRegLoc() && ByVal && Flags.getByValSize() <= 8)
890 llvm_unreachable("ByValSize must be bigger than 8 bytes");
891
892 bool InReg = VA.isRegLoc() &&
893 (!ByVal || (ByVal && Flags.getByValSize() > 8));
894
895 if (InReg) {
896 MVT RegVT = VA.getLocVT();
897 if (VA.getLocInfo() == CCValAssign::BCvt)
898 RegVT = VA.getValVT();
899
900 const TargetRegisterClass *RC = getRegClassFor(RegVT);
901 Register VReg = MRI.createVirtualRegister(RC);
902 SDValue Copy = DAG.getCopyFromReg(Chain, dl, VReg, RegVT);
903
904 // Treat values of type MVT::i1 specially: they are passed in
905 // registers of type i32, but they need to remain as values of
906 // type i1 for consistency of the argument lowering.
907 if (VA.getValVT() == MVT::i1) {
908 assert(RegVT.getSizeInBits() <= 32);
909 SDValue T = DAG.getNode(ISD::AND, dl, RegVT,
910 Copy, DAG.getConstant(1, dl, RegVT));
911 Copy = DAG.getSetCC(dl, MVT::i1, T, DAG.getConstant(0, dl, RegVT),
912 ISD::SETNE);
913 } else {
914#ifndef NDEBUG
915 unsigned RegSize = RegVT.getSizeInBits();
916 assert(RegSize == 32 || RegSize == 64 ||
917 Subtarget.isHVXVectorType(RegVT));
918#endif
919 }
920 InVals.push_back(Copy);
921 MRI.addLiveIn(VA.getLocReg(), VReg);
922 HFL.FirstVarArgSavedReg = NextSingleReg(*RC, VA.getLocReg());
923 } else {
924 assert(VA.isMemLoc() && "Argument should be passed in memory");
925
926 // If it's a byval parameter, then we need to compute the
927 // "real" size, not the size of the pointer.
928 unsigned ObjSize = Flags.isByVal()
929 ? Flags.getByValSize()
930 : VA.getLocVT().getStoreSizeInBits() / 8;
931
932 // Create the frame index object for this incoming parameter.
934 int FI = MFI.CreateFixedObject(ObjSize, Offset, true);
935 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
936
937 if (Flags.isByVal()) {
938 // If it's a pass-by-value aggregate, then do not dereference the stack
939 // location. Instead, we should generate a reference to the stack
940 // location.
941 InVals.push_back(FIN);
942 } else {
943 SDValue L = DAG.getLoad(VA.getValVT(), dl, Chain, FIN,
945 InVals.push_back(L);
946 }
947 }
948 }
949
950 if (IsVarArg && Subtarget.isEnvironmentMusl()) {
951 for (int i = HFL.FirstVarArgSavedReg; i < 6; i++)
952 MRI.addLiveIn(Hexagon::R0+i);
953 }
954
955 if (IsVarArg && Subtarget.isEnvironmentMusl()) {
956 HMFI.setFirstNamedArgFrameIndex(HMFI.getFirstNamedArgFrameIndex() - 1);
957 HMFI.setLastNamedArgFrameIndex(-int(MFI.getNumFixedObjects()));
958
959 // Create Frame index for the start of register saved area.
960 int NumVarArgRegs = 6 - HFL.FirstVarArgSavedReg;
961 bool RequiresPadding = (NumVarArgRegs & 1);
962 int RegSaveAreaSizePlusPadding = RequiresPadding
963 ? (NumVarArgRegs + 1) * 4
964 : NumVarArgRegs * 4;
965
966 if (RegSaveAreaSizePlusPadding > 0) {
967 // The offset to saved register area should be 8 byte aligned.
968 int RegAreaStart = HEXAGON_LRFP_SIZE + CCInfo.getStackSize();
969 if (!(RegAreaStart % 8))
970 RegAreaStart = (RegAreaStart + 7) & -8;
971
972 int RegSaveAreaFrameIndex =
973 MFI.CreateFixedObject(RegSaveAreaSizePlusPadding, RegAreaStart, true);
974 HMFI.setRegSavedAreaStartFrameIndex(RegSaveAreaFrameIndex);
975
976 // This will point to the next argument passed via stack.
977 int Offset = RegAreaStart + RegSaveAreaSizePlusPadding;
978 int FI = MFI.CreateFixedObject(Hexagon_PointerSize, Offset, true);
979 HMFI.setVarArgsFrameIndex(FI);
980 } else {
981 // This will point to the next argument passed via stack, when
982 // there is no saved register area.
983 int Offset = HEXAGON_LRFP_SIZE + CCInfo.getStackSize();
984 int FI = MFI.CreateFixedObject(Hexagon_PointerSize, Offset, true);
985 HMFI.setRegSavedAreaStartFrameIndex(FI);
986 HMFI.setVarArgsFrameIndex(FI);
987 }
988 }
989
990
991 if (IsVarArg && !Subtarget.isEnvironmentMusl()) {
992 // This will point to the next argument passed via stack.
993 int Offset = HEXAGON_LRFP_SIZE + CCInfo.getStackSize();
994 int FI = MFI.CreateFixedObject(Hexagon_PointerSize, Offset, true);
995 HMFI.setVarArgsFrameIndex(FI);
996 }
997
998 return Chain;
999}
1000
1001SDValue
1003 // VASTART stores the address of the VarArgsFrameIndex slot into the
1004 // memory location argument.
1007 SDValue Addr = DAG.getFrameIndex(QFI->getVarArgsFrameIndex(), MVT::i32);
1008 const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
1009
1010 if (!Subtarget.isEnvironmentMusl()) {
1011 return DAG.getStore(Op.getOperand(0), SDLoc(Op), Addr, Op.getOperand(1),
1012 MachinePointerInfo(SV));
1013 }
1014 auto &FuncInfo = *MF.getInfo<HexagonMachineFunctionInfo>();
1015 auto &HFL = *Subtarget.getFrameLowering();
1016 SDLoc DL(Op);
1018
1019 // Get frame index of va_list.
1020 SDValue FIN = Op.getOperand(1);
1021
1022 // If first Vararg register is odd, add 4 bytes to start of
1023 // saved register area to point to the first register location.
1024 // This is because the saved register area has to be 8 byte aligned.
1025 // In case of an odd start register, there will be 4 bytes of padding in
1026 // the beginning of saved register area. If all registers area used up,
1027 // the following condition will handle it correctly.
1028 SDValue SavedRegAreaStartFrameIndex =
1029 DAG.getFrameIndex(FuncInfo.getRegSavedAreaStartFrameIndex(), MVT::i32);
1030
1031 auto PtrVT = getPointerTy(DAG.getDataLayout());
1032
1033 if (HFL.FirstVarArgSavedReg & 1)
1034 SavedRegAreaStartFrameIndex =
1035 DAG.getNode(ISD::ADD, DL, PtrVT,
1036 DAG.getFrameIndex(FuncInfo.getRegSavedAreaStartFrameIndex(),
1037 MVT::i32),
1038 DAG.getIntPtrConstant(4, DL));
1039
1040 // Store the saved register area start pointer.
1041 SDValue Store =
1042 DAG.getStore(Op.getOperand(0), DL,
1043 SavedRegAreaStartFrameIndex,
1044 FIN, MachinePointerInfo(SV));
1045 MemOps.push_back(Store);
1046
1047 // Store saved register area end pointer.
1048 FIN = DAG.getNode(ISD::ADD, DL, PtrVT,
1049 FIN, DAG.getIntPtrConstant(4, DL));
1050 Store = DAG.getStore(Op.getOperand(0), DL,
1051 DAG.getFrameIndex(FuncInfo.getVarArgsFrameIndex(),
1052 PtrVT),
1053 FIN, MachinePointerInfo(SV, 4));
1054 MemOps.push_back(Store);
1055
1056 // Store overflow area pointer.
1057 FIN = DAG.getNode(ISD::ADD, DL, PtrVT,
1058 FIN, DAG.getIntPtrConstant(4, DL));
1059 Store = DAG.getStore(Op.getOperand(0), DL,
1060 DAG.getFrameIndex(FuncInfo.getVarArgsFrameIndex(),
1061 PtrVT),
1062 FIN, MachinePointerInfo(SV, 8));
1063 MemOps.push_back(Store);
1064
1065 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOps);
1066}
1067
1068SDValue
1070 // Assert that the linux ABI is enabled for the current compilation.
1071 assert(Subtarget.isEnvironmentMusl() && "Linux ABI should be enabled");
1072 SDValue Chain = Op.getOperand(0);
1073 SDValue DestPtr = Op.getOperand(1);
1074 SDValue SrcPtr = Op.getOperand(2);
1075 const Value *DestSV = cast<SrcValueSDNode>(Op.getOperand(3))->getValue();
1076 const Value *SrcSV = cast<SrcValueSDNode>(Op.getOperand(4))->getValue();
1077 SDLoc DL(Op);
1078 // Size of the va_list is 12 bytes as it has 3 pointers. Therefore,
1079 // we need to memcopy 12 bytes from va_list to another similar list.
1080 return DAG.getMemcpy(Chain, DL, DestPtr, SrcPtr,
1081 DAG.getIntPtrConstant(12, DL), Align(4), Align(4),
1082 /*isVolatile*/ false, false, /*CI=*/nullptr,
1083 std::nullopt, MachinePointerInfo(DestSV),
1084 MachinePointerInfo(SrcSV));
1085}
1086
1088 const SDLoc &dl(Op);
1089 SDValue LHS = Op.getOperand(0);
1090 SDValue RHS = Op.getOperand(1);
1091 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
1092 MVT ResTy = ty(Op);
1093 MVT OpTy = ty(LHS);
1094
1095 if (OpTy == MVT::v2i16 || OpTy == MVT::v4i8) {
1096 assert(OpTy.getVectorElementType().isScalarInteger());
1097 MVT WideTy = OpTy.widenIntegerElementType();
1098 return DAG.getSetCC(dl, ResTy,
1099 DAG.getSExtOrTrunc(LHS, SDLoc(LHS), WideTy),
1100 DAG.getSExtOrTrunc(RHS, SDLoc(RHS), WideTy), CC);
1101 }
1102
1103 // Treat all other vector types as legal.
1104 if (ResTy.isVector())
1105 return Op;
1106
1107 // Equality comparisons of short integers should use sign-extend, not
1108 // zero-extend, since we can represent small negative values in the compare
1109 // instructions. The LLVM default is to use zero-extend arbitrarily in
1110 // these cases.
1111 auto isSExtFree = [this](SDValue N) {
1112 switch (N.getOpcode()) {
1113 case ISD::TRUNCATE: {
1114 // A sign-extend of a truncate of a sign-extend is free.
1115 SDValue Op = N.getOperand(0);
1116 if (Op.getOpcode() != ISD::AssertSext)
1117 return false;
1118 EVT OrigTy = cast<VTSDNode>(Op.getOperand(1))->getVT();
1119 unsigned ThisBW = ty(N).getSizeInBits();
1120 unsigned OrigBW = OrigTy.getSizeInBits();
1121 // The type that was sign-extended to get the AssertSext must be
1122 // narrower than the type of N (so that N has still the same value
1123 // as the original).
1124 return ThisBW >= OrigBW;
1125 }
1126 case ISD::LOAD:
1127 // We have sign-extended loads.
1128 return true;
1129 }
1130 return false;
1131 };
1132
1133 // Only do this for equality comparisons. Signed comparisons are already
1134 // sign-extended by the generic operand promotion, and for unsigned
1135 // comparisons a sign-extension is never profitable: it does not change the
1136 // result (sign-extension preserves the unsigned ordering of the values of
1137 // the narrower type), but it turns constants with the sign bit of the
1138 // narrower type set into large 32-bit values, which then have to be
1139 // materialized in a register or use a constant extender.
1140 if ((OpTy == MVT::i8 || OpTy == MVT::i16) && ISD::isIntEqualitySetCC(CC)) {
1142 bool IsNegative = C && C->getAPIntValue().isNegative();
1143 if (IsNegative || isSExtFree(LHS) || isSExtFree(RHS))
1144 return DAG.getSetCC(dl, ResTy,
1145 DAG.getSExtOrTrunc(LHS, SDLoc(LHS), MVT::i32),
1146 DAG.getSExtOrTrunc(RHS, SDLoc(RHS), MVT::i32), CC);
1147 }
1148
1149 return SDValue();
1150}
1151
1152SDValue
1154 SDValue PredOp = Op.getOperand(0);
1155 SDValue Op1 = Op.getOperand(1), Op2 = Op.getOperand(2);
1156 MVT OpTy = ty(Op1);
1157 const SDLoc &dl(Op);
1158
1159 if (OpTy == MVT::v2i16 || OpTy == MVT::v4i8) {
1160 assert(OpTy.getVectorElementType().isScalarInteger());
1161 MVT WideTy = OpTy.widenIntegerElementType();
1162 // Generate (trunc (select (_, sext, sext))).
1163 return DAG.getSExtOrTrunc(
1164 DAG.getSelect(dl, WideTy, PredOp,
1165 DAG.getSExtOrTrunc(Op1, dl, WideTy),
1166 DAG.getSExtOrTrunc(Op2, dl, WideTy)),
1167 dl, OpTy);
1168 }
1169
1170 return SDValue();
1171}
1172
1173SDValue
1175 EVT ValTy = Op.getValueType();
1177 Constant *CVal = nullptr;
1178 bool isVTi1Type = false;
1179 if (auto *CV = dyn_cast<ConstantVector>(CPN->getConstVal())) {
1180 if (cast<VectorType>(CV->getType())->getElementType()->isIntegerTy(1)) {
1182 unsigned VecLen = CV->getNumOperands();
1183 assert(isPowerOf2_32(VecLen) &&
1184 "conversion only supported for pow2 VectorSize");
1185 for (unsigned i = 0; i < VecLen; ++i)
1186 NewConst.push_back(ConstantInt::get(Type::getInt8Ty(CV->getContext()),
1187 CV->getOperand(i)->isNullValue()));
1188
1189 CVal = ConstantVector::get(NewConst);
1190 isVTi1Type = true;
1191 }
1192 }
1193 Align Alignment = CPN->getAlign();
1194 bool IsPositionIndependent = isPositionIndependent();
1195 unsigned char TF = IsPositionIndependent ? HexagonII::MO_PCREL : 0;
1196
1197 unsigned Offset = 0;
1198 SDValue T;
1199 if (CPN->isMachineConstantPoolEntry())
1200 T = DAG.getTargetConstantPool(CPN->getMachineCPVal(), ValTy, Alignment,
1201 Offset, TF);
1202 else if (isVTi1Type)
1203 T = DAG.getTargetConstantPool(CVal, ValTy, Alignment, Offset, TF);
1204 else
1205 T = DAG.getTargetConstantPool(CPN->getConstVal(), ValTy, Alignment, Offset,
1206 TF);
1207
1208 assert(cast<ConstantPoolSDNode>(T)->getTargetFlags() == TF &&
1209 "Inconsistent target flag encountered");
1210
1211 if (IsPositionIndependent)
1212 return DAG.getNode(HexagonISD::AT_PCREL, SDLoc(Op), ValTy, T);
1213 return DAG.getNode(HexagonISD::CP, SDLoc(Op), ValTy, T);
1214}
1215
1216SDValue
1218 EVT VT = Op.getValueType();
1219 int Idx = cast<JumpTableSDNode>(Op)->getIndex();
1220 if (isPositionIndependent()) {
1222 return DAG.getNode(HexagonISD::AT_PCREL, SDLoc(Op), VT, T);
1223 }
1224
1225 SDValue T = DAG.getTargetJumpTable(Idx, VT);
1226 return DAG.getNode(HexagonISD::JT, SDLoc(Op), VT, T);
1227}
1228
1229SDValue
1231 const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo();
1233 MachineFrameInfo &MFI = MF.getFrameInfo();
1234 MFI.setReturnAddressIsTaken(true);
1235
1236 EVT VT = Op.getValueType();
1237 SDLoc dl(Op);
1238 unsigned Depth = Op.getConstantOperandVal(0);
1239 if (Depth) {
1240 SDValue FrameAddr = LowerFRAMEADDR(Op, DAG);
1241 SDValue Offset = DAG.getConstant(4, dl, MVT::i32);
1242 return DAG.getLoad(VT, dl, DAG.getEntryNode(),
1243 DAG.getNode(ISD::ADD, dl, VT, FrameAddr, Offset),
1245 }
1246
1247 // Return LR, which contains the return address. Mark it an implicit live-in.
1248 Register Reg = MF.addLiveIn(HRI.getRARegister(), getRegClassFor(MVT::i32));
1249 return DAG.getCopyFromReg(DAG.getEntryNode(), dl, Reg, VT);
1250}
1251
1252SDValue
1254 const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo();
1256 MFI.setFrameAddressIsTaken(true);
1257
1258 EVT VT = Op.getValueType();
1259 SDLoc dl(Op);
1260 unsigned Depth = Op.getConstantOperandVal(0);
1261 SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl,
1262 HRI.getFrameRegister(), VT);
1263 while (Depth--)
1264 FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr,
1266 return FrameAddr;
1267}
1268
1269SDValue
1271 SDLoc dl(Op);
1272 return DAG.getNode(HexagonISD::BARRIER, dl, MVT::Other, Op.getOperand(0));
1273}
1274
1275SDValue
1277 SDLoc dl(Op);
1278 auto *GAN = cast<GlobalAddressSDNode>(Op);
1279 auto PtrVT = getPointerTy(DAG.getDataLayout());
1280 auto *GV = GAN->getGlobal();
1281 int64_t Offset = GAN->getOffset();
1282
1283 auto &HLOF = *HTM.getObjFileLowering();
1284 Reloc::Model RM = HTM.getRelocationModel();
1285
1286 if (RM == Reloc::Static) {
1287 SDValue GA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, Offset);
1288 const GlobalObject *GO = GV->getAliaseeObject();
1289 if (GO && Subtarget.useSmallData() && HLOF.isGlobalInSmallSection(GO, HTM))
1290 return DAG.getNode(HexagonISD::CONST32_GP, dl, PtrVT, GA);
1291 return DAG.getNode(HexagonISD::CONST32, dl, PtrVT, GA);
1292 }
1293
1294 bool UsePCRel = getTargetMachine().shouldAssumeDSOLocal(GV);
1295 if (UsePCRel) {
1296 SDValue GA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, Offset,
1298 return DAG.getNode(HexagonISD::AT_PCREL, dl, PtrVT, GA);
1299 }
1300
1301 // Use GOT index.
1302 SDValue GOT = DAG.getGLOBAL_OFFSET_TABLE(PtrVT);
1303 SDValue GA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, HexagonII::MO_GOT);
1304 SDValue Off = DAG.getConstant(Offset, dl, MVT::i32);
1305 return DAG.getNode(HexagonISD::AT_GOT, dl, PtrVT, GOT, GA, Off);
1306}
1307
1308// Specifies that for loads and stores VT can be promoted to PromotedLdStVT.
1309SDValue
1311 const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress();
1312 SDLoc dl(Op);
1313 EVT PtrVT = getPointerTy(DAG.getDataLayout());
1314
1315 Reloc::Model RM = HTM.getRelocationModel();
1316 if (RM == Reloc::Static) {
1317 SDValue A = DAG.getTargetBlockAddress(BA, PtrVT);
1318 return DAG.getNode(HexagonISD::CONST32_GP, dl, PtrVT, A);
1319 }
1320
1322 return DAG.getNode(HexagonISD::AT_PCREL, dl, PtrVT, A);
1323}
1324
1325SDValue
1327 const {
1328 EVT PtrVT = getPointerTy(DAG.getDataLayout());
1331 return DAG.getNode(HexagonISD::AT_PCREL, SDLoc(Op), PtrVT, GOTSym);
1332}
1333
1334SDValue
1336 GlobalAddressSDNode *GA, SDValue Glue, EVT PtrVT, unsigned ReturnReg,
1337 unsigned char OperandFlags) const {
1339 MachineFrameInfo &MFI = MF.getFrameInfo();
1340 SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
1341 SDLoc dl(GA);
1342 SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl,
1343 GA->getValueType(0),
1344 GA->getOffset(),
1345 OperandFlags);
1346 // Create Operands for the call.The Operands should have the following:
1347 // 1. Chain SDValue
1348 // 2. Callee which in this case is the Global address value.
1349 // 3. Registers live into the call.In this case its R0, as we
1350 // have just one argument to be passed.
1351 // 4. Glue.
1352 // Note: The order is important.
1353
1354 const auto &HRI = *Subtarget.getRegisterInfo();
1355 const uint32_t *Mask = HRI.getCallPreservedMask(MF, CallingConv::C);
1356 assert(Mask && "Missing call preserved mask for calling convention");
1357 SDValue Ops[] = { Chain, TGA, DAG.getRegister(Hexagon::R0, PtrVT),
1358 DAG.getRegisterMask(Mask), Glue };
1359 Chain = DAG.getNode(HexagonISD::CALL, dl, NodeTys, Ops);
1360
1361 // Inform MFI that function has calls.
1362 MFI.setAdjustsStack(true);
1363
1364 Glue = Chain.getValue(1);
1365 return DAG.getCopyFromReg(Chain, dl, ReturnReg, PtrVT, Glue);
1366}
1367
1368//
1369// Lower using the initial executable model for TLS addresses
1370//
1371SDValue
1373 SelectionDAG &DAG) const {
1374 SDLoc dl(GA);
1375 int64_t Offset = GA->getOffset();
1376 auto PtrVT = getPointerTy(DAG.getDataLayout());
1377
1378 // Get the thread pointer.
1379 SDValue TP = DAG.getCopyFromReg(DAG.getEntryNode(), dl, Hexagon::UGP, PtrVT);
1380
1381 bool IsPositionIndependent = isPositionIndependent();
1382 unsigned char TF =
1383 IsPositionIndependent ? HexagonII::MO_IEGOT : HexagonII::MO_IE;
1384
1385 // First generate the TLS symbol address
1386 SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl, PtrVT,
1387 Offset, TF);
1388
1389 SDValue Sym = DAG.getNode(HexagonISD::CONST32, dl, PtrVT, TGA);
1390
1391 if (IsPositionIndependent) {
1392 // Generate the GOT pointer in case of position independent code
1393 SDValue GOT = LowerGLOBAL_OFFSET_TABLE(Sym, DAG);
1394
1395 // Add the TLS Symbol address to GOT pointer.This gives
1396 // GOT relative relocation for the symbol.
1397 Sym = DAG.getNode(ISD::ADD, dl, PtrVT, GOT, Sym);
1398 }
1399
1400 // Load the offset value for TLS symbol.This offset is relative to
1401 // thread pointer.
1402 SDValue LoadOffset =
1403 DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), Sym, MachinePointerInfo());
1404
1405 // Address of the thread local variable is the add of thread
1406 // pointer and the offset of the variable.
1407 return DAG.getNode(ISD::ADD, dl, PtrVT, TP, LoadOffset);
1408}
1409
1410//
1411// Lower using the local executable model for TLS addresses
1412//
1413SDValue
1415 SelectionDAG &DAG) const {
1416 SDLoc dl(GA);
1417 int64_t Offset = GA->getOffset();
1418 auto PtrVT = getPointerTy(DAG.getDataLayout());
1419
1420 // Get the thread pointer.
1421 SDValue TP = DAG.getCopyFromReg(DAG.getEntryNode(), dl, Hexagon::UGP, PtrVT);
1422 // Generate the TLS symbol address
1423 SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl, PtrVT, Offset,
1425 SDValue Sym = DAG.getNode(HexagonISD::CONST32, dl, PtrVT, TGA);
1426
1427 // Address of the thread local variable is the add of thread
1428 // pointer and the offset of the variable.
1429 return DAG.getNode(ISD::ADD, dl, PtrVT, TP, Sym);
1430}
1431
1432//
1433// Lower using the general dynamic model for TLS addresses
1434//
1435SDValue
1437 SelectionDAG &DAG) const {
1438 SDLoc dl(GA);
1439 int64_t Offset = GA->getOffset();
1440 auto PtrVT = getPointerTy(DAG.getDataLayout());
1441
1442 // First generate the TLS symbol address
1443 SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl, PtrVT, Offset,
1445
1446 // Then, generate the GOT pointer
1447 SDValue GOT = LowerGLOBAL_OFFSET_TABLE(TGA, DAG);
1448
1449 // Add the TLS symbol and the GOT pointer
1450 SDValue Sym = DAG.getNode(HexagonISD::CONST32, dl, PtrVT, TGA);
1451 SDValue Chain = DAG.getNode(ISD::ADD, dl, PtrVT, GOT, Sym);
1452
1453 // Copy over the argument to R0
1454 SDValue InGlue;
1455 Chain = DAG.getCopyToReg(DAG.getEntryNode(), dl, Hexagon::R0, Chain, InGlue);
1456 InGlue = Chain.getValue(1);
1457
1458 unsigned Flags = DAG.getSubtarget<HexagonSubtarget>().useLongCalls()
1461
1462 return GetDynamicTLSAddr(DAG, Chain, GA, InGlue, PtrVT,
1463 Hexagon::R0, Flags);
1464}
1465
1466//
1467// Lower TLS addresses.
1468//
1469// For now for dynamic models, we only support the general dynamic model.
1470//
1471SDValue
1473 SelectionDAG &DAG) const {
1475
1476 switch (HTM.getTLSModel(GA->getGlobal())) {
1479 return LowerToTLSGeneralDynamicModel(GA, DAG);
1481 return LowerToTLSInitialExecModel(GA, DAG);
1483 return LowerToTLSLocalExecModel(GA, DAG);
1484 }
1485 llvm_unreachable("Bogus TLS model");
1486}
1487
1488//===----------------------------------------------------------------------===//
1489// TargetLowering Implementation
1490//===----------------------------------------------------------------------===//
1491
1493 const HexagonSubtarget &ST)
1494 : TargetLowering(TM, ST),
1495 HTM(static_cast<const HexagonTargetMachine &>(TM)), Subtarget(ST) {
1496 auto &HRI = *Subtarget.getRegisterInfo();
1497
1501 setStackPointerRegisterToSaveRestore(HRI.getStackRegister());
1504
1507
1510 else
1512
1513 // Limits for inline expansion of memcpy/memmove
1520
1522
1523 //
1524 // Set up register classes.
1525 //
1526
1527 addRegisterClass(MVT::i1, &Hexagon::PredRegsRegClass);
1528 addRegisterClass(MVT::v2i1, &Hexagon::PredRegsRegClass); // bbbbaaaa
1529 addRegisterClass(MVT::v4i1, &Hexagon::PredRegsRegClass); // ddccbbaa
1530 addRegisterClass(MVT::v8i1, &Hexagon::PredRegsRegClass); // hgfedcba
1531 addRegisterClass(MVT::i32, &Hexagon::IntRegsRegClass);
1532 addRegisterClass(MVT::v2i16, &Hexagon::IntRegsRegClass);
1533 addRegisterClass(MVT::v4i8, &Hexagon::IntRegsRegClass);
1534 addRegisterClass(MVT::i64, &Hexagon::DoubleRegsRegClass);
1535 addRegisterClass(MVT::v8i8, &Hexagon::DoubleRegsRegClass);
1536 addRegisterClass(MVT::v4i16, &Hexagon::DoubleRegsRegClass);
1537 addRegisterClass(MVT::v2i32, &Hexagon::DoubleRegsRegClass);
1538
1539 addRegisterClass(MVT::f32, &Hexagon::IntRegsRegClass);
1540 addRegisterClass(MVT::f64, &Hexagon::DoubleRegsRegClass);
1541
1542 //
1543 // Handling of scalar operations.
1544 //
1545 // All operations default to "legal", except:
1546 // - indexed loads and stores (pre-/post-incremented),
1547 // - ANY_EXTEND_VECTOR_INREG, ATOMIC_CMP_SWAP_WITH_SUCCESS, CONCAT_VECTORS,
1548 // ConstantFP, FCEIL, FCOPYSIGN, FEXP, FEXP2, FFLOOR, FGETSIGN,
1549 // FLOG, FLOG2, FLOG10, FMAXIMUMNUM, FMINIMUMNUM, FNEARBYINT, FRINT, FROUND,
1550 // TRAP, FTRUNC, PREFETCH, SIGN_EXTEND_VECTOR_INREG,
1551 // ZERO_EXTEND_VECTOR_INREG,
1552 // which default to "expand" for at least one type.
1553
1554 // Misc operations.
1557 setOperationAction(ISD::TRAP, MVT::Other, Legal);
1574
1575 // Custom legalize GlobalAddress nodes into CONST32.
1579
1580 // Hexagon needs to optimize cases with negative constants.
1584 setOperationAction(ISD::SETCC, MVT::v2i16, Custom);
1585
1586 // VASTART needs to be custom lowered to use the VarArgsFrameIndex.
1588 setOperationAction(ISD::VAEND, MVT::Other, Expand);
1589 setOperationAction(ISD::VAARG, MVT::Other, Expand);
1590 if (Subtarget.isEnvironmentMusl())
1592 else
1594
1598
1599 if (EmitJumpTables)
1601 else
1602 setMinimumJumpTableEntries(std::numeric_limits<unsigned>::max());
1603 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
1604
1605 for (unsigned LegalIntOp :
1607 setOperationAction(LegalIntOp, MVT::i32, Legal);
1608 setOperationAction(LegalIntOp, MVT::i64, Legal);
1609 }
1610
1611 // Hexagon has A4_addp_c and A4_subp_c that take and generate a carry bit,
1612 // but they only operate on i64.
1613 for (MVT VT : MVT::integer_valuetypes()) {
1620 }
1623
1628
1629 // Popcount can count # of 1s in i64 but returns i32.
1634
1639
1644
1645 for (unsigned IntExpOp :
1650 for (MVT VT : MVT::integer_valuetypes())
1651 setOperationAction(IntExpOp, VT, Expand);
1652 }
1653 for (MVT VT : MVT::fp_valuetypes()) {
1654 for (unsigned FPExpOp : {ISD::FDIV, ISD::FSQRT, ISD::FSIN, ISD::FCOS,
1656 setOperationAction(FPExpOp, VT, Expand);
1657
1659 }
1660
1661 // No extending loads from i32.
1662 for (MVT VT : MVT::integer_valuetypes()) {
1663 setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i32, Expand);
1664 setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i32, Expand);
1665 setLoadExtAction(ISD::EXTLOAD, VT, MVT::i32, Expand);
1666 }
1667 // Turn FP truncstore into trunc + store.
1668 setTruncStoreAction(MVT::f64, MVT::f32, Expand);
1669 setTruncStoreAction(MVT::f32, MVT::bf16, Expand);
1670 setTruncStoreAction(MVT::f64, MVT::bf16, Expand);
1671 // Turn FP extload into load/fpextend.
1672 for (MVT VT : MVT::fp_valuetypes())
1673 setLoadExtAction(ISD::EXTLOAD, VT, MVT::f32, Expand);
1674
1675 // Expand BR_CC and SELECT_CC for all integer and fp types.
1676 for (MVT VT : MVT::integer_valuetypes()) {
1679 }
1680 for (MVT VT : MVT::fp_valuetypes()) {
1683 }
1684 setOperationAction(ISD::BR_CC, MVT::Other, Expand);
1685
1686 //
1687 // Handling of vector operations.
1688 //
1689
1690 // Set the action for vector operations to "expand", then override it with
1691 // either "custom" or "legal" for specific cases.
1692 // clang-format off
1693 static const unsigned VectExpOps[] = {
1694 // Integer arithmetic:
1698 // Logical/bit:
1701 // Floating point arithmetic/math functions:
1709 // Misc:
1711 // Vector:
1717 };
1718 // clang-format on
1719
1721 for (unsigned VectExpOp : VectExpOps)
1722 setOperationAction(VectExpOp, VT, Expand);
1723
1724 // Expand all extending loads and truncating stores:
1725 for (MVT TargetVT : MVT::fixedlen_vector_valuetypes()) {
1726 if (TargetVT == VT)
1727 continue;
1728 setLoadExtAction(ISD::EXTLOAD, TargetVT, VT, Expand);
1729 setLoadExtAction(ISD::ZEXTLOAD, TargetVT, VT, Expand);
1730 setLoadExtAction(ISD::SEXTLOAD, TargetVT, VT, Expand);
1731 setTruncStoreAction(VT, TargetVT, Expand);
1732 }
1733
1734 // Normalize all inputs to SELECT to be vectors of i32.
1735 if (VT.getVectorElementType() != MVT::i32) {
1736 MVT VT32 = MVT::getVectorVT(MVT::i32, VT.getSizeInBits()/32);
1738 AddPromotedToType(ISD::SELECT, VT, VT32);
1739 }
1743 }
1744
1747
1748 // Extending loads from (native) vectors of i8 into (native) vectors of i16
1749 // are legal.
1750 setLoadExtAction(ISD::EXTLOAD, MVT::v2i16, MVT::v2i8, Legal);
1751 setLoadExtAction(ISD::ZEXTLOAD, MVT::v2i16, MVT::v2i8, Legal);
1752 setLoadExtAction(ISD::SEXTLOAD, MVT::v2i16, MVT::v2i8, Legal);
1753 setLoadExtAction(ISD::EXTLOAD, MVT::v4i16, MVT::v4i8, Legal);
1754 setLoadExtAction(ISD::ZEXTLOAD, MVT::v4i16, MVT::v4i8, Legal);
1755 setLoadExtAction(ISD::SEXTLOAD, MVT::v4i16, MVT::v4i8, Legal);
1756
1760
1761 // Types natively supported:
1762 for (MVT NativeVT : {MVT::v8i1, MVT::v4i1, MVT::v2i1, MVT::v4i8,
1763 MVT::v8i8, MVT::v2i16, MVT::v4i16, MVT::v2i32}) {
1770
1771 setOperationAction(ISD::ADD, NativeVT, Legal);
1772 setOperationAction(ISD::SUB, NativeVT, Legal);
1773 setOperationAction(ISD::MUL, NativeVT, Legal);
1774 setOperationAction(ISD::AND, NativeVT, Legal);
1775 setOperationAction(ISD::OR, NativeVT, Legal);
1776 setOperationAction(ISD::XOR, NativeVT, Legal);
1777
1778 if (NativeVT.getVectorElementType() != MVT::i1) {
1782 }
1783 }
1784
1785 for (MVT VT : {MVT::v8i8, MVT::v4i16, MVT::v2i32}) {
1790 }
1791
1792 // Custom lower unaligned loads.
1793 // Also, for both loads and stores, verify the alignment of the address
1794 // in case it is a compile-time constant. This is a usability feature to
1795 // provide a meaningful error message to users.
1796 for (MVT VT : {MVT::i16, MVT::i32, MVT::v4i8, MVT::i64, MVT::v8i8,
1797 MVT::v2i16, MVT::v4i16, MVT::v2i32}) {
1800 }
1801
1802 // Custom-lower load/stores of boolean vectors.
1803 for (MVT VT : {MVT::v2i1, MVT::v4i1, MVT::v8i1}) {
1806 }
1807
1808 // Normalize integer compares to EQ/GT/UGT
1809 for (MVT VT : {MVT::v2i16, MVT::v4i8, MVT::v8i8, MVT::v2i32, MVT::v4i16,
1810 MVT::v2i32}) {
1818 }
1819
1820 // Normalize boolean compares to [U]LE/[U]LT
1821 for (MVT VT : {MVT::i1, MVT::v2i1, MVT::v4i1, MVT::v8i1}) {
1826 }
1827
1828 // Custom-lower bitcasts from i8 to v8i1.
1830 setOperationAction(ISD::SETCC, MVT::v2i16, Custom);
1836
1837 // V5+.
1843
1852
1865
1866 // Special handling for half-precision floating point conversions.
1867 // Lower half float conversions into library calls.
1875
1876 setLoadExtAction(ISD::EXTLOAD, MVT::f32, MVT::f16, Expand);
1877 setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f16, Expand);
1878 setLoadExtAction(ISD::EXTLOAD, MVT::f32, MVT::bf16, Expand);
1879 setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::bf16, Expand);
1880
1881 setTruncStoreAction(MVT::f32, MVT::f16, Expand);
1882 setTruncStoreAction(MVT::f64, MVT::f16, Expand);
1883
1884 // Handling of indexed loads/stores: default is "expand".
1885 //
1886 for (MVT VT : {MVT::i8, MVT::i16, MVT::i32, MVT::i64, MVT::f32, MVT::f64,
1887 MVT::v2i16, MVT::v2i32, MVT::v4i8, MVT::v4i16, MVT::v8i8}) {
1890 }
1891
1892 // Subtarget-specific operation actions.
1893 //
1894 if (Subtarget.hasV60Ops()) {
1899 }
1900 if (Subtarget.hasV66Ops()) {
1903 }
1904 if (Subtarget.hasV67Ops()) {
1910 }
1911
1915
1916 if (Subtarget.useHVXOps())
1917 initializeHVXLowering();
1918
1920}
1921
1922bool
1923HexagonTargetLowering::validateConstPtrAlignment(SDValue Ptr, Align NeedAlign,
1924 const SDLoc &dl, SelectionDAG &DAG) const {
1925 auto *CA = dyn_cast<ConstantSDNode>(Ptr);
1926 if (!CA)
1927 return true;
1928 unsigned Addr = CA->getZExtValue();
1929 Align HaveAlign =
1930 Addr != 0 ? Align::fromLog2(llvm::countr_zero(Addr)) : NeedAlign;
1931 if (HaveAlign >= NeedAlign)
1932 return true;
1933
1934 static int DK_MisalignedTrap = llvm::getNextAvailablePluginDiagnosticKind();
1935
1936 struct DiagnosticInfoMisalignedTrap : public DiagnosticInfo {
1937 DiagnosticInfoMisalignedTrap(StringRef M)
1938 : DiagnosticInfo(DK_MisalignedTrap, DS_Remark), Msg(M) {}
1939 void print(DiagnosticPrinter &DP) const override {
1940 DP << Msg;
1941 }
1942 static bool classof(const DiagnosticInfo *DI) {
1943 return DI->getKind() == DK_MisalignedTrap;
1944 }
1945 StringRef Msg;
1946 };
1947
1948 std::string ErrMsg;
1949 raw_string_ostream O(ErrMsg);
1950 O << "Misaligned constant address: " << format_hex(Addr, 10)
1951 << " has alignment " << HaveAlign.value()
1952 << ", but the memory access requires " << NeedAlign.value();
1953 if (DebugLoc DL = dl.getDebugLoc())
1954 DL.print(O << ", at ");
1955 O << ". The instruction has been replaced with a trap.";
1956
1957 DAG.getContext()->diagnose(DiagnosticInfoMisalignedTrap(O.str()));
1958 return false;
1959}
1960
1961SDValue
1962HexagonTargetLowering::replaceMemWithUndef(SDValue Op, SelectionDAG &DAG)
1963 const {
1964 const SDLoc &dl(Op);
1965 auto *LS = cast<LSBaseSDNode>(Op.getNode());
1966 assert(!LS->isIndexed() && "Not expecting indexed ops on constant address");
1967
1968 SDValue Chain = LS->getChain();
1969 SDValue Trap = DAG.getNode(ISD::TRAP, dl, MVT::Other, Chain);
1970 if (LS->getOpcode() == ISD::LOAD)
1971 return DAG.getMergeValues({DAG.getUNDEF(ty(Op)), Trap}, dl);
1972 return Trap;
1973}
1974
1975// Bit-reverse Load Intrinsic: Check if the instruction is a bit reverse load
1976// intrinsic.
1977static bool isBrevLdIntrinsic(const Value *Inst) {
1978 unsigned ID = cast<IntrinsicInst>(Inst)->getIntrinsicID();
1979 return (ID == Intrinsic::hexagon_L2_loadrd_pbr ||
1980 ID == Intrinsic::hexagon_L2_loadri_pbr ||
1981 ID == Intrinsic::hexagon_L2_loadrh_pbr ||
1982 ID == Intrinsic::hexagon_L2_loadruh_pbr ||
1983 ID == Intrinsic::hexagon_L2_loadrb_pbr ||
1984 ID == Intrinsic::hexagon_L2_loadrub_pbr);
1985}
1986
1987// Bit-reverse Load Intrinsic :Crawl up and figure out the object from previous
1988// instruction. So far we only handle bitcast, extract value and bit reverse
1989// load intrinsic instructions. Should we handle CGEP ?
1991 if (Operator::getOpcode(V) == Instruction::ExtractValue ||
1992 Operator::getOpcode(V) == Instruction::BitCast)
1993 V = cast<Operator>(V)->getOperand(0);
1994 else if (isa<IntrinsicInst>(V) && isBrevLdIntrinsic(V))
1995 V = cast<Instruction>(V)->getOperand(0);
1996 return V;
1997}
1998
1999// Bit-reverse Load Intrinsic: For a PHI Node return either an incoming edge or
2000// a back edge. If the back edge comes from the intrinsic itself, the incoming
2001// edge is returned.
2002static Value *returnEdge(const PHINode *PN, Value *IntrBaseVal) {
2003 const BasicBlock *Parent = PN->getParent();
2004 int Idx = -1;
2005 for (unsigned i = 0, e = PN->getNumIncomingValues(); i < e; ++i) {
2006 BasicBlock *Blk = PN->getIncomingBlock(i);
2007 // Determine if the back edge is originated from intrinsic.
2008 if (Blk == Parent) {
2009 Value *BackEdgeVal = PN->getIncomingValue(i);
2010 Value *BaseVal;
2011 // Loop over till we return the same Value or we hit the IntrBaseVal.
2012 do {
2013 BaseVal = BackEdgeVal;
2014 BackEdgeVal = getBrevLdObject(BackEdgeVal);
2015 } while ((BaseVal != BackEdgeVal) && (IntrBaseVal != BackEdgeVal));
2016 // If the getBrevLdObject returns IntrBaseVal, we should return the
2017 // incoming edge.
2018 if (IntrBaseVal == BackEdgeVal)
2019 continue;
2020 Idx = i;
2021 break;
2022 } else // Set the node to incoming edge.
2023 Idx = i;
2024 }
2025 assert(Idx >= 0 && "Unexpected index to incoming argument in PHI");
2026 return PN->getIncomingValue(Idx);
2027}
2028
2029// Bit-reverse Load Intrinsic: Figure out the underlying object the base
2030// pointer points to, for the bit-reverse load intrinsic. Setting this to
2031// memoperand might help alias analysis to figure out the dependencies.
2032// A bit-reverse load accesses the base pointer with its low 16 bits reversed,
2033// and post-increments the base pointer by the modifier value. For a chain of
2034// bit-reverse loads, the offset that a load accesses relative to the
2035// underlying object is the bit-reverse of the sum of the modifiers of the
2036// preceding loads in the chain. Offset is set to that value, and HasOffset is
2037// set to true, when the sum is known, that is when all of those modifiers are
2038// constants and the sum fits in 16 unsigned bits. Otherwise HasOffset is set
2039// to false and Offset is left unchanged.
2041 bool &HasOffset) {
2042 Value *IntrBaseVal = V;
2043 Value *BaseVal;
2044 int64_t Sum = 0;
2045 HasOffset = true;
2046 // Loop over till we return the same Value, implies we either figure out
2047 // the object or we hit a PHI
2048 do {
2049 BaseVal = V;
2050 V = getBrevLdObject(V);
2051 // Identify if this is part of a chain of bit-reverse loads, and accumulate
2052 // the modifier of the preceding load in the chain.
2053 if (HasOffset && BaseVal != V && isa<IntrinsicInst>(V) &&
2054 isBrevLdIntrinsic(V)) {
2055 Value *Modifier = cast<IntrinsicInst>(V)->getOperand(1);
2056 if (auto *CN = dyn_cast<ConstantInt>(Modifier))
2057 Sum += CN->getSExtValue();
2058 else
2059 HasOffset = false;
2060 }
2061 } while (BaseVal != V);
2062
2063 // Only the low 16 bits of the base pointer take part in the bit-reverse. A
2064 // sum that does not fit in them would also change the remaining bits.
2065 if (HasOffset && Sum >= 0 && isUInt<16>(Sum))
2066 Offset = APInt(16, Sum).reverseBits().getZExtValue();
2067 else
2068 HasOffset = false;
2069
2070 // Identify the object from PHINode.
2071 if (const PHINode *PN = dyn_cast<PHINode>(V))
2072 return returnEdge(PN, IntrBaseVal);
2073 // For non PHI nodes, the object is the last value returned by getBrevLdObject
2074 else
2075 return V;
2076}
2077
2078/// Given an intrinsic, checks if on the target the intrinsic will need to map
2079/// to a MemIntrinsicNode (touches memory). If this is the case, it stores
2080/// the intrinsic information into the Infos vector.
2083 MachineFunction &MF, unsigned Intrinsic) const {
2084 IntrinsicInfo Info;
2085 switch (Intrinsic) {
2086 case Intrinsic::hexagon_L2_loadrd_pbr:
2087 case Intrinsic::hexagon_L2_loadri_pbr:
2088 case Intrinsic::hexagon_L2_loadrh_pbr:
2089 case Intrinsic::hexagon_L2_loadruh_pbr:
2090 case Intrinsic::hexagon_L2_loadrb_pbr:
2091 case Intrinsic::hexagon_L2_loadrub_pbr: {
2092 Info.opc = ISD::INTRINSIC_W_CHAIN;
2093 auto &DL = I.getDataLayout();
2094 auto &Cont = I.getCalledFunction()->getParent()->getContext();
2095 // The intrinsic function call is of the form { ElTy, i8* }
2096 // @llvm.hexagon.L2.loadXX.pbr(i8*, i32). The pointer and memory access type
2097 // should be derived from ElTy.
2098 Type *ElTy = I.getCalledFunction()->getReturnType()->getStructElementType(0);
2099 Info.memVT = MVT::getVT(ElTy);
2100 llvm::Value *BasePtrVal = I.getOperand(0);
2101 // The offset value comes through the Modifier register. Determine the
2102 // offset that is going to be accessed relative to the underlying object.
2103 // If it cannot be determined, leave the pointer information out of the
2104 // memory operand, so that alias analysis stays conservative.
2105 bool HasOffset = false;
2106 Info.offset = 0;
2107 Value *UnderlyingObj =
2108 getUnderLyingObjectForBrevLdIntr(BasePtrVal, Info.offset, HasOffset);
2109 // The underlying object is unknown if the base pointer could not be traced
2110 // back to a pointer value. Also, unless the object is aligned to 64K, the
2111 // low 16 bits of the base pointer are not known, and reversing them can
2112 // produce an address anywhere in the surrounding 64K region, possibly
2113 // outside of the object.
2114 if (!UnderlyingObj->getType()->isPointerTy() ||
2115 UnderlyingObj->getPointerAlignment(DL) < Align(65536))
2116 HasOffset = false;
2117 if (HasOffset)
2118 Info.ptrVal = UnderlyingObj;
2119 Info.align = DL.getABITypeAlign(Info.memVT.getTypeForEVT(Cont));
2120 Info.flags = MachineMemOperand::MOLoad;
2121 Infos.push_back(Info);
2122 return;
2123 }
2124 case Intrinsic::hexagon_V6_vgathermw:
2125 case Intrinsic::hexagon_V6_vgathermw_128B:
2126 case Intrinsic::hexagon_V6_vgathermh:
2127 case Intrinsic::hexagon_V6_vgathermh_128B:
2128 case Intrinsic::hexagon_V6_vgathermhw:
2129 case Intrinsic::hexagon_V6_vgathermhw_128B:
2130 case Intrinsic::hexagon_V6_vgathermwq:
2131 case Intrinsic::hexagon_V6_vgathermwq_128B:
2132 case Intrinsic::hexagon_V6_vgathermhq:
2133 case Intrinsic::hexagon_V6_vgathermhq_128B:
2134 case Intrinsic::hexagon_V6_vgathermhwq:
2135 case Intrinsic::hexagon_V6_vgathermhwq_128B:
2136 case Intrinsic::hexagon_V6_vgather_vscattermh:
2137 case Intrinsic::hexagon_V6_vgather_vscattermh_128B: {
2138 const Module &M = *I.getParent()->getParent()->getParent();
2139 Info.opc = ISD::INTRINSIC_W_CHAIN;
2140 Type *VecTy = I.getArgOperand(I.arg_size() - 1)->getType();
2141 assert(VecTy->isVectorTy() && "Expected vector operand for vgather");
2142 Info.memVT = MVT::getVT(VecTy);
2143 Info.ptrVal = I.getArgOperand(0);
2144 Info.offset = 0;
2145 Info.align =
2146 MaybeAlign(M.getDataLayout().getTypeAllocSizeInBits(VecTy) / 8);
2149 Infos.push_back(Info);
2150 return;
2151 }
2152 default:
2153 break;
2154 }
2155}
2156
2158 return X.getValueType().isScalarInteger(); // 'tstbit'
2159}
2160
2162 return isTruncateFree(EVT::getEVT(Ty1), EVT::getEVT(Ty2));
2163}
2164
2166 if (!VT1.isSimple() || !VT2.isSimple())
2167 return false;
2168 return VT1.getSimpleVT() == MVT::i64 && VT2.getSimpleVT() == MVT::i32;
2169}
2170
2175
2176// Should we expand the build vector with shuffles?
2178 unsigned DefinedValues) const {
2179 return false;
2180}
2181
2184 unsigned Index) const {
2186 if (!ResVT.isSimple() || !SrcVT.isSimple())
2188
2189 MVT ResTy = ResVT.getSimpleVT(), SrcTy = SrcVT.getSimpleVT();
2190 if (ResTy.getVectorElementType() != MVT::i1)
2192
2193 // Non-HVX bool vectors are relatively cheap.
2194 if (SrcTy.getVectorNumElements() <= 8)
2197}
2198
2203
2205 EVT VT) const {
2206 return true;
2207}
2208
2211 unsigned VecLen = VT.getVectorMinNumElements();
2213
2214 if (VecLen == 1 || VT.isScalableVector())
2216
2217 if (Subtarget.useHVXOps()) {
2218 unsigned Action = getPreferredHvxVectorAction(VT);
2219 if (Action != ~0u)
2220 return static_cast<TargetLoweringBase::LegalizeTypeAction>(Action);
2221 }
2222
2223 // Always widen (remaining) vectors of i1.
2224 if (ElemTy == MVT::i1)
2226 // Widen non-power-of-2 vectors. Such types cannot be split right now,
2227 // and computeRegisterProperties will override "split" with "widen",
2228 // which can cause other issues.
2229 if (!isPowerOf2_32(VecLen))
2231
2233}
2234
2237 if (Subtarget.useHVXOps()) {
2238 unsigned Action = getCustomHvxOperationAction(Op);
2239 if (Action != ~0u)
2240 return static_cast<TargetLoweringBase::LegalizeAction>(Action);
2241 }
2243}
2244
2245std::pair<SDValue, int>
2246HexagonTargetLowering::getBaseAndOffset(SDValue Addr) const {
2247 if (Addr.getOpcode() == ISD::ADD) {
2248 SDValue Op1 = Addr.getOperand(1);
2249 if (auto *CN = dyn_cast<const ConstantSDNode>(Op1.getNode()))
2250 return { Addr.getOperand(0), CN->getSExtValue() };
2251 }
2252 return { Addr, 0 };
2253}
2254
2255// Lower a vector shuffle (V1, V2, V3). V1 and V2 are the two vectors
2256// to select data from, V3 is the permutation.
2257SDValue
2259 const {
2260 const auto *SVN = cast<ShuffleVectorSDNode>(Op);
2261 ArrayRef<int> AM = SVN->getMask();
2262 assert(AM.size() <= 8 && "Unexpected shuffle mask");
2263 unsigned VecLen = AM.size();
2264
2265 MVT VecTy = ty(Op);
2266 assert(!Subtarget.isHVXVectorType(VecTy, true) &&
2267 "HVX shuffles should be legal");
2268 assert(VecTy.getSizeInBits() <= 64 && "Unexpected vector length");
2269
2270 SDValue Op0 = Op.getOperand(0);
2271 SDValue Op1 = Op.getOperand(1);
2272 const SDLoc &dl(Op);
2273
2274 // If the inputs are not the same as the output, bail. This is not an
2275 // error situation, but complicates the handling and the default expansion
2276 // (into BUILD_VECTOR) should be adequate.
2277 if (ty(Op0) != VecTy || ty(Op1) != VecTy)
2278 return SDValue();
2279
2280 // Normalize the mask so that the first non-negative index comes from
2281 // the first operand.
2282 SmallVector<int, 8> Mask(AM);
2283 unsigned F = llvm::find_if(AM, [](int M) { return M >= 0; }) - AM.data();
2284 if (F == AM.size())
2285 return DAG.getUNDEF(VecTy);
2286 if (AM[F] >= int(VecLen)) {
2288 std::swap(Op0, Op1);
2289 }
2290
2291 // Express the shuffle mask in terms of bytes.
2292 SmallVector<int,8> ByteMask;
2293 unsigned ElemBytes = VecTy.getVectorElementType().getSizeInBits() / 8;
2294 for (int M : Mask) {
2295 if (M < 0) {
2296 for (unsigned j = 0; j != ElemBytes; ++j)
2297 ByteMask.push_back(-1);
2298 } else {
2299 for (unsigned j = 0; j != ElemBytes; ++j)
2300 ByteMask.push_back(M*ElemBytes + j);
2301 }
2302 }
2303 assert(ByteMask.size() <= 8);
2304
2305 // All non-undef (non-negative) indexes are well within [0..127], so they
2306 // fit in a single byte. Build two 64-bit words:
2307 // - MaskIdx where each byte is the corresponding index (for non-negative
2308 // indexes), and 0xFF for negative indexes, and
2309 // - MaskUnd that has 0xFF for each negative index.
2310 uint64_t MaskIdx = 0;
2311 uint64_t MaskUnd = 0;
2312 for (unsigned i = 0, e = ByteMask.size(); i != e; ++i) {
2313 unsigned S = 8*i;
2314 uint64_t M = ByteMask[i] & 0xFF;
2315 if (M == 0xFF)
2316 MaskUnd |= M << S;
2317 MaskIdx |= M << S;
2318 }
2319
2320 if (ByteMask.size() == 4) {
2321 // Identity.
2322 if (MaskIdx == (0x03020100 | MaskUnd))
2323 return Op0;
2324 // Byte swap.
2325 if (MaskIdx == (0x00010203 | MaskUnd)) {
2326 SDValue T0 = DAG.getBitcast(MVT::i32, Op0);
2327 SDValue T1 = DAG.getNode(ISD::BSWAP, dl, MVT::i32, T0);
2328 return DAG.getBitcast(VecTy, T1);
2329 }
2330
2331 // Byte packs.
2332 SDValue Concat10 =
2333 getCombine(Op1, Op0, dl, typeJoin({ty(Op1), ty(Op0)}), DAG);
2334 if (MaskIdx == (0x06040200 | MaskUnd))
2335 return getInstr(Hexagon::S2_vtrunehb, dl, VecTy, {Concat10}, DAG);
2336 if (MaskIdx == (0x07050301 | MaskUnd))
2337 return getInstr(Hexagon::S2_vtrunohb, dl, VecTy, {Concat10}, DAG);
2338
2339 SDValue Concat01 =
2340 getCombine(Op0, Op1, dl, typeJoin({ty(Op0), ty(Op1)}), DAG);
2341 if (MaskIdx == (0x02000604 | MaskUnd))
2342 return getInstr(Hexagon::S2_vtrunehb, dl, VecTy, {Concat01}, DAG);
2343 if (MaskIdx == (0x03010705 | MaskUnd))
2344 return getInstr(Hexagon::S2_vtrunohb, dl, VecTy, {Concat01}, DAG);
2345 }
2346
2347 if (ByteMask.size() == 8) {
2348 // Identity.
2349 if (MaskIdx == (0x0706050403020100ull | MaskUnd))
2350 return Op0;
2351 // Byte swap.
2352 if (MaskIdx == (0x0001020304050607ull | MaskUnd)) {
2353 SDValue T0 = DAG.getBitcast(MVT::i64, Op0);
2354 SDValue T1 = DAG.getNode(ISD::BSWAP, dl, MVT::i64, T0);
2355 return DAG.getBitcast(VecTy, T1);
2356 }
2357
2358 // Halfword picks.
2359 if (MaskIdx == (0x0d0c050409080100ull | MaskUnd))
2360 return getInstr(Hexagon::S2_shuffeh, dl, VecTy, {Op1, Op0}, DAG);
2361 if (MaskIdx == (0x0f0e07060b0a0302ull | MaskUnd))
2362 return getInstr(Hexagon::S2_shuffoh, dl, VecTy, {Op1, Op0}, DAG);
2363 if (MaskIdx == (0x0d0c090805040100ull | MaskUnd))
2364 return getInstr(Hexagon::S2_vtrunewh, dl, VecTy, {Op1, Op0}, DAG);
2365 if (MaskIdx == (0x0f0e0b0a07060302ull | MaskUnd))
2366 return getInstr(Hexagon::S2_vtrunowh, dl, VecTy, {Op1, Op0}, DAG);
2367 if (MaskIdx == (0x0706030205040100ull | MaskUnd)) {
2368 VectorPair P = opSplit(Op0, dl, DAG);
2369 return getInstr(Hexagon::S2_packhl, dl, VecTy, {P.second, P.first}, DAG);
2370 }
2371
2372 // Byte packs.
2373 if (MaskIdx == (0x0e060c040a020800ull | MaskUnd))
2374 return getInstr(Hexagon::S2_shuffeb, dl, VecTy, {Op1, Op0}, DAG);
2375 if (MaskIdx == (0x0f070d050b030901ull | MaskUnd))
2376 return getInstr(Hexagon::S2_shuffob, dl, VecTy, {Op1, Op0}, DAG);
2377 }
2378
2379 return SDValue();
2380}
2381
2382SDValue
2383HexagonTargetLowering::getSplatValue(SDValue Op, SelectionDAG &DAG) const {
2384 switch (Op.getOpcode()) {
2385 case ISD::BUILD_VECTOR:
2387 return S;
2388 break;
2389 case ISD::SPLAT_VECTOR:
2390 return Op.getOperand(0);
2391 }
2392 return SDValue();
2393}
2394
2395// Create a Hexagon-specific node for shifting a vector by an integer.
2396SDValue
2397HexagonTargetLowering::getVectorShiftByInt(SDValue Op, SelectionDAG &DAG)
2398 const {
2399 unsigned NewOpc;
2400 switch (Op.getOpcode()) {
2401 case ISD::SHL:
2402 NewOpc = HexagonISD::VASL;
2403 break;
2404 case ISD::SRA:
2405 NewOpc = HexagonISD::VASR;
2406 break;
2407 case ISD::SRL:
2408 NewOpc = HexagonISD::VLSR;
2409 break;
2410 default:
2411 llvm_unreachable("Unexpected shift opcode");
2412 }
2413 if (SDValue Sp = getSplatValue(Op.getOperand(1), DAG)) {
2414 const SDLoc dl(Op);
2415 // Canonicalize shift amount to i32 as required.
2416 SDValue Sh = Sp;
2417 if (Sh.getValueType() != MVT::i32)
2418 Sh = DAG.getZExtOrTrunc(Sh, dl, MVT::i32);
2419
2420 assert(Sh.getValueType() == MVT::i32 &&
2421 "Hexagon vector shift-by-int must use i32 shift operand");
2422 return DAG.getNode(NewOpc, dl, ty(Op), Op.getOperand(0), Sh);
2423 }
2424
2425 return SDValue();
2426}
2427
2428SDValue
2430 const SDLoc &dl(Op);
2431
2432 // First try to convert the shift (by vector) to a shift by a scalar.
2433 // If we first split the shift, the shift amount will become 'extract
2434 // subvector', and will no longer be recognized as scalar.
2435 SDValue Res = Op;
2436 if (SDValue S = getVectorShiftByInt(Op, DAG))
2437 Res = S;
2438
2439 unsigned Opc = Res.getOpcode();
2440 switch (Opc) {
2441 case HexagonISD::VASR:
2442 case HexagonISD::VLSR:
2443 case HexagonISD::VASL:
2444 break;
2445 default:
2446 // No instructions for shifts by non-scalars.
2447 return SDValue();
2448 }
2449
2450 MVT ResTy = ty(Res);
2451 if (ResTy.getVectorElementType() != MVT::i8)
2452 return Res;
2453
2454 // For shifts of i8, extend the inputs to i16, then truncate back to i8.
2455 assert(ResTy.getVectorElementType() == MVT::i8);
2456 SDValue Val = Res.getOperand(0), Amt = Res.getOperand(1);
2457
2458 auto ShiftPartI8 = [&dl, &DAG, this](unsigned Opc, SDValue V, SDValue A) {
2459 MVT Ty = ty(V);
2460 MVT ExtTy = MVT::getVectorVT(MVT::i16, Ty.getVectorNumElements());
2461 SDValue ExtV = Opc == HexagonISD::VASR ? DAG.getSExtOrTrunc(V, dl, ExtTy)
2462 : DAG.getZExtOrTrunc(V, dl, ExtTy);
2463 SDValue ExtS = DAG.getNode(Opc, dl, ExtTy, {ExtV, A});
2464 return DAG.getZExtOrTrunc(ExtS, dl, Ty);
2465 };
2466
2467 if (ResTy.getSizeInBits() == 32)
2468 return ShiftPartI8(Opc, Val, Amt);
2469
2470 auto [LoV, HiV] = opSplit(Val, dl, DAG);
2471 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResTy,
2472 {ShiftPartI8(Opc, LoV, Amt), ShiftPartI8(Opc, HiV, Amt)});
2473}
2474
2475SDValue
2477 if (isa<ConstantSDNode>(Op.getOperand(1).getNode()))
2478 return Op;
2479 return SDValue();
2480}
2481
2482SDValue
2484 MVT ResTy = ty(Op);
2485 SDValue InpV = Op.getOperand(0);
2486 MVT InpTy = ty(InpV);
2487 assert(ResTy.getSizeInBits() == InpTy.getSizeInBits());
2488 const SDLoc &dl(Op);
2489
2490 // Handle conversion from i8 to v8i1.
2491 if (InpTy == MVT::i8) {
2492 if (ResTy == MVT::v8i1) {
2493 SDValue Sc = DAG.getBitcast(tyScalar(InpTy), InpV);
2494 SDValue Ext = DAG.getZExtOrTrunc(Sc, dl, MVT::i32);
2495 return getInstr(Hexagon::C2_tfrrp, dl, ResTy, Ext, DAG);
2496 }
2497 return SDValue();
2498 }
2499
2500 return Op;
2501}
2502
2503bool
2504HexagonTargetLowering::getBuildVectorConstInts(ArrayRef<SDValue> Values,
2505 MVT VecTy, SelectionDAG &DAG,
2506 MutableArrayRef<ConstantInt*> Consts) const {
2508 unsigned ElemWidth = ElemTy.getSizeInBits();
2509 IntegerType *IntTy = IntegerType::get(*DAG.getContext(), ElemWidth);
2510 bool AllConst = true;
2511
2512 for (unsigned i = 0, e = Values.size(); i != e; ++i) {
2513 SDValue V = Values[i];
2514 if (V.isUndef()) {
2515 Consts[i] = ConstantInt::get(IntTy, 0);
2516 continue;
2517 }
2518 // Make sure to always cast to IntTy.
2519 if (auto *CN = dyn_cast<ConstantSDNode>(V.getNode())) {
2520 const ConstantInt *CI = CN->getConstantIntValue();
2521 Consts[i] = cast<ConstantInt>(
2522 ConstantInt::get(IntTy, CI->getValue().trunc(ElemWidth)));
2523 } else if (auto *CN = dyn_cast<ConstantFPSDNode>(V.getNode())) {
2524 const ConstantFP *CF = CN->getConstantFPValue();
2525 APInt A = CF->getValueAPF().bitcastToAPInt();
2526 Consts[i] = ConstantInt::get(IntTy, A.getZExtValue());
2527 } else {
2528 AllConst = false;
2529 }
2530 }
2531 return AllConst;
2532}
2533
2534SDValue
2535HexagonTargetLowering::buildVector32(ArrayRef<SDValue> Elem, const SDLoc &dl,
2536 MVT VecTy, SelectionDAG &DAG) const {
2537 MVT ElemTy = VecTy.getVectorElementType();
2538 assert(VecTy.getVectorNumElements() == Elem.size());
2539
2540 SmallVector<ConstantInt*,4> Consts(Elem.size());
2541 bool AllConst = getBuildVectorConstInts(Elem, VecTy, DAG, Consts);
2542
2543 unsigned First, Num = Elem.size();
2544 for (First = 0; First != Num; ++First) {
2545 if (!isUndef(Elem[First]))
2546 break;
2547 }
2548 if (First == Num)
2549 return DAG.getUNDEF(VecTy);
2550
2551 if (AllConst &&
2552 llvm::all_of(Consts, [](ConstantInt *CI) { return CI->isZero(); }))
2553 return getZero(dl, VecTy, DAG);
2554
2555 if (ElemTy == MVT::i16 || ElemTy == MVT::f16) {
2556 assert(Elem.size() == 2);
2557 if (AllConst) {
2558 // The 'Consts' array will have all values as integers regardless
2559 // of the vector element type.
2560 uint32_t V = (Consts[0]->getZExtValue() & 0xFFFF) |
2561 Consts[1]->getZExtValue() << 16;
2562 return DAG.getBitcast(VecTy, DAG.getConstant(V, dl, MVT::i32));
2563 }
2564 SDValue E0, E1;
2565 if (ElemTy == MVT::f16) {
2566 E0 = DAG.getZExtOrTrunc(DAG.getBitcast(MVT::i16, Elem[0]), dl, MVT::i32);
2567 E1 = DAG.getZExtOrTrunc(DAG.getBitcast(MVT::i16, Elem[1]), dl, MVT::i32);
2568 } else {
2569 E0 = Elem[0];
2570 E1 = Elem[1];
2571 }
2572 SDValue N = getInstr(Hexagon::A2_combine_ll, dl, MVT::i32, {E1, E0}, DAG);
2573 return DAG.getBitcast(VecTy, N);
2574 }
2575
2576 if (ElemTy == MVT::i8) {
2577 // First try generating a constant.
2578 if (AllConst) {
2579 uint32_t V = (Consts[0]->getZExtValue() & 0xFF) |
2580 (Consts[1]->getZExtValue() & 0xFF) << 8 |
2581 (Consts[2]->getZExtValue() & 0xFF) << 16 |
2582 Consts[3]->getZExtValue() << 24;
2583 return DAG.getBitcast(MVT::v4i8, DAG.getConstant(V, dl, MVT::i32));
2584 }
2585
2586 // Then try splat.
2587 bool IsSplat = true;
2588 for (unsigned i = First+1; i != Num; ++i) {
2589 if (Elem[i] == Elem[First] || isUndef(Elem[i]))
2590 continue;
2591 IsSplat = false;
2592 break;
2593 }
2594 if (IsSplat) {
2595 // Legalize the operand of SPLAT_VECTOR.
2596 SDValue Ext = DAG.getZExtOrTrunc(Elem[First], dl, MVT::i32);
2597 return DAG.getNode(ISD::SPLAT_VECTOR, dl, VecTy, Ext);
2598 }
2599
2600 // Generate
2601 // (zxtb(Elem[0]) | (zxtb(Elem[1]) << 8)) |
2602 // (zxtb(Elem[2]) | (zxtb(Elem[3]) << 8)) << 16
2603 assert(Elem.size() == 4);
2604 SDValue Vs[4];
2605 for (unsigned i = 0; i != 4; ++i) {
2606 Vs[i] = DAG.getZExtOrTrunc(Elem[i], dl, MVT::i32);
2607 Vs[i] = DAG.getZeroExtendInReg(Vs[i], dl, MVT::i8);
2608 }
2609 SDValue S8 = DAG.getConstant(8, dl, MVT::i32);
2610 SDValue T0 = DAG.getNode(ISD::SHL, dl, MVT::i32, {Vs[1], S8});
2611 SDValue T1 = DAG.getNode(ISD::SHL, dl, MVT::i32, {Vs[3], S8});
2612 SDValue B0 = DAG.getNode(ISD::OR, dl, MVT::i32, {Vs[0], T0});
2613 SDValue B1 = DAG.getNode(ISD::OR, dl, MVT::i32, {Vs[2], T1});
2614
2615 SDValue R = getInstr(Hexagon::A2_combine_ll, dl, MVT::i32, {B1, B0}, DAG);
2616 return DAG.getBitcast(MVT::v4i8, R);
2617 }
2618
2619#ifndef NDEBUG
2620 dbgs() << "VecTy: " << VecTy << '\n';
2621#endif
2622 llvm_unreachable("Unexpected vector element type");
2623}
2624
2625SDValue
2626HexagonTargetLowering::buildVector64(ArrayRef<SDValue> Elem, const SDLoc &dl,
2627 MVT VecTy, SelectionDAG &DAG) const {
2628 MVT ElemTy = VecTy.getVectorElementType();
2629 assert(VecTy.getVectorNumElements() == Elem.size());
2630
2631 SmallVector<ConstantInt*,8> Consts(Elem.size());
2632 bool AllConst = getBuildVectorConstInts(Elem, VecTy, DAG, Consts);
2633
2634 unsigned First, Num = Elem.size();
2635 for (First = 0; First != Num; ++First) {
2636 if (!isUndef(Elem[First]))
2637 break;
2638 }
2639 if (First == Num)
2640 return DAG.getUNDEF(VecTy);
2641
2642 if (AllConst &&
2643 llvm::all_of(Consts, [](ConstantInt *CI) { return CI->isZero(); }))
2644 return getZero(dl, VecTy, DAG);
2645
2646 // First try splat if possible.
2647 if (ElemTy == MVT::i16 || ElemTy == MVT::f16) {
2648 bool IsSplat = true;
2649 for (unsigned i = First+1; i != Num; ++i) {
2650 if (Elem[i] == Elem[First] || isUndef(Elem[i]))
2651 continue;
2652 IsSplat = false;
2653 break;
2654 }
2655 if (IsSplat) {
2656 // Legalize the operand of SPLAT_VECTOR
2657 SDValue S = ElemTy == MVT::f16 ? DAG.getBitcast(MVT::i16, Elem[First])
2658 : Elem[First];
2659 SDValue Ext = DAG.getZExtOrTrunc(S, dl, MVT::i32);
2660 return DAG.getNode(ISD::SPLAT_VECTOR, dl, VecTy, Ext);
2661 }
2662 }
2663
2664 // Then try constant.
2665 if (AllConst) {
2666 uint64_t Val = 0;
2667 unsigned W = ElemTy.getSizeInBits();
2668 uint64_t Mask = (1ull << W) - 1;
2669 for (unsigned i = 0; i != Num; ++i)
2670 Val = (Val << W) | (Consts[Num-1-i]->getZExtValue() & Mask);
2671 SDValue V0 = DAG.getConstant(Val, dl, MVT::i64);
2672 return DAG.getBitcast(VecTy, V0);
2673 }
2674
2675 // Build two 32-bit vectors and concatenate.
2676 MVT HalfTy = MVT::getVectorVT(ElemTy, Num/2);
2677 SDValue L = (ElemTy == MVT::i32)
2678 ? Elem[0]
2679 : buildVector32(Elem.take_front(Num/2), dl, HalfTy, DAG);
2680 SDValue H = (ElemTy == MVT::i32)
2681 ? Elem[1]
2682 : buildVector32(Elem.drop_front(Num/2), dl, HalfTy, DAG);
2683 return getCombine(H, L, dl, VecTy, DAG);
2684}
2685
2686SDValue
2687HexagonTargetLowering::extractVector(SDValue VecV, SDValue IdxV,
2688 const SDLoc &dl, MVT ValTy, MVT ResTy,
2689 SelectionDAG &DAG) const {
2690 MVT VecTy = ty(VecV);
2691 assert(!ValTy.isVector() ||
2692 VecTy.getVectorElementType() == ValTy.getVectorElementType());
2693 if (VecTy.getVectorElementType() == MVT::i1)
2694 return extractVectorPred(VecV, IdxV, dl, ValTy, ResTy, DAG);
2695
2696 unsigned VecWidth = VecTy.getSizeInBits();
2697 unsigned ValWidth = ValTy.getSizeInBits();
2698 unsigned ElemWidth = VecTy.getVectorElementType().getSizeInBits();
2699 assert((VecWidth % ElemWidth) == 0);
2700 assert(VecWidth == 32 || VecWidth == 64);
2701
2702 // Cast everything to scalar integer types.
2703 MVT ScalarTy = tyScalar(VecTy);
2704 VecV = DAG.getBitcast(ScalarTy, VecV);
2705
2706 SDValue WidthV = DAG.getConstant(ValWidth, dl, MVT::i32);
2707 SDValue ExtV;
2708
2709 if (auto *IdxN = dyn_cast<ConstantSDNode>(IdxV)) {
2710 unsigned Off = IdxN->getZExtValue() * ElemWidth;
2711 if (VecWidth == 64 && ValWidth == 32) {
2712 assert(Off == 0 || Off == 32);
2713 ExtV = Off == 0 ? LoHalf(VecV, DAG) : HiHalf(VecV, DAG);
2714 } else if (Off == 0 && (ValWidth % 8) == 0) {
2715 ExtV = DAG.getZeroExtendInReg(VecV, dl, tyScalar(ValTy));
2716 } else {
2717 SDValue OffV = DAG.getConstant(Off, dl, MVT::i32);
2718 // The return type of EXTRACTU must be the same as the type of the
2719 // input vector.
2720 ExtV = DAG.getNode(HexagonISD::EXTRACTU, dl, ScalarTy,
2721 {VecV, WidthV, OffV});
2722 }
2723 } else {
2724 if (ty(IdxV) != MVT::i32)
2725 IdxV = DAG.getZExtOrTrunc(IdxV, dl, MVT::i32);
2726 SDValue OffV = DAG.getNode(ISD::MUL, dl, MVT::i32, IdxV,
2727 DAG.getConstant(ElemWidth, dl, MVT::i32));
2728 ExtV = DAG.getNode(HexagonISD::EXTRACTU, dl, ScalarTy,
2729 {VecV, WidthV, OffV});
2730 }
2731
2732 // Cast ExtV to the requested result type.
2733 ExtV = DAG.getZExtOrTrunc(ExtV, dl, tyScalar(ResTy));
2734 ExtV = DAG.getBitcast(ResTy, ExtV);
2735 return ExtV;
2736}
2737
2738SDValue
2739HexagonTargetLowering::extractVectorPred(SDValue VecV, SDValue IdxV,
2740 const SDLoc &dl, MVT ValTy, MVT ResTy,
2741 SelectionDAG &DAG) const {
2742 // Special case for v{8,4,2}i1 (the only boolean vectors legal in Hexagon
2743 // without any coprocessors).
2744 MVT VecTy = ty(VecV);
2745 unsigned VecWidth = VecTy.getSizeInBits();
2746 unsigned ValWidth = ValTy.getSizeInBits();
2747 assert(VecWidth == VecTy.getVectorNumElements() &&
2748 "Vector elements should equal vector width size");
2749 assert(VecWidth == 8 || VecWidth == 4 || VecWidth == 2);
2750
2751 // Check if this is an extract of the lowest bit.
2752 if (isNullConstant(IdxV) && ValTy.getSizeInBits() == 1) {
2753 // Extracting the lowest bit is a no-op, but it changes the type,
2754 // so it must be kept as an operation to avoid errors related to
2755 // type mismatches.
2756 return DAG.getNode(HexagonISD::TYPECAST, dl, MVT::i1, VecV);
2757 }
2758
2759 // If the value extracted is a single bit, use tstbit.
2760 if (ValWidth == 1) {
2761 SDValue A0 = getInstr(Hexagon::C2_tfrpr, dl, MVT::i32, {VecV}, DAG);
2762 SDValue M0 = DAG.getConstant(8 / VecWidth, dl, MVT::i32);
2763 SDValue I0 = DAG.getNode(ISD::MUL, dl, MVT::i32, IdxV, M0);
2764 return DAG.getNode(HexagonISD::TSTBIT, dl, MVT::i1, A0, I0);
2765 }
2766
2767 // Each bool vector (v2i1, v4i1, v8i1) always occupies 8 bits in
2768 // a predicate register. The elements of the vector are repeated
2769 // in the register (if necessary) so that the total number is 8.
2770 // The extracted subvector will need to be expanded in such a way.
2771 unsigned Scale = VecWidth / ValWidth;
2772
2773 // Generate (p2d VecV) >> 8*Idx to move the interesting bytes to
2774 // position 0.
2775 assert(ty(IdxV) == MVT::i32);
2776 unsigned VecRep = 8 / VecWidth;
2777 SDValue S0 = DAG.getNode(ISD::MUL, dl, MVT::i32, IdxV,
2778 DAG.getConstant(8*VecRep, dl, MVT::i32));
2779 SDValue T0 = DAG.getNode(HexagonISD::P2D, dl, MVT::i64, VecV);
2780 SDValue T1 = DAG.getNode(ISD::SRL, dl, MVT::i64, T0, S0);
2781 while (Scale > 1) {
2782 // The longest possible subvector is at most 32 bits, so it is always
2783 // contained in the low subregister.
2784 T1 = LoHalf(T1, DAG);
2785 T1 = expandPredicate(T1, dl, DAG);
2786 Scale /= 2;
2787 }
2788
2789 return DAG.getNode(HexagonISD::D2P, dl, ResTy, T1);
2790}
2791
2792SDValue
2793HexagonTargetLowering::insertVector(SDValue VecV, SDValue ValV, SDValue IdxV,
2794 const SDLoc &dl, MVT ValTy,
2795 SelectionDAG &DAG) const {
2796 MVT VecTy = ty(VecV);
2797 if (VecTy.getVectorElementType() == MVT::i1)
2798 return insertVectorPred(VecV, ValV, IdxV, dl, ValTy, DAG);
2799
2800 unsigned VecWidth = VecTy.getSizeInBits();
2801 unsigned ValWidth = ValTy.getSizeInBits();
2802 assert(VecWidth == 32 || VecWidth == 64);
2803 assert((VecWidth % ValWidth) == 0);
2804
2805 // Cast everything to scalar integer types.
2806 MVT ScalarTy = MVT::getIntegerVT(VecWidth);
2807 // The actual type of ValV may be different than ValTy (which is related
2808 // to the vector type).
2809 unsigned VW = ty(ValV).getSizeInBits();
2810 ValV = DAG.getBitcast(MVT::getIntegerVT(VW), ValV);
2811 VecV = DAG.getBitcast(ScalarTy, VecV);
2812 if (VW != VecWidth)
2813 ValV = DAG.getAnyExtOrTrunc(ValV, dl, ScalarTy);
2814
2815 SDValue WidthV = DAG.getConstant(ValWidth, dl, MVT::i32);
2816 SDValue InsV;
2817
2818 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(IdxV)) {
2819 unsigned W = C->getZExtValue() * ValWidth;
2820 SDValue OffV = DAG.getConstant(W, dl, MVT::i32);
2821 InsV = DAG.getNode(HexagonISD::INSERT, dl, ScalarTy,
2822 {VecV, ValV, WidthV, OffV});
2823 } else {
2824 if (ty(IdxV) != MVT::i32)
2825 IdxV = DAG.getZExtOrTrunc(IdxV, dl, MVT::i32);
2826 SDValue OffV = DAG.getNode(ISD::MUL, dl, MVT::i32, IdxV, WidthV);
2827 InsV = DAG.getNode(HexagonISD::INSERT, dl, ScalarTy,
2828 {VecV, ValV, WidthV, OffV});
2829 }
2830
2831 return DAG.getNode(ISD::BITCAST, dl, VecTy, InsV);
2832}
2833
2834SDValue
2835HexagonTargetLowering::insertVectorPred(SDValue VecV, SDValue ValV,
2836 SDValue IdxV, const SDLoc &dl,
2837 MVT ValTy, SelectionDAG &DAG) const {
2838 MVT VecTy = ty(VecV);
2839 unsigned VecLen = VecTy.getVectorNumElements();
2840
2841 if (ValTy == MVT::i1) {
2842 SDValue ToReg = getInstr(Hexagon::C2_tfrpr, dl, MVT::i32, {VecV}, DAG);
2843 SDValue Ext = DAG.getSExtOrTrunc(ValV, dl, MVT::i32);
2844 SDValue Width = DAG.getConstant(8 / VecLen, dl, MVT::i32);
2845 SDValue Idx = DAG.getNode(ISD::MUL, dl, MVT::i32, IdxV, Width);
2846 SDValue Ins =
2847 DAG.getNode(HexagonISD::INSERT, dl, MVT::i32, {ToReg, Ext, Width, Idx});
2848 return getInstr(Hexagon::C2_tfrrp, dl, VecTy, {Ins}, DAG);
2849 }
2850
2851 assert(ValTy.getVectorElementType() == MVT::i1);
2852 SDValue ValR = ValTy.isVector()
2853 ? DAG.getNode(HexagonISD::P2D, dl, MVT::i64, ValV)
2854 : DAG.getSExtOrTrunc(ValV, dl, MVT::i64);
2855
2856 unsigned Scale = VecLen / ValTy.getVectorNumElements();
2857 assert(Scale > 1);
2858
2859 for (unsigned R = Scale; R > 1; R /= 2) {
2860 ValR = contractPredicate(ValR, dl, DAG);
2861 ValR = getCombine(DAG.getUNDEF(MVT::i32), ValR, dl, MVT::i64, DAG);
2862 }
2863
2864 SDValue Width = DAG.getConstant(64 / Scale, dl, MVT::i32);
2865 SDValue Idx = DAG.getNode(ISD::MUL, dl, MVT::i32, IdxV, Width);
2866 SDValue VecR = DAG.getNode(HexagonISD::P2D, dl, MVT::i64, VecV);
2867 SDValue Ins =
2868 DAG.getNode(HexagonISD::INSERT, dl, MVT::i64, {VecR, ValR, Width, Idx});
2869 return DAG.getNode(HexagonISD::D2P, dl, VecTy, Ins);
2870}
2871
2872SDValue
2873HexagonTargetLowering::expandPredicate(SDValue Vec32, const SDLoc &dl,
2874 SelectionDAG &DAG) const {
2875 assert(ty(Vec32).getSizeInBits() == 32);
2876 if (isUndef(Vec32))
2877 return DAG.getUNDEF(MVT::i64);
2878 SDValue P = DAG.getBitcast(MVT::v4i8, Vec32);
2879 SDValue X = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::v4i16, P);
2880 return DAG.getBitcast(MVT::i64, X);
2881}
2882
2883SDValue
2884HexagonTargetLowering::contractPredicate(SDValue Vec64, const SDLoc &dl,
2885 SelectionDAG &DAG) const {
2886 assert(ty(Vec64).getSizeInBits() == 64);
2887 if (isUndef(Vec64))
2888 return DAG.getUNDEF(MVT::i32);
2889 // Collect even bytes:
2890 SDValue A = DAG.getBitcast(MVT::v8i8, Vec64);
2891 SDValue S = DAG.getVectorShuffle(MVT::v8i8, dl, A, DAG.getUNDEF(MVT::v8i8),
2892 {0, 2, 4, 6, 1, 3, 5, 7});
2893 return extractVector(S, DAG.getConstant(0, dl, MVT::i32), dl, MVT::v4i8,
2894 MVT::i32, DAG);
2895}
2896
2897SDValue
2898HexagonTargetLowering::getZero(const SDLoc &dl, MVT Ty, SelectionDAG &DAG)
2899 const {
2900 if (Ty.isVector()) {
2901 unsigned W = Ty.getSizeInBits();
2902 if (W <= 64)
2903 return DAG.getBitcast(Ty, DAG.getConstant(0, dl, MVT::getIntegerVT(W)));
2904 return DAG.getNode(ISD::SPLAT_VECTOR, dl, Ty, getZero(dl, MVT::i32, DAG));
2905 }
2906
2907 if (Ty.isInteger())
2908 return DAG.getConstant(0, dl, Ty);
2909 if (Ty.isFloatingPoint())
2910 return DAG.getConstantFP(0.0, dl, Ty);
2911 llvm_unreachable("Invalid type for zero");
2912}
2913
2914SDValue
2915HexagonTargetLowering::appendUndef(SDValue Val, MVT ResTy, SelectionDAG &DAG)
2916 const {
2917 MVT ValTy = ty(Val);
2919
2920 unsigned ValLen = ValTy.getVectorNumElements();
2921 unsigned ResLen = ResTy.getVectorNumElements();
2922 if (ValLen == ResLen)
2923 return Val;
2924
2925 const SDLoc &dl(Val);
2926 assert(ValLen < ResLen);
2927 assert(ResLen % ValLen == 0);
2928
2929 SmallVector<SDValue, 4> Concats = {Val};
2930 for (unsigned i = 1, e = ResLen / ValLen; i < e; ++i)
2931 Concats.push_back(DAG.getUNDEF(ValTy));
2932
2933 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResTy, Concats);
2934}
2935
2936SDValue
2937HexagonTargetLowering::getCombine(SDValue Hi, SDValue Lo, const SDLoc &dl,
2938 MVT ResTy, SelectionDAG &DAG) const {
2939 MVT ElemTy = ty(Hi);
2940 assert(ElemTy == ty(Lo));
2941
2942 if (!ElemTy.isVector()) {
2943 assert(ElemTy.isScalarInteger());
2944 MVT PairTy = ElemTy.widenIntegerElementType();
2945 SDValue Pair = DAG.getNode(ISD::BUILD_PAIR, dl, PairTy, Lo, Hi);
2946 return DAG.getBitcast(ResTy, Pair);
2947 }
2948
2949 unsigned Width = ElemTy.getSizeInBits();
2950 MVT IntTy = MVT::getIntegerVT(Width);
2951 SDValue Pair =
2953 {DAG.getBitcast(IntTy, Lo), DAG.getBitcast(IntTy, Hi)});
2954 return DAG.getBitcast(ResTy, Pair);
2955}
2956
2957SDValue
2959 MVT VecTy = ty(Op);
2960 unsigned BW = VecTy.getSizeInBits();
2961 const SDLoc &dl(Op);
2963 for (unsigned i = 0, e = Op.getNumOperands(); i != e; ++i)
2964 Ops.push_back(Op.getOperand(i));
2965
2966 if (BW == 32)
2967 return buildVector32(Ops, dl, VecTy, DAG);
2968 if (BW == 64)
2969 return buildVector64(Ops, dl, VecTy, DAG);
2970
2971 if (VecTy == MVT::v8i1 || VecTy == MVT::v4i1 || VecTy == MVT::v2i1) {
2972 // Check if this is a special case or all-0 or all-1.
2973 bool All0 = true, All1 = true;
2974 for (SDValue P : Ops) {
2975 auto *CN = dyn_cast<ConstantSDNode>(P.getNode());
2976 if (CN == nullptr) {
2977 All0 = All1 = false;
2978 break;
2979 }
2980 uint32_t C = CN->getZExtValue();
2981 All0 &= (C == 0);
2982 All1 &= (C == 1);
2983 }
2984 if (All0)
2985 return DAG.getNode(HexagonISD::PFALSE, dl, VecTy);
2986 if (All1)
2987 return DAG.getNode(HexagonISD::PTRUE, dl, VecTy);
2988
2989 // For each i1 element in the resulting predicate register, put 1
2990 // shifted by the index of the element into a general-purpose register,
2991 // then or them together and transfer it back into a predicate register.
2992 SDValue Rs[8];
2993 SDValue Z = getZero(dl, MVT::i32, DAG);
2994 // Always produce 8 bits, repeat inputs if necessary.
2995 unsigned Rep = 8 / VecTy.getVectorNumElements();
2996 for (unsigned i = 0; i != 8; ++i) {
2997 SDValue S = DAG.getConstant(1ull << i, dl, MVT::i32);
2998 Rs[i] = DAG.getSelect(dl, MVT::i32, Ops[i/Rep], S, Z);
2999 }
3000 for (ArrayRef<SDValue> A(Rs); A.size() != 1; A = A.drop_back(A.size()/2)) {
3001 for (unsigned i = 0, e = A.size()/2; i != e; ++i)
3002 Rs[i] = DAG.getNode(ISD::OR, dl, MVT::i32, Rs[2*i], Rs[2*i+1]);
3003 }
3004 // Move the value directly to a predicate register.
3005 return getInstr(Hexagon::C2_tfrrp, dl, VecTy, {Rs[0]}, DAG);
3006 }
3007
3008 return SDValue();
3009}
3010
3011SDValue
3013 SelectionDAG &DAG) const {
3014 MVT VecTy = ty(Op);
3015 const SDLoc &dl(Op);
3016 if (VecTy.getSizeInBits() == 64) {
3017 assert(Op.getNumOperands() == 2);
3018 return getCombine(Op.getOperand(1), Op.getOperand(0), dl, VecTy, DAG);
3019 }
3020
3022 if (ElemTy == MVT::i1) {
3023 assert(VecTy == MVT::v2i1 || VecTy == MVT::v4i1 || VecTy == MVT::v8i1);
3024 MVT OpTy = ty(Op.getOperand(0));
3025 // Scale is how many times the operands need to be contracted to match
3026 // the representation in the target register.
3027 unsigned Scale = VecTy.getVectorNumElements() / OpTy.getVectorNumElements();
3028 assert(Scale == Op.getNumOperands() && Scale > 1);
3029
3030 // First, convert all bool vectors to integers, then generate pairwise
3031 // inserts to form values of doubled length. Up until there are only
3032 // two values left to concatenate, all of these values will fit in a
3033 // 32-bit integer, so keep them as i32 to use 32-bit inserts.
3034 SmallVector<SDValue,4> Words[2];
3035 unsigned IdxW = 0;
3036
3037 for (SDValue P : Op.getNode()->op_values()) {
3038 SDValue W = DAG.getNode(HexagonISD::P2D, dl, MVT::i64, P);
3039 for (unsigned R = Scale; R > 1; R /= 2) {
3040 W = contractPredicate(W, dl, DAG);
3041 W = getCombine(DAG.getUNDEF(MVT::i32), W, dl, MVT::i64, DAG);
3042 }
3043 W = LoHalf(W, DAG);
3044 Words[IdxW].push_back(W);
3045 }
3046
3047 while (Scale > 2) {
3048 SDValue WidthV = DAG.getConstant(64 / Scale, dl, MVT::i32);
3049 Words[IdxW ^ 1].clear();
3050
3051 for (unsigned i = 0, e = Words[IdxW].size(); i != e; i += 2) {
3052 SDValue W0 = Words[IdxW][i], W1 = Words[IdxW][i+1];
3053 // Insert W1 into W0 right next to the significant bits of W0.
3054 SDValue T = DAG.getNode(HexagonISD::INSERT, dl, MVT::i32,
3055 {W0, W1, WidthV, WidthV});
3056 Words[IdxW ^ 1].push_back(T);
3057 }
3058 IdxW ^= 1;
3059 Scale /= 2;
3060 }
3061
3062 // At this point there should only be two words left, and Scale should be 2.
3063 assert(Scale == 2 && Words[IdxW].size() == 2);
3064
3065 SDValue WW = getCombine(Words[IdxW][1], Words[IdxW][0], dl, MVT::i64, DAG);
3066 return DAG.getNode(HexagonISD::D2P, dl, VecTy, WW);
3067 }
3068
3069 return SDValue();
3070}
3071
3072SDValue
3074 SelectionDAG &DAG) const {
3075 SDValue Vec = Op.getOperand(0);
3076 MVT ElemTy = ty(Vec).getVectorElementType();
3077 return extractVector(Vec, Op.getOperand(1), SDLoc(Op), ElemTy, ty(Op), DAG);
3078}
3079
3080SDValue
3082 SelectionDAG &DAG) const {
3083 return extractVector(Op.getOperand(0), Op.getOperand(1), SDLoc(Op),
3084 ty(Op), ty(Op), DAG);
3085}
3086
3087SDValue
3089 SelectionDAG &DAG) const {
3090 return insertVector(Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
3091 SDLoc(Op), ty(Op).getVectorElementType(), DAG);
3092}
3093
3094SDValue
3096 SelectionDAG &DAG) const {
3097 SDValue ValV = Op.getOperand(1);
3098 return insertVector(Op.getOperand(0), ValV, Op.getOperand(2),
3099 SDLoc(Op), ty(ValV), DAG);
3100}
3101
3102bool
3104 // Assuming the caller does not have either a signext or zeroext modifier, and
3105 // only one value is accepted, any reasonable truncation is allowed.
3106 if (!Ty1->isIntegerTy() || !Ty2->isIntegerTy())
3107 return false;
3108
3109 // FIXME: in principle up to 64-bit could be made safe, but it would be very
3110 // fragile at the moment: any support for multiple value returns would be
3111 // liable to disallow tail calls involving i64 -> iN truncation in many cases.
3112 return Ty1->getPrimitiveSizeInBits() <= 32;
3113}
3114
3115SDValue
3117 MVT Ty = ty(Op);
3118 const SDLoc &dl(Op);
3119 LoadSDNode *LN = cast<LoadSDNode>(Op.getNode());
3120 MVT MemTy = LN->getMemoryVT().getSimpleVT();
3122
3123 bool LoadPred = MemTy == MVT::v2i1 || MemTy == MVT::v4i1 || MemTy == MVT::v8i1;
3124 if (LoadPred) {
3125 SDValue NL = DAG.getLoad(
3126 LN->getAddressingMode(), ISD::ZEXTLOAD, MVT::i32, dl, LN->getChain(),
3127 LN->getBasePtr(), LN->getOffset(), LN->getPointerInfo(),
3128 /*MemoryVT*/ MVT::i8, LN->getAlign(), LN->getMemOperand()->getFlags(),
3129 MMOMetadata(LN->getAAInfo(), LN->getRanges()));
3130 LN = cast<LoadSDNode>(NL.getNode());
3131 }
3132
3133 Align ClaimAlign = LN->getAlign();
3134 if (!validateConstPtrAlignment(LN->getBasePtr(), ClaimAlign, dl, DAG))
3135 return replaceMemWithUndef(Op, DAG);
3136
3137 // Call LowerUnalignedLoad for all loads, it recognizes loads that
3138 // don't need extra aligning.
3139 SDValue LU = LowerUnalignedLoad(SDValue(LN, 0), DAG);
3140 if (LoadPred) {
3141 SDValue TP = getInstr(Hexagon::C2_tfrrp, dl, MemTy, {LU}, DAG);
3142 if (ET == ISD::SEXTLOAD) {
3143 TP = DAG.getSExtOrTrunc(TP, dl, Ty);
3144 } else if (ET != ISD::NON_EXTLOAD) {
3145 TP = DAG.getZExtOrTrunc(TP, dl, Ty);
3146 }
3147 SDValue Ch = cast<LoadSDNode>(LU.getNode())->getChain();
3148 return DAG.getMergeValues({TP, Ch}, dl);
3149 }
3150 return LU;
3151}
3152
3153SDValue
3155 const SDLoc &dl(Op);
3156 StoreSDNode *SN = cast<StoreSDNode>(Op.getNode());
3157 SDValue Val = SN->getValue();
3158 MVT Ty = ty(Val);
3159
3160 if (Ty == MVT::v2i1 || Ty == MVT::v4i1 || Ty == MVT::v8i1) {
3161 // Store the exact predicate (all bits).
3162 SDValue TR = getInstr(Hexagon::C2_tfrpr, dl, MVT::i32, {Val}, DAG);
3163 SDValue NS = DAG.getTruncStore(SN->getChain(), dl, TR, SN->getBasePtr(),
3164 MVT::i8, SN->getMemOperand());
3165 if (SN->isIndexed()) {
3166 NS = DAG.getIndexedStore(NS, dl, SN->getBasePtr(), SN->getOffset(),
3167 SN->getAddressingMode());
3168 }
3169 SN = cast<StoreSDNode>(NS.getNode());
3170 }
3171
3172 Align ClaimAlign = SN->getAlign();
3173 if (!validateConstPtrAlignment(SN->getBasePtr(), ClaimAlign, dl, DAG))
3174 return replaceMemWithUndef(Op, DAG);
3175
3176 MVT StoreTy = SN->getMemoryVT().getSimpleVT();
3177 Align NeedAlign = Subtarget.getTypeAlignment(StoreTy);
3178 if (ClaimAlign < NeedAlign)
3179 return expandUnalignedStore(SN, DAG);
3180 return SDValue(SN, 0);
3181}
3182
3183SDValue
3185 const {
3186 LoadSDNode *LN = cast<LoadSDNode>(Op.getNode());
3187 MVT LoadTy = ty(Op);
3188 unsigned NeedAlign = Subtarget.getTypeAlignment(LoadTy).value();
3189 unsigned HaveAlign = LN->getAlign().value();
3190 if (HaveAlign >= NeedAlign)
3191 return Op;
3192
3193 const SDLoc &dl(Op);
3194 const DataLayout &DL = DAG.getDataLayout();
3195 LLVMContext &Ctx = *DAG.getContext();
3196
3197 // If the load aligning is disabled or the load can be broken up into two
3198 // smaller legal loads, do the default (target-independent) expansion.
3199 bool DoDefault = false;
3200 // Handle it in the default way if this is an indexed load.
3201 if (!LN->isUnindexed())
3202 DoDefault = true;
3203
3204 if (!AlignLoads) {
3206 *LN->getMemOperand()))
3207 return Op;
3208 DoDefault = true;
3209 }
3210 if (!DoDefault && (2 * HaveAlign) == NeedAlign) {
3211 // The PartTy is the equivalent of "getLoadableTypeOfSize(HaveAlign)".
3212 MVT PartTy = HaveAlign <= 8 ? MVT::getIntegerVT(8 * HaveAlign)
3213 : MVT::getVectorVT(MVT::i8, HaveAlign);
3214 DoDefault =
3215 allowsMemoryAccessForAlignment(Ctx, DL, PartTy, *LN->getMemOperand());
3216 }
3217 if (DoDefault) {
3218 std::pair<SDValue, SDValue> P = expandUnalignedLoad(LN, DAG);
3219 return DAG.getMergeValues({P.first, P.second}, dl);
3220 }
3221
3222 // The code below generates two loads, both aligned as NeedAlign, and
3223 // with the distance of NeedAlign between them. For that to cover the
3224 // bits that need to be loaded (and without overlapping), the size of
3225 // the loads should be equal to NeedAlign. This is true for all loadable
3226 // types, but add an assertion in case something changes in the future.
3227 assert(LoadTy.getSizeInBits() == 8*NeedAlign);
3228
3229 unsigned LoadLen = NeedAlign;
3230 SDValue Base = LN->getBasePtr();
3231 SDValue Chain = LN->getChain();
3232 auto BO = getBaseAndOffset(Base);
3233 unsigned BaseOpc = BO.first.getOpcode();
3234 if (BaseOpc == HexagonISD::VALIGNADDR && BO.second % LoadLen == 0)
3235 return Op;
3236
3237 if (BO.second % LoadLen != 0) {
3238 BO.first = DAG.getNode(ISD::ADD, dl, MVT::i32, BO.first,
3239 DAG.getConstant(BO.second % LoadLen, dl, MVT::i32));
3240 BO.second -= BO.second % LoadLen;
3241 }
3242 SDValue BaseNoOff = (BaseOpc != HexagonISD::VALIGNADDR)
3243 ? DAG.getNode(HexagonISD::VALIGNADDR, dl, MVT::i32, BO.first,
3244 DAG.getConstant(NeedAlign, dl, MVT::i32))
3245 : BO.first;
3246 SDValue Base0 =
3247 DAG.getMemBasePlusOffset(BaseNoOff, TypeSize::getFixed(BO.second), dl);
3248 SDValue Base1 = DAG.getMemBasePlusOffset(
3249 BaseNoOff, TypeSize::getFixed(BO.second + LoadLen), dl);
3250
3251 MachineMemOperand *WideMMO = nullptr;
3252 if (MachineMemOperand *MMO = LN->getMemOperand()) {
3254 WideMMO = MF.getMachineMemOperand(
3255 MMO->getPointerInfo(), MMO->getFlags(), 2 * LoadLen, Align(LoadLen),
3256 MMOMetadata(MMO->getAAInfo(), MMO->getRanges()), MMO->getSyncScopeID(),
3257 MMO->getSuccessOrdering(), MMO->getFailureOrdering());
3258 }
3259
3260 SDValue Load0 = DAG.getLoad(LoadTy, dl, Chain, Base0, WideMMO);
3261 SDValue Load1 = DAG.getLoad(LoadTy, dl, Chain, Base1, WideMMO);
3262
3263 SDValue Aligned = DAG.getNode(HexagonISD::VALIGN, dl, LoadTy,
3264 {Load1, Load0, BaseNoOff.getOperand(0)});
3265 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
3266 Load0.getValue(1), Load1.getValue(1));
3267 SDValue M = DAG.getMergeValues({Aligned, NewChain}, dl);
3268 return M;
3269}
3270
3271SDValue
3273 SDValue X = Op.getOperand(0), Y = Op.getOperand(1);
3274 auto *CY = dyn_cast<ConstantSDNode>(Y);
3275 if (!CY)
3276 return SDValue();
3277
3278 const SDLoc &dl(Op);
3279 SDVTList VTs = Op.getNode()->getVTList();
3280 assert(VTs.NumVTs == 2);
3281 assert(VTs.VTs[1] == MVT::i1);
3282 unsigned Opc = Op.getOpcode();
3283
3284 if (CY) {
3285 uint64_t VY = CY->getZExtValue();
3286 assert(VY != 0 && "This should have been folded");
3287 // X +/- 1
3288 if (VY != 1)
3289 return SDValue();
3290
3291 if (Opc == ISD::UADDO) {
3292 SDValue Op = DAG.getNode(ISD::ADD, dl, VTs.VTs[0], {X, Y});
3293 SDValue Ov = DAG.getSetCC(dl, MVT::i1, Op, getZero(dl, ty(Op), DAG),
3294 ISD::SETEQ);
3295 return DAG.getMergeValues({Op, Ov}, dl);
3296 }
3297 if (Opc == ISD::USUBO) {
3298 SDValue Op = DAG.getNode(ISD::SUB, dl, VTs.VTs[0], {X, Y});
3299 SDValue Ov = DAG.getSetCC(dl, MVT::i1, Op,
3300 DAG.getAllOnesConstant(dl, ty(Op)), ISD::SETEQ);
3301 return DAG.getMergeValues({Op, Ov}, dl);
3302 }
3303 }
3304
3305 return SDValue();
3306}
3307
3309 SelectionDAG &DAG) const {
3310 const SDLoc &dl(Op);
3311 unsigned Opc = Op.getOpcode();
3312 SDValue X = Op.getOperand(0), Y = Op.getOperand(1), C = Op.getOperand(2);
3313
3314 if (Opc == ISD::UADDO_CARRY)
3315 return DAG.getNode(HexagonISD::ADDC, dl, Op.getNode()->getVTList(),
3316 { X, Y, C });
3317
3318 EVT CarryTy = C.getValueType();
3319 SDValue SubC = DAG.getNode(HexagonISD::SUBC, dl, Op.getNode()->getVTList(),
3320 { X, Y, DAG.getLogicalNOT(dl, C, CarryTy) });
3321 SDValue Out[] = { SubC.getValue(0),
3322 DAG.getLogicalNOT(dl, SubC.getValue(1), CarryTy) };
3323 return DAG.getMergeValues(Out, dl);
3324}
3325
3326SDValue
3328 SDValue Chain = Op.getOperand(0);
3329 SDValue Offset = Op.getOperand(1);
3330 SDValue Handler = Op.getOperand(2);
3331 SDLoc dl(Op);
3332 auto PtrVT = getPointerTy(DAG.getDataLayout());
3333
3334 // Mark function as containing a call to EH_RETURN.
3335 HexagonMachineFunctionInfo *FuncInfo =
3337 FuncInfo->setHasEHReturn();
3338
3339 unsigned OffsetReg = Hexagon::R28;
3340
3341 SDValue StoreAddr =
3342 DAG.getNode(ISD::ADD, dl, PtrVT, DAG.getRegister(Hexagon::R30, PtrVT),
3343 DAG.getIntPtrConstant(4, dl));
3344 Chain = DAG.getStore(Chain, dl, Handler, StoreAddr, MachinePointerInfo());
3345 Chain = DAG.getCopyToReg(Chain, dl, OffsetReg, Offset);
3346
3347 // Not needed we already use it as explicit input to EH_RETURN.
3348 // MF.getRegInfo().addLiveOut(OffsetReg);
3349
3350 return DAG.getNode(HexagonISD::EH_RETURN, dl, MVT::Other, Chain);
3351}
3352
3353SDValue
3355 unsigned Opc = Op.getOpcode();
3356 // Handle INLINEASM first.
3358 return LowerINLINEASM(Op, DAG);
3359
3360 if (isHvxOperation(Op.getNode(), DAG)) {
3361 // If HVX lowering returns nothing, try the default lowering.
3362 if (SDValue V = LowerHvxOperation(Op, DAG))
3363 return V;
3364 }
3365
3366 switch (Opc) {
3367 default:
3368#ifndef NDEBUG
3369 Op.getNode()->dumpr(&DAG);
3370#endif
3371 llvm_unreachable("Should not custom lower this!");
3372
3373 case ISD::FDIV:
3374 return LowerFDIV(Op, DAG);
3375 case ISD::CONCAT_VECTORS: return LowerCONCAT_VECTORS(Op, DAG);
3380 case ISD::BUILD_VECTOR: return LowerBUILD_VECTOR(Op, DAG);
3381 case ISD::VECTOR_SHUFFLE: return LowerVECTOR_SHUFFLE(Op, DAG);
3382 case ISD::BITCAST: return LowerBITCAST(Op, DAG);
3383 case ISD::LOAD: return LowerLoad(Op, DAG);
3384 case ISD::STORE: return LowerStore(Op, DAG);
3385 case ISD::UADDO:
3386 case ISD::USUBO: return LowerUAddSubO(Op, DAG);
3387 case ISD::UADDO_CARRY:
3388 case ISD::USUBO_CARRY: return LowerUAddSubOCarry(Op, DAG);
3389 case ISD::SRA:
3390 case ISD::SHL:
3391 case ISD::SRL: return LowerVECTOR_SHIFT(Op, DAG);
3392 case ISD::ROTL: return LowerROTL(Op, DAG);
3393 case ISD::ConstantPool: return LowerConstantPool(Op, DAG);
3394 case ISD::JumpTable: return LowerJumpTable(Op, DAG);
3395 case ISD::EH_RETURN: return LowerEH_RETURN(Op, DAG);
3396 case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG);
3397 case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
3399 case ISD::ATOMIC_FENCE: return LowerATOMIC_FENCE(Op, DAG);
3400 case ISD::GlobalAddress: return LowerGLOBALADDRESS(Op, DAG);
3401 case ISD::BlockAddress: return LowerBlockAddress(Op, DAG);
3403 case ISD::VACOPY: return LowerVACOPY(Op, DAG);
3404 case ISD::VASTART: return LowerVASTART(Op, DAG);
3406 case ISD::SETCC: return LowerSETCC(Op, DAG);
3407 case ISD::VSELECT: return LowerVSELECT(Op, DAG);
3409 case ISD::INTRINSIC_VOID: return LowerINTRINSIC_VOID(Op, DAG);
3410 case ISD::PREFETCH:
3411 return LowerPREFETCH(Op, DAG);
3412 case ISD::FMAXIMUM:
3413 case ISD::FMINIMUM:
3414 return LowerFMINFMAX(Op, DAG);
3415 break;
3416 }
3417
3418 return SDValue();
3419}
3420
3421void
3424 SelectionDAG &DAG) const {
3425 if (isHvxOperation(N, DAG)) {
3426 LowerHvxOperationWrapper(N, Results, DAG);
3427 if (!Results.empty())
3428 return;
3429 }
3430
3431 SDValue Op(N, 0);
3432 unsigned Opc = N->getOpcode();
3433
3434 switch (Opc) {
3435 case HexagonISD::SSAT:
3436 case HexagonISD::USAT:
3437 Results.push_back(opJoin(SplitVectorOp(Op, DAG), SDLoc(Op), DAG));
3438 break;
3439 case ISD::STORE:
3440 // We are only custom-lowering stores to verify the alignment of the
3441 // address if it is a compile-time constant. Since a store can be
3442 // modified during type-legalization (the value being stored may need
3443 // legalization), return empty Results here to indicate that we don't
3444 // really make any changes in the custom lowering.
3445 return;
3446 default:
3448 break;
3449 }
3450}
3451
3452void
3455 SelectionDAG &DAG) const {
3456 if (isHvxOperation(N, DAG)) {
3457 ReplaceHvxNodeResults(N, Results, DAG);
3458 if (!Results.empty())
3459 return;
3460 }
3461
3462 const SDLoc &dl(N);
3463 switch (N->getOpcode()) {
3464 case ISD::SRL:
3465 case ISD::SRA:
3466 case ISD::SHL:
3467 return;
3468 case ISD::BITCAST:
3469 // Handle a bitcast from v8i1 to i8.
3470 if (N->getValueType(0) == MVT::i8) {
3471 if (N->getOperand(0).getValueType() == MVT::v8i1) {
3472 SDValue P = getInstr(Hexagon::C2_tfrpr, dl, MVT::i32,
3473 N->getOperand(0), DAG);
3474 SDValue T = DAG.getAnyExtOrTrunc(P, dl, MVT::i8);
3475 Results.push_back(T);
3476 }
3477 }
3478 break;
3479 }
3480}
3481
3482SDValue
3484 DAGCombinerInfo &DCI) const {
3485 SDValue Op(N, 0);
3486 const SDLoc &dl(Op);
3487 unsigned Opc = Op.getOpcode();
3488
3489 // Combining transformations applicable for arbitrary vector sizes.
3490 if (DCI.isBeforeLegalizeOps()) {
3491 switch (Opc) {
3492 case ISD::VECREDUCE_ADD:
3493 if (SDValue V = splitVecReduceAdd(N, DCI.DAG))
3494 return V;
3495 if (SDValue V = expandVecReduceAdd(N, DCI.DAG))
3496 return V;
3497 return SDValue();
3501 if (SDValue V = splitExtendingPartialReduceMLA(N, DCI.DAG))
3502 return V;
3503 return SDValue();
3504 }
3505 } else {
3506 switch (Opc) {
3507 case ISD::VSELECT: {
3508 // (vselect (xor x, ptrue), v0, v1) -> (vselect x, v1, v0)
3509 SDValue Cond = Op.getOperand(0);
3510 if (Cond->getOpcode() == ISD::XOR) {
3511 SDValue C0 = Cond.getOperand(0), C1 = Cond.getOperand(1);
3512 if (C1->getOpcode() == HexagonISD::PTRUE) {
3513 SDValue VSel = DCI.DAG.getNode(ISD::VSELECT, dl, ty(Op), C0,
3514 Op.getOperand(2), Op.getOperand(1));
3515 return VSel;
3516 }
3517 }
3518 return SDValue();
3519 }
3520 }
3521 }
3522
3523 if (isHvxOperation(N, DCI.DAG)) {
3524 if (SDValue V = PerformHvxDAGCombine(N, DCI))
3525 return V;
3526 return SDValue();
3527 }
3528
3529 if (Opc == ISD::TRUNCATE) {
3530 SDValue Op0 = Op.getOperand(0);
3531 // fold (truncate (build pair x, y)) -> (truncate x) or x
3532 if (Op0.getOpcode() == ISD::BUILD_PAIR) {
3533 EVT TruncTy = Op.getValueType();
3534 SDValue Elem0 = Op0.getOperand(0);
3535 // if we match the low element of the pair, just return it.
3536 if (Elem0.getValueType() == TruncTy)
3537 return Elem0;
3538 // otherwise, if the low part is still too large, apply the truncate.
3539 if (Elem0.getValueType().bitsGT(TruncTy))
3540 return DCI.DAG.getNode(ISD::TRUNCATE, dl, TruncTy, Elem0);
3541 }
3542 }
3543
3544 if (DCI.isBeforeLegalizeOps())
3545 return SDValue();
3546
3547 switch (Opc) {
3548 case HexagonISD::P2D: {
3549 SDValue P = Op.getOperand(0);
3550 switch (P.getOpcode()) {
3551 case HexagonISD::PTRUE:
3552 return DCI.DAG.getAllOnesConstant(dl, ty(Op));
3553 case HexagonISD::PFALSE:
3554 return getZero(dl, ty(Op), DCI.DAG);
3555 default:
3556 break;
3557 }
3558 break;
3559 }
3560 case ISD::TRUNCATE: {
3561 SDValue Op0 = Op.getOperand(0);
3562 // fold (truncate (build pair x, y)) -> (truncate x) or x
3563 if (Op0.getOpcode() == ISD::BUILD_PAIR) {
3564 MVT TruncTy = ty(Op);
3565 SDValue Elem0 = Op0.getOperand(0);
3566 // if we match the low element of the pair, just return it.
3567 if (ty(Elem0) == TruncTy)
3568 return Elem0;
3569 // otherwise, if the low part is still too large, apply the truncate.
3570 if (ty(Elem0).bitsGT(TruncTy))
3571 return DCI.DAG.getNode(ISD::TRUNCATE, dl, TruncTy, Elem0);
3572 }
3573 break;
3574 }
3575 case ISD::OR: {
3576 // fold (or (shl xx, s), (zext y)) -> (COMBINE (shl xx, s-32), y)
3577 // if s >= 32
3578 auto fold0 = [&, this](SDValue Op) {
3579 if (ty(Op) != MVT::i64)
3580 return SDValue();
3581 SDValue Shl = Op.getOperand(0);
3582 SDValue Zxt = Op.getOperand(1);
3583 if (Shl.getOpcode() != ISD::SHL)
3584 std::swap(Shl, Zxt);
3585
3586 if (Shl.getOpcode() != ISD::SHL || Zxt.getOpcode() != ISD::ZERO_EXTEND)
3587 return SDValue();
3588
3589 SDValue Z = Zxt.getOperand(0);
3590 auto *Amt = dyn_cast<ConstantSDNode>(Shl.getOperand(1));
3591 if (Amt && Amt->getZExtValue() >= 32 && ty(Z).getSizeInBits() <= 32) {
3592 unsigned A = Amt->getZExtValue();
3593 SDValue S = Shl.getOperand(0);
3594 SDValue T0 = DCI.DAG.getNode(ISD::SHL, dl, ty(S), S,
3595 DCI.DAG.getConstant(A - 32, dl, MVT::i32));
3596 SDValue T1 = DCI.DAG.getZExtOrTrunc(T0, dl, MVT::i32);
3597 SDValue T2 = DCI.DAG.getZExtOrTrunc(Z, dl, MVT::i32);
3598 return DCI.DAG.getNode(HexagonISD::COMBINE, dl, MVT::i64, {T1, T2});
3599 }
3600 return SDValue();
3601 };
3602
3603 if (SDValue R = fold0(Op))
3604 return R;
3605 break;
3606 }
3607 }
3608
3609 return SDValue();
3610}
3611
3612/// Returns relocation base for the given PIC jumptable.
3613SDValue
3615 SelectionDAG &DAG) const {
3616 int Idx = cast<JumpTableSDNode>(Table)->getIndex();
3617 EVT VT = Table.getValueType();
3619 return DAG.getNode(HexagonISD::AT_PCREL, SDLoc(Table), VT, T);
3620}
3621
3622//===----------------------------------------------------------------------===//
3623// Inline Assembly Support
3624//===----------------------------------------------------------------------===//
3625
3628 if (Constraint.size() == 1) {
3629 switch (Constraint[0]) {
3630 case 'q':
3631 case 'v':
3632 if (Subtarget.useHVXOps())
3633 return C_RegisterClass;
3634 break;
3635 case 'a':
3636 return C_RegisterClass;
3637 default:
3638 break;
3639 }
3640 }
3641 return TargetLowering::getConstraintType(Constraint);
3642}
3643
3644std::pair<unsigned, const TargetRegisterClass*>
3646 const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const {
3647
3648 if (Constraint.size() == 1) {
3649 switch (Constraint[0]) {
3650 case 'r': // R0-R31
3651 switch (VT.SimpleTy) {
3652 default:
3653 return {0u, nullptr};
3654 case MVT::i1:
3655 case MVT::i8:
3656 case MVT::i16:
3657 case MVT::i32:
3658 case MVT::f32:
3659 return {0u, &Hexagon::IntRegsRegClass};
3660 case MVT::i64:
3661 case MVT::f64:
3662 return {0u, &Hexagon::DoubleRegsRegClass};
3663 }
3664 break;
3665 case 'a': // M0-M1
3666 if (VT != MVT::i32)
3667 return {0u, nullptr};
3668 return {0u, &Hexagon::ModRegsRegClass};
3669 case 'q': // q0-q3
3670 switch (VT.getSizeInBits()) {
3671 default:
3672 return {0u, nullptr};
3673 case 64:
3674 case 128:
3675 return {0u, &Hexagon::HvxQRRegClass};
3676 }
3677 break;
3678 case 'v': // V0-V31
3679 switch (VT.getSizeInBits()) {
3680 default:
3681 return {0u, nullptr};
3682 case 512:
3683 return {0u, &Hexagon::HvxVRRegClass};
3684 case 1024:
3685 if (Subtarget.hasV60Ops() && Subtarget.useHVX128BOps())
3686 return {0u, &Hexagon::HvxVRRegClass};
3687 return {0u, &Hexagon::HvxWRRegClass};
3688 case 2048:
3689 return {0u, &Hexagon::HvxWRRegClass};
3690 }
3691 break;
3692 default:
3693 return {0u, nullptr};
3694 }
3695 }
3696
3697 return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
3698}
3699
3700/// Returns how to materialize the specified FP immediate.
3703 bool ForCodeSize) const {
3704 return FPImmAction::Legal;
3705}
3706
3707/// Returns true if it is beneficial to convert a load of a constant
3708/// to just the constant itself.
3710 Type *Ty) const {
3711 if (!ConstantLoadsToImm)
3712 return false;
3713
3714 assert(Ty->isIntegerTy());
3715 unsigned BitSize = Ty->getPrimitiveSizeInBits();
3716 return (BitSize > 0 && BitSize <= 64);
3717}
3718
3719/// isLegalAddressingMode - Return true if the addressing mode represented by
3720/// AM is legal for this target, for a load/store of the specified type.
3722 const AddrMode &AM, Type *Ty,
3723 unsigned AS, Instruction *I) const {
3724 if (Ty->isSized()) {
3725 // When LSR detects uses of the same base address to access different
3726 // types (e.g. unions), it will assume a conservative type for these
3727 // uses:
3728 // LSR Use: Kind=Address of void in addrspace(4294967295), ...
3729 // The type Ty passed here would then be "void". Skip the alignment
3730 // checks, but do not return false right away, since that confuses
3731 // LSR into crashing.
3732 Align A = DL.getABITypeAlign(Ty);
3733 // The base offset must be a multiple of the alignment.
3734 if (!isAligned(A, AM.BaseOffs))
3735 return false;
3736 // The shifted offset must fit in 11 bits.
3737 if (!isInt<11>(AM.BaseOffs >> Log2(A)))
3738 return false;
3739 }
3740
3741 // No global is ever allowed as a base.
3742 if (AM.BaseGV)
3743 return false;
3744
3745 int Scale = AM.Scale;
3746 if (Scale < 0)
3747 Scale = -Scale;
3748 switch (Scale) {
3749 case 0: // No scale reg, "r+i", "r", or just "i".
3750 break;
3751 default: // No scaled addressing mode.
3752 return false;
3753 }
3754 return true;
3755}
3756
3757/// Return true if folding a constant offset with the given GlobalAddress is
3758/// legal. It is frequently not legal in PIC relocation models.
3760 const {
3761 return HTM.getRelocationModel() == Reloc::Static;
3762}
3763
3764/// isLegalICmpImmediate - Return true if the specified immediate is legal
3765/// icmp immediate, that is the target has icmp instructions which can compare
3766/// a register against the immediate without having to materialize the
3767/// immediate into a register.
3769 return Imm >= -512 && Imm <= 511;
3770}
3771
3772/// IsEligibleForTailCallOptimization - Check whether the call is eligible
3773/// for tail call optimization. Targets which want to do tail call
3774/// optimization should implement this function.
3776 SDValue Callee,
3777 CallingConv::ID CalleeCC,
3778 bool IsVarArg,
3779 bool IsCalleeStructRet,
3780 bool IsCallerStructRet,
3782 const SmallVectorImpl<SDValue> &OutVals,
3784 SelectionDAG& DAG) const {
3785 const Function &CallerF = DAG.getMachineFunction().getFunction();
3786 CallingConv::ID CallerCC = CallerF.getCallingConv();
3787 bool CCMatch = CallerCC == CalleeCC;
3788
3789 // ***************************************************************************
3790 // Look for obvious safe cases to perform tail call optimization that do not
3791 // require ABI changes.
3792 // ***************************************************************************
3793
3794 // If this is a tail call via a function pointer, then don't do it!
3795 if (!isa<GlobalAddressSDNode>(Callee) &&
3796 !isa<ExternalSymbolSDNode>(Callee)) {
3797 return false;
3798 }
3799
3800 // Do not optimize if the calling conventions do not match and the conventions
3801 // used are not C or Fast.
3802 if (!CCMatch) {
3803 bool R = (CallerCC == CallingConv::C || CallerCC == CallingConv::Fast);
3804 bool E = (CalleeCC == CallingConv::C || CalleeCC == CallingConv::Fast);
3805 // If R & E, then ok.
3806 if (!R || !E)
3807 return false;
3808 }
3809
3810 // Do not tail call optimize vararg calls.
3811 if (IsVarArg)
3812 return false;
3813
3814 // Also avoid tail call optimization if either caller or callee uses struct
3815 // return semantics.
3816 if (IsCalleeStructRet || IsCallerStructRet)
3817 return false;
3818
3819 // In addition to the cases above, we also disable Tail Call Optimization if
3820 // the calling convention code that at least one outgoing argument needs to
3821 // go on the stack. We cannot check that here because at this point that
3822 // information is not available.
3823 return true;
3824}
3825
3826/// Returns the target specific optimal type for load and store operations as
3827/// a result of memset, memcpy, and memmove lowering.
3828///
3829/// If DstAlign is zero that means it's safe to destination alignment can
3830/// satisfy any constraint. Similarly if SrcAlign is zero it means there isn't
3831/// a need to check it against alignment requirement, probably because the
3832/// source does not need to be loaded. If 'IsMemset' is true, that means it's
3833/// expanding a memset. If 'ZeroMemset' is true, that means it's a memset of
3834/// zero. 'MemcpyStrSrc' indicates whether the memcpy source is constant so it
3835/// does not need to be loaded. It returns EVT::Other if the type should be
3836/// determined using generic target-independent logic.
3838 LLVMContext &Context, const MemOp &Op,
3839 const AttributeList &FuncAttributes) const {
3840 if (Op.size() >= 8 && Op.isAligned(Align(8)))
3841 return MVT::i64;
3842 if (Op.size() >= 4 && Op.isAligned(Align(4)))
3843 return MVT::i32;
3844 if (Op.size() >= 2 && Op.isAligned(Align(2)))
3845 return MVT::i16;
3846 return MVT::Other;
3847}
3848
3849// The helpers below are versions of llvm::getShuffleReduction and
3850// llvm::getOrderedReduction, adapted to use during DAG passes and simplified as
3851// follows:
3852// - ICmp and FCmp are not handled;
3853// - in every step in getShuffleReduction, the input is split into halves (not
3854// pairwise).
3855
3857 SelectionDAG &DAG) {
3858 assert(Op != Instruction::ICmp && Op != Instruction::FCmp);
3859
3860 EVT VT = Vec.getValueType();
3861 EVT EltT = VT.getVectorElementType();
3862 unsigned VF = VT.getVectorNumElements();
3863 assert(VF > 0 &&
3864 "Reduction emission only supported for non-zero length vectors!");
3865
3866 SDLoc DL(Vec);
3867 SDValue Result = DAG.getExtractVectorElt(DL, EltT, Vec, 0);
3868 for (unsigned ExtractIdx = 1; ExtractIdx < VF; ++ExtractIdx) {
3869 SDValue Ext = DAG.getExtractVectorElt(DL, EltT, Vec, ExtractIdx);
3870 Result = DAG.getNode(Op, DL, EltT, {Result, Ext});
3871 }
3872
3873 return Result;
3874}
3875
3877 SelectionDAG &DAG) {
3878 assert(Op != Instruction::ICmp && Op != Instruction::FCmp);
3879
3880 EVT VT = Vec.getValueType();
3881 unsigned VF = VT.getVectorNumElements();
3882 if (VF == 0)
3883 llvm_unreachable("Vector must be non-zero length");
3884 // VF is a power of 2 so we can emit the reduction using log2(VF) shuffles
3885 // and vector ops, reducing the set of values being computed by half each
3886 // round.
3887 assert(isPowerOf2_32(VF) &&
3888 "Reduction emission only supported for pow2 vectors!");
3889
3890 SDLoc DL(Vec);
3891 // TODO: Is it correct to create double-vector shuffle and fill 3/4 of it with
3892 // undefs?
3893 SmallVector<int, 32> ShuffleMask(VF);
3894 for (unsigned i = VF; i > 1; i >>= 1) {
3895 // Move the upper half of the vector to the lower half.
3896 for (unsigned j = 0; j != i / 2; ++j)
3897 ShuffleMask[j] = i / 2 + j;
3898 // Fill the rest of the mask with undef.
3899 std::fill(&ShuffleMask[i / 2], ShuffleMask.end(), -1);
3900
3901 SDValue Shuf =
3902 DAG.getVectorShuffle(VT, DL, Vec, DAG.getUNDEF(VT), ShuffleMask);
3903
3904 Vec = DAG.getNode(Op, DL, VT, {Vec, Shuf});
3905 }
3906 // The result is in the first element of the vector.
3907 return DAG.getExtractVectorElt(DL, VT.getVectorElementType(), Vec, 0);
3908}
3909
3910SDValue HexagonTargetLowering::expandVecReduceAdd(SDNode *N,
3911 SelectionDAG &DAG) const {
3912 // Since we disabled automatic reduction expansion, generate log2 ladder code
3913 // if the vector is of a power-of-two length.
3914 SDValue Input = N->getOperand(0);
3915 if (isPowerOf2_32(Input.getValueType().getVectorNumElements()))
3916 return getShuffleReduction(Input, ISD::ADD, DAG);
3917 // Otherwise, reduction will be scalarized.
3918 return getOrderedReduction(Input, ISD::ADD, DAG);
3919}
3920
3922 LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace,
3923 Align Alignment, MachineMemOperand::Flags Flags, unsigned *Fast) const {
3924 if (!VT.isSimple())
3925 return false;
3926 MVT SVT = VT.getSimpleVT();
3927 if (Subtarget.isHVXVectorType(SVT, true))
3928 return allowsHvxMemoryAccess(SVT, Flags, Fast);
3930 Context, DL, VT, AddrSpace, Alignment, Flags, Fast);
3931}
3932
3934 EVT VT, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags,
3935 unsigned *Fast) const {
3936 if (!VT.isSimple())
3937 return false;
3938 MVT SVT = VT.getSimpleVT();
3939 if (Subtarget.isHVXVectorType(SVT, true))
3940 return allowsHvxMisalignedMemoryAccesses(SVT, Flags, Fast);
3941 if (Fast)
3942 *Fast = 0;
3943 return false;
3944}
3945
3946std::pair<const TargetRegisterClass*, uint8_t>
3947HexagonTargetLowering::findRepresentativeClass(const TargetRegisterInfo *TRI,
3948 MVT VT) const {
3949 if (Subtarget.isHVXVectorType(VT, true)) {
3950 unsigned BitWidth = VT.getSizeInBits();
3951 unsigned VecWidth = Subtarget.getVectorLength() * 8;
3952
3953 if (VT.getVectorElementType() == MVT::i1)
3954 return std::make_pair(&Hexagon::HvxQRRegClass, 1);
3955 if (BitWidth == VecWidth)
3956 return std::make_pair(&Hexagon::HvxVRRegClass, 1);
3957 assert(BitWidth == 2 * VecWidth);
3958 return std::make_pair(&Hexagon::HvxWRRegClass, 1);
3959 }
3960
3962}
3963
3965 SDNode *Load, ISD::LoadExtType ExtTy, EVT NewVT,
3966 std::optional<unsigned> ByteOffset) const {
3967 // TODO: This may be worth removing. Check regression tests for diffs.
3969 ByteOffset))
3970 return false;
3971
3972 auto *L = cast<LoadSDNode>(Load);
3973 std::pair<SDValue, int> BO = getBaseAndOffset(L->getBasePtr());
3974 // Small-data object, do not shrink.
3975 if (BO.first.getOpcode() == HexagonISD::CONST32_GP)
3976 return false;
3978 auto &HTM = static_cast<const HexagonTargetMachine &>(getTargetMachine());
3979 const auto *GO = dyn_cast_or_null<const GlobalObject>(GA->getGlobal());
3980 return !GO || !HTM.getObjFileLowering()->isGlobalInSmallSection(GO, HTM);
3981 }
3982 return true;
3983}
3984
3986 SDNode *Node) const {
3987 AdjustHvxInstrPostInstrSelection(MI, Node);
3988}
3989
3991 Type *ValueTy, Value *Addr,
3992 AtomicOrdering Ord) const {
3993 unsigned SZ = ValueTy->getPrimitiveSizeInBits();
3994 assert((SZ == 32 || SZ == 64) && "Only 32/64-bit atomic loads supported");
3995 Intrinsic::ID IntID = (SZ == 32) ? Intrinsic::hexagon_L2_loadw_locked
3996 : Intrinsic::hexagon_L4_loadd_locked;
3997
3998 Value *Call =
3999 Builder.CreateIntrinsic(IntID, Addr, /*FMFSource=*/nullptr, "larx");
4000
4001 return Builder.CreateBitCast(Call, ValueTy);
4002}
4003
4004/// Perform a store-conditional operation to Addr. Return the status of the
4005/// store. This should be 0 if the store succeeded, non-zero otherwise.
4007 Value *Val, Value *Addr,
4008 AtomicOrdering Ord) const {
4009 BasicBlock *BB = Builder.GetInsertBlock();
4010 Module *M = BB->getParent()->getParent();
4011 Type *Ty = Val->getType();
4012 unsigned SZ = Ty->getPrimitiveSizeInBits();
4013
4014 Type *CastTy = Builder.getIntNTy(SZ);
4015 assert((SZ == 32 || SZ == 64) && "Only 32/64-bit atomic stores supported");
4016 Intrinsic::ID IntID = (SZ == 32) ? Intrinsic::hexagon_S2_storew_locked
4017 : Intrinsic::hexagon_S4_stored_locked;
4018
4019 Val = Builder.CreateBitCast(Val, CastTy);
4020
4021 Value *Call = Builder.CreateIntrinsic(IntID, {Addr, Val},
4022 /*FMFSource=*/nullptr, "stcx");
4023 Value *Cmp = Builder.CreateICmpEQ(Call, Builder.getInt32(0), "");
4024 Value *Ext = Builder.CreateZExt(Cmp, Type::getInt32Ty(M->getContext()));
4025 return Ext;
4026}
4027
4030 // Do not expand loads and stores that don't exceed 64 bits.
4031 return LI->getType()->getPrimitiveSizeInBits() > 64
4034}
4035
4038 // Do not expand loads and stores that don't exceed 64 bits.
4039 return SI->getValueOperand()->getType()->getPrimitiveSizeInBits() > 64
4042}
4043
4049
4051 MachineInstr &MI, MachineBasicBlock *BB) const {
4052 switch (MI.getOpcode()) {
4053 case TargetOpcode::PATCHABLE_EVENT_CALL:
4054 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
4055 // These are lowered in the AsmPrinter.
4056 return BB;
4057 default:
4058 llvm_unreachable("Unexpected instruction with custom inserter");
4059 }
4060}
4061
4065 const TargetInstrInfo *TII) const {
4066 assert(MBBI->isCall() && MBBI->getCFIType() &&
4067 "Invalid call instruction for a KCFI check");
4068
4069 switch (MBBI->getOpcode()) {
4070 case Hexagon::J2_callr:
4071 case Hexagon::PS_callr_nr:
4072 break;
4073 default:
4074 llvm_unreachable("Unexpected CFI call opcode");
4075 }
4076
4077 MachineOperand &Target = MBBI->getOperand(0);
4078 assert(Target.isReg() && "Invalid target operand for an indirect call");
4079 Target.setIsRenamable(false);
4080
4081 return BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(Hexagon::KCFI_CHECK))
4082 .addReg(Target.getReg())
4083 .addImm(MBBI->getCFIType())
4084 .getInstr();
4085}
4086
4088 const Instruction &AndI) const {
4089 // Only sink 'and' mask to cmp use block if it is masking a single bit since
4090 // this will fold the and/cmp/br into a single tstbit instruction.
4092 if (!Mask)
4093 return false;
4094 return Mask->getValue().isPowerOf2();
4095}
4096
4097// Check if the result of the node is only used as a return value, as
4098// otherwise we can't perform a tail-call.
4100 SDValue &Chain) const {
4101 if (N->getNumValues() != 1)
4102 return false;
4103 if (!N->hasNUsesOfValue(1, 0))
4104 return false;
4105
4106 SDNode *Copy = *N->user_begin();
4107
4108 if (Copy->getOpcode() == ISD::BITCAST) {
4109 return isUsedByReturnOnly(Copy, Chain);
4110 }
4111
4112 if (Copy->getOpcode() != ISD::CopyToReg) {
4113 return false;
4114 }
4115
4116 // If the ISD::CopyToReg has a glue operand, we conservatively assume it
4117 // isn't safe to perform a tail call.
4118 if (Copy->getOperand(Copy->getNumOperands() - 1).getValueType() == MVT::Glue)
4119 return false;
4120
4121 // The copy must be used by a HexagonISD::RET_GLUE, and nothing else.
4122 bool HasRet = false;
4123 for (SDNode *Node : Copy->users()) {
4124 if (Node->getOpcode() != HexagonISD::RET_GLUE)
4125 return false;
4126 HasRet = true;
4127 }
4128 if (!HasRet)
4129 return false;
4130
4131 Chain = Copy->getOperand(0);
4132 return true;
4133}
4134
4136 const MachineFunction &MF) const {
4137 if (MF.getFunction().hasFnAttribute("probe-stack"))
4138 return MF.getFunction().getFnAttribute("probe-stack").getValueAsString() ==
4139 "inline-asm";
4140 return false;
4141}
4142
4144 Align StackAlign) const {
4145 const Function &Fn = MF.getFunction();
4146 unsigned StackProbeSize =
4147 Fn.getFnAttributeAsParsedInteger("stack-probe-size", 4096);
4148 // Round down to the stack alignment.
4149 StackProbeSize = alignDown(StackProbeSize, StackAlign.value());
4150 return StackProbeSize ? StackProbeSize : StackAlign.value();
4151}
unsigned RegSize
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
aarch64 promote const
uint64_t uint64_t
uint64_t Imm
constexpr LLT S8
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
Function Alias Analysis Results
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
#define X(NUM, ENUM, NAME)
Definition ELF.h:665
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
const HexagonInstrInfo * TII
static cl::opt< bool > ConstantLoadsToImm("constant-loads-to-imm", cl::Hidden, cl::init(true), cl::desc("Convert constant loads to immediate values."))
static bool CC_SkipOdd(unsigned &ValNo, MVT &ValVT, MVT &LocVT, CCValAssign::LocInfo &LocInfo, ISD::ArgFlagsTy &ArgFlags, CCState &State)
static cl::opt< bool > AlignLoads("hexagon-align-loads", cl::Hidden, cl::init(false), cl::desc("Rewrite unaligned loads as a pair of aligned loads"))
static bool isBrevLdIntrinsic(const Value *Inst)
static Value * getUnderLyingObjectForBrevLdIntr(Value *V, int &Offset, bool &HasOffset)
static Value * getBrevLdObject(Value *V)
static cl::opt< bool > DisableArgsMinAlignment("hexagon-disable-args-min-alignment", cl::Hidden, cl::init(false), cl::desc("Disable minimum alignment of 1 for " "arguments passed by value on stack"))
static Value * returnEdge(const PHINode *PN, Value *IntrBaseVal)
static SDValue CreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain, ISD::ArgFlagsTy Flags, SelectionDAG &DAG, const SDLoc &dl)
CreateCopyOfByValArgument - Make a copy of an aggregate at address specified by "Src" to address "Dst...
static cl::opt< bool > EmitJumpTables("hexagon-emit-jump-tables", cl::init(true), cl::Hidden, cl::desc("Control jump table emission on Hexagon target"))
static cl::opt< int > MinimumJumpTables("minimum-jump-tables", cl::Hidden, cl::init(5), cl::desc("Set minimum jump tables"))
static cl::opt< bool > EnableHexSDNodeSched("enable-hexagon-sdnode-sched", cl::Hidden, cl::desc("Enable Hexagon SDNode scheduling"))
#define Hexagon_PointerSize
#define HEXAGON_LRFP_SIZE
#define HEXAGON_GOT_SYM_NAME
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define RegName(no)
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define G(x, y, z)
Definition MD5.cpp:55
#define H(x, y, z)
Definition MD5.cpp:56
std::pair< MCSymbol *, MachineModuleInfoImpl::StubValueTy > PairTy
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define T
#define T1
#define P(N)
SmallVector< MachineOperand, 4 > Cond
int64_t C1
RISCVCC::CondCode CC
MachineRegisterInfo & MRI
int64_t C0
const char * Msg
This file defines the SmallVector class.
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 llvm::Type * getVectorElementType(llvm::Type *Ty)
APInt bitcastToAPInt() const
Definition APFloat.h:1475
Class for arbitrary precision integers.
Definition APInt.h:78
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1560
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
Definition APInt.cpp:970
LLVM_ABI APInt reverseBits() const
Definition APInt.cpp:786
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
Definition ArrayRef.h:194
size_t size() const
Get the array size.
Definition ArrayRef.h:141
const T * data() const
Definition ArrayRef.h:138
An instruction that atomically checks whether a specified value is in a memory location,...
LLVM_ABI StringRef getValueAsString() const
Return the attribute's value as a string.
LLVM Basic Block Representation.
Definition BasicBlock.h:62
const Function * getParent() const
Return the enclosing method, or null if none.
Definition BasicBlock.h:213
The address of a basic block.
Definition Constants.h:1088
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...
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
int64_t getLocMemOffset() const
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
This class represents a function call, abstracting a target machine's calling convention.
bool isTailCall() const
const APFloat & getValueAPF() const
Definition Constants.h:463
This is the shared class of boolean and integer constants.
Definition Constants.h:87
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
Definition Constants.h:219
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Definition Constants.h:168
const APInt & getValue() const
Return the constant as an APInt value reference.
Definition Constants.h:159
MachineConstantPoolValue * getMachineCPVal() const
const Constant * getConstVal() const
int64_t getSExtValue() const
static LLVM_ABI Constant * get(ArrayRef< Constant * > V)
This is an important base class in LLVM.
Definition Constant.h:44
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
This is the base abstract class for diagnostic reporting in the backend.
Interface for custom diagnostic printing.
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
Definition Function.h:699
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
Definition Function.cpp:766
uint64_t getFnAttributeAsParsedInteger(StringRef Kind, uint64_t Default=0) const
For a string attribute Kind, parse attribute as an integer.
Definition Function.cpp:778
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Definition Function.h:273
bool hasStructRetAttr() const
Determine if the function returns a structure through first or second pointer argument.
Definition Function.h:673
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition Function.cpp:731
const GlobalValue * getGlobal() const
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI const GlobalObject * getAliaseeObject() const
Definition Globals.cpp:521
Hexagon target-specific information for each MachineFunction.
Register getFrameRegister(const MachineFunction &MF) const override
const uint32_t * getCallPreservedMask(const MachineFunction &MF, CallingConv::ID) const override
bool isHVXVectorType(EVT VecTy, bool IncludeBool=false) const
unsigned getVectorLength() const
SDValue getPICJumpTableRelocBase(SDValue Table, SelectionDAG &DAG) const override
Returns relocation base for the given PIC jumptable.
SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const
SDValue LowerFMINFMAX(SDValue Op, SelectionDAG &DAG) const
MachineInstr * EmitKCFICheck(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator &MBBI, const TargetInstrInfo *TII) const override
SDValue LowerGLOBAL_OFFSET_TABLE(SDValue Op, SelectionDAG &DAG) const
bool isMaskAndCmp0FoldingBeneficial(const Instruction &AndI) const override
Return if the target supports combining a chain like:
SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const
void AdjustInstrPostInstrSelection(MachineInstr &MI, SDNode *Node) const override
This method should be implemented by targets that mark instructions with the 'hasPostISelHook' flag.
bool isTargetCanonicalConstantNode(SDValue Op) const override
Returns true if the given Opc is considered a canonical constant for the target, which should not be ...
ConstraintType getConstraintType(StringRef Constraint) const override
Given a constraint, return the type of constraint it is for this target.
bool isTruncateFree(Type *Ty1, Type *Ty2) const override
Return true if it's free to truncate a value of type FromTy to type ToTy.
MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
unsigned getStackProbeSize(const MachineFunction &MF, Align StackAlign) const
SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const
SDValue LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const
ExtractSubvectorCost getExtractSubvectorCost(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return the cost of extracting a subvector of type ResVT from a vector of type SrcVT,...
SDValue LowerUAddSubO(SDValue Op, SelectionDAG &DAG) const
Value * emitLoadLinked(IRBuilderBase &Builder, Type *ValueTy, Value *Addr, AtomicOrdering Ord) const override
Perform a load-linked operation on Addr, returning a "Value *" with the corresponding pointee type.
bool isLegalICmpImmediate(int64_t Imm) const override
isLegalICmpImmediate - Return true if the specified immediate is legal icmp immediate,...
bool shouldReduceLoadWidth(SDNode *Load, ISD::LoadExtType ExtTy, EVT NewVT, std::optional< unsigned > ByteOffset) const override
Return true if it is profitable to reduce a load to a smaller type.
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
isLegalAddressingMode - Return true if the addressing mode represented by AM is legal for this target...
SDValue LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const
AtomicExpansionKind shouldExpandAtomicStoreInIR(StoreInst *SI) const override
Returns how the given (atomic) store should be expanded by the IR-level AtomicExpand pass into.
SDValue GetDynamicTLSAddr(SelectionDAG &DAG, SDValue Chain, GlobalAddressSDNode *GA, SDValue InGlue, EVT PtrVT, unsigned ReturnReg, unsigned char OperandGlues) 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,...
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const
bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
Returns true by value, base pointer and offset pointer and addressing mode by reference if this node ...
SDValue LowerUnalignedLoad(SDValue Op, SelectionDAG &DAG) const
SDValue LowerFDIV(SDValue Op, SelectionDAG &DAG) const
SDValue LowerVACOPY(SDValue Op, SelectionDAG &DAG) const
unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const override
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
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,...
bool mayBeEmittedAsTailCall(const CallInst *CI) const override
Return true if the target may be able emit the call instruction as a tail call.
AtomicExpansionKind shouldExpandAtomicLoadInIR(LoadInst *LI) const override
Returns how the given (atomic) load should be expanded by the IR-level AtomicExpand pass.
bool isUsedByReturnOnly(SDNode *N, SDValue &Chain) const override
Return true if result of the specified node is used by a return node only.
SDValue LowerCallResult(SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &dl, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals, const SmallVectorImpl< SDValue > &OutVals, SDValue Callee) const
LowerCallResult - Lower the result values of an ISD::CALL into the appropriate copies out of appropri...
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const
SDValue LowerToTLSInitialExecModel(GlobalAddressSDNode *GA, SelectionDAG &DAG) const
SDValue LowerToTLSGeneralDynamicModel(GlobalAddressSDNode *GA, SelectionDAG &DAG) const
bool allowsMemoryAccess(LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags, unsigned *Fast) const override
Return true if the target supports a memory access of this type for the given address space and align...
SDValue LowerINSERT_SUBVECTOR(SDValue Op, SelectionDAG &DAG) const
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *BB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
SDValue LowerROTL(SDValue Op, SelectionDAG &DAG) const
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const
SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const
SDValue LowerLoad(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...
bool isShuffleMaskLegal(ArrayRef< int > Mask, EVT VT) const override
Targets can use this to indicate that they only support some VECTOR_SHUFFLE operations,...
LegalizeAction getCustomOperationAction(SDNode &Op) const override
How to legalize this custom operation?
SDValue LowerToTLSLocalExecModel(GlobalAddressSDNode *GA, SelectionDAG &DAG) const
SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const
bool allowTruncateForTailCall(Type *Ty1, Type *Ty2) const override
Return true if a truncation from FromTy to ToTy is permitted when deciding whether a call is in tail ...
SDValue LowerUAddSubOCarry(SDValue Op, SelectionDAG &DAG) const
bool shouldExpandBuildVectorWithShuffles(EVT VT, unsigned DefinedValues) const override
bool shouldConvertConstantLoadToIntImm(const APInt &Imm, Type *Ty) const override
Returns true if it is beneficial to convert a load of a constant to just the constant itself.
SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const
SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVectorImpl< SDValue > &InVals) const override
LowerCall - Functions arguments are copied from virtual regs to (physical regs)/(stack frame),...
bool allowsMisalignedMemoryAccesses(EVT VT, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags, unsigned *Fast) const override
Determine if the target supports unaligned memory accesses.
SDValue LowerStore(SDValue Op, SelectionDAG &DAG) const
SDValue LowerPREFETCH(SDValue Op, SelectionDAG &DAG) const
bool hasInlineStackProbe(const MachineFunction &MF) const override
SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
This callback is invoked when a node result type is illegal for the target, and the operation was reg...
Value * emitStoreConditional(IRBuilderBase &Builder, Value *Val, Value *Addr, AtomicOrdering Ord) const override
Perform a store-conditional operation to Addr.
bool hasBitTest(SDValue X, SDValue Y) const override
Return true if the target has a bit-test instruction: (X & (1 << Y)) ==/!= 0 This knowledge can be us...
HexagonTargetLowering(const TargetMachine &TM, const HexagonSubtarget &ST)
SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
bool IsEligibleForTailCallOptimization(SDValue Callee, CallingConv::ID CalleeCC, bool isVarArg, bool isCalleeStructRet, bool isCallerStructRet, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SmallVectorImpl< ISD::InputArg > &Ins, SelectionDAG &DAG) const
IsEligibleForTailCallOptimization - Check whether the call is eligible for tail call optimization.
SDValue LowerVSELECT(SDValue Op, SelectionDAG &DAG) const
void LowerOperationWrapper(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
This callback is invoked by the type legalizer to legalize nodes with an illegal operand type but leg...
SDValue LowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG) const
SDValue LowerVECTOR_SHIFT(SDValue Op, SelectionDAG &DAG) const
SDValue LowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG) const
SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const
FPImmAction getFPImmAction(const APFloat &Imm, EVT VT, bool ForCodeSize) const override
Returns how to materialize the specified FP immediate.
std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override
Given a physical register constraint (e.g.
SDValue LowerBITCAST(SDValue Op, SelectionDAG &DAG) const
bool isFMAFasterThanFMulAndFAdd(const MachineFunction &, EVT) const override
Return true if an FMA operation is faster than a pair of mul and add instructions.
SDValue LowerEXTRACT_SUBVECTOR(SDValue Op, SelectionDAG &DAG) const
EVT getOptimalMemOpType(LLVMContext &Context, const MemOp &Op, const AttributeList &FuncAttributes) const override
Returns the target specific optimal type for load and store operations as a result of memset,...
SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const
LegalizeTypeAction getPreferredVectorAction(MVT VT) const override
Return the preferred vector type legalization action.
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, 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 LowerGLOBALADDRESS(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.
void getTgtMemIntrinsic(SmallVectorImpl< IntrinsicInfo > &Infos, const CallBase &I, MachineFunction &MF, unsigned Intrinsic) const override
Given an intrinsic, checks if on the target the intrinsic will need to map to a MemIntrinsicNode (tou...
AtomicExpansionKind shouldExpandAtomicCmpXchgInIR(const AtomicCmpXchgInst *AI) const override
Returns how the given atomic cmpxchg should be expanded by the IR-level AtomicExpand pass.
std::pair< MVT, unsigned > handleMaskRegisterForCallingConv(const HexagonSubtarget &Subtarget, EVT VT) const
SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const
SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG) const
Common base class shared among various IRBuilders.
Definition IRBuilder.h:111
Class to represent integer types.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
Definition Type.cpp:338
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:76
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
Base class for LoadSDNode and StoreSDNode.
ISD::MemIndexedMode getAddressingMode() const
Return the addressing mode for this load or store: unindexed, pre-inc, pre-dec, post-inc,...
bool isUnindexed() const
Return true if this is NOT a pre/post inc/dec load/store.
bool isIndexed() const
Return true if this is a pre/post inc/dec load/store.
An instruction for reading from memory.
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
const SDValue & getOffset() const
ISD::LoadExtType getExtensionType() const
Return whether this is a plain node, or one of the varieties of value-extending loads.
unsigned getID() const
getID() - Return the register class ID number.
Machine Value Type.
@ INVALID_SIMPLE_VALUE_TYPE
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
SimpleValueType SimpleTy
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool isInteger() const
Return true if this is an integer or a vector integer type.
bool isScalableVector() const
Return true if this is a vector value type where the runtime length is machine dependent.
static LLVM_ABI MVT getVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
MVT widenIntegerElementType() const
static auto integer_valuetypes()
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
static auto fixedlen_vector_valuetypes()
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
TypeSize getStoreSizeInBits() const
Return the number of bits overwritten by a store of the specified value type.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
static MVT getIntegerVT(unsigned BitWidth)
static auto fp_valuetypes()
LLVM_ABI void print(raw_ostream &OS, const SlotIndexes *=nullptr, bool IsStandalone=true) const
Instructions::iterator instr_iterator
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.
LLVM_ABI void ensureMaxAlignment(Align Alignment)
Make sure the function's frame is at least Align bytes aligned.
void setFrameAddressIsTaken(bool T)
void setHasTailCall(bool V=true)
void setReturnAddressIsTaken(bool s)
unsigned getNumFixedObjects() const
Return the number of fixed objects.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
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.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
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.
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
A description of a memory reference used in the backend.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
Flags getFlags() const
Return the raw flags of the source value,.
MachineOperand class - Representation of each machine instruction operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const MDNode * getRanges() const
Returns the Ranges that describes the dereference.
Align getAlign() const
AAMDNodes getAAInfo() const
Returns the AA info that describes the dereference.
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
const MachinePointerInfo & getPointerInfo() const
const SDValue & getChain() const
EVT getMemoryVT() const
Return the type of the in-memory value.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:294
unsigned getOpcode() const
Return the opcode for this Instruction or ConstantExpr.
Definition Operator.h:43
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
unsigned getNumIncomingValues() const
Return the number of incoming edges.
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...
const DebugLoc & getDebugLoc() const
Represents one node in the SelectionDAG.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
void setCFIType(uint32_t Type)
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOperand(unsigned i) const
unsigned getOpcode() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
SDValue getExtractVectorElt(const SDLoc &DL, EVT VT, SDValue Vec, unsigned Idx)
Extract element at Idx from Vec.
const TargetSubtargetInfo & getSubtarget() const
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 SDValue getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget=false, bool IsOpaque=false)
LLVM_ABI SDValue getConstantFP(double Val, const SDLoc &DL, EVT VT, bool isTarget=false)
Create a ConstantFPSDNode wrapping a constant value.
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
SDValue getGLOBAL_OFFSET_TABLE(EVT VT)
Return a GLOBAL_OFFSET_TABLE node. This does not have a useful SDLoc.
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false, SDNodeFlags Flags={})
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
LLVM_ABI SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align DstAlign, Align SrcAlign, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), BatchAAResults *BatchAA=nullptr)
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
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 getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, SDValue Offset, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
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)
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Helper function to build ISD::STORE nodes.
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 getMemBasePlusOffset(SDValue Base, TypeSize Offset, const SDLoc &DL, const SDNodeFlags Flags=SDNodeFlags())
Returns sum of the base pointer and offset.
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 ...
LLVM_ABI SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Loads are not normal binary operators: their result type is not determined by their operands,...
LLVM_ABI SDValue getIndexedStore(SDValue OrigStore, const SDLoc &dl, SDValue Base, SDValue Offset, ISD::MemIndexedMode AM)
LLVM_ABI SDValue getAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either any-extending or truncat...
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetBlockAddress(const BlockAddress *BA, EVT VT, int64_t Offset=0, unsigned TargetFlags=0)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
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.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
LLVM_ABI SDValue getLogicalNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a logical NOT operation as (XOR Val, BooleanOne).
static void commuteMask(MutableArrayRef< int > Mask)
Change values in a shuffle permute mask assuming the two vector operands have swapped position.
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.
An instruction for storing to memory.
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)
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...
virtual bool shouldReduceLoadWidth(SDNode *Load, ISD::LoadExtType ExtTy, EVT NewVT, std::optional< unsigned > ByteOffset=std::nullopt) const
Return true if it is profitable to reduce a load to a smaller type.
LegalizeAction
This enum indicates whether operations are valid for a target, and if not, what action should be used...
unsigned MaxStoresPerMemcpyOptSize
Likewise for functions with the OptSize attribute.
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
const TargetMachine & getTargetMachine() const
virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
LegalizeTypeAction
This enum indicates whether a types are legal for a target, and if not, what action should be used to...
void setIndexedLoadAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed load does or does not work with the specified type and indicate w...
void setPrefLoopAlignment(Align Alignment)
Set the target's preferred loop alignment.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
virtual unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
unsigned MaxStoresPerMemsetOptSize
Likewise for functions with the OptSize attribute.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
unsigned MaxStoresPerMemmove
Specify maximum number of store instructions per memmove call.
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
unsigned MaxStoresPerMemmoveOptSize
Likewise for functions with the OptSize attribute.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
void setIndexedStoreAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed store does or does not work with the specified type and indicate ...
ExtractSubvectorCost
Enum that specifies how expensive lowering an EXTRACT_SUBVECTOR is.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
unsigned MaxStoresPerMemset
Specify maximum number of store instructions per memset call.
void setMinimumJumpTableEntries(unsigned Val)
Indicate the minimum number of blocks to generate jump tables.
FPImmAction
How the legalizer should materialize a floating-point immediate.
@ Legal
The target can instruction select the immediate natively.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
bool isOperationLegalOrCustom(unsigned Op, EVT VT, bool LegalOnly=false) const
Return true if the specified operation is legal on this target or can be made legal with custom lower...
virtual bool allowsMemoryAccess(LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const
Return true if the target supports a memory access of this type for the given address space and align...
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....
void AddPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT)
If Opc/OrigVT is specified as being promoted, the promotion code defaults to trying a larger integer/...
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
void setCondCodeAction(ArrayRef< ISD::CondCode > CCs, MVT VT, LegalizeAction Action)
Indicate that the specified condition code is or isn't supported on the target and indicate what to d...
virtual std::pair< const TargetRegisterClass *, uint8_t > findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) const
Return the largest legal super-reg register class of the register class for the specified type and it...
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...
bool allowsMemoryAccessForAlignment(LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace=0, Align Alignment=Align(1), MachineMemOperand::Flags Flags=MachineMemOperand::MONone, unsigned *Fast=nullptr) const
This function returns true if the memory access is aligned or if the target allows this specific unal...
unsigned MaxStoresPerMemcpy
Specify maximum number of store instructions per memcpy call.
void setSchedulingPreference(Sched::Preference Pref)
Specify the target scheduling preference.
virtual bool isTargetCanonicalConstantNode(SDValue Op) const
Returns true if the given Opc is considered a canonical constant for the target, which should not be ...
SDValue expandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG) const
Expands an unaligned store to 2 half-size stores for integer values, and possibly more for vectors.
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
std::pair< SDValue, SDValue > expandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG) const
Expands an unaligned load to 2 half-size loads for an integer, and possibly more for vectors.
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 void LowerOperationWrapper(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const
This callback is invoked by the type legalizer to legalize nodes with an illegal operand type but leg...
Primary interface to the complete machine description for the target machine.
bool shouldAssumeDSOLocal(const GlobalValue *GV) const
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Target - Wrapper for Target specific information.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:352
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
bool isVectorTy() const
True if this is an instance of VectorType.
Definition Type.h:283
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:299
bool isPointerTy() const
True if this is an instance of PointerType.
Definition Type.h:277
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Definition Type.cpp:297
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
Definition Type.cpp:187
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:252
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
Definition Type.cpp:303
Value * getOperand(unsigned i) const
Definition User.h:207
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:257
LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
Definition Value.cpp:986
const ParentTy * getParent() const
Definition ilist_node.h:34
CallInst * Call
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
Definition Attributor.h:164
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ 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
@ MO_PCREL
MO_PCREL - On a symbol operand, indicates a PC-relative relocation Used for computing a global addres...
@ MO_GOT
MO_GOT - Indicates a GOT-relative relocation.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
Definition ISDOpcodes.h:845
@ 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.
@ PARTIAL_REDUCE_SMLA
PARTIAL_REDUCE_[U|S]MLA(Accumulator, Input1, Input2) The partial reduction nodes sign or zero extend ...
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
Definition ISDOpcodes.h:277
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
Definition ISDOpcodes.h:605
@ BSWAP
Byte Swap and Counting operators.
Definition ISDOpcodes.h:805
@ 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:266
@ 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:879
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
Definition ISDOpcodes.h:523
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
Definition ISDOpcodes.h:222
@ GlobalAddress
Definition ISDOpcodes.h:90
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
Definition ISDOpcodes.h:906
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
Definition ISDOpcodes.h:589
@ FADD
Simple binary floating point operators.
Definition ISDOpcodes.h:420
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
Definition ISDOpcodes.h:765
@ 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:282
@ 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...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
Definition ISDOpcodes.h:256
@ FLDEXP
FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
@ GlobalTLSAddress
Definition ISDOpcodes.h:91
@ EH_RETURN
OUTCHAIN = EH_RETURN(INCHAIN, OFFSET, HANDLER) - This node represents 'eh_return' gcc dwarf builtin,...
Definition ISDOpcodes.h:158
@ PARTIAL_REDUCE_UMLA
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:870
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
Definition ISDOpcodes.h:675
@ READSTEADYCOUNTER
READSTEADYCOUNTER - This corresponds to the readfixedcounter intrinsic.
@ PREFETCH
PREFETCH - This corresponds to a prefetch intrinsic.
@ FSINCOS
FSINCOS - Compute both fsin and fcos as a single operation.
@ FNEG
Perform various unary floating-point operations inspired by libm.
@ BR_CC
BR_CC - Conditional branch.
@ SSUBO
Same for subtraction.
Definition ISDOpcodes.h:355
@ BR_JT
BR_JT - Jumptable branch.
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition ISDOpcodes.h:822
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
Definition ISDOpcodes.h:682
@ VACOPY
VACOPY - VACOPY has 5 operands: an input chain, a destination pointer, a source pointer,...
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
Definition ISDOpcodes.h:351
@ VECREDUCE_ADD
Integer reductions may have a result type larger than the vector element type.
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:787
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
Definition ISDOpcodes.h:659
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
Definition ISDOpcodes.h:619
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition ISDOpcodes.h:581
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
Definition ISDOpcodes.h:226
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:876
@ DEBUGTRAP
DEBUGTRAP - Trap intended to get the attention of a debugger.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition ISDOpcodes.h:837
@ FMINNUM
FMINNUM/FMAXNUM - Same semantics as the llvm.minnum/maxnum intrinsics.
@ DYNAMIC_STACKALLOC
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition ISDOpcodes.h:914
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition ISDOpcodes.h:745
@ GLOBAL_OFFSET_TABLE
The address of the GOT.
Definition ISDOpcodes.h:105
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
Definition ISDOpcodes.h:831
@ UADDO_CARRY
Carry-using nodes for multiple precision addition and subtraction.
Definition ISDOpcodes.h:331
@ INLINEASM_BR
INLINEASM_BR - Branching version of inline asm. Used by asm-goto.
@ BF16_TO_FP
BF16_TO_FP, FP_TO_BF16 - These operators are used to perform promotions and truncation for bfloat16.
@ FRAMEADDR
FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and llvm.returnaddress on the DAG.
Definition ISDOpcodes.h:112
@ FMINIMUM
FMINIMUM/FMAXIMUM - Same semantics as the llvm.minimum/maximum intrinsics.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:952
@ READCYCLECOUNTER
READCYCLECOUNTER - This corresponds to the readcyclecounter intrinsic.
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:757
@ TRAP
TRAP - Trapping instruction.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
Definition ISDOpcodes.h:207
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
Definition ISDOpcodes.h:570
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
Definition ISDOpcodes.h:55
@ INLINEASM
INLINEASM - Represents an inline asm block.
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:882
@ VAARG
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
Definition ISDOpcodes.h:859
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
Definition ISDOpcodes.h:64
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
Definition ISDOpcodes.h:539
@ PARTIAL_REDUCE_SUMLA
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
Definition ISDOpcodes.h:368
@ FMINIMUMNUM
FMINIMUMNUM/FMAXIMUMNUM - Same semantics as the llvm.minimumnum/maximumnum intrinsics.
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
Definition ISDOpcodes.h:215
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
Definition ISDOpcodes.h:561
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
bool isIntEqualitySetCC(CondCode Code)
Return true if this is a setcc instruction that performs an equality comparison when used with intege...
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
initializer< Ty > init(const Ty &Val)
constexpr double e
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition STLExtras.h:1685
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:166
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
RelativeUniformCounterPtr Values
Definition InstrProf.h:91
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
Definition Alignment.h:139
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
Definition MathExtras.h:546
LLVM_ABI Value * getSplatValue(const Value *V)
Get splat value if the input is a splat vector or return nullptr.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition bit.h:204
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI Value * getShuffleReduction(IRBuilderBase &Builder, Value *Src, unsigned Op, TargetTransformInfo::ReductionShuffle RS, RecurKind MinMaxKind=RecurKind::None)
Generates a vector reduction using shufflevectors to reduce the value.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
FormattedNumber format_hex(uint64_t N, unsigned Width, bool Upper=false)
format_hex - Output N as a fixed width hexadecimal.
Definition Format.h:164
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.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Definition MCRegister.h:21
@ Fast
Assign the register banks as fast as possible (default).
DWARFExpression::Operation Op
LLVM_ABI int getNextAvailablePluginDiagnosticKind()
Get the next available kind ID for a plugin diagnostic.
unsigned M0(unsigned Val)
Definition VE.h:393
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1788
unsigned Log2(Align A)
Returns the log2 of the alignment.
Definition Alignment.h:202
LLVM_ABI Value * getOrderedReduction(IRBuilderBase &Builder, Value *Acc, Value *Src, unsigned Op, RecurKind MinMaxKind=RecurKind::None)
Generates an ordered vector reduction using extracts to reduce the value.
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:880
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:82
static constexpr Align fromLog2(unsigned Log2Value)
Returns an alignment of 1 << Log2Value bytes.
Definition Alignment.h:73
Extended Value Type.
Definition ValueTypes.h:35
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
Definition ValueTypes.h:145
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
Definition ValueTypes.h:307
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
Definition ValueTypes.h:396
bool isPow2VectorType() const
Returns true if the given vector is a power of 2.
Definition ValueTypes.h:501
static LLVM_ABI EVT getEVT(Type *Ty, bool HandleUnknown=false)
Return the value type corresponding to the specified type.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
Definition ValueTypes.h:339
EVT getVectorElementType() const
Given a vector type, return the type of each element.
Definition ValueTypes.h:351
bool isVectorOf(EVT EltVT) const
Return true if this is a vector with matching element type.
Definition ValueTypes.h:181
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
Definition ValueTypes.h:359
LLVM IR metadata carried by a MachineMemOperand.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
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:111
This represents a list of ValueType's that has been intern'd by a SelectionDAG.
unsigned int NumVTs
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
This structure contains all information that is necessary for lowering calls.
SmallVector< ISD::InputArg, 32 > Ins
SmallVector< ISD::OutputArg, 32 > Outs