LLVM 23.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
192 return TargetLowering::getRegisterTypeForCallingConv(Context, CC, VT);
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
235 return CCInfo.CheckReturn(Outs, RetCC_Hexagon_HVX);
236 return CCInfo.CheckReturn(Outs, RetCC_Hexagon);
237}
238
239// LowerReturn - Lower ISD::RET. If a struct is larger than 8 bytes and is
240// passed by value, the function prototype is modified to return void and
241// the value is stored in memory pointed by a pointer passed by caller.
244 bool IsVarArg,
246 const SmallVectorImpl<SDValue> &OutVals,
247 const SDLoc &dl, SelectionDAG &DAG) const {
248 // CCValAssign - represent the assignment of the return value to locations.
250
251 // CCState - Info about the registers and stack slot.
252 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
253 *DAG.getContext());
254
255 // Analyze return values of ISD::RET
256 if (Subtarget.useHVXOps())
257 CCInfo.AnalyzeReturn(Outs, RetCC_Hexagon_HVX);
258 else
259 CCInfo.AnalyzeReturn(Outs, RetCC_Hexagon);
260
261 SDValue Glue;
262 SmallVector<SDValue, 4> RetOps(1, Chain);
263
264 // Copy the result values into the output registers.
265 for (unsigned i = 0; i != RVLocs.size(); ++i) {
266 CCValAssign &VA = RVLocs[i];
267 SDValue Val = OutVals[i];
268
269 switch (VA.getLocInfo()) {
270 default:
271 // Loc info must be one of Full, BCvt, SExt, ZExt, or AExt.
272 llvm_unreachable("Unknown loc info!");
274 break;
276 Val = DAG.getBitcast(VA.getLocVT(), Val);
277 break;
279 Val = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Val);
280 break;
282 Val = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Val);
283 break;
285 Val = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Val);
286 break;
287 }
288
289 Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), Val, Glue);
290
291 // Guarantee that all emitted copies are stuck together with flags.
292 Glue = Chain.getValue(1);
293 RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
294 }
295
296 RetOps[0] = Chain; // Update chain.
297
298 // Add the glue if we have it.
299 if (Glue.getNode())
300 RetOps.push_back(Glue);
301
302 return DAG.getNode(HexagonISD::RET_GLUE, dl, MVT::Other, RetOps);
303}
304
306 // If either no tail call or told not to tail call at all, don't.
307 return CI->isTailCall();
308}
309
311 const char* RegName, LLT VT, const MachineFunction &) const {
312 // Just support r19, the linux kernel uses it.
314 .Case("r0", Hexagon::R0)
315 .Case("r1", Hexagon::R1)
316 .Case("r2", Hexagon::R2)
317 .Case("r3", Hexagon::R3)
318 .Case("r4", Hexagon::R4)
319 .Case("r5", Hexagon::R5)
320 .Case("r6", Hexagon::R6)
321 .Case("r7", Hexagon::R7)
322 .Case("r8", Hexagon::R8)
323 .Case("r9", Hexagon::R9)
324 .Case("r10", Hexagon::R10)
325 .Case("r11", Hexagon::R11)
326 .Case("r12", Hexagon::R12)
327 .Case("r13", Hexagon::R13)
328 .Case("r14", Hexagon::R14)
329 .Case("r15", Hexagon::R15)
330 .Case("r16", Hexagon::R16)
331 .Case("r17", Hexagon::R17)
332 .Case("r18", Hexagon::R18)
333 .Case("r19", Hexagon::R19)
334 .Case("r20", Hexagon::R20)
335 .Case("r21", Hexagon::R21)
336 .Case("r22", Hexagon::R22)
337 .Case("r23", Hexagon::R23)
338 .Case("r24", Hexagon::R24)
339 .Case("r25", Hexagon::R25)
340 .Case("r26", Hexagon::R26)
341 .Case("r27", Hexagon::R27)
342 .Case("r28", Hexagon::R28)
343 .Case("r29", Hexagon::R29)
344 .Case("r30", Hexagon::R30)
345 .Case("r31", Hexagon::R31)
346 .Case("r1:0", Hexagon::D0)
347 .Case("r3:2", Hexagon::D1)
348 .Case("r5:4", Hexagon::D2)
349 .Case("r7:6", Hexagon::D3)
350 .Case("r9:8", Hexagon::D4)
351 .Case("r11:10", Hexagon::D5)
352 .Case("r13:12", Hexagon::D6)
353 .Case("r15:14", Hexagon::D7)
354 .Case("r17:16", Hexagon::D8)
355 .Case("r19:18", Hexagon::D9)
356 .Case("r21:20", Hexagon::D10)
357 .Case("r23:22", Hexagon::D11)
358 .Case("r25:24", Hexagon::D12)
359 .Case("r27:26", Hexagon::D13)
360 .Case("r29:28", Hexagon::D14)
361 .Case("r31:30", Hexagon::D15)
362 .Case("sp", Hexagon::R29)
363 .Case("fp", Hexagon::R30)
364 .Case("lr", Hexagon::R31)
365 .Case("p0", Hexagon::P0)
366 .Case("p1", Hexagon::P1)
367 .Case("p2", Hexagon::P2)
368 .Case("p3", Hexagon::P3)
369 .Case("sa0", Hexagon::SA0)
370 .Case("lc0", Hexagon::LC0)
371 .Case("sa1", Hexagon::SA1)
372 .Case("lc1", Hexagon::LC1)
373 .Case("m0", Hexagon::M0)
374 .Case("m1", Hexagon::M1)
375 .Case("usr", Hexagon::USR)
376 .Case("ugp", Hexagon::UGP)
377 .Case("cs0", Hexagon::CS0)
378 .Case("cs1", Hexagon::CS1)
379 .Default(Register());
380 return Reg;
381}
382
383/// LowerCallResult - Lower the result values of an ISD::CALL into the
384/// appropriate copies out of appropriate physical registers. This assumes that
385/// Chain/Glue are the input chain/glue to use, and that TheCall is the call
386/// being lowered. Returns a SDNode with the same number of values as the
387/// ISD::CALL.
389 SDValue Chain, SDValue Glue, CallingConv::ID CallConv, bool IsVarArg,
390 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
392 const SmallVectorImpl<SDValue> &OutVals, SDValue Callee) const {
393 // Assign locations to each value returned by this call.
395
396 CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
397 *DAG.getContext());
398
399 if (Subtarget.useHVXOps())
400 CCInfo.AnalyzeCallResult(Ins, RetCC_Hexagon_HVX);
401 else
402 CCInfo.AnalyzeCallResult(Ins, RetCC_Hexagon);
403
404 // Copy all of the result registers out of their specified physreg.
405 for (unsigned i = 0; i != RVLocs.size(); ++i) {
406 SDValue RetVal;
407 if (RVLocs[i].getValVT() == MVT::i1) {
408 // Return values of type MVT::i1 require special handling. The reason
409 // is that MVT::i1 is associated with the PredRegs register class, but
410 // values of that type are still returned in R0. Generate an explicit
411 // copy into a predicate register from R0, and treat the value of the
412 // predicate register as the call result.
413 auto &MRI = DAG.getMachineFunction().getRegInfo();
414 SDValue FR0 = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(),
415 MVT::i32, Glue);
416 // FR0 = (Value, Chain, Glue)
417 Register PredR = MRI.createVirtualRegister(&Hexagon::PredRegsRegClass);
418 SDValue TPR = DAG.getCopyToReg(FR0.getValue(1), dl, PredR,
419 FR0.getValue(0), FR0.getValue(2));
420 // TPR = (Chain, Glue)
421 // Don't glue this CopyFromReg, because it copies from a virtual
422 // register. If it is glued to the call, InstrEmitter will add it
423 // as an implicit def to the call (EmitMachineNode).
424 RetVal = DAG.getCopyFromReg(TPR.getValue(0), dl, PredR, MVT::i1);
425 Glue = TPR.getValue(1);
426 Chain = TPR.getValue(0);
427 } else {
428 RetVal = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(),
429 RVLocs[i].getValVT(), Glue);
430 Glue = RetVal.getValue(2);
431 Chain = RetVal.getValue(1);
432 }
433 InVals.push_back(RetVal.getValue(0));
434 }
435
436 return Chain;
437}
438
439/// LowerCall - Functions arguments are copied from virtual regs to
440/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted.
443 SmallVectorImpl<SDValue> &InVals) const {
444 SelectionDAG &DAG = CLI.DAG;
445 SDLoc &dl = CLI.DL;
447 SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
449 SDValue Chain = CLI.Chain;
450 SDValue Callee = CLI.Callee;
451 CallingConv::ID CallConv = CLI.CallConv;
452 bool IsVarArg = CLI.IsVarArg;
453 bool DoesNotReturn = CLI.DoesNotReturn;
454
455 bool IsStructRet = Outs.empty() ? false : Outs[0].Flags.isSRet();
457 MachineFrameInfo &MFI = MF.getFrameInfo();
458 auto PtrVT = getPointerTy(MF.getDataLayout());
459
461 Callee = DAG.getTargetGlobalAddress(GAN->getGlobal(), dl, MVT::i32);
462
463 // Linux ABI treats var-arg calls the same way as regular ones.
464 bool TreatAsVarArg = !Subtarget.isEnvironmentMusl() && IsVarArg;
465
466 // Analyze operands of the call, assigning locations to each operand.
468 CCState CCInfo(CallConv, TreatAsVarArg, MF, ArgLocs, *DAG.getContext());
469
470 if (Subtarget.useHVXOps())
471 CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon_HVX);
473 CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon_Legacy);
474 else
475 CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon);
476
477 if (CLI.IsTailCall) {
478 bool StructAttrFlag = MF.getFunction().hasStructRetAttr();
479 CLI.IsTailCall = IsEligibleForTailCallOptimization(Callee, CallConv,
480 IsVarArg, IsStructRet, StructAttrFlag, Outs,
481 OutVals, Ins, DAG);
482 for (const CCValAssign &VA : ArgLocs) {
483 if (VA.isMemLoc()) {
484 CLI.IsTailCall = false;
485 break;
486 }
487 }
488 LLVM_DEBUG(dbgs() << (CLI.IsTailCall ? "Eligible for Tail Call\n"
489 : "Argument must be passed on stack. "
490 "Not eligible for Tail Call\n"));
491 }
492 // Get a count of how many bytes are to be pushed on the stack.
493 unsigned NumBytes = CCInfo.getStackSize();
495 SmallVector<SDValue, 8> MemOpChains;
496
497 const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo();
498 SDValue StackPtr =
499 DAG.getCopyFromReg(Chain, dl, HRI.getStackRegister(), PtrVT);
500
501 bool NeedsArgAlign = false;
502 Align LargestAlignSeen;
503 // Walk the register/memloc assignments, inserting copies/loads.
504 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
505 CCValAssign &VA = ArgLocs[i];
506 SDValue Arg = OutVals[i];
507 ISD::ArgFlagsTy Flags = Outs[i].Flags;
508 // Record if we need > 8 byte alignment on an argument.
509 bool ArgAlign = Subtarget.isHVXVectorType(VA.getValVT());
510 NeedsArgAlign |= ArgAlign;
511
512 // Promote the value if needed.
513 switch (VA.getLocInfo()) {
514 default:
515 // Loc info must be one of Full, BCvt, SExt, ZExt, or AExt.
516 llvm_unreachable("Unknown loc info!");
518 break;
520 Arg = DAG.getBitcast(VA.getLocVT(), Arg);
521 break;
523 Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);
524 break;
526 Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);
527 break;
529 Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);
530 break;
531 }
532
533 if (VA.isMemLoc()) {
534 unsigned LocMemOffset = VA.getLocMemOffset();
535 SDValue MemAddr = DAG.getConstant(LocMemOffset, dl,
536 StackPtr.getValueType());
537 MemAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, MemAddr);
538 if (ArgAlign)
539 LargestAlignSeen = std::max(
540 LargestAlignSeen, Align(VA.getLocVT().getStoreSizeInBits() / 8));
541 if (Flags.isByVal()) {
542 // The argument is a struct passed by value. According to LLVM, "Arg"
543 // is a pointer.
544 MemOpChains.push_back(CreateCopyOfByValArgument(Arg, MemAddr, Chain,
545 Flags, DAG, dl));
546 } else {
548 DAG.getMachineFunction(), LocMemOffset);
549 SDValue S = DAG.getStore(Chain, dl, Arg, MemAddr, LocPI);
550 MemOpChains.push_back(S);
551 }
552 continue;
553 }
554
555 // Arguments that can be passed on register must be kept at RegsToPass
556 // vector.
557 if (VA.isRegLoc())
558 RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
559 }
560
561 if (NeedsArgAlign && Subtarget.hasV60Ops()) {
562 LLVM_DEBUG(dbgs() << "Function needs byte stack align due to call args\n");
563 Align VecAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass);
564 LargestAlignSeen = std::max(LargestAlignSeen, VecAlign);
565 MFI.ensureMaxAlignment(LargestAlignSeen);
566 }
567 // Transform all store nodes into one single node because all store
568 // nodes are independent of each other.
569 if (!MemOpChains.empty())
570 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
571
572 SDValue Glue;
573 if (!CLI.IsTailCall) {
574 Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, dl);
575 Glue = Chain.getValue(1);
576 }
577
578 // Build a sequence of copy-to-reg nodes chained together with token
579 // chain and flag operands which copy the outgoing args into registers.
580 // The Glue is necessary since all emitted instructions must be
581 // stuck together.
582 if (!CLI.IsTailCall) {
583 for (const auto &R : RegsToPass) {
584 Chain = DAG.getCopyToReg(Chain, dl, R.first, R.second, Glue);
585 Glue = Chain.getValue(1);
586 }
587 } else {
588 // For tail calls lower the arguments to the 'real' stack slot.
589 //
590 // Force all the incoming stack arguments to be loaded from the stack
591 // before any new outgoing arguments are stored to the stack, because the
592 // outgoing stack slots may alias the incoming argument stack slots, and
593 // the alias isn't otherwise explicit. This is slightly more conservative
594 // than necessary, because it means that each store effectively depends
595 // on every argument instead of just those arguments it would clobber.
596 //
597 // Do not flag preceding copytoreg stuff together with the following stuff.
598 Glue = SDValue();
599 for (const auto &R : RegsToPass) {
600 Chain = DAG.getCopyToReg(Chain, dl, R.first, R.second, Glue);
601 Glue = Chain.getValue(1);
602 }
603 Glue = SDValue();
604 }
605
606 bool LongCalls = MF.getSubtarget<HexagonSubtarget>().useLongCalls();
607 unsigned Flags = LongCalls ? HexagonII::HMOTF_ConstExtended : 0;
608
609 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
610 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
611 // node so that legalize doesn't hack it.
613 Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, PtrVT, 0, Flags);
614 } else if (ExternalSymbolSDNode *S =
616 Callee = DAG.getTargetExternalSymbol(S->getSymbol(), PtrVT, Flags);
617 }
618
619 // Returns a chain & a flag for retval copy to use.
621 Ops.push_back(Chain);
622 Ops.push_back(Callee);
623
624 // Add argument registers to the end of the list so that they are
625 // known live into the call.
626 for (const auto &R : RegsToPass)
627 Ops.push_back(DAG.getRegister(R.first, R.second.getValueType()));
628
629 const uint32_t *Mask = HRI.getCallPreservedMask(MF, CallConv);
630 assert(Mask && "Missing call preserved mask for calling convention");
631 Ops.push_back(DAG.getRegisterMask(Mask));
632
633 if (Glue.getNode())
634 Ops.push_back(Glue);
635
636 if (CLI.IsTailCall) {
637 MFI.setHasTailCall();
638 return DAG.getNode(HexagonISD::TC_RETURN, dl, MVT::Other, Ops);
639 }
640
641 // Set this here because we need to know this for "hasFP" in frame lowering.
642 // The target-independent code calls getFrameRegister before setting it, and
643 // getFrameRegister uses hasFP to determine whether the function has FP.
644 MFI.setHasCalls(true);
645
646 unsigned OpCode = DoesNotReturn ? HexagonISD::CALLnr : HexagonISD::CALL;
647 Chain = DAG.getNode(OpCode, dl, {MVT::Other, MVT::Glue}, Ops);
648 if (CLI.CFIType)
649 Chain.getNode()->setCFIType(CLI.CFIType->getZExtValue());
650 Glue = Chain.getValue(1);
651
652 // Create the CALLSEQ_END node.
653 Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, Glue, dl);
654 Glue = Chain.getValue(1);
655
656 // Handle result values, copying them out of physregs into vregs that we
657 // return.
658 return LowerCallResult(Chain, Glue, CallConv, IsVarArg, Ins, dl, DAG,
659 InVals, OutVals, Callee);
660}
661
662/// Returns true by value, base pointer and offset pointer and addressing
663/// mode by reference if this node can be combined with a load / store to
664/// form a post-indexed load / store.
667 SelectionDAG &DAG) const {
669 if (!LSN)
670 return false;
671 EVT VT = LSN->getMemoryVT();
672 if (!VT.isSimple())
673 return false;
674 bool IsLegalType = VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32 ||
675 VT == MVT::i64 || VT == MVT::f32 || VT == MVT::f64 ||
676 VT == MVT::v2i16 || VT == MVT::v2i32 || VT == MVT::v4i8 ||
677 VT == MVT::v4i16 || VT == MVT::v8i8 ||
678 Subtarget.isHVXVectorType(VT.getSimpleVT());
679 if (!IsLegalType)
680 return false;
681
682 if (Op->getOpcode() != ISD::ADD)
683 return false;
684 Base = Op->getOperand(0);
685 Offset = Op->getOperand(1);
686 if (!isa<ConstantSDNode>(Offset.getNode()))
687 return false;
688 AM = ISD::POST_INC;
689
690 int32_t V = cast<ConstantSDNode>(Offset.getNode())->getSExtValue();
691 return Subtarget.getInstrInfo()->isValidAutoIncImm(VT, V);
692}
693
696 return SDValue();
697 else
698 return Op;
699}
700
704 auto &HMFI = *MF.getInfo<HexagonMachineFunctionInfo>();
705 const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo();
706 unsigned LR = HRI.getRARegister();
707
708 if ((Op.getOpcode() != ISD::INLINEASM &&
709 Op.getOpcode() != ISD::INLINEASM_BR) || HMFI.hasClobberLR())
710 return Op;
711
712 unsigned NumOps = Op.getNumOperands();
713 if (Op.getOperand(NumOps-1).getValueType() == MVT::Glue)
714 --NumOps; // Ignore the flag operand.
715
716 for (unsigned i = InlineAsm::Op_FirstOperand; i != NumOps;) {
717 const InlineAsm::Flag Flags(Op.getConstantOperandVal(i));
718 unsigned NumVals = Flags.getNumOperandRegisters();
719 ++i; // Skip the ID value.
720
721 switch (Flags.getKind()) {
722 default:
723 llvm_unreachable("Bad flags!");
727 i += NumVals;
728 break;
732 for (; NumVals; --NumVals, ++i) {
733 Register Reg = cast<RegisterSDNode>(Op.getOperand(i))->getReg();
734 if (Reg != LR)
735 continue;
736 HMFI.setHasClobberLR(true);
737 return Op;
738 }
739 break;
740 }
741 }
742 }
743
744 return Op;
745}
746
747// Need to transform ISD::PREFETCH into something that doesn't inherit
748// all of the properties of ISD::PREFETCH, specifically SDNPMayLoad and
749// SDNPMayStore.
751 SelectionDAG &DAG) const {
752 SDValue Chain = Op.getOperand(0);
753 SDValue Addr = Op.getOperand(1);
754 // Lower it to DCFETCH($reg, #0). A "pat" will try to merge the offset in,
755 // if the "reg" is fed by an "add".
756 SDLoc DL(Op);
757 SDValue Zero = DAG.getConstant(0, DL, MVT::i32);
758 return DAG.getNode(HexagonISD::DCFETCH, DL, MVT::Other, Chain, Addr, Zero);
759}
760
762 SelectionDAG &DAG) const {
763 SDValue Chain = Op.getOperand(0);
764 unsigned IntNo = Op.getConstantOperandVal(1);
765 // Lower the hexagon_prefetch builtin to DCFETCH, as above.
766 if (IntNo == Intrinsic::hexagon_prefetch) {
767 SDValue Addr = Op.getOperand(2);
768 SDLoc DL(Op);
769 SDValue Zero = DAG.getConstant(0, DL, MVT::i32);
770 return DAG.getNode(HexagonISD::DCFETCH, DL, MVT::Other, Chain, Addr, Zero);
771 }
772 return SDValue();
773}
774
777 SelectionDAG &DAG) const {
778 SDValue Chain = Op.getOperand(0);
779 SDValue Size = Op.getOperand(1);
780 SDValue Align = Op.getOperand(2);
781 SDLoc dl(Op);
782
784 assert(AlignConst && "Non-constant Align in LowerDYNAMIC_STACKALLOC");
785
786 unsigned A = AlignConst->getSExtValue();
787 auto &HFI = *Subtarget.getFrameLowering();
788 // "Zero" means natural stack alignment.
789 if (A == 0)
790 A = HFI.getStackAlign().value();
791
792 LLVM_DEBUG({
793 dbgs () << __func__ << " Align: " << A << " Size: ";
794 Size.getNode()->dump(&DAG);
795 dbgs() << "\n";
796 });
797
798 SDValue AC = DAG.getConstant(A, dl, MVT::i32);
799 SDVTList VTs = DAG.getVTList(MVT::i32, MVT::Other);
800 SDValue AA = DAG.getNode(HexagonISD::ALLOCA, dl, VTs, Chain, Size, AC);
801
803 return AA;
804}
805
807 SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
808 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
809 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
811 MachineFrameInfo &MFI = MF.getFrameInfo();
813
814 // Linux ABI treats var-arg calls the same way as regular ones.
815 bool TreatAsVarArg = !Subtarget.isEnvironmentMusl() && IsVarArg;
816
817 // Assign locations to all of the incoming arguments.
819 CCState CCInfo(CallConv, TreatAsVarArg, MF, ArgLocs, *DAG.getContext());
820
821 if (Subtarget.useHVXOps())
822 CCInfo.AnalyzeFormalArguments(Ins, CC_Hexagon_HVX);
824 CCInfo.AnalyzeFormalArguments(Ins, CC_Hexagon_Legacy);
825 else
826 CCInfo.AnalyzeFormalArguments(Ins, CC_Hexagon);
827
828 // For LLVM, in the case when returning a struct by value (>8byte),
829 // the first argument is a pointer that points to the location on caller's
830 // stack where the return value will be stored. For Hexagon, the location on
831 // caller's stack is passed only when the struct size is smaller than (and
832 // equal to) 8 bytes. If not, no address will be passed into callee and
833 // callee return the result directly through R0/R1.
834 auto NextSingleReg = [] (const TargetRegisterClass &RC, unsigned Reg) {
835 switch (RC.getID()) {
836 case Hexagon::IntRegsRegClassID:
837 return Reg - Hexagon::R0 + 1;
838 case Hexagon::DoubleRegsRegClassID:
839 return (Reg - Hexagon::D0 + 1) * 2;
840 case Hexagon::HvxVRRegClassID:
841 return Reg - Hexagon::V0 + 1;
842 case Hexagon::HvxWRRegClassID:
843 return (Reg - Hexagon::W0 + 1) * 2;
844 }
845 llvm_unreachable("Unexpected register class");
846 };
847
848 auto &HFL = const_cast<HexagonFrameLowering&>(*Subtarget.getFrameLowering());
849 auto &HMFI = *MF.getInfo<HexagonMachineFunctionInfo>();
850 HFL.FirstVarArgSavedReg = 0;
852
853 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
854 CCValAssign &VA = ArgLocs[i];
855 ISD::ArgFlagsTy Flags = Ins[i].Flags;
856 bool ByVal = Flags.isByVal();
857
858 // Arguments passed in registers:
859 // 1. 32- and 64-bit values and HVX vectors are passed directly,
860 // 2. Large structs are passed via an address, and the address is
861 // passed in a register.
862 if (VA.isRegLoc() && ByVal && Flags.getByValSize() <= 8)
863 llvm_unreachable("ByValSize must be bigger than 8 bytes");
864
865 bool InReg = VA.isRegLoc() &&
866 (!ByVal || (ByVal && Flags.getByValSize() > 8));
867
868 if (InReg) {
869 MVT RegVT = VA.getLocVT();
870 if (VA.getLocInfo() == CCValAssign::BCvt)
871 RegVT = VA.getValVT();
872
873 const TargetRegisterClass *RC = getRegClassFor(RegVT);
874 Register VReg = MRI.createVirtualRegister(RC);
875 SDValue Copy = DAG.getCopyFromReg(Chain, dl, VReg, RegVT);
876
877 // Treat values of type MVT::i1 specially: they are passed in
878 // registers of type i32, but they need to remain as values of
879 // type i1 for consistency of the argument lowering.
880 if (VA.getValVT() == MVT::i1) {
881 assert(RegVT.getSizeInBits() <= 32);
882 SDValue T = DAG.getNode(ISD::AND, dl, RegVT,
883 Copy, DAG.getConstant(1, dl, RegVT));
884 Copy = DAG.getSetCC(dl, MVT::i1, T, DAG.getConstant(0, dl, RegVT),
885 ISD::SETNE);
886 } else {
887#ifndef NDEBUG
888 unsigned RegSize = RegVT.getSizeInBits();
889 assert(RegSize == 32 || RegSize == 64 ||
890 Subtarget.isHVXVectorType(RegVT));
891#endif
892 }
893 InVals.push_back(Copy);
894 MRI.addLiveIn(VA.getLocReg(), VReg);
895 HFL.FirstVarArgSavedReg = NextSingleReg(*RC, VA.getLocReg());
896 } else {
897 assert(VA.isMemLoc() && "Argument should be passed in memory");
898
899 // If it's a byval parameter, then we need to compute the
900 // "real" size, not the size of the pointer.
901 unsigned ObjSize = Flags.isByVal()
902 ? Flags.getByValSize()
903 : VA.getLocVT().getStoreSizeInBits() / 8;
904
905 // Create the frame index object for this incoming parameter.
907 int FI = MFI.CreateFixedObject(ObjSize, Offset, true);
908 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
909
910 if (Flags.isByVal()) {
911 // If it's a pass-by-value aggregate, then do not dereference the stack
912 // location. Instead, we should generate a reference to the stack
913 // location.
914 InVals.push_back(FIN);
915 } else {
916 SDValue L = DAG.getLoad(VA.getValVT(), dl, Chain, FIN,
918 InVals.push_back(L);
919 }
920 }
921 }
922
923 if (IsVarArg && Subtarget.isEnvironmentMusl()) {
924 for (int i = HFL.FirstVarArgSavedReg; i < 6; i++)
925 MRI.addLiveIn(Hexagon::R0+i);
926 }
927
928 if (IsVarArg && Subtarget.isEnvironmentMusl()) {
929 HMFI.setFirstNamedArgFrameIndex(HMFI.getFirstNamedArgFrameIndex() - 1);
930 HMFI.setLastNamedArgFrameIndex(-int(MFI.getNumFixedObjects()));
931
932 // Create Frame index for the start of register saved area.
933 int NumVarArgRegs = 6 - HFL.FirstVarArgSavedReg;
934 bool RequiresPadding = (NumVarArgRegs & 1);
935 int RegSaveAreaSizePlusPadding = RequiresPadding
936 ? (NumVarArgRegs + 1) * 4
937 : NumVarArgRegs * 4;
938
939 if (RegSaveAreaSizePlusPadding > 0) {
940 // The offset to saved register area should be 8 byte aligned.
941 int RegAreaStart = HEXAGON_LRFP_SIZE + CCInfo.getStackSize();
942 if (!(RegAreaStart % 8))
943 RegAreaStart = (RegAreaStart + 7) & -8;
944
945 int RegSaveAreaFrameIndex =
946 MFI.CreateFixedObject(RegSaveAreaSizePlusPadding, RegAreaStart, true);
947 HMFI.setRegSavedAreaStartFrameIndex(RegSaveAreaFrameIndex);
948
949 // This will point to the next argument passed via stack.
950 int Offset = RegAreaStart + RegSaveAreaSizePlusPadding;
951 int FI = MFI.CreateFixedObject(Hexagon_PointerSize, Offset, true);
952 HMFI.setVarArgsFrameIndex(FI);
953 } else {
954 // This will point to the next argument passed via stack, when
955 // there is no saved register area.
956 int Offset = HEXAGON_LRFP_SIZE + CCInfo.getStackSize();
957 int FI = MFI.CreateFixedObject(Hexagon_PointerSize, Offset, true);
958 HMFI.setRegSavedAreaStartFrameIndex(FI);
959 HMFI.setVarArgsFrameIndex(FI);
960 }
961 }
962
963
964 if (IsVarArg && !Subtarget.isEnvironmentMusl()) {
965 // This will point to the next argument passed via stack.
966 int Offset = HEXAGON_LRFP_SIZE + CCInfo.getStackSize();
967 int FI = MFI.CreateFixedObject(Hexagon_PointerSize, Offset, true);
968 HMFI.setVarArgsFrameIndex(FI);
969 }
970
971 return Chain;
972}
973
976 // VASTART stores the address of the VarArgsFrameIndex slot into the
977 // memory location argument.
980 SDValue Addr = DAG.getFrameIndex(QFI->getVarArgsFrameIndex(), MVT::i32);
981 const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
982
983 if (!Subtarget.isEnvironmentMusl()) {
984 return DAG.getStore(Op.getOperand(0), SDLoc(Op), Addr, Op.getOperand(1),
986 }
987 auto &FuncInfo = *MF.getInfo<HexagonMachineFunctionInfo>();
988 auto &HFL = *Subtarget.getFrameLowering();
989 SDLoc DL(Op);
991
992 // Get frame index of va_list.
993 SDValue FIN = Op.getOperand(1);
994
995 // If first Vararg register is odd, add 4 bytes to start of
996 // saved register area to point to the first register location.
997 // This is because the saved register area has to be 8 byte aligned.
998 // In case of an odd start register, there will be 4 bytes of padding in
999 // the beginning of saved register area. If all registers area used up,
1000 // the following condition will handle it correctly.
1001 SDValue SavedRegAreaStartFrameIndex =
1002 DAG.getFrameIndex(FuncInfo.getRegSavedAreaStartFrameIndex(), MVT::i32);
1003
1004 auto PtrVT = getPointerTy(DAG.getDataLayout());
1005
1006 if (HFL.FirstVarArgSavedReg & 1)
1007 SavedRegAreaStartFrameIndex =
1008 DAG.getNode(ISD::ADD, DL, PtrVT,
1009 DAG.getFrameIndex(FuncInfo.getRegSavedAreaStartFrameIndex(),
1010 MVT::i32),
1011 DAG.getIntPtrConstant(4, DL));
1012
1013 // Store the saved register area start pointer.
1014 SDValue Store =
1015 DAG.getStore(Op.getOperand(0), DL,
1016 SavedRegAreaStartFrameIndex,
1017 FIN, MachinePointerInfo(SV));
1018 MemOps.push_back(Store);
1019
1020 // Store saved register area end pointer.
1021 FIN = DAG.getNode(ISD::ADD, DL, PtrVT,
1022 FIN, DAG.getIntPtrConstant(4, DL));
1023 Store = DAG.getStore(Op.getOperand(0), DL,
1024 DAG.getFrameIndex(FuncInfo.getVarArgsFrameIndex(),
1025 PtrVT),
1026 FIN, MachinePointerInfo(SV, 4));
1027 MemOps.push_back(Store);
1028
1029 // Store overflow area pointer.
1030 FIN = DAG.getNode(ISD::ADD, DL, PtrVT,
1031 FIN, DAG.getIntPtrConstant(4, DL));
1032 Store = DAG.getStore(Op.getOperand(0), DL,
1033 DAG.getFrameIndex(FuncInfo.getVarArgsFrameIndex(),
1034 PtrVT),
1035 FIN, MachinePointerInfo(SV, 8));
1036 MemOps.push_back(Store);
1037
1038 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOps);
1039}
1040
1041SDValue
1043 // Assert that the linux ABI is enabled for the current compilation.
1044 assert(Subtarget.isEnvironmentMusl() && "Linux ABI should be enabled");
1045 SDValue Chain = Op.getOperand(0);
1046 SDValue DestPtr = Op.getOperand(1);
1047 SDValue SrcPtr = Op.getOperand(2);
1048 const Value *DestSV = cast<SrcValueSDNode>(Op.getOperand(3))->getValue();
1049 const Value *SrcSV = cast<SrcValueSDNode>(Op.getOperand(4))->getValue();
1050 SDLoc DL(Op);
1051 // Size of the va_list is 12 bytes as it has 3 pointers. Therefore,
1052 // we need to memcopy 12 bytes from va_list to another similar list.
1053 return DAG.getMemcpy(Chain, DL, DestPtr, SrcPtr,
1054 DAG.getIntPtrConstant(12, DL), Align(4), Align(4),
1055 /*isVolatile*/ false, false, /*CI=*/nullptr,
1056 std::nullopt, MachinePointerInfo(DestSV),
1057 MachinePointerInfo(SrcSV));
1058}
1059
1061 const SDLoc &dl(Op);
1062 SDValue LHS = Op.getOperand(0);
1063 SDValue RHS = Op.getOperand(1);
1064 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
1065 MVT ResTy = ty(Op);
1066 MVT OpTy = ty(LHS);
1067
1068 if (OpTy == MVT::v2i16 || OpTy == MVT::v4i8) {
1069 assert(OpTy.getVectorElementType().isScalarInteger());
1070 MVT WideTy = OpTy.widenIntegerElementType();
1071 return DAG.getSetCC(dl, ResTy,
1072 DAG.getSExtOrTrunc(LHS, SDLoc(LHS), WideTy),
1073 DAG.getSExtOrTrunc(RHS, SDLoc(RHS), WideTy), CC);
1074 }
1075
1076 // Treat all other vector types as legal.
1077 if (ResTy.isVector())
1078 return Op;
1079
1080 // Comparisons of short integers should use sign-extend, not zero-extend,
1081 // since we can represent small negative values in the compare instructions.
1082 // The LLVM default is to use zero-extend arbitrarily in these cases.
1083 auto isSExtFree = [this](SDValue N) {
1084 switch (N.getOpcode()) {
1085 case ISD::TRUNCATE: {
1086 // A sign-extend of a truncate of a sign-extend is free.
1087 SDValue Op = N.getOperand(0);
1088 if (Op.getOpcode() != ISD::AssertSext)
1089 return false;
1090 EVT OrigTy = cast<VTSDNode>(Op.getOperand(1))->getVT();
1091 unsigned ThisBW = ty(N).getSizeInBits();
1092 unsigned OrigBW = OrigTy.getSizeInBits();
1093 // The type that was sign-extended to get the AssertSext must be
1094 // narrower than the type of N (so that N has still the same value
1095 // as the original).
1096 return ThisBW >= OrigBW;
1097 }
1098 case ISD::LOAD:
1099 // We have sign-extended loads.
1100 return true;
1101 }
1102 return false;
1103 };
1104
1105 if (OpTy == MVT::i8 || OpTy == MVT::i16) {
1107 bool IsNegative = C && C->getAPIntValue().isNegative();
1108 if (IsNegative || isSExtFree(LHS) || isSExtFree(RHS))
1109 return DAG.getSetCC(dl, ResTy,
1110 DAG.getSExtOrTrunc(LHS, SDLoc(LHS), MVT::i32),
1111 DAG.getSExtOrTrunc(RHS, SDLoc(RHS), MVT::i32), CC);
1112 }
1113
1114 return SDValue();
1115}
1116
1117SDValue
1119 SDValue PredOp = Op.getOperand(0);
1120 SDValue Op1 = Op.getOperand(1), Op2 = Op.getOperand(2);
1121 MVT OpTy = ty(Op1);
1122 const SDLoc &dl(Op);
1123
1124 if (OpTy == MVT::v2i16 || OpTy == MVT::v4i8) {
1125 assert(OpTy.getVectorElementType().isScalarInteger());
1126 MVT WideTy = OpTy.widenIntegerElementType();
1127 // Generate (trunc (select (_, sext, sext))).
1128 return DAG.getSExtOrTrunc(
1129 DAG.getSelect(dl, WideTy, PredOp,
1130 DAG.getSExtOrTrunc(Op1, dl, WideTy),
1131 DAG.getSExtOrTrunc(Op2, dl, WideTy)),
1132 dl, OpTy);
1133 }
1134
1135 return SDValue();
1136}
1137
1138SDValue
1140 EVT ValTy = Op.getValueType();
1142 Constant *CVal = nullptr;
1143 bool isVTi1Type = false;
1144 if (auto *CV = dyn_cast<ConstantVector>(CPN->getConstVal())) {
1145 if (cast<VectorType>(CV->getType())->getElementType()->isIntegerTy(1)) {
1146 IRBuilder<> IRB(CV->getContext());
1148 unsigned VecLen = CV->getNumOperands();
1149 assert(isPowerOf2_32(VecLen) &&
1150 "conversion only supported for pow2 VectorSize");
1151 for (unsigned i = 0; i < VecLen; ++i)
1152 NewConst.push_back(IRB.getInt8(CV->getOperand(i)->isNullValue()));
1153
1154 CVal = ConstantVector::get(NewConst);
1155 isVTi1Type = true;
1156 }
1157 }
1158 Align Alignment = CPN->getAlign();
1159 bool IsPositionIndependent = isPositionIndependent();
1160 unsigned char TF = IsPositionIndependent ? HexagonII::MO_PCREL : 0;
1161
1162 unsigned Offset = 0;
1163 SDValue T;
1164 if (CPN->isMachineConstantPoolEntry())
1165 T = DAG.getTargetConstantPool(CPN->getMachineCPVal(), ValTy, Alignment,
1166 Offset, TF);
1167 else if (isVTi1Type)
1168 T = DAG.getTargetConstantPool(CVal, ValTy, Alignment, Offset, TF);
1169 else
1170 T = DAG.getTargetConstantPool(CPN->getConstVal(), ValTy, Alignment, Offset,
1171 TF);
1172
1173 assert(cast<ConstantPoolSDNode>(T)->getTargetFlags() == TF &&
1174 "Inconsistent target flag encountered");
1175
1176 if (IsPositionIndependent)
1177 return DAG.getNode(HexagonISD::AT_PCREL, SDLoc(Op), ValTy, T);
1178 return DAG.getNode(HexagonISD::CP, SDLoc(Op), ValTy, T);
1179}
1180
1181SDValue
1183 EVT VT = Op.getValueType();
1184 int Idx = cast<JumpTableSDNode>(Op)->getIndex();
1185 if (isPositionIndependent()) {
1187 return DAG.getNode(HexagonISD::AT_PCREL, SDLoc(Op), VT, T);
1188 }
1189
1190 SDValue T = DAG.getTargetJumpTable(Idx, VT);
1191 return DAG.getNode(HexagonISD::JT, SDLoc(Op), VT, T);
1192}
1193
1194SDValue
1196 const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo();
1198 MachineFrameInfo &MFI = MF.getFrameInfo();
1199 MFI.setReturnAddressIsTaken(true);
1200
1201 EVT VT = Op.getValueType();
1202 SDLoc dl(Op);
1203 unsigned Depth = Op.getConstantOperandVal(0);
1204 if (Depth) {
1205 SDValue FrameAddr = LowerFRAMEADDR(Op, DAG);
1206 SDValue Offset = DAG.getConstant(4, dl, MVT::i32);
1207 return DAG.getLoad(VT, dl, DAG.getEntryNode(),
1208 DAG.getNode(ISD::ADD, dl, VT, FrameAddr, Offset),
1210 }
1211
1212 // Return LR, which contains the return address. Mark it an implicit live-in.
1213 Register Reg = MF.addLiveIn(HRI.getRARegister(), getRegClassFor(MVT::i32));
1214 return DAG.getCopyFromReg(DAG.getEntryNode(), dl, Reg, VT);
1215}
1216
1217SDValue
1219 const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo();
1221 MFI.setFrameAddressIsTaken(true);
1222
1223 EVT VT = Op.getValueType();
1224 SDLoc dl(Op);
1225 unsigned Depth = Op.getConstantOperandVal(0);
1226 SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl,
1227 HRI.getFrameRegister(), VT);
1228 while (Depth--)
1229 FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr,
1231 return FrameAddr;
1232}
1233
1234SDValue
1236 SDLoc dl(Op);
1237 return DAG.getNode(HexagonISD::BARRIER, dl, MVT::Other, Op.getOperand(0));
1238}
1239
1240SDValue
1242 SDLoc dl(Op);
1243 auto *GAN = cast<GlobalAddressSDNode>(Op);
1244 auto PtrVT = getPointerTy(DAG.getDataLayout());
1245 auto *GV = GAN->getGlobal();
1246 int64_t Offset = GAN->getOffset();
1247
1248 auto &HLOF = *HTM.getObjFileLowering();
1249 Reloc::Model RM = HTM.getRelocationModel();
1250
1251 if (RM == Reloc::Static) {
1252 SDValue GA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, Offset);
1253 const GlobalObject *GO = GV->getAliaseeObject();
1254 if (GO && Subtarget.useSmallData() && HLOF.isGlobalInSmallSection(GO, HTM))
1255 return DAG.getNode(HexagonISD::CONST32_GP, dl, PtrVT, GA);
1256 return DAG.getNode(HexagonISD::CONST32, dl, PtrVT, GA);
1257 }
1258
1259 bool UsePCRel = getTargetMachine().shouldAssumeDSOLocal(GV);
1260 if (UsePCRel) {
1261 SDValue GA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, Offset,
1263 return DAG.getNode(HexagonISD::AT_PCREL, dl, PtrVT, GA);
1264 }
1265
1266 // Use GOT index.
1267 SDValue GOT = DAG.getGLOBAL_OFFSET_TABLE(PtrVT);
1268 SDValue GA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, HexagonII::MO_GOT);
1269 SDValue Off = DAG.getConstant(Offset, dl, MVT::i32);
1270 return DAG.getNode(HexagonISD::AT_GOT, dl, PtrVT, GOT, GA, Off);
1271}
1272
1273// Specifies that for loads and stores VT can be promoted to PromotedLdStVT.
1274SDValue
1276 const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress();
1277 SDLoc dl(Op);
1278 EVT PtrVT = getPointerTy(DAG.getDataLayout());
1279
1280 Reloc::Model RM = HTM.getRelocationModel();
1281 if (RM == Reloc::Static) {
1282 SDValue A = DAG.getTargetBlockAddress(BA, PtrVT);
1283 return DAG.getNode(HexagonISD::CONST32_GP, dl, PtrVT, A);
1284 }
1285
1287 return DAG.getNode(HexagonISD::AT_PCREL, dl, PtrVT, A);
1288}
1289
1290SDValue
1292 const {
1293 EVT PtrVT = getPointerTy(DAG.getDataLayout());
1296 return DAG.getNode(HexagonISD::AT_PCREL, SDLoc(Op), PtrVT, GOTSym);
1297}
1298
1299SDValue
1301 GlobalAddressSDNode *GA, SDValue Glue, EVT PtrVT, unsigned ReturnReg,
1302 unsigned char OperandFlags) const {
1304 MachineFrameInfo &MFI = MF.getFrameInfo();
1305 SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
1306 SDLoc dl(GA);
1307 SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl,
1308 GA->getValueType(0),
1309 GA->getOffset(),
1310 OperandFlags);
1311 // Create Operands for the call.The Operands should have the following:
1312 // 1. Chain SDValue
1313 // 2. Callee which in this case is the Global address value.
1314 // 3. Registers live into the call.In this case its R0, as we
1315 // have just one argument to be passed.
1316 // 4. Glue.
1317 // Note: The order is important.
1318
1319 const auto &HRI = *Subtarget.getRegisterInfo();
1320 const uint32_t *Mask = HRI.getCallPreservedMask(MF, CallingConv::C);
1321 assert(Mask && "Missing call preserved mask for calling convention");
1322 SDValue Ops[] = { Chain, TGA, DAG.getRegister(Hexagon::R0, PtrVT),
1323 DAG.getRegisterMask(Mask), Glue };
1324 Chain = DAG.getNode(HexagonISD::CALL, dl, NodeTys, Ops);
1325
1326 // Inform MFI that function has calls.
1327 MFI.setAdjustsStack(true);
1328
1329 Glue = Chain.getValue(1);
1330 return DAG.getCopyFromReg(Chain, dl, ReturnReg, PtrVT, Glue);
1331}
1332
1333//
1334// Lower using the initial executable model for TLS addresses
1335//
1336SDValue
1338 SelectionDAG &DAG) const {
1339 SDLoc dl(GA);
1340 int64_t Offset = GA->getOffset();
1341 auto PtrVT = getPointerTy(DAG.getDataLayout());
1342
1343 // Get the thread pointer.
1344 SDValue TP = DAG.getCopyFromReg(DAG.getEntryNode(), dl, Hexagon::UGP, PtrVT);
1345
1346 bool IsPositionIndependent = isPositionIndependent();
1347 unsigned char TF =
1348 IsPositionIndependent ? HexagonII::MO_IEGOT : HexagonII::MO_IE;
1349
1350 // First generate the TLS symbol address
1351 SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl, PtrVT,
1352 Offset, TF);
1353
1354 SDValue Sym = DAG.getNode(HexagonISD::CONST32, dl, PtrVT, TGA);
1355
1356 if (IsPositionIndependent) {
1357 // Generate the GOT pointer in case of position independent code
1358 SDValue GOT = LowerGLOBAL_OFFSET_TABLE(Sym, DAG);
1359
1360 // Add the TLS Symbol address to GOT pointer.This gives
1361 // GOT relative relocation for the symbol.
1362 Sym = DAG.getNode(ISD::ADD, dl, PtrVT, GOT, Sym);
1363 }
1364
1365 // Load the offset value for TLS symbol.This offset is relative to
1366 // thread pointer.
1367 SDValue LoadOffset =
1368 DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), Sym, MachinePointerInfo());
1369
1370 // Address of the thread local variable is the add of thread
1371 // pointer and the offset of the variable.
1372 return DAG.getNode(ISD::ADD, dl, PtrVT, TP, LoadOffset);
1373}
1374
1375//
1376// Lower using the local executable model for TLS addresses
1377//
1378SDValue
1380 SelectionDAG &DAG) const {
1381 SDLoc dl(GA);
1382 int64_t Offset = GA->getOffset();
1383 auto PtrVT = getPointerTy(DAG.getDataLayout());
1384
1385 // Get the thread pointer.
1386 SDValue TP = DAG.getCopyFromReg(DAG.getEntryNode(), dl, Hexagon::UGP, PtrVT);
1387 // Generate the TLS symbol address
1388 SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl, PtrVT, Offset,
1390 SDValue Sym = DAG.getNode(HexagonISD::CONST32, dl, PtrVT, TGA);
1391
1392 // Address of the thread local variable is the add of thread
1393 // pointer and the offset of the variable.
1394 return DAG.getNode(ISD::ADD, dl, PtrVT, TP, Sym);
1395}
1396
1397//
1398// Lower using the general dynamic model for TLS addresses
1399//
1400SDValue
1402 SelectionDAG &DAG) const {
1403 SDLoc dl(GA);
1404 int64_t Offset = GA->getOffset();
1405 auto PtrVT = getPointerTy(DAG.getDataLayout());
1406
1407 // First generate the TLS symbol address
1408 SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl, PtrVT, Offset,
1410
1411 // Then, generate the GOT pointer
1412 SDValue GOT = LowerGLOBAL_OFFSET_TABLE(TGA, DAG);
1413
1414 // Add the TLS symbol and the GOT pointer
1415 SDValue Sym = DAG.getNode(HexagonISD::CONST32, dl, PtrVT, TGA);
1416 SDValue Chain = DAG.getNode(ISD::ADD, dl, PtrVT, GOT, Sym);
1417
1418 // Copy over the argument to R0
1419 SDValue InGlue;
1420 Chain = DAG.getCopyToReg(DAG.getEntryNode(), dl, Hexagon::R0, Chain, InGlue);
1421 InGlue = Chain.getValue(1);
1422
1423 unsigned Flags = DAG.getSubtarget<HexagonSubtarget>().useLongCalls()
1426
1427 return GetDynamicTLSAddr(DAG, Chain, GA, InGlue, PtrVT,
1428 Hexagon::R0, Flags);
1429}
1430
1431//
1432// Lower TLS addresses.
1433//
1434// For now for dynamic models, we only support the general dynamic model.
1435//
1436SDValue
1438 SelectionDAG &DAG) const {
1440
1441 switch (HTM.getTLSModel(GA->getGlobal())) {
1444 return LowerToTLSGeneralDynamicModel(GA, DAG);
1446 return LowerToTLSInitialExecModel(GA, DAG);
1448 return LowerToTLSLocalExecModel(GA, DAG);
1449 }
1450 llvm_unreachable("Bogus TLS model");
1451}
1452
1453//===----------------------------------------------------------------------===//
1454// TargetLowering Implementation
1455//===----------------------------------------------------------------------===//
1456
1458 const HexagonSubtarget &ST)
1459 : TargetLowering(TM, ST),
1460 HTM(static_cast<const HexagonTargetMachine &>(TM)), Subtarget(ST) {
1461 auto &HRI = *Subtarget.getRegisterInfo();
1462
1466 setStackPointerRegisterToSaveRestore(HRI.getStackRegister());
1469
1472
1475 else
1477
1478 // Limits for inline expansion of memcpy/memmove
1485
1487
1488 //
1489 // Set up register classes.
1490 //
1491
1492 addRegisterClass(MVT::i1, &Hexagon::PredRegsRegClass);
1493 addRegisterClass(MVT::v2i1, &Hexagon::PredRegsRegClass); // bbbbaaaa
1494 addRegisterClass(MVT::v4i1, &Hexagon::PredRegsRegClass); // ddccbbaa
1495 addRegisterClass(MVT::v8i1, &Hexagon::PredRegsRegClass); // hgfedcba
1496 addRegisterClass(MVT::i32, &Hexagon::IntRegsRegClass);
1497 addRegisterClass(MVT::v2i16, &Hexagon::IntRegsRegClass);
1498 addRegisterClass(MVT::v4i8, &Hexagon::IntRegsRegClass);
1499 addRegisterClass(MVT::i64, &Hexagon::DoubleRegsRegClass);
1500 addRegisterClass(MVT::v8i8, &Hexagon::DoubleRegsRegClass);
1501 addRegisterClass(MVT::v4i16, &Hexagon::DoubleRegsRegClass);
1502 addRegisterClass(MVT::v2i32, &Hexagon::DoubleRegsRegClass);
1503
1504 addRegisterClass(MVT::f32, &Hexagon::IntRegsRegClass);
1505 addRegisterClass(MVT::f64, &Hexagon::DoubleRegsRegClass);
1506
1507 //
1508 // Handling of scalar operations.
1509 //
1510 // All operations default to "legal", except:
1511 // - indexed loads and stores (pre-/post-incremented),
1512 // - ANY_EXTEND_VECTOR_INREG, ATOMIC_CMP_SWAP_WITH_SUCCESS, CONCAT_VECTORS,
1513 // ConstantFP, FCEIL, FCOPYSIGN, FEXP, FEXP2, FFLOOR, FGETSIGN,
1514 // FLOG, FLOG2, FLOG10, FMAXIMUMNUM, FMINIMUMNUM, FNEARBYINT, FRINT, FROUND,
1515 // TRAP, FTRUNC, PREFETCH, SIGN_EXTEND_VECTOR_INREG,
1516 // ZERO_EXTEND_VECTOR_INREG,
1517 // which default to "expand" for at least one type.
1518
1519 // Misc operations.
1522 setOperationAction(ISD::TRAP, MVT::Other, Legal);
1539
1540 // Custom legalize GlobalAddress nodes into CONST32.
1544
1545 // Hexagon needs to optimize cases with negative constants.
1549 setOperationAction(ISD::SETCC, MVT::v2i16, Custom);
1550
1551 // VASTART needs to be custom lowered to use the VarArgsFrameIndex.
1553 setOperationAction(ISD::VAEND, MVT::Other, Expand);
1554 setOperationAction(ISD::VAARG, MVT::Other, Expand);
1555 if (Subtarget.isEnvironmentMusl())
1557 else
1559
1563
1564 if (EmitJumpTables)
1566 else
1567 setMinimumJumpTableEntries(std::numeric_limits<unsigned>::max());
1568 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
1569
1570 for (unsigned LegalIntOp :
1572 setOperationAction(LegalIntOp, MVT::i32, Legal);
1573 setOperationAction(LegalIntOp, MVT::i64, Legal);
1574 }
1575
1576 // Hexagon has A4_addp_c and A4_subp_c that take and generate a carry bit,
1577 // but they only operate on i64.
1578 for (MVT VT : MVT::integer_valuetypes()) {
1585 }
1588
1593
1594 // Popcount can count # of 1s in i64 but returns i32.
1599
1604
1609
1610 for (unsigned IntExpOp :
1615 for (MVT VT : MVT::integer_valuetypes())
1616 setOperationAction(IntExpOp, VT, Expand);
1617 }
1618 for (MVT VT : MVT::fp_valuetypes()) {
1619 for (unsigned FPExpOp : {ISD::FDIV, ISD::FSQRT, ISD::FSIN, ISD::FCOS,
1621 setOperationAction(FPExpOp, VT, Expand);
1622
1624 }
1625
1626 // No extending loads from i32.
1627 for (MVT VT : MVT::integer_valuetypes()) {
1628 setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i32, Expand);
1629 setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i32, Expand);
1630 setLoadExtAction(ISD::EXTLOAD, VT, MVT::i32, Expand);
1631 }
1632 // Turn FP truncstore into trunc + store.
1633 setTruncStoreAction(MVT::f64, MVT::f32, Expand);
1634 setTruncStoreAction(MVT::f32, MVT::bf16, Expand);
1635 setTruncStoreAction(MVT::f64, MVT::bf16, Expand);
1636 // Turn FP extload into load/fpextend.
1637 for (MVT VT : MVT::fp_valuetypes())
1638 setLoadExtAction(ISD::EXTLOAD, VT, MVT::f32, Expand);
1639
1640 // Expand BR_CC and SELECT_CC for all integer and fp types.
1641 for (MVT VT : MVT::integer_valuetypes()) {
1644 }
1645 for (MVT VT : MVT::fp_valuetypes()) {
1648 }
1649 setOperationAction(ISD::BR_CC, MVT::Other, Expand);
1650
1651 //
1652 // Handling of vector operations.
1653 //
1654
1655 // Set the action for vector operations to "expand", then override it with
1656 // either "custom" or "legal" for specific cases.
1657 // clang-format off
1658 static const unsigned VectExpOps[] = {
1659 // Integer arithmetic:
1663 // Logical/bit:
1666 // Floating point arithmetic/math functions:
1674 // Misc:
1676 // Vector:
1682 };
1683 // clang-format on
1684
1686 for (unsigned VectExpOp : VectExpOps)
1687 setOperationAction(VectExpOp, VT, Expand);
1688
1689 // Expand all extending loads and truncating stores:
1690 for (MVT TargetVT : MVT::fixedlen_vector_valuetypes()) {
1691 if (TargetVT == VT)
1692 continue;
1693 setLoadExtAction(ISD::EXTLOAD, TargetVT, VT, Expand);
1694 setLoadExtAction(ISD::ZEXTLOAD, TargetVT, VT, Expand);
1695 setLoadExtAction(ISD::SEXTLOAD, TargetVT, VT, Expand);
1696 setTruncStoreAction(VT, TargetVT, Expand);
1697 }
1698
1699 // Normalize all inputs to SELECT to be vectors of i32.
1700 if (VT.getVectorElementType() != MVT::i32) {
1701 MVT VT32 = MVT::getVectorVT(MVT::i32, VT.getSizeInBits()/32);
1703 AddPromotedToType(ISD::SELECT, VT, VT32);
1704 }
1708 }
1709
1712
1713 // Extending loads from (native) vectors of i8 into (native) vectors of i16
1714 // are legal.
1715 setLoadExtAction(ISD::EXTLOAD, MVT::v2i16, MVT::v2i8, Legal);
1716 setLoadExtAction(ISD::ZEXTLOAD, MVT::v2i16, MVT::v2i8, Legal);
1717 setLoadExtAction(ISD::SEXTLOAD, MVT::v2i16, MVT::v2i8, Legal);
1718 setLoadExtAction(ISD::EXTLOAD, MVT::v4i16, MVT::v4i8, Legal);
1719 setLoadExtAction(ISD::ZEXTLOAD, MVT::v4i16, MVT::v4i8, Legal);
1720 setLoadExtAction(ISD::SEXTLOAD, MVT::v4i16, MVT::v4i8, Legal);
1721
1725
1726 // Types natively supported:
1727 for (MVT NativeVT : {MVT::v8i1, MVT::v4i1, MVT::v2i1, MVT::v4i8,
1728 MVT::v8i8, MVT::v2i16, MVT::v4i16, MVT::v2i32}) {
1735
1736 setOperationAction(ISD::ADD, NativeVT, Legal);
1737 setOperationAction(ISD::SUB, NativeVT, Legal);
1738 setOperationAction(ISD::MUL, NativeVT, Legal);
1739 setOperationAction(ISD::AND, NativeVT, Legal);
1740 setOperationAction(ISD::OR, NativeVT, Legal);
1741 setOperationAction(ISD::XOR, NativeVT, Legal);
1742
1743 if (NativeVT.getVectorElementType() != MVT::i1) {
1747 }
1748 }
1749
1750 for (MVT VT : {MVT::v8i8, MVT::v4i16, MVT::v2i32}) {
1755 }
1756
1757 // Custom lower unaligned loads.
1758 // Also, for both loads and stores, verify the alignment of the address
1759 // in case it is a compile-time constant. This is a usability feature to
1760 // provide a meaningful error message to users.
1761 for (MVT VT : {MVT::i16, MVT::i32, MVT::v4i8, MVT::i64, MVT::v8i8,
1762 MVT::v2i16, MVT::v4i16, MVT::v2i32}) {
1765 }
1766
1767 // Custom-lower load/stores of boolean vectors.
1768 for (MVT VT : {MVT::v2i1, MVT::v4i1, MVT::v8i1}) {
1771 }
1772
1773 // Normalize integer compares to EQ/GT/UGT
1774 for (MVT VT : {MVT::v2i16, MVT::v4i8, MVT::v8i8, MVT::v2i32, MVT::v4i16,
1775 MVT::v2i32}) {
1783 }
1784
1785 // Normalize boolean compares to [U]LE/[U]LT
1786 for (MVT VT : {MVT::i1, MVT::v2i1, MVT::v4i1, MVT::v8i1}) {
1791 }
1792
1793 // Custom-lower bitcasts from i8 to v8i1.
1795 setOperationAction(ISD::SETCC, MVT::v2i16, Custom);
1801
1802 // V5+.
1808
1811
1824
1825 // Special handling for half-precision floating point conversions.
1826 // Lower half float conversions into library calls.
1834
1835 setLoadExtAction(ISD::EXTLOAD, MVT::f32, MVT::f16, Expand);
1836 setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f16, Expand);
1837 setLoadExtAction(ISD::EXTLOAD, MVT::f32, MVT::bf16, Expand);
1838 setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::bf16, Expand);
1839
1840 setTruncStoreAction(MVT::f32, MVT::f16, Expand);
1841 setTruncStoreAction(MVT::f64, MVT::f16, Expand);
1842
1843 // Handling of indexed loads/stores: default is "expand".
1844 //
1845 for (MVT VT : {MVT::i8, MVT::i16, MVT::i32, MVT::i64, MVT::f32, MVT::f64,
1846 MVT::v2i16, MVT::v2i32, MVT::v4i8, MVT::v4i16, MVT::v8i8}) {
1849 }
1850
1851 // Subtarget-specific operation actions.
1852 //
1853 if (Subtarget.hasV60Ops()) {
1858 }
1859 if (Subtarget.hasV66Ops()) {
1862 }
1863 if (Subtarget.hasV67Ops()) {
1867 }
1868
1872
1873 if (Subtarget.useHVXOps())
1874 initializeHVXLowering();
1875
1877}
1878
1879bool
1880HexagonTargetLowering::validateConstPtrAlignment(SDValue Ptr, Align NeedAlign,
1881 const SDLoc &dl, SelectionDAG &DAG) const {
1882 auto *CA = dyn_cast<ConstantSDNode>(Ptr);
1883 if (!CA)
1884 return true;
1885 unsigned Addr = CA->getZExtValue();
1886 Align HaveAlign =
1887 Addr != 0 ? Align(1ull << llvm::countr_zero(Addr)) : NeedAlign;
1888 if (HaveAlign >= NeedAlign)
1889 return true;
1890
1891 static int DK_MisalignedTrap = llvm::getNextAvailablePluginDiagnosticKind();
1892
1893 struct DiagnosticInfoMisalignedTrap : public DiagnosticInfo {
1894 DiagnosticInfoMisalignedTrap(StringRef M)
1895 : DiagnosticInfo(DK_MisalignedTrap, DS_Remark), Msg(M) {}
1896 void print(DiagnosticPrinter &DP) const override {
1897 DP << Msg;
1898 }
1899 static bool classof(const DiagnosticInfo *DI) {
1900 return DI->getKind() == DK_MisalignedTrap;
1901 }
1902 StringRef Msg;
1903 };
1904
1905 std::string ErrMsg;
1906 raw_string_ostream O(ErrMsg);
1907 O << "Misaligned constant address: " << format_hex(Addr, 10)
1908 << " has alignment " << HaveAlign.value()
1909 << ", but the memory access requires " << NeedAlign.value();
1910 if (DebugLoc DL = dl.getDebugLoc())
1911 DL.print(O << ", at ");
1912 O << ". The instruction has been replaced with a trap.";
1913
1914 DAG.getContext()->diagnose(DiagnosticInfoMisalignedTrap(O.str()));
1915 return false;
1916}
1917
1918SDValue
1919HexagonTargetLowering::replaceMemWithUndef(SDValue Op, SelectionDAG &DAG)
1920 const {
1921 const SDLoc &dl(Op);
1922 auto *LS = cast<LSBaseSDNode>(Op.getNode());
1923 assert(!LS->isIndexed() && "Not expecting indexed ops on constant address");
1924
1925 SDValue Chain = LS->getChain();
1926 SDValue Trap = DAG.getNode(ISD::TRAP, dl, MVT::Other, Chain);
1927 if (LS->getOpcode() == ISD::LOAD)
1928 return DAG.getMergeValues({DAG.getUNDEF(ty(Op)), Trap}, dl);
1929 return Trap;
1930}
1931
1932// Bit-reverse Load Intrinsic: Check if the instruction is a bit reverse load
1933// intrinsic.
1934static bool isBrevLdIntrinsic(const Value *Inst) {
1935 unsigned ID = cast<IntrinsicInst>(Inst)->getIntrinsicID();
1936 return (ID == Intrinsic::hexagon_L2_loadrd_pbr ||
1937 ID == Intrinsic::hexagon_L2_loadri_pbr ||
1938 ID == Intrinsic::hexagon_L2_loadrh_pbr ||
1939 ID == Intrinsic::hexagon_L2_loadruh_pbr ||
1940 ID == Intrinsic::hexagon_L2_loadrb_pbr ||
1941 ID == Intrinsic::hexagon_L2_loadrub_pbr);
1942}
1943
1944// Bit-reverse Load Intrinsic :Crawl up and figure out the object from previous
1945// instruction. So far we only handle bitcast, extract value and bit reverse
1946// load intrinsic instructions. Should we handle CGEP ?
1948 if (Operator::getOpcode(V) == Instruction::ExtractValue ||
1949 Operator::getOpcode(V) == Instruction::BitCast)
1950 V = cast<Operator>(V)->getOperand(0);
1951 else if (isa<IntrinsicInst>(V) && isBrevLdIntrinsic(V))
1952 V = cast<Instruction>(V)->getOperand(0);
1953 return V;
1954}
1955
1956// Bit-reverse Load Intrinsic: For a PHI Node return either an incoming edge or
1957// a back edge. If the back edge comes from the intrinsic itself, the incoming
1958// edge is returned.
1959static Value *returnEdge(const PHINode *PN, Value *IntrBaseVal) {
1960 const BasicBlock *Parent = PN->getParent();
1961 int Idx = -1;
1962 for (unsigned i = 0, e = PN->getNumIncomingValues(); i < e; ++i) {
1963 BasicBlock *Blk = PN->getIncomingBlock(i);
1964 // Determine if the back edge is originated from intrinsic.
1965 if (Blk == Parent) {
1966 Value *BackEdgeVal = PN->getIncomingValue(i);
1967 Value *BaseVal;
1968 // Loop over till we return the same Value or we hit the IntrBaseVal.
1969 do {
1970 BaseVal = BackEdgeVal;
1971 BackEdgeVal = getBrevLdObject(BackEdgeVal);
1972 } while ((BaseVal != BackEdgeVal) && (IntrBaseVal != BackEdgeVal));
1973 // If the getBrevLdObject returns IntrBaseVal, we should return the
1974 // incoming edge.
1975 if (IntrBaseVal == BackEdgeVal)
1976 continue;
1977 Idx = i;
1978 break;
1979 } else // Set the node to incoming edge.
1980 Idx = i;
1981 }
1982 assert(Idx >= 0 && "Unexpected index to incoming argument in PHI");
1983 return PN->getIncomingValue(Idx);
1984}
1985
1986// Bit-reverse Load Intrinsic: Figure out the underlying object the base
1987// pointer points to, for the bit-reverse load intrinsic. Setting this to
1988// memoperand might help alias analysis to figure out the dependencies.
1990 Value *IntrBaseVal = V;
1991 Value *BaseVal;
1992 // Loop over till we return the same Value, implies we either figure out
1993 // the object or we hit a PHI
1994 do {
1995 BaseVal = V;
1996 V = getBrevLdObject(V);
1997 } while (BaseVal != V);
1998
1999 // Identify the object from PHINode.
2000 if (const PHINode *PN = dyn_cast<PHINode>(V))
2001 return returnEdge(PN, IntrBaseVal);
2002 // For non PHI nodes, the object is the last value returned by getBrevLdObject
2003 else
2004 return V;
2005}
2006
2007/// Given an intrinsic, checks if on the target the intrinsic will need to map
2008/// to a MemIntrinsicNode (touches memory). If this is the case, it stores
2009/// the intrinsic information into the Infos vector.
2012 MachineFunction &MF, unsigned Intrinsic) const {
2013 IntrinsicInfo Info;
2014 switch (Intrinsic) {
2015 case Intrinsic::hexagon_L2_loadrd_pbr:
2016 case Intrinsic::hexagon_L2_loadri_pbr:
2017 case Intrinsic::hexagon_L2_loadrh_pbr:
2018 case Intrinsic::hexagon_L2_loadruh_pbr:
2019 case Intrinsic::hexagon_L2_loadrb_pbr:
2020 case Intrinsic::hexagon_L2_loadrub_pbr: {
2021 Info.opc = ISD::INTRINSIC_W_CHAIN;
2022 auto &DL = I.getDataLayout();
2023 auto &Cont = I.getCalledFunction()->getParent()->getContext();
2024 // The intrinsic function call is of the form { ElTy, i8* }
2025 // @llvm.hexagon.L2.loadXX.pbr(i8*, i32). The pointer and memory access type
2026 // should be derived from ElTy.
2027 Type *ElTy = I.getCalledFunction()->getReturnType()->getStructElementType(0);
2028 Info.memVT = MVT::getVT(ElTy);
2029 llvm::Value *BasePtrVal = I.getOperand(0);
2030 Info.ptrVal = getUnderLyingObjectForBrevLdIntr(BasePtrVal);
2031 // The offset value comes through Modifier register. For now, assume the
2032 // offset is 0.
2033 Info.offset = 0;
2034 Info.align = DL.getABITypeAlign(Info.memVT.getTypeForEVT(Cont));
2035 Info.flags = MachineMemOperand::MOLoad;
2036 Infos.push_back(Info);
2037 return;
2038 }
2039 case Intrinsic::hexagon_V6_vgathermw:
2040 case Intrinsic::hexagon_V6_vgathermw_128B:
2041 case Intrinsic::hexagon_V6_vgathermh:
2042 case Intrinsic::hexagon_V6_vgathermh_128B:
2043 case Intrinsic::hexagon_V6_vgathermhw:
2044 case Intrinsic::hexagon_V6_vgathermhw_128B:
2045 case Intrinsic::hexagon_V6_vgathermwq:
2046 case Intrinsic::hexagon_V6_vgathermwq_128B:
2047 case Intrinsic::hexagon_V6_vgathermhq:
2048 case Intrinsic::hexagon_V6_vgathermhq_128B:
2049 case Intrinsic::hexagon_V6_vgathermhwq:
2050 case Intrinsic::hexagon_V6_vgathermhwq_128B:
2051 case Intrinsic::hexagon_V6_vgather_vscattermh:
2052 case Intrinsic::hexagon_V6_vgather_vscattermh_128B: {
2053 const Module &M = *I.getParent()->getParent()->getParent();
2054 Info.opc = ISD::INTRINSIC_W_CHAIN;
2055 Type *VecTy = I.getArgOperand(I.arg_size() - 1)->getType();
2056 assert(VecTy->isVectorTy() && "Expected vector operand for vgather");
2057 Info.memVT = MVT::getVT(VecTy);
2058 Info.ptrVal = I.getArgOperand(0);
2059 Info.offset = 0;
2060 Info.align =
2061 MaybeAlign(M.getDataLayout().getTypeAllocSizeInBits(VecTy) / 8);
2064 Infos.push_back(Info);
2065 return;
2066 }
2067 default:
2068 break;
2069 }
2070}
2071
2073 return X.getValueType().isScalarInteger(); // 'tstbit'
2074}
2075
2077 return isTruncateFree(EVT::getEVT(Ty1), EVT::getEVT(Ty2));
2078}
2079
2081 if (!VT1.isSimple() || !VT2.isSimple())
2082 return false;
2083 return VT1.getSimpleVT() == MVT::i64 && VT2.getSimpleVT() == MVT::i32;
2084}
2085
2090
2091// Should we expand the build vector with shuffles?
2093 unsigned DefinedValues) const {
2094 return false;
2095}
2096
2098 unsigned Index) const {
2100 if (!ResVT.isSimple() || !SrcVT.isSimple())
2101 return false;
2102
2103 MVT ResTy = ResVT.getSimpleVT(), SrcTy = SrcVT.getSimpleVT();
2104 if (ResTy.getVectorElementType() != MVT::i1)
2105 return true;
2106
2107 // Non-HVX bool vectors are relatively cheap.
2108 return SrcTy.getVectorNumElements() <= 8;
2109}
2110
2115
2117 EVT VT) const {
2118 return true;
2119}
2120
2123 unsigned VecLen = VT.getVectorMinNumElements();
2124 MVT ElemTy = VT.getVectorElementType();
2125
2126 if (VecLen == 1 || VT.isScalableVector())
2128
2129 if (Subtarget.useHVXOps()) {
2130 unsigned Action = getPreferredHvxVectorAction(VT);
2131 if (Action != ~0u)
2132 return static_cast<TargetLoweringBase::LegalizeTypeAction>(Action);
2133 }
2134
2135 // Always widen (remaining) vectors of i1.
2136 if (ElemTy == MVT::i1)
2138 // Widen non-power-of-2 vectors. Such types cannot be split right now,
2139 // and computeRegisterProperties will override "split" with "widen",
2140 // which can cause other issues.
2141 if (!isPowerOf2_32(VecLen))
2143
2145}
2146
2149 if (Subtarget.useHVXOps()) {
2150 unsigned Action = getCustomHvxOperationAction(Op);
2151 if (Action != ~0u)
2152 return static_cast<TargetLoweringBase::LegalizeAction>(Action);
2153 }
2155}
2156
2157std::pair<SDValue, int>
2158HexagonTargetLowering::getBaseAndOffset(SDValue Addr) const {
2159 if (Addr.getOpcode() == ISD::ADD) {
2160 SDValue Op1 = Addr.getOperand(1);
2161 if (auto *CN = dyn_cast<const ConstantSDNode>(Op1.getNode()))
2162 return { Addr.getOperand(0), CN->getSExtValue() };
2163 }
2164 return { Addr, 0 };
2165}
2166
2167// Lower a vector shuffle (V1, V2, V3). V1 and V2 are the two vectors
2168// to select data from, V3 is the permutation.
2169SDValue
2171 const {
2172 const auto *SVN = cast<ShuffleVectorSDNode>(Op);
2173 ArrayRef<int> AM = SVN->getMask();
2174 assert(AM.size() <= 8 && "Unexpected shuffle mask");
2175 unsigned VecLen = AM.size();
2176
2177 MVT VecTy = ty(Op);
2178 assert(!Subtarget.isHVXVectorType(VecTy, true) &&
2179 "HVX shuffles should be legal");
2180 assert(VecTy.getSizeInBits() <= 64 && "Unexpected vector length");
2181
2182 SDValue Op0 = Op.getOperand(0);
2183 SDValue Op1 = Op.getOperand(1);
2184 const SDLoc &dl(Op);
2185
2186 // If the inputs are not the same as the output, bail. This is not an
2187 // error situation, but complicates the handling and the default expansion
2188 // (into BUILD_VECTOR) should be adequate.
2189 if (ty(Op0) != VecTy || ty(Op1) != VecTy)
2190 return SDValue();
2191
2192 // Normalize the mask so that the first non-negative index comes from
2193 // the first operand.
2194 SmallVector<int, 8> Mask(AM);
2195 unsigned F = llvm::find_if(AM, [](int M) { return M >= 0; }) - AM.data();
2196 if (F == AM.size())
2197 return DAG.getUNDEF(VecTy);
2198 if (AM[F] >= int(VecLen)) {
2200 std::swap(Op0, Op1);
2201 }
2202
2203 // Express the shuffle mask in terms of bytes.
2204 SmallVector<int,8> ByteMask;
2205 unsigned ElemBytes = VecTy.getVectorElementType().getSizeInBits() / 8;
2206 for (int M : Mask) {
2207 if (M < 0) {
2208 for (unsigned j = 0; j != ElemBytes; ++j)
2209 ByteMask.push_back(-1);
2210 } else {
2211 for (unsigned j = 0; j != ElemBytes; ++j)
2212 ByteMask.push_back(M*ElemBytes + j);
2213 }
2214 }
2215 assert(ByteMask.size() <= 8);
2216
2217 // All non-undef (non-negative) indexes are well within [0..127], so they
2218 // fit in a single byte. Build two 64-bit words:
2219 // - MaskIdx where each byte is the corresponding index (for non-negative
2220 // indexes), and 0xFF for negative indexes, and
2221 // - MaskUnd that has 0xFF for each negative index.
2222 uint64_t MaskIdx = 0;
2223 uint64_t MaskUnd = 0;
2224 for (unsigned i = 0, e = ByteMask.size(); i != e; ++i) {
2225 unsigned S = 8*i;
2226 uint64_t M = ByteMask[i] & 0xFF;
2227 if (M == 0xFF)
2228 MaskUnd |= M << S;
2229 MaskIdx |= M << S;
2230 }
2231
2232 if (ByteMask.size() == 4) {
2233 // Identity.
2234 if (MaskIdx == (0x03020100 | MaskUnd))
2235 return Op0;
2236 // Byte swap.
2237 if (MaskIdx == (0x00010203 | MaskUnd)) {
2238 SDValue T0 = DAG.getBitcast(MVT::i32, Op0);
2239 SDValue T1 = DAG.getNode(ISD::BSWAP, dl, MVT::i32, T0);
2240 return DAG.getBitcast(VecTy, T1);
2241 }
2242
2243 // Byte packs.
2244 SDValue Concat10 =
2245 getCombine(Op1, Op0, dl, typeJoin({ty(Op1), ty(Op0)}), DAG);
2246 if (MaskIdx == (0x06040200 | MaskUnd))
2247 return getInstr(Hexagon::S2_vtrunehb, dl, VecTy, {Concat10}, DAG);
2248 if (MaskIdx == (0x07050301 | MaskUnd))
2249 return getInstr(Hexagon::S2_vtrunohb, dl, VecTy, {Concat10}, DAG);
2250
2251 SDValue Concat01 =
2252 getCombine(Op0, Op1, dl, typeJoin({ty(Op0), ty(Op1)}), DAG);
2253 if (MaskIdx == (0x02000604 | MaskUnd))
2254 return getInstr(Hexagon::S2_vtrunehb, dl, VecTy, {Concat01}, DAG);
2255 if (MaskIdx == (0x03010705 | MaskUnd))
2256 return getInstr(Hexagon::S2_vtrunohb, dl, VecTy, {Concat01}, DAG);
2257 }
2258
2259 if (ByteMask.size() == 8) {
2260 // Identity.
2261 if (MaskIdx == (0x0706050403020100ull | MaskUnd))
2262 return Op0;
2263 // Byte swap.
2264 if (MaskIdx == (0x0001020304050607ull | MaskUnd)) {
2265 SDValue T0 = DAG.getBitcast(MVT::i64, Op0);
2266 SDValue T1 = DAG.getNode(ISD::BSWAP, dl, MVT::i64, T0);
2267 return DAG.getBitcast(VecTy, T1);
2268 }
2269
2270 // Halfword picks.
2271 if (MaskIdx == (0x0d0c050409080100ull | MaskUnd))
2272 return getInstr(Hexagon::S2_shuffeh, dl, VecTy, {Op1, Op0}, DAG);
2273 if (MaskIdx == (0x0f0e07060b0a0302ull | MaskUnd))
2274 return getInstr(Hexagon::S2_shuffoh, dl, VecTy, {Op1, Op0}, DAG);
2275 if (MaskIdx == (0x0d0c090805040100ull | MaskUnd))
2276 return getInstr(Hexagon::S2_vtrunewh, dl, VecTy, {Op1, Op0}, DAG);
2277 if (MaskIdx == (0x0f0e0b0a07060302ull | MaskUnd))
2278 return getInstr(Hexagon::S2_vtrunowh, dl, VecTy, {Op1, Op0}, DAG);
2279 if (MaskIdx == (0x0706030205040100ull | MaskUnd)) {
2280 VectorPair P = opSplit(Op0, dl, DAG);
2281 return getInstr(Hexagon::S2_packhl, dl, VecTy, {P.second, P.first}, DAG);
2282 }
2283
2284 // Byte packs.
2285 if (MaskIdx == (0x0e060c040a020800ull | MaskUnd))
2286 return getInstr(Hexagon::S2_shuffeb, dl, VecTy, {Op1, Op0}, DAG);
2287 if (MaskIdx == (0x0f070d050b030901ull | MaskUnd))
2288 return getInstr(Hexagon::S2_shuffob, dl, VecTy, {Op1, Op0}, DAG);
2289 }
2290
2291 return SDValue();
2292}
2293
2294SDValue
2295HexagonTargetLowering::getSplatValue(SDValue Op, SelectionDAG &DAG) const {
2296 switch (Op.getOpcode()) {
2297 case ISD::BUILD_VECTOR:
2299 return S;
2300 break;
2301 case ISD::SPLAT_VECTOR:
2302 return Op.getOperand(0);
2303 }
2304 return SDValue();
2305}
2306
2307// Create a Hexagon-specific node for shifting a vector by an integer.
2308SDValue
2309HexagonTargetLowering::getVectorShiftByInt(SDValue Op, SelectionDAG &DAG)
2310 const {
2311 unsigned NewOpc;
2312 switch (Op.getOpcode()) {
2313 case ISD::SHL:
2314 NewOpc = HexagonISD::VASL;
2315 break;
2316 case ISD::SRA:
2317 NewOpc = HexagonISD::VASR;
2318 break;
2319 case ISD::SRL:
2320 NewOpc = HexagonISD::VLSR;
2321 break;
2322 default:
2323 llvm_unreachable("Unexpected shift opcode");
2324 }
2325 if (SDValue Sp = getSplatValue(Op.getOperand(1), DAG)) {
2326 const SDLoc dl(Op);
2327 // Canonicalize shift amount to i32 as required.
2328 SDValue Sh = Sp;
2329 if (Sh.getValueType() != MVT::i32)
2330 Sh = DAG.getZExtOrTrunc(Sh, dl, MVT::i32);
2331
2332 assert(Sh.getValueType() == MVT::i32 &&
2333 "Hexagon vector shift-by-int must use i32 shift operand");
2334 return DAG.getNode(NewOpc, dl, ty(Op), Op.getOperand(0), Sh);
2335 }
2336
2337 return SDValue();
2338}
2339
2340SDValue
2342 const SDLoc &dl(Op);
2343
2344 // First try to convert the shift (by vector) to a shift by a scalar.
2345 // If we first split the shift, the shift amount will become 'extract
2346 // subvector', and will no longer be recognized as scalar.
2347 SDValue Res = Op;
2348 if (SDValue S = getVectorShiftByInt(Op, DAG))
2349 Res = S;
2350
2351 unsigned Opc = Res.getOpcode();
2352 switch (Opc) {
2353 case HexagonISD::VASR:
2354 case HexagonISD::VLSR:
2355 case HexagonISD::VASL:
2356 break;
2357 default:
2358 // No instructions for shifts by non-scalars.
2359 return SDValue();
2360 }
2361
2362 MVT ResTy = ty(Res);
2363 if (ResTy.getVectorElementType() != MVT::i8)
2364 return Res;
2365
2366 // For shifts of i8, extend the inputs to i16, then truncate back to i8.
2367 assert(ResTy.getVectorElementType() == MVT::i8);
2368 SDValue Val = Res.getOperand(0), Amt = Res.getOperand(1);
2369
2370 auto ShiftPartI8 = [&dl, &DAG, this](unsigned Opc, SDValue V, SDValue A) {
2371 MVT Ty = ty(V);
2372 MVT ExtTy = MVT::getVectorVT(MVT::i16, Ty.getVectorNumElements());
2373 SDValue ExtV = Opc == HexagonISD::VASR ? DAG.getSExtOrTrunc(V, dl, ExtTy)
2374 : DAG.getZExtOrTrunc(V, dl, ExtTy);
2375 SDValue ExtS = DAG.getNode(Opc, dl, ExtTy, {ExtV, A});
2376 return DAG.getZExtOrTrunc(ExtS, dl, Ty);
2377 };
2378
2379 if (ResTy.getSizeInBits() == 32)
2380 return ShiftPartI8(Opc, Val, Amt);
2381
2382 auto [LoV, HiV] = opSplit(Val, dl, DAG);
2383 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResTy,
2384 {ShiftPartI8(Opc, LoV, Amt), ShiftPartI8(Opc, HiV, Amt)});
2385}
2386
2387SDValue
2389 if (isa<ConstantSDNode>(Op.getOperand(1).getNode()))
2390 return Op;
2391 return SDValue();
2392}
2393
2394SDValue
2396 MVT ResTy = ty(Op);
2397 SDValue InpV = Op.getOperand(0);
2398 MVT InpTy = ty(InpV);
2399 assert(ResTy.getSizeInBits() == InpTy.getSizeInBits());
2400 const SDLoc &dl(Op);
2401
2402 // Handle conversion from i8 to v8i1.
2403 if (InpTy == MVT::i8) {
2404 if (ResTy == MVT::v8i1) {
2405 SDValue Sc = DAG.getBitcast(tyScalar(InpTy), InpV);
2406 SDValue Ext = DAG.getZExtOrTrunc(Sc, dl, MVT::i32);
2407 return getInstr(Hexagon::C2_tfrrp, dl, ResTy, Ext, DAG);
2408 }
2409 return SDValue();
2410 }
2411
2412 return Op;
2413}
2414
2415bool
2416HexagonTargetLowering::getBuildVectorConstInts(ArrayRef<SDValue> Values,
2417 MVT VecTy, SelectionDAG &DAG,
2418 MutableArrayRef<ConstantInt*> Consts) const {
2419 MVT ElemTy = VecTy.getVectorElementType();
2420 unsigned ElemWidth = ElemTy.getSizeInBits();
2421 IntegerType *IntTy = IntegerType::get(*DAG.getContext(), ElemWidth);
2422 bool AllConst = true;
2423
2424 for (unsigned i = 0, e = Values.size(); i != e; ++i) {
2425 SDValue V = Values[i];
2426 if (V.isUndef()) {
2427 Consts[i] = ConstantInt::get(IntTy, 0);
2428 continue;
2429 }
2430 // Make sure to always cast to IntTy.
2431 if (auto *CN = dyn_cast<ConstantSDNode>(V.getNode())) {
2432 const ConstantInt *CI = CN->getConstantIntValue();
2433 Consts[i] = cast<ConstantInt>(
2434 ConstantInt::get(IntTy, CI->getValue().trunc(ElemWidth)));
2435 } else if (auto *CN = dyn_cast<ConstantFPSDNode>(V.getNode())) {
2436 const ConstantFP *CF = CN->getConstantFPValue();
2437 APInt A = CF->getValueAPF().bitcastToAPInt();
2438 Consts[i] = ConstantInt::get(IntTy, A.getZExtValue());
2439 } else {
2440 AllConst = false;
2441 }
2442 }
2443 return AllConst;
2444}
2445
2446SDValue
2447HexagonTargetLowering::buildVector32(ArrayRef<SDValue> Elem, const SDLoc &dl,
2448 MVT VecTy, SelectionDAG &DAG) const {
2449 MVT ElemTy = VecTy.getVectorElementType();
2450 assert(VecTy.getVectorNumElements() == Elem.size());
2451
2452 SmallVector<ConstantInt*,4> Consts(Elem.size());
2453 bool AllConst = getBuildVectorConstInts(Elem, VecTy, DAG, Consts);
2454
2455 unsigned First, Num = Elem.size();
2456 for (First = 0; First != Num; ++First) {
2457 if (!isUndef(Elem[First]))
2458 break;
2459 }
2460 if (First == Num)
2461 return DAG.getUNDEF(VecTy);
2462
2463 if (AllConst &&
2464 llvm::all_of(Consts, [](ConstantInt *CI) { return CI->isZero(); }))
2465 return getZero(dl, VecTy, DAG);
2466
2467 if (ElemTy == MVT::i16 || ElemTy == MVT::f16) {
2468 assert(Elem.size() == 2);
2469 if (AllConst) {
2470 // The 'Consts' array will have all values as integers regardless
2471 // of the vector element type.
2472 uint32_t V = (Consts[0]->getZExtValue() & 0xFFFF) |
2473 Consts[1]->getZExtValue() << 16;
2474 return DAG.getBitcast(VecTy, DAG.getConstant(V, dl, MVT::i32));
2475 }
2476 SDValue E0, E1;
2477 if (ElemTy == MVT::f16) {
2478 E0 = DAG.getZExtOrTrunc(DAG.getBitcast(MVT::i16, Elem[0]), dl, MVT::i32);
2479 E1 = DAG.getZExtOrTrunc(DAG.getBitcast(MVT::i16, Elem[1]), dl, MVT::i32);
2480 } else {
2481 E0 = Elem[0];
2482 E1 = Elem[1];
2483 }
2484 SDValue N = getInstr(Hexagon::A2_combine_ll, dl, MVT::i32, {E1, E0}, DAG);
2485 return DAG.getBitcast(VecTy, N);
2486 }
2487
2488 if (ElemTy == MVT::i8) {
2489 // First try generating a constant.
2490 if (AllConst) {
2491 uint32_t V = (Consts[0]->getZExtValue() & 0xFF) |
2492 (Consts[1]->getZExtValue() & 0xFF) << 8 |
2493 (Consts[2]->getZExtValue() & 0xFF) << 16 |
2494 Consts[3]->getZExtValue() << 24;
2495 return DAG.getBitcast(MVT::v4i8, DAG.getConstant(V, dl, MVT::i32));
2496 }
2497
2498 // Then try splat.
2499 bool IsSplat = true;
2500 for (unsigned i = First+1; i != Num; ++i) {
2501 if (Elem[i] == Elem[First] || isUndef(Elem[i]))
2502 continue;
2503 IsSplat = false;
2504 break;
2505 }
2506 if (IsSplat) {
2507 // Legalize the operand of SPLAT_VECTOR.
2508 SDValue Ext = DAG.getZExtOrTrunc(Elem[First], dl, MVT::i32);
2509 return DAG.getNode(ISD::SPLAT_VECTOR, dl, VecTy, Ext);
2510 }
2511
2512 // Generate
2513 // (zxtb(Elem[0]) | (zxtb(Elem[1]) << 8)) |
2514 // (zxtb(Elem[2]) | (zxtb(Elem[3]) << 8)) << 16
2515 assert(Elem.size() == 4);
2516 SDValue Vs[4];
2517 for (unsigned i = 0; i != 4; ++i) {
2518 Vs[i] = DAG.getZExtOrTrunc(Elem[i], dl, MVT::i32);
2519 Vs[i] = DAG.getZeroExtendInReg(Vs[i], dl, MVT::i8);
2520 }
2521 SDValue S8 = DAG.getConstant(8, dl, MVT::i32);
2522 SDValue T0 = DAG.getNode(ISD::SHL, dl, MVT::i32, {Vs[1], S8});
2523 SDValue T1 = DAG.getNode(ISD::SHL, dl, MVT::i32, {Vs[3], S8});
2524 SDValue B0 = DAG.getNode(ISD::OR, dl, MVT::i32, {Vs[0], T0});
2525 SDValue B1 = DAG.getNode(ISD::OR, dl, MVT::i32, {Vs[2], T1});
2526
2527 SDValue R = getInstr(Hexagon::A2_combine_ll, dl, MVT::i32, {B1, B0}, DAG);
2528 return DAG.getBitcast(MVT::v4i8, R);
2529 }
2530
2531#ifndef NDEBUG
2532 dbgs() << "VecTy: " << VecTy << '\n';
2533#endif
2534 llvm_unreachable("Unexpected vector element type");
2535}
2536
2537SDValue
2538HexagonTargetLowering::buildVector64(ArrayRef<SDValue> Elem, const SDLoc &dl,
2539 MVT VecTy, SelectionDAG &DAG) const {
2540 MVT ElemTy = VecTy.getVectorElementType();
2541 assert(VecTy.getVectorNumElements() == Elem.size());
2542
2543 SmallVector<ConstantInt*,8> Consts(Elem.size());
2544 bool AllConst = getBuildVectorConstInts(Elem, VecTy, DAG, Consts);
2545
2546 unsigned First, Num = Elem.size();
2547 for (First = 0; First != Num; ++First) {
2548 if (!isUndef(Elem[First]))
2549 break;
2550 }
2551 if (First == Num)
2552 return DAG.getUNDEF(VecTy);
2553
2554 if (AllConst &&
2555 llvm::all_of(Consts, [](ConstantInt *CI) { return CI->isZero(); }))
2556 return getZero(dl, VecTy, DAG);
2557
2558 // First try splat if possible.
2559 if (ElemTy == MVT::i16 || ElemTy == MVT::f16) {
2560 bool IsSplat = true;
2561 for (unsigned i = First+1; i != Num; ++i) {
2562 if (Elem[i] == Elem[First] || isUndef(Elem[i]))
2563 continue;
2564 IsSplat = false;
2565 break;
2566 }
2567 if (IsSplat) {
2568 // Legalize the operand of SPLAT_VECTOR
2569 SDValue S = ElemTy == MVT::f16 ? DAG.getBitcast(MVT::i16, Elem[First])
2570 : Elem[First];
2571 SDValue Ext = DAG.getZExtOrTrunc(S, dl, MVT::i32);
2572 return DAG.getNode(ISD::SPLAT_VECTOR, dl, VecTy, Ext);
2573 }
2574 }
2575
2576 // Then try constant.
2577 if (AllConst) {
2578 uint64_t Val = 0;
2579 unsigned W = ElemTy.getSizeInBits();
2580 uint64_t Mask = (1ull << W) - 1;
2581 for (unsigned i = 0; i != Num; ++i)
2582 Val = (Val << W) | (Consts[Num-1-i]->getZExtValue() & Mask);
2583 SDValue V0 = DAG.getConstant(Val, dl, MVT::i64);
2584 return DAG.getBitcast(VecTy, V0);
2585 }
2586
2587 // Build two 32-bit vectors and concatenate.
2588 MVT HalfTy = MVT::getVectorVT(ElemTy, Num/2);
2589 SDValue L = (ElemTy == MVT::i32)
2590 ? Elem[0]
2591 : buildVector32(Elem.take_front(Num/2), dl, HalfTy, DAG);
2592 SDValue H = (ElemTy == MVT::i32)
2593 ? Elem[1]
2594 : buildVector32(Elem.drop_front(Num/2), dl, HalfTy, DAG);
2595 return getCombine(H, L, dl, VecTy, DAG);
2596}
2597
2598SDValue
2599HexagonTargetLowering::extractVector(SDValue VecV, SDValue IdxV,
2600 const SDLoc &dl, MVT ValTy, MVT ResTy,
2601 SelectionDAG &DAG) const {
2602 MVT VecTy = ty(VecV);
2603 assert(!ValTy.isVector() ||
2604 VecTy.getVectorElementType() == ValTy.getVectorElementType());
2605 if (VecTy.getVectorElementType() == MVT::i1)
2606 return extractVectorPred(VecV, IdxV, dl, ValTy, ResTy, DAG);
2607
2608 unsigned VecWidth = VecTy.getSizeInBits();
2609 unsigned ValWidth = ValTy.getSizeInBits();
2610 unsigned ElemWidth = VecTy.getVectorElementType().getSizeInBits();
2611 assert((VecWidth % ElemWidth) == 0);
2612 assert(VecWidth == 32 || VecWidth == 64);
2613
2614 // Cast everything to scalar integer types.
2615 MVT ScalarTy = tyScalar(VecTy);
2616 VecV = DAG.getBitcast(ScalarTy, VecV);
2617
2618 SDValue WidthV = DAG.getConstant(ValWidth, dl, MVT::i32);
2619 SDValue ExtV;
2620
2621 if (auto *IdxN = dyn_cast<ConstantSDNode>(IdxV)) {
2622 unsigned Off = IdxN->getZExtValue() * ElemWidth;
2623 if (VecWidth == 64 && ValWidth == 32) {
2624 assert(Off == 0 || Off == 32);
2625 ExtV = Off == 0 ? LoHalf(VecV, DAG) : HiHalf(VecV, DAG);
2626 } else if (Off == 0 && (ValWidth % 8) == 0) {
2627 ExtV = DAG.getZeroExtendInReg(VecV, dl, tyScalar(ValTy));
2628 } else {
2629 SDValue OffV = DAG.getConstant(Off, dl, MVT::i32);
2630 // The return type of EXTRACTU must be the same as the type of the
2631 // input vector.
2632 ExtV = DAG.getNode(HexagonISD::EXTRACTU, dl, ScalarTy,
2633 {VecV, WidthV, OffV});
2634 }
2635 } else {
2636 if (ty(IdxV) != MVT::i32)
2637 IdxV = DAG.getZExtOrTrunc(IdxV, dl, MVT::i32);
2638 SDValue OffV = DAG.getNode(ISD::MUL, dl, MVT::i32, IdxV,
2639 DAG.getConstant(ElemWidth, dl, MVT::i32));
2640 ExtV = DAG.getNode(HexagonISD::EXTRACTU, dl, ScalarTy,
2641 {VecV, WidthV, OffV});
2642 }
2643
2644 // Cast ExtV to the requested result type.
2645 ExtV = DAG.getZExtOrTrunc(ExtV, dl, tyScalar(ResTy));
2646 ExtV = DAG.getBitcast(ResTy, ExtV);
2647 return ExtV;
2648}
2649
2650SDValue
2651HexagonTargetLowering::extractVectorPred(SDValue VecV, SDValue IdxV,
2652 const SDLoc &dl, MVT ValTy, MVT ResTy,
2653 SelectionDAG &DAG) const {
2654 // Special case for v{8,4,2}i1 (the only boolean vectors legal in Hexagon
2655 // without any coprocessors).
2656 MVT VecTy = ty(VecV);
2657 unsigned VecWidth = VecTy.getSizeInBits();
2658 unsigned ValWidth = ValTy.getSizeInBits();
2659 assert(VecWidth == VecTy.getVectorNumElements() &&
2660 "Vector elements should equal vector width size");
2661 assert(VecWidth == 8 || VecWidth == 4 || VecWidth == 2);
2662
2663 // Check if this is an extract of the lowest bit.
2664 if (isNullConstant(IdxV) && ValTy.getSizeInBits() == 1) {
2665 // Extracting the lowest bit is a no-op, but it changes the type,
2666 // so it must be kept as an operation to avoid errors related to
2667 // type mismatches.
2668 return DAG.getNode(HexagonISD::TYPECAST, dl, MVT::i1, VecV);
2669 }
2670
2671 // If the value extracted is a single bit, use tstbit.
2672 if (ValWidth == 1) {
2673 SDValue A0 = getInstr(Hexagon::C2_tfrpr, dl, MVT::i32, {VecV}, DAG);
2674 SDValue M0 = DAG.getConstant(8 / VecWidth, dl, MVT::i32);
2675 SDValue I0 = DAG.getNode(ISD::MUL, dl, MVT::i32, IdxV, M0);
2676 return DAG.getNode(HexagonISD::TSTBIT, dl, MVT::i1, A0, I0);
2677 }
2678
2679 // Each bool vector (v2i1, v4i1, v8i1) always occupies 8 bits in
2680 // a predicate register. The elements of the vector are repeated
2681 // in the register (if necessary) so that the total number is 8.
2682 // The extracted subvector will need to be expanded in such a way.
2683 unsigned Scale = VecWidth / ValWidth;
2684
2685 // Generate (p2d VecV) >> 8*Idx to move the interesting bytes to
2686 // position 0.
2687 assert(ty(IdxV) == MVT::i32);
2688 unsigned VecRep = 8 / VecWidth;
2689 SDValue S0 = DAG.getNode(ISD::MUL, dl, MVT::i32, IdxV,
2690 DAG.getConstant(8*VecRep, dl, MVT::i32));
2691 SDValue T0 = DAG.getNode(HexagonISD::P2D, dl, MVT::i64, VecV);
2692 SDValue T1 = DAG.getNode(ISD::SRL, dl, MVT::i64, T0, S0);
2693 while (Scale > 1) {
2694 // The longest possible subvector is at most 32 bits, so it is always
2695 // contained in the low subregister.
2696 T1 = LoHalf(T1, DAG);
2697 T1 = expandPredicate(T1, dl, DAG);
2698 Scale /= 2;
2699 }
2700
2701 return DAG.getNode(HexagonISD::D2P, dl, ResTy, T1);
2702}
2703
2704SDValue
2705HexagonTargetLowering::insertVector(SDValue VecV, SDValue ValV, SDValue IdxV,
2706 const SDLoc &dl, MVT ValTy,
2707 SelectionDAG &DAG) const {
2708 MVT VecTy = ty(VecV);
2709 if (VecTy.getVectorElementType() == MVT::i1)
2710 return insertVectorPred(VecV, ValV, IdxV, dl, ValTy, DAG);
2711
2712 unsigned VecWidth = VecTy.getSizeInBits();
2713 unsigned ValWidth = ValTy.getSizeInBits();
2714 assert(VecWidth == 32 || VecWidth == 64);
2715 assert((VecWidth % ValWidth) == 0);
2716
2717 // Cast everything to scalar integer types.
2718 MVT ScalarTy = MVT::getIntegerVT(VecWidth);
2719 // The actual type of ValV may be different than ValTy (which is related
2720 // to the vector type).
2721 unsigned VW = ty(ValV).getSizeInBits();
2722 ValV = DAG.getBitcast(MVT::getIntegerVT(VW), ValV);
2723 VecV = DAG.getBitcast(ScalarTy, VecV);
2724 if (VW != VecWidth)
2725 ValV = DAG.getAnyExtOrTrunc(ValV, dl, ScalarTy);
2726
2727 SDValue WidthV = DAG.getConstant(ValWidth, dl, MVT::i32);
2728 SDValue InsV;
2729
2730 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(IdxV)) {
2731 unsigned W = C->getZExtValue() * ValWidth;
2732 SDValue OffV = DAG.getConstant(W, dl, MVT::i32);
2733 InsV = DAG.getNode(HexagonISD::INSERT, dl, ScalarTy,
2734 {VecV, ValV, WidthV, OffV});
2735 } else {
2736 if (ty(IdxV) != MVT::i32)
2737 IdxV = DAG.getZExtOrTrunc(IdxV, dl, MVT::i32);
2738 SDValue OffV = DAG.getNode(ISD::MUL, dl, MVT::i32, IdxV, WidthV);
2739 InsV = DAG.getNode(HexagonISD::INSERT, dl, ScalarTy,
2740 {VecV, ValV, WidthV, OffV});
2741 }
2742
2743 return DAG.getNode(ISD::BITCAST, dl, VecTy, InsV);
2744}
2745
2746SDValue
2747HexagonTargetLowering::insertVectorPred(SDValue VecV, SDValue ValV,
2748 SDValue IdxV, const SDLoc &dl,
2749 MVT ValTy, SelectionDAG &DAG) const {
2750 MVT VecTy = ty(VecV);
2751 unsigned VecLen = VecTy.getVectorNumElements();
2752
2753 if (ValTy == MVT::i1) {
2754 SDValue ToReg = getInstr(Hexagon::C2_tfrpr, dl, MVT::i32, {VecV}, DAG);
2755 SDValue Ext = DAG.getSExtOrTrunc(ValV, dl, MVT::i32);
2756 SDValue Width = DAG.getConstant(8 / VecLen, dl, MVT::i32);
2757 SDValue Idx = DAG.getNode(ISD::MUL, dl, MVT::i32, IdxV, Width);
2758 SDValue Ins =
2759 DAG.getNode(HexagonISD::INSERT, dl, MVT::i32, {ToReg, Ext, Width, Idx});
2760 return getInstr(Hexagon::C2_tfrrp, dl, VecTy, {Ins}, DAG);
2761 }
2762
2763 assert(ValTy.getVectorElementType() == MVT::i1);
2764 SDValue ValR = ValTy.isVector()
2765 ? DAG.getNode(HexagonISD::P2D, dl, MVT::i64, ValV)
2766 : DAG.getSExtOrTrunc(ValV, dl, MVT::i64);
2767
2768 unsigned Scale = VecLen / ValTy.getVectorNumElements();
2769 assert(Scale > 1);
2770
2771 for (unsigned R = Scale; R > 1; R /= 2) {
2772 ValR = contractPredicate(ValR, dl, DAG);
2773 ValR = getCombine(DAG.getUNDEF(MVT::i32), ValR, dl, MVT::i64, DAG);
2774 }
2775
2776 SDValue Width = DAG.getConstant(64 / Scale, dl, MVT::i32);
2777 SDValue Idx = DAG.getNode(ISD::MUL, dl, MVT::i32, IdxV, Width);
2778 SDValue VecR = DAG.getNode(HexagonISD::P2D, dl, MVT::i64, VecV);
2779 SDValue Ins =
2780 DAG.getNode(HexagonISD::INSERT, dl, MVT::i64, {VecR, ValR, Width, Idx});
2781 return DAG.getNode(HexagonISD::D2P, dl, VecTy, Ins);
2782}
2783
2784SDValue
2785HexagonTargetLowering::expandPredicate(SDValue Vec32, const SDLoc &dl,
2786 SelectionDAG &DAG) const {
2787 assert(ty(Vec32).getSizeInBits() == 32);
2788 if (isUndef(Vec32))
2789 return DAG.getUNDEF(MVT::i64);
2790 SDValue P = DAG.getBitcast(MVT::v4i8, Vec32);
2791 SDValue X = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::v4i16, P);
2792 return DAG.getBitcast(MVT::i64, X);
2793}
2794
2795SDValue
2796HexagonTargetLowering::contractPredicate(SDValue Vec64, const SDLoc &dl,
2797 SelectionDAG &DAG) const {
2798 assert(ty(Vec64).getSizeInBits() == 64);
2799 if (isUndef(Vec64))
2800 return DAG.getUNDEF(MVT::i32);
2801 // Collect even bytes:
2802 SDValue A = DAG.getBitcast(MVT::v8i8, Vec64);
2803 SDValue S = DAG.getVectorShuffle(MVT::v8i8, dl, A, DAG.getUNDEF(MVT::v8i8),
2804 {0, 2, 4, 6, 1, 3, 5, 7});
2805 return extractVector(S, DAG.getConstant(0, dl, MVT::i32), dl, MVT::v4i8,
2806 MVT::i32, DAG);
2807}
2808
2809SDValue
2810HexagonTargetLowering::getZero(const SDLoc &dl, MVT Ty, SelectionDAG &DAG)
2811 const {
2812 if (Ty.isVector()) {
2813 unsigned W = Ty.getSizeInBits();
2814 if (W <= 64)
2815 return DAG.getBitcast(Ty, DAG.getConstant(0, dl, MVT::getIntegerVT(W)));
2816 return DAG.getNode(ISD::SPLAT_VECTOR, dl, Ty, getZero(dl, MVT::i32, DAG));
2817 }
2818
2819 if (Ty.isInteger())
2820 return DAG.getConstant(0, dl, Ty);
2821 if (Ty.isFloatingPoint())
2822 return DAG.getConstantFP(0.0, dl, Ty);
2823 llvm_unreachable("Invalid type for zero");
2824}
2825
2826SDValue
2827HexagonTargetLowering::appendUndef(SDValue Val, MVT ResTy, SelectionDAG &DAG)
2828 const {
2829 MVT ValTy = ty(Val);
2831
2832 unsigned ValLen = ValTy.getVectorNumElements();
2833 unsigned ResLen = ResTy.getVectorNumElements();
2834 if (ValLen == ResLen)
2835 return Val;
2836
2837 const SDLoc &dl(Val);
2838 assert(ValLen < ResLen);
2839 assert(ResLen % ValLen == 0);
2840
2841 SmallVector<SDValue, 4> Concats = {Val};
2842 for (unsigned i = 1, e = ResLen / ValLen; i < e; ++i)
2843 Concats.push_back(DAG.getUNDEF(ValTy));
2844
2845 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResTy, Concats);
2846}
2847
2848SDValue
2849HexagonTargetLowering::getCombine(SDValue Hi, SDValue Lo, const SDLoc &dl,
2850 MVT ResTy, SelectionDAG &DAG) const {
2851 MVT ElemTy = ty(Hi);
2852 assert(ElemTy == ty(Lo));
2853
2854 if (!ElemTy.isVector()) {
2855 assert(ElemTy.isScalarInteger());
2856 MVT PairTy = ElemTy.widenIntegerElementType();
2857 SDValue Pair = DAG.getNode(ISD::BUILD_PAIR, dl, PairTy, Lo, Hi);
2858 return DAG.getBitcast(ResTy, Pair);
2859 }
2860
2861 unsigned Width = ElemTy.getSizeInBits();
2862 MVT IntTy = MVT::getIntegerVT(Width);
2863 SDValue Pair =
2865 {DAG.getBitcast(IntTy, Lo), DAG.getBitcast(IntTy, Hi)});
2866 return DAG.getBitcast(ResTy, Pair);
2867}
2868
2869SDValue
2871 MVT VecTy = ty(Op);
2872 unsigned BW = VecTy.getSizeInBits();
2873 const SDLoc &dl(Op);
2875 for (unsigned i = 0, e = Op.getNumOperands(); i != e; ++i)
2876 Ops.push_back(Op.getOperand(i));
2877
2878 if (BW == 32)
2879 return buildVector32(Ops, dl, VecTy, DAG);
2880 if (BW == 64)
2881 return buildVector64(Ops, dl, VecTy, DAG);
2882
2883 if (VecTy == MVT::v8i1 || VecTy == MVT::v4i1 || VecTy == MVT::v2i1) {
2884 // Check if this is a special case or all-0 or all-1.
2885 bool All0 = true, All1 = true;
2886 for (SDValue P : Ops) {
2887 auto *CN = dyn_cast<ConstantSDNode>(P.getNode());
2888 if (CN == nullptr) {
2889 All0 = All1 = false;
2890 break;
2891 }
2892 uint32_t C = CN->getZExtValue();
2893 All0 &= (C == 0);
2894 All1 &= (C == 1);
2895 }
2896 if (All0)
2897 return DAG.getNode(HexagonISD::PFALSE, dl, VecTy);
2898 if (All1)
2899 return DAG.getNode(HexagonISD::PTRUE, dl, VecTy);
2900
2901 // For each i1 element in the resulting predicate register, put 1
2902 // shifted by the index of the element into a general-purpose register,
2903 // then or them together and transfer it back into a predicate register.
2904 SDValue Rs[8];
2905 SDValue Z = getZero(dl, MVT::i32, DAG);
2906 // Always produce 8 bits, repeat inputs if necessary.
2907 unsigned Rep = 8 / VecTy.getVectorNumElements();
2908 for (unsigned i = 0; i != 8; ++i) {
2909 SDValue S = DAG.getConstant(1ull << i, dl, MVT::i32);
2910 Rs[i] = DAG.getSelect(dl, MVT::i32, Ops[i/Rep], S, Z);
2911 }
2912 for (ArrayRef<SDValue> A(Rs); A.size() != 1; A = A.drop_back(A.size()/2)) {
2913 for (unsigned i = 0, e = A.size()/2; i != e; ++i)
2914 Rs[i] = DAG.getNode(ISD::OR, dl, MVT::i32, Rs[2*i], Rs[2*i+1]);
2915 }
2916 // Move the value directly to a predicate register.
2917 return getInstr(Hexagon::C2_tfrrp, dl, VecTy, {Rs[0]}, DAG);
2918 }
2919
2920 return SDValue();
2921}
2922
2923SDValue
2925 SelectionDAG &DAG) const {
2926 MVT VecTy = ty(Op);
2927 const SDLoc &dl(Op);
2928 if (VecTy.getSizeInBits() == 64) {
2929 assert(Op.getNumOperands() == 2);
2930 return getCombine(Op.getOperand(1), Op.getOperand(0), dl, VecTy, DAG);
2931 }
2932
2933 MVT ElemTy = VecTy.getVectorElementType();
2934 if (ElemTy == MVT::i1) {
2935 assert(VecTy == MVT::v2i1 || VecTy == MVT::v4i1 || VecTy == MVT::v8i1);
2936 MVT OpTy = ty(Op.getOperand(0));
2937 // Scale is how many times the operands need to be contracted to match
2938 // the representation in the target register.
2939 unsigned Scale = VecTy.getVectorNumElements() / OpTy.getVectorNumElements();
2940 assert(Scale == Op.getNumOperands() && Scale > 1);
2941
2942 // First, convert all bool vectors to integers, then generate pairwise
2943 // inserts to form values of doubled length. Up until there are only
2944 // two values left to concatenate, all of these values will fit in a
2945 // 32-bit integer, so keep them as i32 to use 32-bit inserts.
2946 SmallVector<SDValue,4> Words[2];
2947 unsigned IdxW = 0;
2948
2949 for (SDValue P : Op.getNode()->op_values()) {
2950 SDValue W = DAG.getNode(HexagonISD::P2D, dl, MVT::i64, P);
2951 for (unsigned R = Scale; R > 1; R /= 2) {
2952 W = contractPredicate(W, dl, DAG);
2953 W = getCombine(DAG.getUNDEF(MVT::i32), W, dl, MVT::i64, DAG);
2954 }
2955 W = LoHalf(W, DAG);
2956 Words[IdxW].push_back(W);
2957 }
2958
2959 while (Scale > 2) {
2960 SDValue WidthV = DAG.getConstant(64 / Scale, dl, MVT::i32);
2961 Words[IdxW ^ 1].clear();
2962
2963 for (unsigned i = 0, e = Words[IdxW].size(); i != e; i += 2) {
2964 SDValue W0 = Words[IdxW][i], W1 = Words[IdxW][i+1];
2965 // Insert W1 into W0 right next to the significant bits of W0.
2966 SDValue T = DAG.getNode(HexagonISD::INSERT, dl, MVT::i32,
2967 {W0, W1, WidthV, WidthV});
2968 Words[IdxW ^ 1].push_back(T);
2969 }
2970 IdxW ^= 1;
2971 Scale /= 2;
2972 }
2973
2974 // At this point there should only be two words left, and Scale should be 2.
2975 assert(Scale == 2 && Words[IdxW].size() == 2);
2976
2977 SDValue WW = getCombine(Words[IdxW][1], Words[IdxW][0], dl, MVT::i64, DAG);
2978 return DAG.getNode(HexagonISD::D2P, dl, VecTy, WW);
2979 }
2980
2981 return SDValue();
2982}
2983
2984SDValue
2986 SelectionDAG &DAG) const {
2987 SDValue Vec = Op.getOperand(0);
2988 MVT ElemTy = ty(Vec).getVectorElementType();
2989 return extractVector(Vec, Op.getOperand(1), SDLoc(Op), ElemTy, ty(Op), DAG);
2990}
2991
2992SDValue
2994 SelectionDAG &DAG) const {
2995 return extractVector(Op.getOperand(0), Op.getOperand(1), SDLoc(Op),
2996 ty(Op), ty(Op), DAG);
2997}
2998
2999SDValue
3001 SelectionDAG &DAG) const {
3002 return insertVector(Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
3003 SDLoc(Op), ty(Op).getVectorElementType(), DAG);
3004}
3005
3006SDValue
3008 SelectionDAG &DAG) const {
3009 SDValue ValV = Op.getOperand(1);
3010 return insertVector(Op.getOperand(0), ValV, Op.getOperand(2),
3011 SDLoc(Op), ty(ValV), DAG);
3012}
3013
3014bool
3016 // Assuming the caller does not have either a signext or zeroext modifier, and
3017 // only one value is accepted, any reasonable truncation is allowed.
3018 if (!Ty1->isIntegerTy() || !Ty2->isIntegerTy())
3019 return false;
3020
3021 // FIXME: in principle up to 64-bit could be made safe, but it would be very
3022 // fragile at the moment: any support for multiple value returns would be
3023 // liable to disallow tail calls involving i64 -> iN truncation in many cases.
3024 return Ty1->getPrimitiveSizeInBits() <= 32;
3025}
3026
3027SDValue
3029 MVT Ty = ty(Op);
3030 const SDLoc &dl(Op);
3031 LoadSDNode *LN = cast<LoadSDNode>(Op.getNode());
3032 MVT MemTy = LN->getMemoryVT().getSimpleVT();
3034
3035 bool LoadPred = MemTy == MVT::v2i1 || MemTy == MVT::v4i1 || MemTy == MVT::v8i1;
3036 if (LoadPred) {
3037 SDValue NL = DAG.getLoad(
3038 LN->getAddressingMode(), ISD::ZEXTLOAD, MVT::i32, dl, LN->getChain(),
3039 LN->getBasePtr(), LN->getOffset(), LN->getPointerInfo(),
3040 /*MemoryVT*/ MVT::i8, LN->getAlign(), LN->getMemOperand()->getFlags(),
3041 LN->getAAInfo(), LN->getRanges());
3042 LN = cast<LoadSDNode>(NL.getNode());
3043 }
3044
3045 Align ClaimAlign = LN->getAlign();
3046 if (!validateConstPtrAlignment(LN->getBasePtr(), ClaimAlign, dl, DAG))
3047 return replaceMemWithUndef(Op, DAG);
3048
3049 // Call LowerUnalignedLoad for all loads, it recognizes loads that
3050 // don't need extra aligning.
3051 SDValue LU = LowerUnalignedLoad(SDValue(LN, 0), DAG);
3052 if (LoadPred) {
3053 SDValue TP = getInstr(Hexagon::C2_tfrrp, dl, MemTy, {LU}, DAG);
3054 if (ET == ISD::SEXTLOAD) {
3055 TP = DAG.getSExtOrTrunc(TP, dl, Ty);
3056 } else if (ET != ISD::NON_EXTLOAD) {
3057 TP = DAG.getZExtOrTrunc(TP, dl, Ty);
3058 }
3059 SDValue Ch = cast<LoadSDNode>(LU.getNode())->getChain();
3060 return DAG.getMergeValues({TP, Ch}, dl);
3061 }
3062 return LU;
3063}
3064
3065SDValue
3067 const SDLoc &dl(Op);
3068 StoreSDNode *SN = cast<StoreSDNode>(Op.getNode());
3069 SDValue Val = SN->getValue();
3070 MVT Ty = ty(Val);
3071
3072 if (Ty == MVT::v2i1 || Ty == MVT::v4i1 || Ty == MVT::v8i1) {
3073 // Store the exact predicate (all bits).
3074 SDValue TR = getInstr(Hexagon::C2_tfrpr, dl, MVT::i32, {Val}, DAG);
3075 SDValue NS = DAG.getTruncStore(SN->getChain(), dl, TR, SN->getBasePtr(),
3076 MVT::i8, SN->getMemOperand());
3077 if (SN->isIndexed()) {
3078 NS = DAG.getIndexedStore(NS, dl, SN->getBasePtr(), SN->getOffset(),
3079 SN->getAddressingMode());
3080 }
3081 SN = cast<StoreSDNode>(NS.getNode());
3082 }
3083
3084 Align ClaimAlign = SN->getAlign();
3085 if (!validateConstPtrAlignment(SN->getBasePtr(), ClaimAlign, dl, DAG))
3086 return replaceMemWithUndef(Op, DAG);
3087
3088 MVT StoreTy = SN->getMemoryVT().getSimpleVT();
3089 Align NeedAlign = Subtarget.getTypeAlignment(StoreTy);
3090 if (ClaimAlign < NeedAlign)
3091 return expandUnalignedStore(SN, DAG);
3092 return SDValue(SN, 0);
3093}
3094
3095SDValue
3097 const {
3098 LoadSDNode *LN = cast<LoadSDNode>(Op.getNode());
3099 MVT LoadTy = ty(Op);
3100 unsigned NeedAlign = Subtarget.getTypeAlignment(LoadTy).value();
3101 unsigned HaveAlign = LN->getAlign().value();
3102 if (HaveAlign >= NeedAlign)
3103 return Op;
3104
3105 const SDLoc &dl(Op);
3106 const DataLayout &DL = DAG.getDataLayout();
3107 LLVMContext &Ctx = *DAG.getContext();
3108
3109 // If the load aligning is disabled or the load can be broken up into two
3110 // smaller legal loads, do the default (target-independent) expansion.
3111 bool DoDefault = false;
3112 // Handle it in the default way if this is an indexed load.
3113 if (!LN->isUnindexed())
3114 DoDefault = true;
3115
3116 if (!AlignLoads) {
3118 *LN->getMemOperand()))
3119 return Op;
3120 DoDefault = true;
3121 }
3122 if (!DoDefault && (2 * HaveAlign) == NeedAlign) {
3123 // The PartTy is the equivalent of "getLoadableTypeOfSize(HaveAlign)".
3124 MVT PartTy = HaveAlign <= 8 ? MVT::getIntegerVT(8 * HaveAlign)
3125 : MVT::getVectorVT(MVT::i8, HaveAlign);
3126 DoDefault =
3127 allowsMemoryAccessForAlignment(Ctx, DL, PartTy, *LN->getMemOperand());
3128 }
3129 if (DoDefault) {
3130 std::pair<SDValue, SDValue> P = expandUnalignedLoad(LN, DAG);
3131 return DAG.getMergeValues({P.first, P.second}, dl);
3132 }
3133
3134 // The code below generates two loads, both aligned as NeedAlign, and
3135 // with the distance of NeedAlign between them. For that to cover the
3136 // bits that need to be loaded (and without overlapping), the size of
3137 // the loads should be equal to NeedAlign. This is true for all loadable
3138 // types, but add an assertion in case something changes in the future.
3139 assert(LoadTy.getSizeInBits() == 8*NeedAlign);
3140
3141 unsigned LoadLen = NeedAlign;
3142 SDValue Base = LN->getBasePtr();
3143 SDValue Chain = LN->getChain();
3144 auto BO = getBaseAndOffset(Base);
3145 unsigned BaseOpc = BO.first.getOpcode();
3146 if (BaseOpc == HexagonISD::VALIGNADDR && BO.second % LoadLen == 0)
3147 return Op;
3148
3149 if (BO.second % LoadLen != 0) {
3150 BO.first = DAG.getNode(ISD::ADD, dl, MVT::i32, BO.first,
3151 DAG.getConstant(BO.second % LoadLen, dl, MVT::i32));
3152 BO.second -= BO.second % LoadLen;
3153 }
3154 SDValue BaseNoOff = (BaseOpc != HexagonISD::VALIGNADDR)
3155 ? DAG.getNode(HexagonISD::VALIGNADDR, dl, MVT::i32, BO.first,
3156 DAG.getConstant(NeedAlign, dl, MVT::i32))
3157 : BO.first;
3158 SDValue Base0 =
3159 DAG.getMemBasePlusOffset(BaseNoOff, TypeSize::getFixed(BO.second), dl);
3160 SDValue Base1 = DAG.getMemBasePlusOffset(
3161 BaseNoOff, TypeSize::getFixed(BO.second + LoadLen), dl);
3162
3163 MachineMemOperand *WideMMO = nullptr;
3164 if (MachineMemOperand *MMO = LN->getMemOperand()) {
3166 WideMMO = MF.getMachineMemOperand(
3167 MMO->getPointerInfo(), MMO->getFlags(), 2 * LoadLen, Align(LoadLen),
3168 MMO->getAAInfo(), MMO->getRanges(), MMO->getSyncScopeID(),
3169 MMO->getSuccessOrdering(), MMO->getFailureOrdering());
3170 }
3171
3172 SDValue Load0 = DAG.getLoad(LoadTy, dl, Chain, Base0, WideMMO);
3173 SDValue Load1 = DAG.getLoad(LoadTy, dl, Chain, Base1, WideMMO);
3174
3175 SDValue Aligned = DAG.getNode(HexagonISD::VALIGN, dl, LoadTy,
3176 {Load1, Load0, BaseNoOff.getOperand(0)});
3177 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
3178 Load0.getValue(1), Load1.getValue(1));
3179 SDValue M = DAG.getMergeValues({Aligned, NewChain}, dl);
3180 return M;
3181}
3182
3183SDValue
3185 SDValue X = Op.getOperand(0), Y = Op.getOperand(1);
3186 auto *CY = dyn_cast<ConstantSDNode>(Y);
3187 if (!CY)
3188 return SDValue();
3189
3190 const SDLoc &dl(Op);
3191 SDVTList VTs = Op.getNode()->getVTList();
3192 assert(VTs.NumVTs == 2);
3193 assert(VTs.VTs[1] == MVT::i1);
3194 unsigned Opc = Op.getOpcode();
3195
3196 if (CY) {
3197 uint64_t VY = CY->getZExtValue();
3198 assert(VY != 0 && "This should have been folded");
3199 // X +/- 1
3200 if (VY != 1)
3201 return SDValue();
3202
3203 if (Opc == ISD::UADDO) {
3204 SDValue Op = DAG.getNode(ISD::ADD, dl, VTs.VTs[0], {X, Y});
3205 SDValue Ov = DAG.getSetCC(dl, MVT::i1, Op, getZero(dl, ty(Op), DAG),
3206 ISD::SETEQ);
3207 return DAG.getMergeValues({Op, Ov}, dl);
3208 }
3209 if (Opc == ISD::USUBO) {
3210 SDValue Op = DAG.getNode(ISD::SUB, dl, VTs.VTs[0], {X, Y});
3211 SDValue Ov = DAG.getSetCC(dl, MVT::i1, Op,
3212 DAG.getAllOnesConstant(dl, ty(Op)), ISD::SETEQ);
3213 return DAG.getMergeValues({Op, Ov}, dl);
3214 }
3215 }
3216
3217 return SDValue();
3218}
3219
3221 SelectionDAG &DAG) const {
3222 const SDLoc &dl(Op);
3223 unsigned Opc = Op.getOpcode();
3224 SDValue X = Op.getOperand(0), Y = Op.getOperand(1), C = Op.getOperand(2);
3225
3226 if (Opc == ISD::UADDO_CARRY)
3227 return DAG.getNode(HexagonISD::ADDC, dl, Op.getNode()->getVTList(),
3228 { X, Y, C });
3229
3230 EVT CarryTy = C.getValueType();
3231 SDValue SubC = DAG.getNode(HexagonISD::SUBC, dl, Op.getNode()->getVTList(),
3232 { X, Y, DAG.getLogicalNOT(dl, C, CarryTy) });
3233 SDValue Out[] = { SubC.getValue(0),
3234 DAG.getLogicalNOT(dl, SubC.getValue(1), CarryTy) };
3235 return DAG.getMergeValues(Out, dl);
3236}
3237
3238SDValue
3240 SDValue Chain = Op.getOperand(0);
3241 SDValue Offset = Op.getOperand(1);
3242 SDValue Handler = Op.getOperand(2);
3243 SDLoc dl(Op);
3244 auto PtrVT = getPointerTy(DAG.getDataLayout());
3245
3246 // Mark function as containing a call to EH_RETURN.
3247 HexagonMachineFunctionInfo *FuncInfo =
3249 FuncInfo->setHasEHReturn();
3250
3251 unsigned OffsetReg = Hexagon::R28;
3252
3253 SDValue StoreAddr =
3254 DAG.getNode(ISD::ADD, dl, PtrVT, DAG.getRegister(Hexagon::R30, PtrVT),
3255 DAG.getIntPtrConstant(4, dl));
3256 Chain = DAG.getStore(Chain, dl, Handler, StoreAddr, MachinePointerInfo());
3257 Chain = DAG.getCopyToReg(Chain, dl, OffsetReg, Offset);
3258
3259 // Not needed we already use it as explicit input to EH_RETURN.
3260 // MF.getRegInfo().addLiveOut(OffsetReg);
3261
3262 return DAG.getNode(HexagonISD::EH_RETURN, dl, MVT::Other, Chain);
3263}
3264
3265SDValue
3267 unsigned Opc = Op.getOpcode();
3268 // Handle INLINEASM first.
3270 return LowerINLINEASM(Op, DAG);
3271
3272 if (isHvxOperation(Op.getNode(), DAG)) {
3273 // If HVX lowering returns nothing, try the default lowering.
3274 if (SDValue V = LowerHvxOperation(Op, DAG))
3275 return V;
3276 }
3277
3278 switch (Opc) {
3279 default:
3280#ifndef NDEBUG
3281 Op.getNode()->dumpr(&DAG);
3282#endif
3283 llvm_unreachable("Should not custom lower this!");
3284
3285 case ISD::FDIV:
3286 return LowerFDIV(Op, DAG);
3287 case ISD::CONCAT_VECTORS: return LowerCONCAT_VECTORS(Op, DAG);
3292 case ISD::BUILD_VECTOR: return LowerBUILD_VECTOR(Op, DAG);
3293 case ISD::VECTOR_SHUFFLE: return LowerVECTOR_SHUFFLE(Op, DAG);
3294 case ISD::BITCAST: return LowerBITCAST(Op, DAG);
3295 case ISD::LOAD: return LowerLoad(Op, DAG);
3296 case ISD::STORE: return LowerStore(Op, DAG);
3297 case ISD::UADDO:
3298 case ISD::USUBO: return LowerUAddSubO(Op, DAG);
3299 case ISD::UADDO_CARRY:
3300 case ISD::USUBO_CARRY: return LowerUAddSubOCarry(Op, DAG);
3301 case ISD::SRA:
3302 case ISD::SHL:
3303 case ISD::SRL: return LowerVECTOR_SHIFT(Op, DAG);
3304 case ISD::ROTL: return LowerROTL(Op, DAG);
3305 case ISD::ConstantPool: return LowerConstantPool(Op, DAG);
3306 case ISD::JumpTable: return LowerJumpTable(Op, DAG);
3307 case ISD::EH_RETURN: return LowerEH_RETURN(Op, DAG);
3308 case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG);
3309 case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
3311 case ISD::ATOMIC_FENCE: return LowerATOMIC_FENCE(Op, DAG);
3312 case ISD::GlobalAddress: return LowerGLOBALADDRESS(Op, DAG);
3313 case ISD::BlockAddress: return LowerBlockAddress(Op, DAG);
3315 case ISD::VACOPY: return LowerVACOPY(Op, DAG);
3316 case ISD::VASTART: return LowerVASTART(Op, DAG);
3318 case ISD::SETCC: return LowerSETCC(Op, DAG);
3319 case ISD::VSELECT: return LowerVSELECT(Op, DAG);
3321 case ISD::INTRINSIC_VOID: return LowerINTRINSIC_VOID(Op, DAG);
3322 case ISD::PREFETCH:
3323 return LowerPREFETCH(Op, DAG);
3324 break;
3325 }
3326
3327 return SDValue();
3328}
3329
3330void
3333 SelectionDAG &DAG) const {
3334 if (isHvxOperation(N, DAG)) {
3335 LowerHvxOperationWrapper(N, Results, DAG);
3336 if (!Results.empty())
3337 return;
3338 }
3339
3340 SDValue Op(N, 0);
3341 unsigned Opc = N->getOpcode();
3342
3343 switch (Opc) {
3344 case HexagonISD::SSAT:
3345 case HexagonISD::USAT:
3346 Results.push_back(opJoin(SplitVectorOp(Op, DAG), SDLoc(Op), DAG));
3347 break;
3348 case ISD::STORE:
3349 // We are only custom-lowering stores to verify the alignment of the
3350 // address if it is a compile-time constant. Since a store can be
3351 // modified during type-legalization (the value being stored may need
3352 // legalization), return empty Results here to indicate that we don't
3353 // really make any changes in the custom lowering.
3354 return;
3355 default:
3357 break;
3358 }
3359}
3360
3361void
3364 SelectionDAG &DAG) const {
3365 if (isHvxOperation(N, DAG)) {
3366 ReplaceHvxNodeResults(N, Results, DAG);
3367 if (!Results.empty())
3368 return;
3369 }
3370
3371 const SDLoc &dl(N);
3372 switch (N->getOpcode()) {
3373 case ISD::SRL:
3374 case ISD::SRA:
3375 case ISD::SHL:
3376 return;
3377 case ISD::BITCAST:
3378 // Handle a bitcast from v8i1 to i8.
3379 if (N->getValueType(0) == MVT::i8) {
3380 if (N->getOperand(0).getValueType() == MVT::v8i1) {
3381 SDValue P = getInstr(Hexagon::C2_tfrpr, dl, MVT::i32,
3382 N->getOperand(0), DAG);
3383 SDValue T = DAG.getAnyExtOrTrunc(P, dl, MVT::i8);
3384 Results.push_back(T);
3385 }
3386 }
3387 break;
3388 }
3389}
3390
3391SDValue
3393 DAGCombinerInfo &DCI) const {
3394 SDValue Op(N, 0);
3395 const SDLoc &dl(Op);
3396 unsigned Opc = Op.getOpcode();
3397
3398 // Combining transformations applicable for arbitrary vector sizes.
3399 if (DCI.isBeforeLegalizeOps()) {
3400 switch (Opc) {
3401 case ISD::VECREDUCE_ADD:
3402 if (SDValue V = splitVecReduceAdd(N, DCI.DAG))
3403 return V;
3404 if (SDValue V = expandVecReduceAdd(N, DCI.DAG))
3405 return V;
3406 return SDValue();
3410 if (SDValue V = splitExtendingPartialReduceMLA(N, DCI.DAG))
3411 return V;
3412 return SDValue();
3413 }
3414 } else {
3415 switch (Opc) {
3416 case ISD::VSELECT: {
3417 // (vselect (xor x, ptrue), v0, v1) -> (vselect x, v1, v0)
3418 SDValue Cond = Op.getOperand(0);
3419 if (Cond->getOpcode() == ISD::XOR) {
3420 SDValue C0 = Cond.getOperand(0), C1 = Cond.getOperand(1);
3421 if (C1->getOpcode() == HexagonISD::PTRUE) {
3422 SDValue VSel = DCI.DAG.getNode(ISD::VSELECT, dl, ty(Op), C0,
3423 Op.getOperand(2), Op.getOperand(1));
3424 return VSel;
3425 }
3426 }
3427 return SDValue();
3428 }
3429 }
3430 }
3431
3432 if (isHvxOperation(N, DCI.DAG)) {
3433 if (SDValue V = PerformHvxDAGCombine(N, DCI))
3434 return V;
3435 return SDValue();
3436 }
3437
3438 if (Opc == ISD::TRUNCATE) {
3439 SDValue Op0 = Op.getOperand(0);
3440 // fold (truncate (build pair x, y)) -> (truncate x) or x
3441 if (Op0.getOpcode() == ISD::BUILD_PAIR) {
3442 EVT TruncTy = Op.getValueType();
3443 SDValue Elem0 = Op0.getOperand(0);
3444 // if we match the low element of the pair, just return it.
3445 if (Elem0.getValueType() == TruncTy)
3446 return Elem0;
3447 // otherwise, if the low part is still too large, apply the truncate.
3448 if (Elem0.getValueType().bitsGT(TruncTy))
3449 return DCI.DAG.getNode(ISD::TRUNCATE, dl, TruncTy, Elem0);
3450 }
3451 }
3452
3453 if (DCI.isBeforeLegalizeOps())
3454 return SDValue();
3455
3456 switch (Opc) {
3457 case HexagonISD::P2D: {
3458 SDValue P = Op.getOperand(0);
3459 switch (P.getOpcode()) {
3460 case HexagonISD::PTRUE:
3461 return DCI.DAG.getAllOnesConstant(dl, ty(Op));
3462 case HexagonISD::PFALSE:
3463 return getZero(dl, ty(Op), DCI.DAG);
3464 default:
3465 break;
3466 }
3467 break;
3468 }
3469 case ISD::TRUNCATE: {
3470 SDValue Op0 = Op.getOperand(0);
3471 // fold (truncate (build pair x, y)) -> (truncate x) or x
3472 if (Op0.getOpcode() == ISD::BUILD_PAIR) {
3473 MVT TruncTy = ty(Op);
3474 SDValue Elem0 = Op0.getOperand(0);
3475 // if we match the low element of the pair, just return it.
3476 if (ty(Elem0) == TruncTy)
3477 return Elem0;
3478 // otherwise, if the low part is still too large, apply the truncate.
3479 if (ty(Elem0).bitsGT(TruncTy))
3480 return DCI.DAG.getNode(ISD::TRUNCATE, dl, TruncTy, Elem0);
3481 }
3482 break;
3483 }
3484 case ISD::OR: {
3485 // fold (or (shl xx, s), (zext y)) -> (COMBINE (shl xx, s-32), y)
3486 // if s >= 32
3487 auto fold0 = [&, this](SDValue Op) {
3488 if (ty(Op) != MVT::i64)
3489 return SDValue();
3490 SDValue Shl = Op.getOperand(0);
3491 SDValue Zxt = Op.getOperand(1);
3492 if (Shl.getOpcode() != ISD::SHL)
3493 std::swap(Shl, Zxt);
3494
3495 if (Shl.getOpcode() != ISD::SHL || Zxt.getOpcode() != ISD::ZERO_EXTEND)
3496 return SDValue();
3497
3498 SDValue Z = Zxt.getOperand(0);
3499 auto *Amt = dyn_cast<ConstantSDNode>(Shl.getOperand(1));
3500 if (Amt && Amt->getZExtValue() >= 32 && ty(Z).getSizeInBits() <= 32) {
3501 unsigned A = Amt->getZExtValue();
3502 SDValue S = Shl.getOperand(0);
3503 SDValue T0 = DCI.DAG.getNode(ISD::SHL, dl, ty(S), S,
3504 DCI.DAG.getConstant(A - 32, dl, MVT::i32));
3505 SDValue T1 = DCI.DAG.getZExtOrTrunc(T0, dl, MVT::i32);
3506 SDValue T2 = DCI.DAG.getZExtOrTrunc(Z, dl, MVT::i32);
3507 return DCI.DAG.getNode(HexagonISD::COMBINE, dl, MVT::i64, {T1, T2});
3508 }
3509 return SDValue();
3510 };
3511
3512 if (SDValue R = fold0(Op))
3513 return R;
3514 break;
3515 }
3516 }
3517
3518 return SDValue();
3519}
3520
3521/// Returns relocation base for the given PIC jumptable.
3522SDValue
3524 SelectionDAG &DAG) const {
3525 int Idx = cast<JumpTableSDNode>(Table)->getIndex();
3526 EVT VT = Table.getValueType();
3528 return DAG.getNode(HexagonISD::AT_PCREL, SDLoc(Table), VT, T);
3529}
3530
3531//===----------------------------------------------------------------------===//
3532// Inline Assembly Support
3533//===----------------------------------------------------------------------===//
3534
3537 if (Constraint.size() == 1) {
3538 switch (Constraint[0]) {
3539 case 'q':
3540 case 'v':
3541 if (Subtarget.useHVXOps())
3542 return C_RegisterClass;
3543 break;
3544 case 'a':
3545 return C_RegisterClass;
3546 default:
3547 break;
3548 }
3549 }
3550 return TargetLowering::getConstraintType(Constraint);
3551}
3552
3553std::pair<unsigned, const TargetRegisterClass*>
3555 const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const {
3556
3557 if (Constraint.size() == 1) {
3558 switch (Constraint[0]) {
3559 case 'r': // R0-R31
3560 switch (VT.SimpleTy) {
3561 default:
3562 return {0u, nullptr};
3563 case MVT::i1:
3564 case MVT::i8:
3565 case MVT::i16:
3566 case MVT::i32:
3567 case MVT::f32:
3568 return {0u, &Hexagon::IntRegsRegClass};
3569 case MVT::i64:
3570 case MVT::f64:
3571 return {0u, &Hexagon::DoubleRegsRegClass};
3572 }
3573 break;
3574 case 'a': // M0-M1
3575 if (VT != MVT::i32)
3576 return {0u, nullptr};
3577 return {0u, &Hexagon::ModRegsRegClass};
3578 case 'q': // q0-q3
3579 switch (VT.getSizeInBits()) {
3580 default:
3581 return {0u, nullptr};
3582 case 64:
3583 case 128:
3584 return {0u, &Hexagon::HvxQRRegClass};
3585 }
3586 break;
3587 case 'v': // V0-V31
3588 switch (VT.getSizeInBits()) {
3589 default:
3590 return {0u, nullptr};
3591 case 512:
3592 return {0u, &Hexagon::HvxVRRegClass};
3593 case 1024:
3594 if (Subtarget.hasV60Ops() && Subtarget.useHVX128BOps())
3595 return {0u, &Hexagon::HvxVRRegClass};
3596 return {0u, &Hexagon::HvxWRRegClass};
3597 case 2048:
3598 return {0u, &Hexagon::HvxWRRegClass};
3599 }
3600 break;
3601 default:
3602 return {0u, nullptr};
3603 }
3604 }
3605
3606 return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
3607}
3608
3609/// isFPImmLegal - Returns true if the target can instruction select the
3610/// specified FP immediate natively. If false, the legalizer will
3611/// materialize the FP immediate as a load from a constant pool.
3613 bool ForCodeSize) const {
3614 return true;
3615}
3616
3617/// Returns true if it is beneficial to convert a load of a constant
3618/// to just the constant itself.
3620 Type *Ty) const {
3621 if (!ConstantLoadsToImm)
3622 return false;
3623
3624 assert(Ty->isIntegerTy());
3625 unsigned BitSize = Ty->getPrimitiveSizeInBits();
3626 return (BitSize > 0 && BitSize <= 64);
3627}
3628
3629/// isLegalAddressingMode - Return true if the addressing mode represented by
3630/// AM is legal for this target, for a load/store of the specified type.
3632 const AddrMode &AM, Type *Ty,
3633 unsigned AS, Instruction *I) const {
3634 if (Ty->isSized()) {
3635 // When LSR detects uses of the same base address to access different
3636 // types (e.g. unions), it will assume a conservative type for these
3637 // uses:
3638 // LSR Use: Kind=Address of void in addrspace(4294967295), ...
3639 // The type Ty passed here would then be "void". Skip the alignment
3640 // checks, but do not return false right away, since that confuses
3641 // LSR into crashing.
3642 Align A = DL.getABITypeAlign(Ty);
3643 // The base offset must be a multiple of the alignment.
3644 if (!isAligned(A, AM.BaseOffs))
3645 return false;
3646 // The shifted offset must fit in 11 bits.
3647 if (!isInt<11>(AM.BaseOffs >> Log2(A)))
3648 return false;
3649 }
3650
3651 // No global is ever allowed as a base.
3652 if (AM.BaseGV)
3653 return false;
3654
3655 int Scale = AM.Scale;
3656 if (Scale < 0)
3657 Scale = -Scale;
3658 switch (Scale) {
3659 case 0: // No scale reg, "r+i", "r", or just "i".
3660 break;
3661 default: // No scaled addressing mode.
3662 return false;
3663 }
3664 return true;
3665}
3666
3667/// Return true if folding a constant offset with the given GlobalAddress is
3668/// legal. It is frequently not legal in PIC relocation models.
3670 const {
3671 return HTM.getRelocationModel() == Reloc::Static;
3672}
3673
3674/// isLegalICmpImmediate - Return true if the specified immediate is legal
3675/// icmp immediate, that is the target has icmp instructions which can compare
3676/// a register against the immediate without having to materialize the
3677/// immediate into a register.
3679 return Imm >= -512 && Imm <= 511;
3680}
3681
3682/// IsEligibleForTailCallOptimization - Check whether the call is eligible
3683/// for tail call optimization. Targets which want to do tail call
3684/// optimization should implement this function.
3686 SDValue Callee,
3687 CallingConv::ID CalleeCC,
3688 bool IsVarArg,
3689 bool IsCalleeStructRet,
3690 bool IsCallerStructRet,
3692 const SmallVectorImpl<SDValue> &OutVals,
3694 SelectionDAG& DAG) const {
3695 const Function &CallerF = DAG.getMachineFunction().getFunction();
3696 CallingConv::ID CallerCC = CallerF.getCallingConv();
3697 bool CCMatch = CallerCC == CalleeCC;
3698
3699 // ***************************************************************************
3700 // Look for obvious safe cases to perform tail call optimization that do not
3701 // require ABI changes.
3702 // ***************************************************************************
3703
3704 // If this is a tail call via a function pointer, then don't do it!
3705 if (!isa<GlobalAddressSDNode>(Callee) &&
3706 !isa<ExternalSymbolSDNode>(Callee)) {
3707 return false;
3708 }
3709
3710 // Do not optimize if the calling conventions do not match and the conventions
3711 // used are not C or Fast.
3712 if (!CCMatch) {
3713 bool R = (CallerCC == CallingConv::C || CallerCC == CallingConv::Fast);
3714 bool E = (CalleeCC == CallingConv::C || CalleeCC == CallingConv::Fast);
3715 // If R & E, then ok.
3716 if (!R || !E)
3717 return false;
3718 }
3719
3720 // Do not tail call optimize vararg calls.
3721 if (IsVarArg)
3722 return false;
3723
3724 // Also avoid tail call optimization if either caller or callee uses struct
3725 // return semantics.
3726 if (IsCalleeStructRet || IsCallerStructRet)
3727 return false;
3728
3729 // In addition to the cases above, we also disable Tail Call Optimization if
3730 // the calling convention code that at least one outgoing argument needs to
3731 // go on the stack. We cannot check that here because at this point that
3732 // information is not available.
3733 return true;
3734}
3735
3736/// Returns the target specific optimal type for load and store operations as
3737/// a result of memset, memcpy, and memmove lowering.
3738///
3739/// If DstAlign is zero that means it's safe to destination alignment can
3740/// satisfy any constraint. Similarly if SrcAlign is zero it means there isn't
3741/// a need to check it against alignment requirement, probably because the
3742/// source does not need to be loaded. If 'IsMemset' is true, that means it's
3743/// expanding a memset. If 'ZeroMemset' is true, that means it's a memset of
3744/// zero. 'MemcpyStrSrc' indicates whether the memcpy source is constant so it
3745/// does not need to be loaded. It returns EVT::Other if the type should be
3746/// determined using generic target-independent logic.
3748 LLVMContext &Context, const MemOp &Op,
3749 const AttributeList &FuncAttributes) const {
3750 if (Op.size() >= 8 && Op.isAligned(Align(8)))
3751 return MVT::i64;
3752 if (Op.size() >= 4 && Op.isAligned(Align(4)))
3753 return MVT::i32;
3754 if (Op.size() >= 2 && Op.isAligned(Align(2)))
3755 return MVT::i16;
3756 return MVT::Other;
3757}
3758
3759// The helpers below are versions of llvm::getShuffleReduction and
3760// llvm::getOrderedReduction, adapted to use during DAG passes and simplified as
3761// follows:
3762// - ICmp and FCmp are not handled;
3763// - in every step in getShuffleReduction, the input is split into halves (not
3764// pairwise).
3765
3767 SelectionDAG &DAG) {
3768 assert(Op != Instruction::ICmp && Op != Instruction::FCmp);
3769
3770 EVT VT = Vec.getValueType();
3771 EVT EltT = VT.getVectorElementType();
3772 unsigned VF = VT.getVectorNumElements();
3773 assert(VF > 0 &&
3774 "Reduction emission only supported for non-zero length vectors!");
3775
3776 SDLoc DL(Vec);
3777 SDValue Result = DAG.getExtractVectorElt(DL, EltT, Vec, 0);
3778 for (unsigned ExtractIdx = 1; ExtractIdx < VF; ++ExtractIdx) {
3779 SDValue Ext = DAG.getExtractVectorElt(DL, EltT, Vec, ExtractIdx);
3780 Result = DAG.getNode(Op, DL, EltT, {Result, Ext});
3781 }
3782
3783 return Result;
3784}
3785
3787 SelectionDAG &DAG) {
3788 assert(Op != Instruction::ICmp && Op != Instruction::FCmp);
3789
3790 EVT VT = Vec.getValueType();
3791 unsigned VF = VT.getVectorNumElements();
3792 if (VF == 0)
3793 llvm_unreachable("Vector must be non-zero length");
3794 // VF is a power of 2 so we can emit the reduction using log2(VF) shuffles
3795 // and vector ops, reducing the set of values being computed by half each
3796 // round.
3797 assert(isPowerOf2_32(VF) &&
3798 "Reduction emission only supported for pow2 vectors!");
3799
3800 SDLoc DL(Vec);
3801 // TODO: Is it correct to create double-vector shuffle and fill 3/4 of it with
3802 // undefs?
3803 SmallVector<int, 32> ShuffleMask(VF);
3804 for (unsigned i = VF; i > 1; i >>= 1) {
3805 // Move the upper half of the vector to the lower half.
3806 for (unsigned j = 0; j != i / 2; ++j)
3807 ShuffleMask[j] = i / 2 + j;
3808 // Fill the rest of the mask with undef.
3809 std::fill(&ShuffleMask[i / 2], ShuffleMask.end(), -1);
3810
3811 SDValue Shuf =
3812 DAG.getVectorShuffle(VT, DL, Vec, DAG.getUNDEF(VT), ShuffleMask);
3813
3814 Vec = DAG.getNode(Op, DL, VT, {Vec, Shuf});
3815 }
3816 // The result is in the first element of the vector.
3817 return DAG.getExtractVectorElt(DL, VT.getVectorElementType(), Vec, 0);
3818}
3819
3820SDValue HexagonTargetLowering::expandVecReduceAdd(SDNode *N,
3821 SelectionDAG &DAG) const {
3822 // Since we disabled automatic reduction expansion, generate log2 ladder code
3823 // if the vector is of a power-of-two length.
3824 SDValue Input = N->getOperand(0);
3826 return getShuffleReduction(Input, ISD::ADD, DAG);
3827 // Otherwise, reduction will be scalarized.
3828 return getOrderedReduction(Input, ISD::ADD, DAG);
3829}
3830
3832 LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace,
3833 Align Alignment, MachineMemOperand::Flags Flags, unsigned *Fast) const {
3834 if (!VT.isSimple())
3835 return false;
3836 MVT SVT = VT.getSimpleVT();
3837 if (Subtarget.isHVXVectorType(SVT, true))
3838 return allowsHvxMemoryAccess(SVT, Flags, Fast);
3840 Context, DL, VT, AddrSpace, Alignment, Flags, Fast);
3841}
3842
3844 EVT VT, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags,
3845 unsigned *Fast) const {
3846 if (!VT.isSimple())
3847 return false;
3848 MVT SVT = VT.getSimpleVT();
3849 if (Subtarget.isHVXVectorType(SVT, true))
3850 return allowsHvxMisalignedMemoryAccesses(SVT, Flags, Fast);
3851 if (Fast)
3852 *Fast = 0;
3853 return false;
3854}
3855
3856std::pair<const TargetRegisterClass*, uint8_t>
3857HexagonTargetLowering::findRepresentativeClass(const TargetRegisterInfo *TRI,
3858 MVT VT) const {
3859 if (Subtarget.isHVXVectorType(VT, true)) {
3860 unsigned BitWidth = VT.getSizeInBits();
3861 unsigned VecWidth = Subtarget.getVectorLength() * 8;
3862
3863 if (VT.getVectorElementType() == MVT::i1)
3864 return std::make_pair(&Hexagon::HvxQRRegClass, 1);
3865 if (BitWidth == VecWidth)
3866 return std::make_pair(&Hexagon::HvxVRRegClass, 1);
3867 assert(BitWidth == 2 * VecWidth);
3868 return std::make_pair(&Hexagon::HvxWRRegClass, 1);
3869 }
3870
3872}
3873
3875 SDNode *Load, ISD::LoadExtType ExtTy, EVT NewVT,
3876 std::optional<unsigned> ByteOffset) const {
3877 // TODO: This may be worth removing. Check regression tests for diffs.
3878 if (!TargetLoweringBase::shouldReduceLoadWidth(Load, ExtTy, NewVT,
3879 ByteOffset))
3880 return false;
3881
3882 auto *L = cast<LoadSDNode>(Load);
3883 std::pair<SDValue, int> BO = getBaseAndOffset(L->getBasePtr());
3884 // Small-data object, do not shrink.
3885 if (BO.first.getOpcode() == HexagonISD::CONST32_GP)
3886 return false;
3888 auto &HTM = static_cast<const HexagonTargetMachine &>(getTargetMachine());
3889 const auto *GO = dyn_cast_or_null<const GlobalObject>(GA->getGlobal());
3890 return !GO || !HTM.getObjFileLowering()->isGlobalInSmallSection(GO, HTM);
3891 }
3892 return true;
3893}
3894
3896 SDNode *Node) const {
3897 AdjustHvxInstrPostInstrSelection(MI, Node);
3898}
3899
3901 Type *ValueTy, Value *Addr,
3902 AtomicOrdering Ord) const {
3903 unsigned SZ = ValueTy->getPrimitiveSizeInBits();
3904 assert((SZ == 32 || SZ == 64) && "Only 32/64-bit atomic loads supported");
3905 Intrinsic::ID IntID = (SZ == 32) ? Intrinsic::hexagon_L2_loadw_locked
3906 : Intrinsic::hexagon_L4_loadd_locked;
3907
3908 Value *Call =
3909 Builder.CreateIntrinsic(IntID, Addr, /*FMFSource=*/nullptr, "larx");
3910
3911 return Builder.CreateBitCast(Call, ValueTy);
3912}
3913
3914/// Perform a store-conditional operation to Addr. Return the status of the
3915/// store. This should be 0 if the store succeeded, non-zero otherwise.
3917 Value *Val, Value *Addr,
3918 AtomicOrdering Ord) const {
3919 BasicBlock *BB = Builder.GetInsertBlock();
3920 Module *M = BB->getParent()->getParent();
3921 Type *Ty = Val->getType();
3922 unsigned SZ = Ty->getPrimitiveSizeInBits();
3923
3924 Type *CastTy = Builder.getIntNTy(SZ);
3925 assert((SZ == 32 || SZ == 64) && "Only 32/64-bit atomic stores supported");
3926 Intrinsic::ID IntID = (SZ == 32) ? Intrinsic::hexagon_S2_storew_locked
3927 : Intrinsic::hexagon_S4_stored_locked;
3928
3929 Val = Builder.CreateBitCast(Val, CastTy);
3930
3931 Value *Call = Builder.CreateIntrinsic(IntID, {Addr, Val},
3932 /*FMFSource=*/nullptr, "stcx");
3933 Value *Cmp = Builder.CreateICmpEQ(Call, Builder.getInt32(0), "");
3934 Value *Ext = Builder.CreateZExt(Cmp, Type::getInt32Ty(M->getContext()));
3935 return Ext;
3936}
3937
3940 // Do not expand loads and stores that don't exceed 64 bits.
3941 return LI->getType()->getPrimitiveSizeInBits() > 64
3944}
3945
3948 // Do not expand loads and stores that don't exceed 64 bits.
3949 return SI->getValueOperand()->getType()->getPrimitiveSizeInBits() > 64
3952}
3953
3959
3961 MachineInstr &MI, MachineBasicBlock *BB) const {
3962 switch (MI.getOpcode()) {
3963 case TargetOpcode::PATCHABLE_EVENT_CALL:
3964 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
3965 // These are lowered in the AsmPrinter.
3966 return BB;
3967 default:
3968 llvm_unreachable("Unexpected instruction with custom inserter");
3969 }
3970}
3971
3975 const TargetInstrInfo *TII) const {
3976 assert(MBBI->isCall() && MBBI->getCFIType() &&
3977 "Invalid call instruction for a KCFI check");
3978
3979 switch (MBBI->getOpcode()) {
3980 case Hexagon::J2_callr:
3981 case Hexagon::PS_callr_nr:
3982 break;
3983 default:
3984 llvm_unreachable("Unexpected CFI call opcode");
3985 }
3986
3987 MachineOperand &Target = MBBI->getOperand(0);
3988 assert(Target.isReg() && "Invalid target operand for an indirect call");
3989 Target.setIsRenamable(false);
3990
3991 return BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(Hexagon::KCFI_CHECK))
3992 .addReg(Target.getReg())
3993 .addImm(MBBI->getCFIType())
3994 .getInstr();
3995}
3996
3998 const Instruction &AndI) const {
3999 // Only sink 'and' mask to cmp use block if it is masking a single bit since
4000 // this will fold the and/cmp/br into a single tstbit instruction.
4002 if (!Mask)
4003 return false;
4004 return Mask->getValue().isPowerOf2();
4005}
4006
4007// Check if the result of the node is only used as a return value, as
4008// otherwise we can't perform a tail-call.
4010 SDValue &Chain) const {
4011 if (N->getNumValues() != 1)
4012 return false;
4013 if (!N->hasNUsesOfValue(1, 0))
4014 return false;
4015
4016 SDNode *Copy = *N->user_begin();
4017
4018 if (Copy->getOpcode() == ISD::BITCAST) {
4019 return isUsedByReturnOnly(Copy, Chain);
4020 }
4021
4022 if (Copy->getOpcode() != ISD::CopyToReg) {
4023 return false;
4024 }
4025
4026 // If the ISD::CopyToReg has a glue operand, we conservatively assume it
4027 // isn't safe to perform a tail call.
4028 if (Copy->getOperand(Copy->getNumOperands() - 1).getValueType() == MVT::Glue)
4029 return false;
4030
4031 // The copy must be used by a HexagonISD::RET_GLUE, and nothing else.
4032 bool HasRet = false;
4033 for (SDNode *Node : Copy->users()) {
4034 if (Node->getOpcode() != HexagonISD::RET_GLUE)
4035 return false;
4036 HasRet = true;
4037 }
4038 if (!HasRet)
4039 return false;
4040
4041 Chain = Copy->getOperand(0);
4042 return true;
4043}
4044
4046 const MachineFunction &MF) const {
4047 if (MF.getFunction().hasFnAttribute("probe-stack"))
4048 return MF.getFunction().getFnAttribute("probe-stack").getValueAsString() ==
4049 "inline-asm";
4050 return false;
4051}
4052
4054 Align StackAlign) const {
4055 const Function &Fn = MF.getFunction();
4056 unsigned StackProbeSize =
4057 Fn.getFnAttributeAsParsedInteger("stack-probe-size", 4096);
4058 // Round down to the stack alignment.
4059 StackProbeSize = alignDown(StackProbeSize, StackAlign.value());
4060 return StackProbeSize ? StackProbeSize : StackAlign.value();
4061}
return SDValue()
unsigned RegSize
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
aarch64 promote const
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:856
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 Value * getUnderLyingObjectForBrevLdIntr(Value *V)
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 * 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)
const SmallVectorImpl< MachineOperand > & Cond
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:1457
Class for arbitrary precision integers.
Definition APInt.h:78
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
Definition APInt.cpp:968
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:43
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:688
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
Definition Function.cpp:758
uint64_t getFnAttributeAsParsedInteger(StringRef Kind, uint64_t Default=0) const
For a string attribute Kind, parse attribute as an integer.
Definition Function.cpp:770
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Definition Function.h:272
bool hasStructRetAttr() const
Determine if the function returns a structure through first or second pointer argument.
Definition Function.h:669
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition Function.cpp:723
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
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
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 isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize) const override
isFPImmLegal - Returns true if the target can instruction select the specified FP immediate natively.
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
bool isExtractSubvectorCheap(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return true if EXTRACT_SUBVECTOR is cheap for extracting this result type from this source type with ...
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
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:114
ConstantInt * getInt8(uint8_t C)
Get a constant 8-bit value.
Definition IRBuilder.h:467
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2893
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:348
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
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 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.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
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...
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,...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
void addLiveIn(MCRegister Reg, Register vreg=Register())
addLiveIn - Add the specified register as a live-in.
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:67
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.
const SDValue & getOperand(unsigned Num) const
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)
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
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 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 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.
LLVM_ABI SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
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 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 ...
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.
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:343
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:288
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:309
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
Definition Type.cpp:197
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:257
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
Definition Type.cpp:313
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:255
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:165
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:829
@ STACKRESTORE
STACKRESTORE has two operands, an input chain and a pointer to restore to it returns an output chain.
@ STACKSAVE
STACKSAVE - STACKSAVE has one operand, an input chain.
@ 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:275
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
Definition ISDOpcodes.h:602
@ BSWAP
Byte Swap and Counting operators.
Definition ISDOpcodes.h:789
@ VAEND
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE.
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:264
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition ISDOpcodes.h:863
@ FMA
FMA - Perform a * b + c with no intermediate rounding step.
Definition ISDOpcodes.h:520
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
Definition ISDOpcodes.h:220
@ GlobalAddress
Definition ISDOpcodes.h:88
@ SINT_TO_FP
[SU]INT_TO_FP - These operators convert integers (whose interpreted sign depends on the first letter)...
Definition ISDOpcodes.h:890
@ CONCAT_VECTORS
CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of vector type with the same length ...
Definition ISDOpcodes.h:586
@ FADD
Simple binary floating point operators.
Definition ISDOpcodes.h:417
@ ABS
ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.
Definition ISDOpcodes.h:749
@ ATOMIC_FENCE
OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) This corresponds to the fence instruction.
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
Definition ISDOpcodes.h:280
@ FP16_TO_FP
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ BUILD_PAIR
BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways.
Definition ISDOpcodes.h:254
@ FLDEXP
FLDEXP - ldexp, inspired by libm (op0 * 2**op1).
@ GlobalTLSAddress
Definition ISDOpcodes.h:89
@ EH_RETURN
OUTCHAIN = EH_RETURN(INCHAIN, OFFSET, HANDLER) - This node represents 'eh_return' gcc dwarf builtin,...
Definition ISDOpcodes.h:156
@ PARTIAL_REDUCE_UMLA
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:854
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
Definition ISDOpcodes.h:667
@ 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:352
@ BR_JT
BR_JT - Jumptable branch.
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
Definition ISDOpcodes.h:806
@ SPLAT_VECTOR
SPLAT_VECTOR(VAL) - Returns a vector with the scalar value VAL duplicated in all lanes.
Definition ISDOpcodes.h:674
@ 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:348
@ VECREDUCE_ADD
Integer reductions may have a result type larger than the vector element type.
@ SHL
Shift and rotation operations.
Definition ISDOpcodes.h:771
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
Definition ISDOpcodes.h:651
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
Definition ISDOpcodes.h:616
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
Definition ISDOpcodes.h:578
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
Definition ISDOpcodes.h:224
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:860
@ 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:821
@ 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:898
@ SMIN
[US]{MIN/MAX} - Binary minimum or maximum of signed or unsigned integers.
Definition ISDOpcodes.h:729
@ GLOBAL_OFFSET_TABLE
The address of the GOT.
Definition ISDOpcodes.h:103
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
Definition ISDOpcodes.h:815
@ UADDO_CARRY
Carry-using nodes for multiple precision addition and subtraction.
Definition ISDOpcodes.h:328
@ 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:110
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
Definition ISDOpcodes.h:936
@ READCYCLECOUNTER
READCYCLECOUNTER - This corresponds to the readcyclecounter intrinsic.
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:741
@ TRAP
TRAP - Trapping instruction.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
Definition ISDOpcodes.h:205
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
Definition ISDOpcodes.h:567
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
Definition ISDOpcodes.h:53
@ INLINEASM
INLINEASM - Represents an inline asm block.
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:866
@ VAARG
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
Definition ISDOpcodes.h:843
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
Definition ISDOpcodes.h:62
@ FCOPYSIGN
FCOPYSIGN(X, Y) - Return the value of X with the sign of Y.
Definition ISDOpcodes.h:536
@ PARTIAL_REDUCE_SUMLA
@ SADDSAT
RESULT = [US]ADDSAT(LHS, RHS) - Perform saturation addition on 2 integers with the same bit width (W)...
Definition ISDOpcodes.h:365
@ FMINIMUMNUM
FMINIMUMNUM/FMAXIMUMNUM - minimumnum/maximumnum that is same with FMINNUM_IEEE and FMAXNUM_IEEE besid...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
Definition ISDOpcodes.h:213
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
Definition ISDOpcodes.h:558
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).
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:573
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:1739
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:1669
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:165
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
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:134
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:279
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.
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:156
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
DWARFExpression::Operation Op
LLVM_ABI int getNextAvailablePluginDiagnosticKind()
Get the next available kind ID for a plugin diagnostic.
unsigned M0(unsigned Val)
Definition VE.h:376
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:1772
unsigned Log2(Align A)
Returns the log2 of the alignment.
Definition Alignment.h:197
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:862
#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:77
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
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:106
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