LLVM 24.0.0git
HexagonISelLowering.cpp
Go to the documentation of this file.
1//===-- HexagonISelLowering.cpp - Hexagon DAG Lowering Implementation -----===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the interfaces that Hexagon uses to lower LLVM code
10// into a selection DAG.
11//
12//===----------------------------------------------------------------------===//
13
14#include "HexagonISelLowering.h"
15#include "Hexagon.h"
17#include "HexagonRegisterInfo.h"
18#include "HexagonSubtarget.h"
21#include "llvm/ADT/APInt.h"
22#include "llvm/ADT/ArrayRef.h"
33#include "llvm/IR/BasicBlock.h"
34#include "llvm/IR/CallingConv.h"
35#include "llvm/IR/DataLayout.h"
39#include "llvm/IR/Function.h"
40#include "llvm/IR/GlobalValue.h"
41#include "llvm/IR/IRBuilder.h"
42#include "llvm/IR/InlineAsm.h"
45#include "llvm/IR/Intrinsics.h"
46#include "llvm/IR/IntrinsicsHexagon.h"
47#include "llvm/IR/Module.h"
48#include "llvm/IR/Type.h"
49#include "llvm/IR/Value.h"
53#include "llvm/Support/Debug.h"
58#include <algorithm>
59#include <cassert>
60#include <cstdint>
61#include <limits>
62#include <utility>
63
64using namespace llvm;
65
66#define DEBUG_TYPE "hexagon-lowering"
67
68static cl::opt<bool> EmitJumpTables("hexagon-emit-jump-tables",
69 cl::init(true), cl::Hidden,
70 cl::desc("Control jump table emission on Hexagon target"));
71
72static cl::opt<bool>
73 EnableHexSDNodeSched("enable-hexagon-sdnode-sched", cl::Hidden,
74 cl::desc("Enable Hexagon SDNode scheduling"));
75
76static cl::opt<int> MinimumJumpTables("minimum-jump-tables", cl::Hidden,
77 cl::init(5),
78 cl::desc("Set minimum jump tables"));
79
80static cl::opt<bool>
81 ConstantLoadsToImm("constant-loads-to-imm", cl::Hidden, cl::init(true),
82 cl::desc("Convert constant loads to immediate values."));
83
84static cl::opt<bool> AlignLoads("hexagon-align-loads",
85 cl::Hidden, cl::init(false),
86 cl::desc("Rewrite unaligned loads as a pair of aligned loads"));
87
88static cl::opt<bool>
89 DisableArgsMinAlignment("hexagon-disable-args-min-alignment", cl::Hidden,
90 cl::init(false),
91 cl::desc("Disable minimum alignment of 1 for "
92 "arguments passed by value on stack"));
93
94// Implement calling convention for Hexagon.
95
96static bool CC_SkipOdd(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
97 CCValAssign::LocInfo &LocInfo,
98 ISD::ArgFlagsTy &ArgFlags, CCState &State) {
99 static const MCPhysReg ArgRegs[] = {
100 Hexagon::R0, Hexagon::R1, Hexagon::R2,
101 Hexagon::R3, Hexagon::R4, Hexagon::R5
102 };
103 const unsigned NumArgRegs = std::size(ArgRegs);
104 unsigned RegNum = State.getFirstUnallocated(ArgRegs);
105
106 // RegNum is an index into ArgRegs: skip a register if RegNum is odd.
107 if (RegNum != NumArgRegs && RegNum % 2 == 1)
108 State.AllocateReg(ArgRegs[RegNum]);
109
110 // Always return false here, as this function only makes sure that the first
111 // unallocated register has an even register number and does not actually
112 // allocate a register for the current argument.
113 return false;
114}
115
116#define GET_CALLING_CONV_IMPL
117#include "HexagonGenCallingConv.inc"
118
120 LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT,
121 unsigned &NumIntermediates, MVT &RegisterVT) const {
122
123 bool isBoolVector = VT.getVectorElementType() == MVT::i1;
124 bool isPowerOf2 = VT.isPow2VectorType();
125 unsigned NumElts = VT.getVectorNumElements();
126
127 // Split vectors of type vXi1 into (X/8) vectors of type v8i1,
128 // where X is divisible by 8.
129 if (isBoolVector && !Subtarget.useHVXOps() && isPowerOf2 && NumElts >= 8) {
130 RegisterVT = MVT::v8i8;
131 IntermediateVT = MVT::v8i1;
132 NumIntermediates = NumElts / 8;
133 return NumIntermediates;
134 }
135
136 // In HVX 64-byte mode, vectors of type vXi1 are split into (X / 64) vectors
137 // of type v64i1, provided that X is divisible by 64.
138 if (isBoolVector && Subtarget.useHVX64BOps() && isPowerOf2 && NumElts >= 64) {
139 RegisterVT = MVT::v64i8;
140 IntermediateVT = MVT::v64i1;
141 NumIntermediates = NumElts / 64;
142 return NumIntermediates;
143 }
144
145 // In HVX 128-byte mode, vectors of type vXi1 are split into (X / 128) vectors
146 // of type v128i1, provided that X is divisible by 128.
147 if (isBoolVector && Subtarget.useHVX128BOps() && isPowerOf2 &&
148 NumElts >= 128) {
149 RegisterVT = MVT::v128i8;
150 IntermediateVT = MVT::v128i1;
151 NumIntermediates = NumElts / 128;
152 return NumIntermediates;
153 }
154
156 Context, CC, VT, IntermediateVT, NumIntermediates, RegisterVT);
157}
158
159std::pair<MVT, unsigned>
161 const HexagonSubtarget &Subtarget, EVT VT) const {
162 assert(VT.getVectorElementType() == MVT::i1);
163
164 const unsigned NumElems = VT.getVectorNumElements();
165
166 if (!VT.isPow2VectorType())
168
169 if (!Subtarget.useHVXOps() && NumElems >= 8)
170 return {MVT::v8i8, NumElems / 8};
171
172 if (Subtarget.useHVX64BOps() && NumElems >= 64)
173 return {MVT::v64i8, NumElems / 64};
174
175 if (Subtarget.useHVX128BOps() && NumElems >= 128)
176 return {MVT::v128i8, NumElems / 128};
177
179}
180
183 EVT VT) const {
184
185 if (VT.isVectorOf(MVT::i1)) {
186 auto [RegisterVT, NumRegisters] =
188 if (RegisterVT != MVT::INVALID_SIMPLE_VALUE_TYPE)
189 return RegisterVT;
190 }
191
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 SelectionDAG &DAG) const {
808 EVT OpVT = Op.getValueType();
809 MVT SimpleVT = OpVT.getSimpleVT();
810 SDLoc DL(Op);
811
812 // Check if any of the inputs are NaN. If so, propagate the NaN
813 // to the output, otherwise return the maximum/minimum of the inputs.
814 // We can safely use ISD::FMINNUM/ISD::FMAXNUM to run
815 // Hexagon's F2_sfmin/F2_sfmax, when no operand is NaN.
816 // Note: We cannot directly compare nodes against NaN node to find NaNs,
817 // because comparing NaN with anything always returns False (except for !=0
818 // which always return True). To work around that, we compare input operands
819 // with themselves under ISD::SETUO, which only returns true if the operand is
820 // NaN.
821
822 SDValue Op1 = Op.getOperand(0);
823 SDValue Op2 = Op.getOperand(1);
824 SDValue isOp1NaN = DAG.getSetCC(DL, MVT::i1, Op1, Op1, ISD::SETUO);
825 SDValue isOp2NaN = DAG.getSetCC(DL, MVT::i1, Op2, Op2, ISD::SETUO);
826
827 switch (Op.getOpcode()) {
828 case ISD::FMAXIMUM: {
829 SDValue FmaxNode = DAG.getNode(ISD::FMAXNUM, DL, SimpleVT, Op1, Op2);
830 SDValue result =
831 DAG.getNode(ISD::SELECT, DL, SimpleVT, isOp2NaN, Op2, FmaxNode);
832 return DAG.getNode(ISD::SELECT, DL, SimpleVT, isOp1NaN, Op1, result);
833 }
834 case ISD::FMINIMUM: {
835 SDValue FminNode = DAG.getNode(ISD::FMINNUM, DL, SimpleVT, Op1, Op2);
836 SDValue result =
837 DAG.getNode(ISD::SELECT, DL, SimpleVT, isOp2NaN, Op2, FminNode);
838 return DAG.getNode(ISD::SELECT, DL, SimpleVT, isOp1NaN, Op1, result);
839 }
840 default:
841 llvm_unreachable("Invalid opcode for LowerFMINFMAX");
842 }
843}
844
846 SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
847 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
848 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
850 MachineFrameInfo &MFI = MF.getFrameInfo();
852
853 // Linux ABI treats var-arg calls the same way as regular ones.
854 bool TreatAsVarArg = !Subtarget.isEnvironmentMusl() && IsVarArg;
855
856 // Assign locations to all of the incoming arguments.
858 CCState CCInfo(CallConv, TreatAsVarArg, MF, ArgLocs, *DAG.getContext());
859
860 if (Subtarget.useHVXOps())
861 CCInfo.AnalyzeFormalArguments(Ins, CC_Hexagon_HVX);
863 CCInfo.AnalyzeFormalArguments(Ins, CC_Hexagon_Legacy);
864 else
865 CCInfo.AnalyzeFormalArguments(Ins, CC_Hexagon);
866
867 // For LLVM, in the case when returning a struct by value (>8byte),
868 // the first argument is a pointer that points to the location on caller's
869 // stack where the return value will be stored. For Hexagon, the location on
870 // caller's stack is passed only when the struct size is smaller than (and
871 // equal to) 8 bytes. If not, no address will be passed into callee and
872 // callee return the result directly through R0/R1.
873 auto NextSingleReg = [] (const TargetRegisterClass &RC, unsigned Reg) {
874 switch (RC.getID()) {
875 case Hexagon::IntRegsRegClassID:
876 return Reg - Hexagon::R0 + 1;
877 case Hexagon::DoubleRegsRegClassID:
878 return (Reg - Hexagon::D0 + 1) * 2;
879 case Hexagon::HvxVRRegClassID:
880 return Reg - Hexagon::V0 + 1;
881 case Hexagon::HvxWRRegClassID:
882 return (Reg - Hexagon::W0 + 1) * 2;
883 }
884 llvm_unreachable("Unexpected register class");
885 };
886
887 auto &HFL = const_cast<HexagonFrameLowering&>(*Subtarget.getFrameLowering());
888 auto &HMFI = *MF.getInfo<HexagonMachineFunctionInfo>();
889 HFL.FirstVarArgSavedReg = 0;
891
892 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
893 CCValAssign &VA = ArgLocs[i];
894 ISD::ArgFlagsTy Flags = Ins[i].Flags;
895 bool ByVal = Flags.isByVal();
896
897 // Arguments passed in registers:
898 // 1. 32- and 64-bit values and HVX vectors are passed directly,
899 // 2. Large structs are passed via an address, and the address is
900 // passed in a register.
901 if (VA.isRegLoc() && ByVal && Flags.getByValSize() <= 8)
902 llvm_unreachable("ByValSize must be bigger than 8 bytes");
903
904 bool InReg = VA.isRegLoc() &&
905 (!ByVal || (ByVal && Flags.getByValSize() > 8));
906
907 if (InReg) {
908 MVT RegVT = VA.getLocVT();
909 if (VA.getLocInfo() == CCValAssign::BCvt)
910 RegVT = VA.getValVT();
911
912 const TargetRegisterClass *RC = getRegClassFor(RegVT);
913 Register VReg = MRI.createVirtualRegister(RC);
914 SDValue Copy = DAG.getCopyFromReg(Chain, dl, VReg, RegVT);
915
916 // Treat values of type MVT::i1 specially: they are passed in
917 // registers of type i32, but they need to remain as values of
918 // type i1 for consistency of the argument lowering.
919 if (VA.getValVT() == MVT::i1) {
920 assert(RegVT.getSizeInBits() <= 32);
921 SDValue T = DAG.getNode(ISD::AND, dl, RegVT,
922 Copy, DAG.getConstant(1, dl, RegVT));
923 Copy = DAG.getSetCC(dl, MVT::i1, T, DAG.getConstant(0, dl, RegVT),
924 ISD::SETNE);
925 } else {
926#ifndef NDEBUG
927 unsigned RegSize = RegVT.getSizeInBits();
928 assert(RegSize == 32 || RegSize == 64 ||
929 Subtarget.isHVXVectorType(RegVT));
930#endif
931 }
932 InVals.push_back(Copy);
933 MRI.addLiveIn(VA.getLocReg(), VReg);
934 HFL.FirstVarArgSavedReg = NextSingleReg(*RC, VA.getLocReg());
935 } else {
936 assert(VA.isMemLoc() && "Argument should be passed in memory");
937
938 // If it's a byval parameter, then we need to compute the
939 // "real" size, not the size of the pointer.
940 unsigned ObjSize = Flags.isByVal()
941 ? Flags.getByValSize()
942 : VA.getLocVT().getStoreSizeInBits() / 8;
943
944 // Create the frame index object for this incoming parameter.
946 int FI = MFI.CreateFixedObject(ObjSize, Offset, true);
947 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
948
949 if (Flags.isByVal()) {
950 // If it's a pass-by-value aggregate, then do not dereference the stack
951 // location. Instead, we should generate a reference to the stack
952 // location.
953 InVals.push_back(FIN);
954 } else {
955 SDValue L = DAG.getLoad(VA.getValVT(), dl, Chain, FIN,
957 InVals.push_back(L);
958 }
959 }
960 }
961
962 if (IsVarArg && Subtarget.isEnvironmentMusl()) {
963 for (int i = HFL.FirstVarArgSavedReg; i < 6; i++)
964 MRI.addLiveIn(Hexagon::R0+i);
965 }
966
967 if (IsVarArg && Subtarget.isEnvironmentMusl()) {
968 HMFI.setFirstNamedArgFrameIndex(HMFI.getFirstNamedArgFrameIndex() - 1);
969 HMFI.setLastNamedArgFrameIndex(-int(MFI.getNumFixedObjects()));
970
971 // Create Frame index for the start of register saved area.
972 int NumVarArgRegs = 6 - HFL.FirstVarArgSavedReg;
973 bool RequiresPadding = (NumVarArgRegs & 1);
974 int RegSaveAreaSizePlusPadding = RequiresPadding
975 ? (NumVarArgRegs + 1) * 4
976 : NumVarArgRegs * 4;
977
978 if (RegSaveAreaSizePlusPadding > 0) {
979 // The offset to saved register area should be 8 byte aligned.
980 int RegAreaStart = HEXAGON_LRFP_SIZE + CCInfo.getStackSize();
981 if (!(RegAreaStart % 8))
982 RegAreaStart = (RegAreaStart + 7) & -8;
983
984 int RegSaveAreaFrameIndex =
985 MFI.CreateFixedObject(RegSaveAreaSizePlusPadding, RegAreaStart, true);
986 HMFI.setRegSavedAreaStartFrameIndex(RegSaveAreaFrameIndex);
987
988 // This will point to the next argument passed via stack.
989 int Offset = RegAreaStart + RegSaveAreaSizePlusPadding;
990 int FI = MFI.CreateFixedObject(Hexagon_PointerSize, Offset, true);
991 HMFI.setVarArgsFrameIndex(FI);
992 } else {
993 // This will point to the next argument passed via stack, when
994 // there is no saved register area.
995 int Offset = HEXAGON_LRFP_SIZE + CCInfo.getStackSize();
996 int FI = MFI.CreateFixedObject(Hexagon_PointerSize, Offset, true);
997 HMFI.setRegSavedAreaStartFrameIndex(FI);
998 HMFI.setVarArgsFrameIndex(FI);
999 }
1000 }
1001
1002
1003 if (IsVarArg && !Subtarget.isEnvironmentMusl()) {
1004 // This will point to the next argument passed via stack.
1005 int Offset = HEXAGON_LRFP_SIZE + CCInfo.getStackSize();
1006 int FI = MFI.CreateFixedObject(Hexagon_PointerSize, Offset, true);
1007 HMFI.setVarArgsFrameIndex(FI);
1008 }
1009
1010 return Chain;
1011}
1012
1013SDValue
1015 // VASTART stores the address of the VarArgsFrameIndex slot into the
1016 // memory location argument.
1019 SDValue Addr = DAG.getFrameIndex(QFI->getVarArgsFrameIndex(), MVT::i32);
1020 const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
1021
1022 if (!Subtarget.isEnvironmentMusl()) {
1023 return DAG.getStore(Op.getOperand(0), SDLoc(Op), Addr, Op.getOperand(1),
1024 MachinePointerInfo(SV));
1025 }
1026 auto &FuncInfo = *MF.getInfo<HexagonMachineFunctionInfo>();
1027 auto &HFL = *Subtarget.getFrameLowering();
1028 SDLoc DL(Op);
1030
1031 // Get frame index of va_list.
1032 SDValue FIN = Op.getOperand(1);
1033
1034 // If first Vararg register is odd, add 4 bytes to start of
1035 // saved register area to point to the first register location.
1036 // This is because the saved register area has to be 8 byte aligned.
1037 // In case of an odd start register, there will be 4 bytes of padding in
1038 // the beginning of saved register area. If all registers area used up,
1039 // the following condition will handle it correctly.
1040 SDValue SavedRegAreaStartFrameIndex =
1041 DAG.getFrameIndex(FuncInfo.getRegSavedAreaStartFrameIndex(), MVT::i32);
1042
1043 auto PtrVT = getPointerTy(DAG.getDataLayout());
1044
1045 if (HFL.FirstVarArgSavedReg & 1)
1046 SavedRegAreaStartFrameIndex =
1047 DAG.getNode(ISD::ADD, DL, PtrVT,
1048 DAG.getFrameIndex(FuncInfo.getRegSavedAreaStartFrameIndex(),
1049 MVT::i32),
1050 DAG.getIntPtrConstant(4, DL));
1051
1052 // Store the saved register area start pointer.
1053 SDValue Store =
1054 DAG.getStore(Op.getOperand(0), DL,
1055 SavedRegAreaStartFrameIndex,
1056 FIN, MachinePointerInfo(SV));
1057 MemOps.push_back(Store);
1058
1059 // Store saved register area end pointer.
1060 FIN = DAG.getNode(ISD::ADD, DL, PtrVT,
1061 FIN, DAG.getIntPtrConstant(4, DL));
1062 Store = DAG.getStore(Op.getOperand(0), DL,
1063 DAG.getFrameIndex(FuncInfo.getVarArgsFrameIndex(),
1064 PtrVT),
1065 FIN, MachinePointerInfo(SV, 4));
1066 MemOps.push_back(Store);
1067
1068 // Store overflow area pointer.
1069 FIN = DAG.getNode(ISD::ADD, DL, PtrVT,
1070 FIN, DAG.getIntPtrConstant(4, DL));
1071 Store = DAG.getStore(Op.getOperand(0), DL,
1072 DAG.getFrameIndex(FuncInfo.getVarArgsFrameIndex(),
1073 PtrVT),
1074 FIN, MachinePointerInfo(SV, 8));
1075 MemOps.push_back(Store);
1076
1077 return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOps);
1078}
1079
1080SDValue
1082 // Assert that the linux ABI is enabled for the current compilation.
1083 assert(Subtarget.isEnvironmentMusl() && "Linux ABI should be enabled");
1084 SDValue Chain = Op.getOperand(0);
1085 SDValue DestPtr = Op.getOperand(1);
1086 SDValue SrcPtr = Op.getOperand(2);
1087 const Value *DestSV = cast<SrcValueSDNode>(Op.getOperand(3))->getValue();
1088 const Value *SrcSV = cast<SrcValueSDNode>(Op.getOperand(4))->getValue();
1089 SDLoc DL(Op);
1090 // Size of the va_list is 12 bytes as it has 3 pointers. Therefore,
1091 // we need to memcopy 12 bytes from va_list to another similar list.
1092 return DAG.getMemcpy(Chain, DL, DestPtr, SrcPtr,
1093 DAG.getIntPtrConstant(12, DL), Align(4), Align(4),
1094 /*isVolatile*/ false, false, /*CI=*/nullptr,
1095 std::nullopt, MachinePointerInfo(DestSV),
1096 MachinePointerInfo(SrcSV));
1097}
1098
1100 const SDLoc &dl(Op);
1101 SDValue LHS = Op.getOperand(0);
1102 SDValue RHS = Op.getOperand(1);
1103 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
1104 MVT ResTy = ty(Op);
1105 MVT OpTy = ty(LHS);
1106
1107 if (OpTy == MVT::v2i16 || OpTy == MVT::v4i8) {
1108 assert(OpTy.getVectorElementType().isScalarInteger());
1109 MVT WideTy = OpTy.widenIntegerElementType();
1110 return DAG.getSetCC(dl, ResTy,
1111 DAG.getSExtOrTrunc(LHS, SDLoc(LHS), WideTy),
1112 DAG.getSExtOrTrunc(RHS, SDLoc(RHS), WideTy), CC);
1113 }
1114
1115 // Treat all other vector types as legal.
1116 if (ResTy.isVector())
1117 return Op;
1118
1119 // Equality comparisons of short integers should use sign-extend, not
1120 // zero-extend, since we can represent small negative values in the compare
1121 // instructions. The LLVM default is to use zero-extend arbitrarily in
1122 // these cases.
1123 auto isSExtFree = [this](SDValue N) {
1124 switch (N.getOpcode()) {
1125 case ISD::TRUNCATE: {
1126 // A sign-extend of a truncate of a sign-extend is free.
1127 SDValue Op = N.getOperand(0);
1128 if (Op.getOpcode() != ISD::AssertSext)
1129 return false;
1130 EVT OrigTy = cast<VTSDNode>(Op.getOperand(1))->getVT();
1131 unsigned ThisBW = ty(N).getSizeInBits();
1132 unsigned OrigBW = OrigTy.getSizeInBits();
1133 // The type that was sign-extended to get the AssertSext must be
1134 // narrower than the type of N (so that N has still the same value
1135 // as the original).
1136 return ThisBW >= OrigBW;
1137 }
1138 case ISD::LOAD:
1139 // We have sign-extended loads.
1140 return true;
1141 }
1142 return false;
1143 };
1144
1145 // Only do this for equality comparisons. Signed comparisons are already
1146 // sign-extended by the generic operand promotion, and for unsigned
1147 // comparisons a sign-extension is never profitable: it does not change the
1148 // result (sign-extension preserves the unsigned ordering of the values of
1149 // the narrower type), but it turns constants with the sign bit of the
1150 // narrower type set into large 32-bit values, which then have to be
1151 // materialized in a register or use a constant extender.
1152 if ((OpTy == MVT::i8 || OpTy == MVT::i16) && ISD::isIntEqualitySetCC(CC)) {
1154 bool IsNegative = C && C->getAPIntValue().isNegative();
1155 if (IsNegative || isSExtFree(LHS) || isSExtFree(RHS))
1156 return DAG.getSetCC(dl, ResTy,
1157 DAG.getSExtOrTrunc(LHS, SDLoc(LHS), MVT::i32),
1158 DAG.getSExtOrTrunc(RHS, SDLoc(RHS), MVT::i32), CC);
1159 }
1160
1161 return SDValue();
1162}
1163
1164SDValue
1166 SDValue PredOp = Op.getOperand(0);
1167 SDValue Op1 = Op.getOperand(1), Op2 = Op.getOperand(2);
1168 MVT OpTy = ty(Op1);
1169 const SDLoc &dl(Op);
1170
1171 if (OpTy == MVT::v2i16 || OpTy == MVT::v4i8) {
1172 assert(OpTy.getVectorElementType().isScalarInteger());
1173 MVT WideTy = OpTy.widenIntegerElementType();
1174 // Generate (trunc (select (_, sext, sext))).
1175 return DAG.getSExtOrTrunc(
1176 DAG.getSelect(dl, WideTy, PredOp,
1177 DAG.getSExtOrTrunc(Op1, dl, WideTy),
1178 DAG.getSExtOrTrunc(Op2, dl, WideTy)),
1179 dl, OpTy);
1180 }
1181
1182 return SDValue();
1183}
1184
1185SDValue
1187 EVT ValTy = Op.getValueType();
1189 Constant *CVal = nullptr;
1190 bool isVTi1Type = false;
1191 if (auto *CV = dyn_cast<ConstantVector>(CPN->getConstVal())) {
1192 if (cast<VectorType>(CV->getType())->getElementType()->isIntegerTy(1)) {
1193 IRBuilder<> IRB(CV->getContext());
1195 unsigned VecLen = CV->getNumOperands();
1196 assert(isPowerOf2_32(VecLen) &&
1197 "conversion only supported for pow2 VectorSize");
1198 for (unsigned i = 0; i < VecLen; ++i)
1199 NewConst.push_back(IRB.getInt8(CV->getOperand(i)->isNullValue()));
1200
1201 CVal = ConstantVector::get(NewConst);
1202 isVTi1Type = true;
1203 }
1204 }
1205 Align Alignment = CPN->getAlign();
1206 bool IsPositionIndependent = isPositionIndependent();
1207 unsigned char TF = IsPositionIndependent ? HexagonII::MO_PCREL : 0;
1208
1209 unsigned Offset = 0;
1210 SDValue T;
1211 if (CPN->isMachineConstantPoolEntry())
1212 T = DAG.getTargetConstantPool(CPN->getMachineCPVal(), ValTy, Alignment,
1213 Offset, TF);
1214 else if (isVTi1Type)
1215 T = DAG.getTargetConstantPool(CVal, ValTy, Alignment, Offset, TF);
1216 else
1217 T = DAG.getTargetConstantPool(CPN->getConstVal(), ValTy, Alignment, Offset,
1218 TF);
1219
1220 assert(cast<ConstantPoolSDNode>(T)->getTargetFlags() == TF &&
1221 "Inconsistent target flag encountered");
1222
1223 if (IsPositionIndependent)
1224 return DAG.getNode(HexagonISD::AT_PCREL, SDLoc(Op), ValTy, T);
1225 return DAG.getNode(HexagonISD::CP, SDLoc(Op), ValTy, T);
1226}
1227
1228SDValue
1230 EVT VT = Op.getValueType();
1231 int Idx = cast<JumpTableSDNode>(Op)->getIndex();
1232 if (isPositionIndependent()) {
1234 return DAG.getNode(HexagonISD::AT_PCREL, SDLoc(Op), VT, T);
1235 }
1236
1237 SDValue T = DAG.getTargetJumpTable(Idx, VT);
1238 return DAG.getNode(HexagonISD::JT, SDLoc(Op), VT, T);
1239}
1240
1241SDValue
1243 const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo();
1245 MachineFrameInfo &MFI = MF.getFrameInfo();
1246 MFI.setReturnAddressIsTaken(true);
1247
1248 EVT VT = Op.getValueType();
1249 SDLoc dl(Op);
1250 unsigned Depth = Op.getConstantOperandVal(0);
1251 if (Depth) {
1252 SDValue FrameAddr = LowerFRAMEADDR(Op, DAG);
1253 SDValue Offset = DAG.getConstant(4, dl, MVT::i32);
1254 return DAG.getLoad(VT, dl, DAG.getEntryNode(),
1255 DAG.getNode(ISD::ADD, dl, VT, FrameAddr, Offset),
1257 }
1258
1259 // Return LR, which contains the return address. Mark it an implicit live-in.
1260 Register Reg = MF.addLiveIn(HRI.getRARegister(), getRegClassFor(MVT::i32));
1261 return DAG.getCopyFromReg(DAG.getEntryNode(), dl, Reg, VT);
1262}
1263
1264SDValue
1266 const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo();
1268 MFI.setFrameAddressIsTaken(true);
1269
1270 EVT VT = Op.getValueType();
1271 SDLoc dl(Op);
1272 unsigned Depth = Op.getConstantOperandVal(0);
1273 SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl,
1274 HRI.getFrameRegister(), VT);
1275 while (Depth--)
1276 FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr,
1278 return FrameAddr;
1279}
1280
1281SDValue
1283 SDLoc dl(Op);
1284 return DAG.getNode(HexagonISD::BARRIER, dl, MVT::Other, Op.getOperand(0));
1285}
1286
1287SDValue
1289 SDLoc dl(Op);
1290 auto *GAN = cast<GlobalAddressSDNode>(Op);
1291 auto PtrVT = getPointerTy(DAG.getDataLayout());
1292 auto *GV = GAN->getGlobal();
1293 int64_t Offset = GAN->getOffset();
1294
1295 auto &HLOF = *HTM.getObjFileLowering();
1296 Reloc::Model RM = HTM.getRelocationModel();
1297
1298 if (RM == Reloc::Static) {
1299 SDValue GA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, Offset);
1300 const GlobalObject *GO = GV->getAliaseeObject();
1301 if (GO && Subtarget.useSmallData() && HLOF.isGlobalInSmallSection(GO, HTM))
1302 return DAG.getNode(HexagonISD::CONST32_GP, dl, PtrVT, GA);
1303 return DAG.getNode(HexagonISD::CONST32, dl, PtrVT, GA);
1304 }
1305
1306 bool UsePCRel = getTargetMachine().shouldAssumeDSOLocal(GV);
1307 if (UsePCRel) {
1308 SDValue GA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, Offset,
1310 return DAG.getNode(HexagonISD::AT_PCREL, dl, PtrVT, GA);
1311 }
1312
1313 // Use GOT index.
1314 SDValue GOT = DAG.getGLOBAL_OFFSET_TABLE(PtrVT);
1315 SDValue GA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, HexagonII::MO_GOT);
1316 SDValue Off = DAG.getConstant(Offset, dl, MVT::i32);
1317 return DAG.getNode(HexagonISD::AT_GOT, dl, PtrVT, GOT, GA, Off);
1318}
1319
1320// Specifies that for loads and stores VT can be promoted to PromotedLdStVT.
1321SDValue
1323 const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress();
1324 SDLoc dl(Op);
1325 EVT PtrVT = getPointerTy(DAG.getDataLayout());
1326
1327 Reloc::Model RM = HTM.getRelocationModel();
1328 if (RM == Reloc::Static) {
1329 SDValue A = DAG.getTargetBlockAddress(BA, PtrVT);
1330 return DAG.getNode(HexagonISD::CONST32_GP, dl, PtrVT, A);
1331 }
1332
1334 return DAG.getNode(HexagonISD::AT_PCREL, dl, PtrVT, A);
1335}
1336
1337SDValue
1339 const {
1340 EVT PtrVT = getPointerTy(DAG.getDataLayout());
1343 return DAG.getNode(HexagonISD::AT_PCREL, SDLoc(Op), PtrVT, GOTSym);
1344}
1345
1346SDValue
1348 GlobalAddressSDNode *GA, SDValue Glue, EVT PtrVT, unsigned ReturnReg,
1349 unsigned char OperandFlags) const {
1351 MachineFrameInfo &MFI = MF.getFrameInfo();
1352 SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
1353 SDLoc dl(GA);
1354 SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl,
1355 GA->getValueType(0),
1356 GA->getOffset(),
1357 OperandFlags);
1358 // Create Operands for the call.The Operands should have the following:
1359 // 1. Chain SDValue
1360 // 2. Callee which in this case is the Global address value.
1361 // 3. Registers live into the call.In this case its R0, as we
1362 // have just one argument to be passed.
1363 // 4. Glue.
1364 // Note: The order is important.
1365
1366 const auto &HRI = *Subtarget.getRegisterInfo();
1367 const uint32_t *Mask = HRI.getCallPreservedMask(MF, CallingConv::C);
1368 assert(Mask && "Missing call preserved mask for calling convention");
1369 SDValue Ops[] = { Chain, TGA, DAG.getRegister(Hexagon::R0, PtrVT),
1370 DAG.getRegisterMask(Mask), Glue };
1371 Chain = DAG.getNode(HexagonISD::CALL, dl, NodeTys, Ops);
1372
1373 // Inform MFI that function has calls.
1374 MFI.setAdjustsStack(true);
1375
1376 Glue = Chain.getValue(1);
1377 return DAG.getCopyFromReg(Chain, dl, ReturnReg, PtrVT, Glue);
1378}
1379
1380//
1381// Lower using the initial executable model for TLS addresses
1382//
1383SDValue
1385 SelectionDAG &DAG) const {
1386 SDLoc dl(GA);
1387 int64_t Offset = GA->getOffset();
1388 auto PtrVT = getPointerTy(DAG.getDataLayout());
1389
1390 // Get the thread pointer.
1391 SDValue TP = DAG.getCopyFromReg(DAG.getEntryNode(), dl, Hexagon::UGP, PtrVT);
1392
1393 bool IsPositionIndependent = isPositionIndependent();
1394 unsigned char TF =
1395 IsPositionIndependent ? HexagonII::MO_IEGOT : HexagonII::MO_IE;
1396
1397 // First generate the TLS symbol address
1398 SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl, PtrVT,
1399 Offset, TF);
1400
1401 SDValue Sym = DAG.getNode(HexagonISD::CONST32, dl, PtrVT, TGA);
1402
1403 if (IsPositionIndependent) {
1404 // Generate the GOT pointer in case of position independent code
1405 SDValue GOT = LowerGLOBAL_OFFSET_TABLE(Sym, DAG);
1406
1407 // Add the TLS Symbol address to GOT pointer.This gives
1408 // GOT relative relocation for the symbol.
1409 Sym = DAG.getNode(ISD::ADD, dl, PtrVT, GOT, Sym);
1410 }
1411
1412 // Load the offset value for TLS symbol.This offset is relative to
1413 // thread pointer.
1414 SDValue LoadOffset =
1415 DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), Sym, MachinePointerInfo());
1416
1417 // Address of the thread local variable is the add of thread
1418 // pointer and the offset of the variable.
1419 return DAG.getNode(ISD::ADD, dl, PtrVT, TP, LoadOffset);
1420}
1421
1422//
1423// Lower using the local executable model for TLS addresses
1424//
1425SDValue
1427 SelectionDAG &DAG) const {
1428 SDLoc dl(GA);
1429 int64_t Offset = GA->getOffset();
1430 auto PtrVT = getPointerTy(DAG.getDataLayout());
1431
1432 // Get the thread pointer.
1433 SDValue TP = DAG.getCopyFromReg(DAG.getEntryNode(), dl, Hexagon::UGP, PtrVT);
1434 // Generate the TLS symbol address
1435 SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl, PtrVT, Offset,
1437 SDValue Sym = DAG.getNode(HexagonISD::CONST32, dl, PtrVT, TGA);
1438
1439 // Address of the thread local variable is the add of thread
1440 // pointer and the offset of the variable.
1441 return DAG.getNode(ISD::ADD, dl, PtrVT, TP, Sym);
1442}
1443
1444//
1445// Lower using the general dynamic model for TLS addresses
1446//
1447SDValue
1449 SelectionDAG &DAG) const {
1450 SDLoc dl(GA);
1451 int64_t Offset = GA->getOffset();
1452 auto PtrVT = getPointerTy(DAG.getDataLayout());
1453
1454 // First generate the TLS symbol address
1455 SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl, PtrVT, Offset,
1457
1458 // Then, generate the GOT pointer
1459 SDValue GOT = LowerGLOBAL_OFFSET_TABLE(TGA, DAG);
1460
1461 // Add the TLS symbol and the GOT pointer
1462 SDValue Sym = DAG.getNode(HexagonISD::CONST32, dl, PtrVT, TGA);
1463 SDValue Chain = DAG.getNode(ISD::ADD, dl, PtrVT, GOT, Sym);
1464
1465 // Copy over the argument to R0
1466 SDValue InGlue;
1467 Chain = DAG.getCopyToReg(DAG.getEntryNode(), dl, Hexagon::R0, Chain, InGlue);
1468 InGlue = Chain.getValue(1);
1469
1470 unsigned Flags = DAG.getSubtarget<HexagonSubtarget>().useLongCalls()
1473
1474 return GetDynamicTLSAddr(DAG, Chain, GA, InGlue, PtrVT,
1475 Hexagon::R0, Flags);
1476}
1477
1478//
1479// Lower TLS addresses.
1480//
1481// For now for dynamic models, we only support the general dynamic model.
1482//
1483SDValue
1485 SelectionDAG &DAG) const {
1487
1488 switch (HTM.getTLSModel(GA->getGlobal())) {
1491 return LowerToTLSGeneralDynamicModel(GA, DAG);
1493 return LowerToTLSInitialExecModel(GA, DAG);
1495 return LowerToTLSLocalExecModel(GA, DAG);
1496 }
1497 llvm_unreachable("Bogus TLS model");
1498}
1499
1500//===----------------------------------------------------------------------===//
1501// TargetLowering Implementation
1502//===----------------------------------------------------------------------===//
1503
1505 const HexagonSubtarget &ST)
1506 : TargetLowering(TM, ST),
1507 HTM(static_cast<const HexagonTargetMachine &>(TM)), Subtarget(ST) {
1508 auto &HRI = *Subtarget.getRegisterInfo();
1509
1513 setStackPointerRegisterToSaveRestore(HRI.getStackRegister());
1516
1519
1522 else
1524
1525 // Limits for inline expansion of memcpy/memmove
1532
1534
1535 //
1536 // Set up register classes.
1537 //
1538
1539 addRegisterClass(MVT::i1, &Hexagon::PredRegsRegClass);
1540 addRegisterClass(MVT::v2i1, &Hexagon::PredRegsRegClass); // bbbbaaaa
1541 addRegisterClass(MVT::v4i1, &Hexagon::PredRegsRegClass); // ddccbbaa
1542 addRegisterClass(MVT::v8i1, &Hexagon::PredRegsRegClass); // hgfedcba
1543 addRegisterClass(MVT::i32, &Hexagon::IntRegsRegClass);
1544 addRegisterClass(MVT::v2i16, &Hexagon::IntRegsRegClass);
1545 addRegisterClass(MVT::v4i8, &Hexagon::IntRegsRegClass);
1546 addRegisterClass(MVT::i64, &Hexagon::DoubleRegsRegClass);
1547 addRegisterClass(MVT::v8i8, &Hexagon::DoubleRegsRegClass);
1548 addRegisterClass(MVT::v4i16, &Hexagon::DoubleRegsRegClass);
1549 addRegisterClass(MVT::v2i32, &Hexagon::DoubleRegsRegClass);
1550
1551 addRegisterClass(MVT::f32, &Hexagon::IntRegsRegClass);
1552 addRegisterClass(MVT::f64, &Hexagon::DoubleRegsRegClass);
1553
1554 //
1555 // Handling of scalar operations.
1556 //
1557 // All operations default to "legal", except:
1558 // - indexed loads and stores (pre-/post-incremented),
1559 // - ANY_EXTEND_VECTOR_INREG, ATOMIC_CMP_SWAP_WITH_SUCCESS, CONCAT_VECTORS,
1560 // ConstantFP, FCEIL, FCOPYSIGN, FEXP, FEXP2, FFLOOR, FGETSIGN,
1561 // FLOG, FLOG2, FLOG10, FMAXIMUMNUM, FMINIMUMNUM, FNEARBYINT, FRINT, FROUND,
1562 // TRAP, FTRUNC, PREFETCH, SIGN_EXTEND_VECTOR_INREG,
1563 // ZERO_EXTEND_VECTOR_INREG,
1564 // which default to "expand" for at least one type.
1565
1566 // Misc operations.
1569 setOperationAction(ISD::TRAP, MVT::Other, Legal);
1586
1587 // Custom legalize GlobalAddress nodes into CONST32.
1591
1592 // Hexagon needs to optimize cases with negative constants.
1596 setOperationAction(ISD::SETCC, MVT::v2i16, Custom);
1597
1598 // VASTART needs to be custom lowered to use the VarArgsFrameIndex.
1600 setOperationAction(ISD::VAEND, MVT::Other, Expand);
1601 setOperationAction(ISD::VAARG, MVT::Other, Expand);
1602 if (Subtarget.isEnvironmentMusl())
1604 else
1606
1610
1611 if (EmitJumpTables)
1613 else
1614 setMinimumJumpTableEntries(std::numeric_limits<unsigned>::max());
1615 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
1616
1617 for (unsigned LegalIntOp :
1619 setOperationAction(LegalIntOp, MVT::i32, Legal);
1620 setOperationAction(LegalIntOp, MVT::i64, Legal);
1621 }
1622
1623 // Hexagon has A4_addp_c and A4_subp_c that take and generate a carry bit,
1624 // but they only operate on i64.
1625 for (MVT VT : MVT::integer_valuetypes()) {
1632 }
1635
1640
1641 // Popcount can count # of 1s in i64 but returns i32.
1646
1651
1656
1657 for (unsigned IntExpOp :
1662 for (MVT VT : MVT::integer_valuetypes())
1663 setOperationAction(IntExpOp, VT, Expand);
1664 }
1665 for (MVT VT : MVT::fp_valuetypes()) {
1666 for (unsigned FPExpOp : {ISD::FDIV, ISD::FSQRT, ISD::FSIN, ISD::FCOS,
1668 setOperationAction(FPExpOp, VT, Expand);
1669
1671 }
1672
1673 // No extending loads from i32.
1674 for (MVT VT : MVT::integer_valuetypes()) {
1675 setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i32, Expand);
1676 setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i32, Expand);
1677 setLoadExtAction(ISD::EXTLOAD, VT, MVT::i32, Expand);
1678 }
1679 // Turn FP truncstore into trunc + store.
1680 setTruncStoreAction(MVT::f64, MVT::f32, Expand);
1681 setTruncStoreAction(MVT::f32, MVT::bf16, Expand);
1682 setTruncStoreAction(MVT::f64, MVT::bf16, Expand);
1683 // Turn FP extload into load/fpextend.
1684 for (MVT VT : MVT::fp_valuetypes())
1685 setLoadExtAction(ISD::EXTLOAD, VT, MVT::f32, Expand);
1686
1687 // Expand BR_CC and SELECT_CC for all integer and fp types.
1688 for (MVT VT : MVT::integer_valuetypes()) {
1691 }
1692 for (MVT VT : MVT::fp_valuetypes()) {
1695 }
1696 setOperationAction(ISD::BR_CC, MVT::Other, Expand);
1697
1698 //
1699 // Handling of vector operations.
1700 //
1701
1702 // Set the action for vector operations to "expand", then override it with
1703 // either "custom" or "legal" for specific cases.
1704 // clang-format off
1705 static const unsigned VectExpOps[] = {
1706 // Integer arithmetic:
1710 // Logical/bit:
1713 // Floating point arithmetic/math functions:
1721 // Misc:
1723 // Vector:
1729 };
1730 // clang-format on
1731
1733 for (unsigned VectExpOp : VectExpOps)
1734 setOperationAction(VectExpOp, VT, Expand);
1735
1736 // Expand all extending loads and truncating stores:
1737 for (MVT TargetVT : MVT::fixedlen_vector_valuetypes()) {
1738 if (TargetVT == VT)
1739 continue;
1740 setLoadExtAction(ISD::EXTLOAD, TargetVT, VT, Expand);
1741 setLoadExtAction(ISD::ZEXTLOAD, TargetVT, VT, Expand);
1742 setLoadExtAction(ISD::SEXTLOAD, TargetVT, VT, Expand);
1743 setTruncStoreAction(VT, TargetVT, Expand);
1744 }
1745
1746 // Normalize all inputs to SELECT to be vectors of i32.
1747 if (VT.getVectorElementType() != MVT::i32) {
1748 MVT VT32 = MVT::getVectorVT(MVT::i32, VT.getSizeInBits()/32);
1750 AddPromotedToType(ISD::SELECT, VT, VT32);
1751 }
1755 }
1756
1759
1760 // Extending loads from (native) vectors of i8 into (native) vectors of i16
1761 // are legal.
1762 setLoadExtAction(ISD::EXTLOAD, MVT::v2i16, MVT::v2i8, Legal);
1763 setLoadExtAction(ISD::ZEXTLOAD, MVT::v2i16, MVT::v2i8, Legal);
1764 setLoadExtAction(ISD::SEXTLOAD, MVT::v2i16, MVT::v2i8, Legal);
1765 setLoadExtAction(ISD::EXTLOAD, MVT::v4i16, MVT::v4i8, Legal);
1766 setLoadExtAction(ISD::ZEXTLOAD, MVT::v4i16, MVT::v4i8, Legal);
1767 setLoadExtAction(ISD::SEXTLOAD, MVT::v4i16, MVT::v4i8, Legal);
1768
1772
1773 // Types natively supported:
1774 for (MVT NativeVT : {MVT::v8i1, MVT::v4i1, MVT::v2i1, MVT::v4i8,
1775 MVT::v8i8, MVT::v2i16, MVT::v4i16, MVT::v2i32}) {
1782
1783 setOperationAction(ISD::ADD, NativeVT, Legal);
1784 setOperationAction(ISD::SUB, NativeVT, Legal);
1785 setOperationAction(ISD::MUL, NativeVT, Legal);
1786 setOperationAction(ISD::AND, NativeVT, Legal);
1787 setOperationAction(ISD::OR, NativeVT, Legal);
1788 setOperationAction(ISD::XOR, NativeVT, Legal);
1789
1790 if (NativeVT.getVectorElementType() != MVT::i1) {
1794 }
1795 }
1796
1797 for (MVT VT : {MVT::v8i8, MVT::v4i16, MVT::v2i32}) {
1802 }
1803
1804 // Custom lower unaligned loads.
1805 // Also, for both loads and stores, verify the alignment of the address
1806 // in case it is a compile-time constant. This is a usability feature to
1807 // provide a meaningful error message to users.
1808 for (MVT VT : {MVT::i16, MVT::i32, MVT::v4i8, MVT::i64, MVT::v8i8,
1809 MVT::v2i16, MVT::v4i16, MVT::v2i32}) {
1812 }
1813
1814 // Custom-lower load/stores of boolean vectors.
1815 for (MVT VT : {MVT::v2i1, MVT::v4i1, MVT::v8i1}) {
1818 }
1819
1820 // Normalize integer compares to EQ/GT/UGT
1821 for (MVT VT : {MVT::v2i16, MVT::v4i8, MVT::v8i8, MVT::v2i32, MVT::v4i16,
1822 MVT::v2i32}) {
1830 }
1831
1832 // Normalize boolean compares to [U]LE/[U]LT
1833 for (MVT VT : {MVT::i1, MVT::v2i1, MVT::v4i1, MVT::v8i1}) {
1838 }
1839
1840 // Custom-lower bitcasts from i8 to v8i1.
1842 setOperationAction(ISD::SETCC, MVT::v2i16, Custom);
1848
1849 // V5+.
1855
1864
1877
1878 // Special handling for half-precision floating point conversions.
1879 // Lower half float conversions into library calls.
1887
1888 setLoadExtAction(ISD::EXTLOAD, MVT::f32, MVT::f16, Expand);
1889 setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f16, Expand);
1890 setLoadExtAction(ISD::EXTLOAD, MVT::f32, MVT::bf16, Expand);
1891 setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::bf16, Expand);
1892
1893 setTruncStoreAction(MVT::f32, MVT::f16, Expand);
1894 setTruncStoreAction(MVT::f64, MVT::f16, Expand);
1895
1896 // Handling of indexed loads/stores: default is "expand".
1897 //
1898 for (MVT VT : {MVT::i8, MVT::i16, MVT::i32, MVT::i64, MVT::f32, MVT::f64,
1899 MVT::v2i16, MVT::v2i32, MVT::v4i8, MVT::v4i16, MVT::v8i8}) {
1902 }
1903
1904 // Subtarget-specific operation actions.
1905 //
1906 if (Subtarget.hasV60Ops()) {
1911 }
1912 if (Subtarget.hasV66Ops()) {
1915 }
1916 if (Subtarget.hasV67Ops()) {
1922 }
1923
1927
1928 if (Subtarget.useHVXOps())
1929 initializeHVXLowering();
1930
1932}
1933
1934bool
1935HexagonTargetLowering::validateConstPtrAlignment(SDValue Ptr, Align NeedAlign,
1936 const SDLoc &dl, SelectionDAG &DAG) const {
1937 auto *CA = dyn_cast<ConstantSDNode>(Ptr);
1938 if (!CA)
1939 return true;
1940 unsigned Addr = CA->getZExtValue();
1941 Align HaveAlign =
1942 Addr != 0 ? Align(1ull << llvm::countr_zero(Addr)) : NeedAlign;
1943 if (HaveAlign >= NeedAlign)
1944 return true;
1945
1946 static int DK_MisalignedTrap = llvm::getNextAvailablePluginDiagnosticKind();
1947
1948 struct DiagnosticInfoMisalignedTrap : public DiagnosticInfo {
1949 DiagnosticInfoMisalignedTrap(StringRef M)
1950 : DiagnosticInfo(DK_MisalignedTrap, DS_Remark), Msg(M) {}
1951 void print(DiagnosticPrinter &DP) const override {
1952 DP << Msg;
1953 }
1954 static bool classof(const DiagnosticInfo *DI) {
1955 return DI->getKind() == DK_MisalignedTrap;
1956 }
1957 StringRef Msg;
1958 };
1959
1960 std::string ErrMsg;
1961 raw_string_ostream O(ErrMsg);
1962 O << "Misaligned constant address: " << format_hex(Addr, 10)
1963 << " has alignment " << HaveAlign.value()
1964 << ", but the memory access requires " << NeedAlign.value();
1965 if (DebugLoc DL = dl.getDebugLoc())
1966 DL.print(O << ", at ");
1967 O << ". The instruction has been replaced with a trap.";
1968
1969 DAG.getContext()->diagnose(DiagnosticInfoMisalignedTrap(O.str()));
1970 return false;
1971}
1972
1973SDValue
1974HexagonTargetLowering::replaceMemWithUndef(SDValue Op, SelectionDAG &DAG)
1975 const {
1976 const SDLoc &dl(Op);
1977 auto *LS = cast<LSBaseSDNode>(Op.getNode());
1978 assert(!LS->isIndexed() && "Not expecting indexed ops on constant address");
1979
1980 SDValue Chain = LS->getChain();
1981 SDValue Trap = DAG.getNode(ISD::TRAP, dl, MVT::Other, Chain);
1982 if (LS->getOpcode() == ISD::LOAD)
1983 return DAG.getMergeValues({DAG.getUNDEF(ty(Op)), Trap}, dl);
1984 return Trap;
1985}
1986
1987// Bit-reverse Load Intrinsic: Check if the instruction is a bit reverse load
1988// intrinsic.
1989static bool isBrevLdIntrinsic(const Value *Inst) {
1990 unsigned ID = cast<IntrinsicInst>(Inst)->getIntrinsicID();
1991 return (ID == Intrinsic::hexagon_L2_loadrd_pbr ||
1992 ID == Intrinsic::hexagon_L2_loadri_pbr ||
1993 ID == Intrinsic::hexagon_L2_loadrh_pbr ||
1994 ID == Intrinsic::hexagon_L2_loadruh_pbr ||
1995 ID == Intrinsic::hexagon_L2_loadrb_pbr ||
1996 ID == Intrinsic::hexagon_L2_loadrub_pbr);
1997}
1998
1999// Bit-reverse Load Intrinsic :Crawl up and figure out the object from previous
2000// instruction. So far we only handle bitcast, extract value and bit reverse
2001// load intrinsic instructions. Should we handle CGEP ?
2003 if (Operator::getOpcode(V) == Instruction::ExtractValue ||
2004 Operator::getOpcode(V) == Instruction::BitCast)
2005 V = cast<Operator>(V)->getOperand(0);
2006 else if (isa<IntrinsicInst>(V) && isBrevLdIntrinsic(V))
2007 V = cast<Instruction>(V)->getOperand(0);
2008 return V;
2009}
2010
2011// Bit-reverse Load Intrinsic: For a PHI Node return either an incoming edge or
2012// a back edge. If the back edge comes from the intrinsic itself, the incoming
2013// edge is returned.
2014static Value *returnEdge(const PHINode *PN, Value *IntrBaseVal) {
2015 const BasicBlock *Parent = PN->getParent();
2016 int Idx = -1;
2017 for (unsigned i = 0, e = PN->getNumIncomingValues(); i < e; ++i) {
2018 BasicBlock *Blk = PN->getIncomingBlock(i);
2019 // Determine if the back edge is originated from intrinsic.
2020 if (Blk == Parent) {
2021 Value *BackEdgeVal = PN->getIncomingValue(i);
2022 Value *BaseVal;
2023 // Loop over till we return the same Value or we hit the IntrBaseVal.
2024 do {
2025 BaseVal = BackEdgeVal;
2026 BackEdgeVal = getBrevLdObject(BackEdgeVal);
2027 } while ((BaseVal != BackEdgeVal) && (IntrBaseVal != BackEdgeVal));
2028 // If the getBrevLdObject returns IntrBaseVal, we should return the
2029 // incoming edge.
2030 if (IntrBaseVal == BackEdgeVal)
2031 continue;
2032 Idx = i;
2033 break;
2034 } else // Set the node to incoming edge.
2035 Idx = i;
2036 }
2037 assert(Idx >= 0 && "Unexpected index to incoming argument in PHI");
2038 return PN->getIncomingValue(Idx);
2039}
2040
2041// Bit-reverse Load Intrinsic: Figure out the underlying object the base
2042// pointer points to, for the bit-reverse load intrinsic. Setting this to
2043// memoperand might help alias analysis to figure out the dependencies.
2044// A bit-reverse load accesses the base pointer with its low 16 bits reversed,
2045// and post-increments the base pointer by the modifier value. For a chain of
2046// bit-reverse loads, the offset that a load accesses relative to the
2047// underlying object is the bit-reverse of the sum of the modifiers of the
2048// preceding loads in the chain. Offset is set to that value, and HasOffset is
2049// set to true, when the sum is known, that is when all of those modifiers are
2050// constants and the sum fits in 16 unsigned bits. Otherwise HasOffset is set
2051// to false and Offset is left unchanged.
2053 bool &HasOffset) {
2054 Value *IntrBaseVal = V;
2055 Value *BaseVal;
2056 int64_t Sum = 0;
2057 HasOffset = true;
2058 // Loop over till we return the same Value, implies we either figure out
2059 // the object or we hit a PHI
2060 do {
2061 BaseVal = V;
2062 V = getBrevLdObject(V);
2063 // Identify if this is part of a chain of bit-reverse loads, and accumulate
2064 // the modifier of the preceding load in the chain.
2065 if (HasOffset && BaseVal != V && isa<IntrinsicInst>(V) &&
2066 isBrevLdIntrinsic(V)) {
2067 Value *Modifier = cast<IntrinsicInst>(V)->getOperand(1);
2068 if (auto *CN = dyn_cast<ConstantInt>(Modifier))
2069 Sum += CN->getSExtValue();
2070 else
2071 HasOffset = false;
2072 }
2073 } while (BaseVal != V);
2074
2075 // Only the low 16 bits of the base pointer take part in the bit-reverse. A
2076 // sum that does not fit in them would also change the remaining bits.
2077 if (HasOffset && Sum >= 0 && isUInt<16>(Sum))
2078 Offset = APInt(16, Sum).reverseBits().getZExtValue();
2079 else
2080 HasOffset = false;
2081
2082 // Identify the object from PHINode.
2083 if (const PHINode *PN = dyn_cast<PHINode>(V))
2084 return returnEdge(PN, IntrBaseVal);
2085 // For non PHI nodes, the object is the last value returned by getBrevLdObject
2086 else
2087 return V;
2088}
2089
2090/// Given an intrinsic, checks if on the target the intrinsic will need to map
2091/// to a MemIntrinsicNode (touches memory). If this is the case, it stores
2092/// the intrinsic information into the Infos vector.
2095 MachineFunction &MF, unsigned Intrinsic) const {
2096 IntrinsicInfo Info;
2097 switch (Intrinsic) {
2098 case Intrinsic::hexagon_L2_loadrd_pbr:
2099 case Intrinsic::hexagon_L2_loadri_pbr:
2100 case Intrinsic::hexagon_L2_loadrh_pbr:
2101 case Intrinsic::hexagon_L2_loadruh_pbr:
2102 case Intrinsic::hexagon_L2_loadrb_pbr:
2103 case Intrinsic::hexagon_L2_loadrub_pbr: {
2104 Info.opc = ISD::INTRINSIC_W_CHAIN;
2105 auto &DL = I.getDataLayout();
2106 auto &Cont = I.getCalledFunction()->getParent()->getContext();
2107 // The intrinsic function call is of the form { ElTy, i8* }
2108 // @llvm.hexagon.L2.loadXX.pbr(i8*, i32). The pointer and memory access type
2109 // should be derived from ElTy.
2110 Type *ElTy = I.getCalledFunction()->getReturnType()->getStructElementType(0);
2111 Info.memVT = MVT::getVT(ElTy);
2112 llvm::Value *BasePtrVal = I.getOperand(0);
2113 // The offset value comes through the Modifier register. Determine the
2114 // offset that is going to be accessed relative to the underlying object.
2115 // If it cannot be determined, leave the pointer information out of the
2116 // memory operand, so that alias analysis stays conservative.
2117 bool HasOffset = false;
2118 Info.offset = 0;
2119 Value *UnderlyingObj =
2120 getUnderLyingObjectForBrevLdIntr(BasePtrVal, Info.offset, HasOffset);
2121 // The underlying object is unknown if the base pointer could not be traced
2122 // back to a pointer value. Also, unless the object is aligned to 64K, the
2123 // low 16 bits of the base pointer are not known, and reversing them can
2124 // produce an address anywhere in the surrounding 64K region, possibly
2125 // outside of the object.
2126 if (!UnderlyingObj->getType()->isPointerTy() ||
2127 UnderlyingObj->getPointerAlignment(DL) < Align(65536))
2128 HasOffset = false;
2129 if (HasOffset)
2130 Info.ptrVal = UnderlyingObj;
2131 Info.align = DL.getABITypeAlign(Info.memVT.getTypeForEVT(Cont));
2132 Info.flags = MachineMemOperand::MOLoad;
2133 Infos.push_back(Info);
2134 return;
2135 }
2136 case Intrinsic::hexagon_V6_vgathermw:
2137 case Intrinsic::hexagon_V6_vgathermw_128B:
2138 case Intrinsic::hexagon_V6_vgathermh:
2139 case Intrinsic::hexagon_V6_vgathermh_128B:
2140 case Intrinsic::hexagon_V6_vgathermhw:
2141 case Intrinsic::hexagon_V6_vgathermhw_128B:
2142 case Intrinsic::hexagon_V6_vgathermwq:
2143 case Intrinsic::hexagon_V6_vgathermwq_128B:
2144 case Intrinsic::hexagon_V6_vgathermhq:
2145 case Intrinsic::hexagon_V6_vgathermhq_128B:
2146 case Intrinsic::hexagon_V6_vgathermhwq:
2147 case Intrinsic::hexagon_V6_vgathermhwq_128B:
2148 case Intrinsic::hexagon_V6_vgather_vscattermh:
2149 case Intrinsic::hexagon_V6_vgather_vscattermh_128B: {
2150 const Module &M = *I.getParent()->getParent()->getParent();
2151 Info.opc = ISD::INTRINSIC_W_CHAIN;
2152 Type *VecTy = I.getArgOperand(I.arg_size() - 1)->getType();
2153 assert(VecTy->isVectorTy() && "Expected vector operand for vgather");
2154 Info.memVT = MVT::getVT(VecTy);
2155 Info.ptrVal = I.getArgOperand(0);
2156 Info.offset = 0;
2157 Info.align =
2158 MaybeAlign(M.getDataLayout().getTypeAllocSizeInBits(VecTy) / 8);
2161 Infos.push_back(Info);
2162 return;
2163 }
2164 default:
2165 break;
2166 }
2167}
2168
2170 return X.getValueType().isScalarInteger(); // 'tstbit'
2171}
2172
2174 return isTruncateFree(EVT::getEVT(Ty1), EVT::getEVT(Ty2));
2175}
2176
2178 if (!VT1.isSimple() || !VT2.isSimple())
2179 return false;
2180 return VT1.getSimpleVT() == MVT::i64 && VT2.getSimpleVT() == MVT::i32;
2181}
2182
2187
2188// Should we expand the build vector with shuffles?
2190 unsigned DefinedValues) const {
2191 return false;
2192}
2193
2196 unsigned Index) const {
2198 if (!ResVT.isSimple() || !SrcVT.isSimple())
2200
2201 MVT ResTy = ResVT.getSimpleVT(), SrcTy = SrcVT.getSimpleVT();
2202 if (ResTy.getVectorElementType() != MVT::i1)
2204
2205 // Non-HVX bool vectors are relatively cheap.
2206 if (SrcTy.getVectorNumElements() <= 8)
2209}
2210
2215
2217 EVT VT) const {
2218 return true;
2219}
2220
2223 unsigned VecLen = VT.getVectorMinNumElements();
2224 MVT ElemTy = VT.getVectorElementType();
2225
2226 if (VecLen == 1 || VT.isScalableVector())
2228
2229 if (Subtarget.useHVXOps()) {
2230 unsigned Action = getPreferredHvxVectorAction(VT);
2231 if (Action != ~0u)
2232 return static_cast<TargetLoweringBase::LegalizeTypeAction>(Action);
2233 }
2234
2235 // Always widen (remaining) vectors of i1.
2236 if (ElemTy == MVT::i1)
2238 // Widen non-power-of-2 vectors. Such types cannot be split right now,
2239 // and computeRegisterProperties will override "split" with "widen",
2240 // which can cause other issues.
2241 if (!isPowerOf2_32(VecLen))
2243
2245}
2246
2249 if (Subtarget.useHVXOps()) {
2250 unsigned Action = getCustomHvxOperationAction(Op);
2251 if (Action != ~0u)
2252 return static_cast<TargetLoweringBase::LegalizeAction>(Action);
2253 }
2255}
2256
2257std::pair<SDValue, int>
2258HexagonTargetLowering::getBaseAndOffset(SDValue Addr) const {
2259 if (Addr.getOpcode() == ISD::ADD) {
2260 SDValue Op1 = Addr.getOperand(1);
2261 if (auto *CN = dyn_cast<const ConstantSDNode>(Op1.getNode()))
2262 return { Addr.getOperand(0), CN->getSExtValue() };
2263 }
2264 return { Addr, 0 };
2265}
2266
2267// Lower a vector shuffle (V1, V2, V3). V1 and V2 are the two vectors
2268// to select data from, V3 is the permutation.
2269SDValue
2271 const {
2272 const auto *SVN = cast<ShuffleVectorSDNode>(Op);
2273 ArrayRef<int> AM = SVN->getMask();
2274 assert(AM.size() <= 8 && "Unexpected shuffle mask");
2275 unsigned VecLen = AM.size();
2276
2277 MVT VecTy = ty(Op);
2278 assert(!Subtarget.isHVXVectorType(VecTy, true) &&
2279 "HVX shuffles should be legal");
2280 assert(VecTy.getSizeInBits() <= 64 && "Unexpected vector length");
2281
2282 SDValue Op0 = Op.getOperand(0);
2283 SDValue Op1 = Op.getOperand(1);
2284 const SDLoc &dl(Op);
2285
2286 // If the inputs are not the same as the output, bail. This is not an
2287 // error situation, but complicates the handling and the default expansion
2288 // (into BUILD_VECTOR) should be adequate.
2289 if (ty(Op0) != VecTy || ty(Op1) != VecTy)
2290 return SDValue();
2291
2292 // Normalize the mask so that the first non-negative index comes from
2293 // the first operand.
2294 SmallVector<int, 8> Mask(AM);
2295 unsigned F = llvm::find_if(AM, [](int M) { return M >= 0; }) - AM.data();
2296 if (F == AM.size())
2297 return DAG.getUNDEF(VecTy);
2298 if (AM[F] >= int(VecLen)) {
2300 std::swap(Op0, Op1);
2301 }
2302
2303 // Express the shuffle mask in terms of bytes.
2304 SmallVector<int,8> ByteMask;
2305 unsigned ElemBytes = VecTy.getVectorElementType().getSizeInBits() / 8;
2306 for (int M : Mask) {
2307 if (M < 0) {
2308 for (unsigned j = 0; j != ElemBytes; ++j)
2309 ByteMask.push_back(-1);
2310 } else {
2311 for (unsigned j = 0; j != ElemBytes; ++j)
2312 ByteMask.push_back(M*ElemBytes + j);
2313 }
2314 }
2315 assert(ByteMask.size() <= 8);
2316
2317 // All non-undef (non-negative) indexes are well within [0..127], so they
2318 // fit in a single byte. Build two 64-bit words:
2319 // - MaskIdx where each byte is the corresponding index (for non-negative
2320 // indexes), and 0xFF for negative indexes, and
2321 // - MaskUnd that has 0xFF for each negative index.
2322 uint64_t MaskIdx = 0;
2323 uint64_t MaskUnd = 0;
2324 for (unsigned i = 0, e = ByteMask.size(); i != e; ++i) {
2325 unsigned S = 8*i;
2326 uint64_t M = ByteMask[i] & 0xFF;
2327 if (M == 0xFF)
2328 MaskUnd |= M << S;
2329 MaskIdx |= M << S;
2330 }
2331
2332 if (ByteMask.size() == 4) {
2333 // Identity.
2334 if (MaskIdx == (0x03020100 | MaskUnd))
2335 return Op0;
2336 // Byte swap.
2337 if (MaskIdx == (0x00010203 | MaskUnd)) {
2338 SDValue T0 = DAG.getBitcast(MVT::i32, Op0);
2339 SDValue T1 = DAG.getNode(ISD::BSWAP, dl, MVT::i32, T0);
2340 return DAG.getBitcast(VecTy, T1);
2341 }
2342
2343 // Byte packs.
2344 SDValue Concat10 =
2345 getCombine(Op1, Op0, dl, typeJoin({ty(Op1), ty(Op0)}), DAG);
2346 if (MaskIdx == (0x06040200 | MaskUnd))
2347 return getInstr(Hexagon::S2_vtrunehb, dl, VecTy, {Concat10}, DAG);
2348 if (MaskIdx == (0x07050301 | MaskUnd))
2349 return getInstr(Hexagon::S2_vtrunohb, dl, VecTy, {Concat10}, DAG);
2350
2351 SDValue Concat01 =
2352 getCombine(Op0, Op1, dl, typeJoin({ty(Op0), ty(Op1)}), DAG);
2353 if (MaskIdx == (0x02000604 | MaskUnd))
2354 return getInstr(Hexagon::S2_vtrunehb, dl, VecTy, {Concat01}, DAG);
2355 if (MaskIdx == (0x03010705 | MaskUnd))
2356 return getInstr(Hexagon::S2_vtrunohb, dl, VecTy, {Concat01}, DAG);
2357 }
2358
2359 if (ByteMask.size() == 8) {
2360 // Identity.
2361 if (MaskIdx == (0x0706050403020100ull | MaskUnd))
2362 return Op0;
2363 // Byte swap.
2364 if (MaskIdx == (0x0001020304050607ull | MaskUnd)) {
2365 SDValue T0 = DAG.getBitcast(MVT::i64, Op0);
2366 SDValue T1 = DAG.getNode(ISD::BSWAP, dl, MVT::i64, T0);
2367 return DAG.getBitcast(VecTy, T1);
2368 }
2369
2370 // Halfword picks.
2371 if (MaskIdx == (0x0d0c050409080100ull | MaskUnd))
2372 return getInstr(Hexagon::S2_shuffeh, dl, VecTy, {Op1, Op0}, DAG);
2373 if (MaskIdx == (0x0f0e07060b0a0302ull | MaskUnd))
2374 return getInstr(Hexagon::S2_shuffoh, dl, VecTy, {Op1, Op0}, DAG);
2375 if (MaskIdx == (0x0d0c090805040100ull | MaskUnd))
2376 return getInstr(Hexagon::S2_vtrunewh, dl, VecTy, {Op1, Op0}, DAG);
2377 if (MaskIdx == (0x0f0e0b0a07060302ull | MaskUnd))
2378 return getInstr(Hexagon::S2_vtrunowh, dl, VecTy, {Op1, Op0}, DAG);
2379 if (MaskIdx == (0x0706030205040100ull | MaskUnd)) {
2380 VectorPair P = opSplit(Op0, dl, DAG);
2381 return getInstr(Hexagon::S2_packhl, dl, VecTy, {P.second, P.first}, DAG);
2382 }
2383
2384 // Byte packs.
2385 if (MaskIdx == (0x0e060c040a020800ull | MaskUnd))
2386 return getInstr(Hexagon::S2_shuffeb, dl, VecTy, {Op1, Op0}, DAG);
2387 if (MaskIdx == (0x0f070d050b030901ull | MaskUnd))
2388 return getInstr(Hexagon::S2_shuffob, dl, VecTy, {Op1, Op0}, DAG);
2389 }
2390
2391 return SDValue();
2392}
2393
2394SDValue
2395HexagonTargetLowering::getSplatValue(SDValue Op, SelectionDAG &DAG) const {
2396 switch (Op.getOpcode()) {
2397 case ISD::BUILD_VECTOR:
2399 return S;
2400 break;
2401 case ISD::SPLAT_VECTOR:
2402 return Op.getOperand(0);
2403 }
2404 return SDValue();
2405}
2406
2407// Create a Hexagon-specific node for shifting a vector by an integer.
2408SDValue
2409HexagonTargetLowering::getVectorShiftByInt(SDValue Op, SelectionDAG &DAG)
2410 const {
2411 unsigned NewOpc;
2412 switch (Op.getOpcode()) {
2413 case ISD::SHL:
2414 NewOpc = HexagonISD::VASL;
2415 break;
2416 case ISD::SRA:
2417 NewOpc = HexagonISD::VASR;
2418 break;
2419 case ISD::SRL:
2420 NewOpc = HexagonISD::VLSR;
2421 break;
2422 default:
2423 llvm_unreachable("Unexpected shift opcode");
2424 }
2425 if (SDValue Sp = getSplatValue(Op.getOperand(1), DAG)) {
2426 const SDLoc dl(Op);
2427 // Canonicalize shift amount to i32 as required.
2428 SDValue Sh = Sp;
2429 if (Sh.getValueType() != MVT::i32)
2430 Sh = DAG.getZExtOrTrunc(Sh, dl, MVT::i32);
2431
2432 assert(Sh.getValueType() == MVT::i32 &&
2433 "Hexagon vector shift-by-int must use i32 shift operand");
2434 return DAG.getNode(NewOpc, dl, ty(Op), Op.getOperand(0), Sh);
2435 }
2436
2437 return SDValue();
2438}
2439
2440SDValue
2442 const SDLoc &dl(Op);
2443
2444 // First try to convert the shift (by vector) to a shift by a scalar.
2445 // If we first split the shift, the shift amount will become 'extract
2446 // subvector', and will no longer be recognized as scalar.
2447 SDValue Res = Op;
2448 if (SDValue S = getVectorShiftByInt(Op, DAG))
2449 Res = S;
2450
2451 unsigned Opc = Res.getOpcode();
2452 switch (Opc) {
2453 case HexagonISD::VASR:
2454 case HexagonISD::VLSR:
2455 case HexagonISD::VASL:
2456 break;
2457 default:
2458 // No instructions for shifts by non-scalars.
2459 return SDValue();
2460 }
2461
2462 MVT ResTy = ty(Res);
2463 if (ResTy.getVectorElementType() != MVT::i8)
2464 return Res;
2465
2466 // For shifts of i8, extend the inputs to i16, then truncate back to i8.
2467 assert(ResTy.getVectorElementType() == MVT::i8);
2468 SDValue Val = Res.getOperand(0), Amt = Res.getOperand(1);
2469
2470 auto ShiftPartI8 = [&dl, &DAG, this](unsigned Opc, SDValue V, SDValue A) {
2471 MVT Ty = ty(V);
2472 MVT ExtTy = MVT::getVectorVT(MVT::i16, Ty.getVectorNumElements());
2473 SDValue ExtV = Opc == HexagonISD::VASR ? DAG.getSExtOrTrunc(V, dl, ExtTy)
2474 : DAG.getZExtOrTrunc(V, dl, ExtTy);
2475 SDValue ExtS = DAG.getNode(Opc, dl, ExtTy, {ExtV, A});
2476 return DAG.getZExtOrTrunc(ExtS, dl, Ty);
2477 };
2478
2479 if (ResTy.getSizeInBits() == 32)
2480 return ShiftPartI8(Opc, Val, Amt);
2481
2482 auto [LoV, HiV] = opSplit(Val, dl, DAG);
2483 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResTy,
2484 {ShiftPartI8(Opc, LoV, Amt), ShiftPartI8(Opc, HiV, Amt)});
2485}
2486
2487SDValue
2489 if (isa<ConstantSDNode>(Op.getOperand(1).getNode()))
2490 return Op;
2491 return SDValue();
2492}
2493
2494SDValue
2496 MVT ResTy = ty(Op);
2497 SDValue InpV = Op.getOperand(0);
2498 MVT InpTy = ty(InpV);
2499 assert(ResTy.getSizeInBits() == InpTy.getSizeInBits());
2500 const SDLoc &dl(Op);
2501
2502 // Handle conversion from i8 to v8i1.
2503 if (InpTy == MVT::i8) {
2504 if (ResTy == MVT::v8i1) {
2505 SDValue Sc = DAG.getBitcast(tyScalar(InpTy), InpV);
2506 SDValue Ext = DAG.getZExtOrTrunc(Sc, dl, MVT::i32);
2507 return getInstr(Hexagon::C2_tfrrp, dl, ResTy, Ext, DAG);
2508 }
2509 return SDValue();
2510 }
2511
2512 return Op;
2513}
2514
2515bool
2516HexagonTargetLowering::getBuildVectorConstInts(ArrayRef<SDValue> Values,
2517 MVT VecTy, SelectionDAG &DAG,
2518 MutableArrayRef<ConstantInt*> Consts) const {
2519 MVT ElemTy = VecTy.getVectorElementType();
2520 unsigned ElemWidth = ElemTy.getSizeInBits();
2521 IntegerType *IntTy = IntegerType::get(*DAG.getContext(), ElemWidth);
2522 bool AllConst = true;
2523
2524 for (unsigned i = 0, e = Values.size(); i != e; ++i) {
2525 SDValue V = Values[i];
2526 if (V.isUndef()) {
2527 Consts[i] = ConstantInt::get(IntTy, 0);
2528 continue;
2529 }
2530 // Make sure to always cast to IntTy.
2531 if (auto *CN = dyn_cast<ConstantSDNode>(V.getNode())) {
2532 const ConstantInt *CI = CN->getConstantIntValue();
2533 Consts[i] = cast<ConstantInt>(
2534 ConstantInt::get(IntTy, CI->getValue().trunc(ElemWidth)));
2535 } else if (auto *CN = dyn_cast<ConstantFPSDNode>(V.getNode())) {
2536 const ConstantFP *CF = CN->getConstantFPValue();
2537 APInt A = CF->getValueAPF().bitcastToAPInt();
2538 Consts[i] = ConstantInt::get(IntTy, A.getZExtValue());
2539 } else {
2540 AllConst = false;
2541 }
2542 }
2543 return AllConst;
2544}
2545
2546SDValue
2547HexagonTargetLowering::buildVector32(ArrayRef<SDValue> Elem, const SDLoc &dl,
2548 MVT VecTy, SelectionDAG &DAG) const {
2549 MVT ElemTy = VecTy.getVectorElementType();
2550 assert(VecTy.getVectorNumElements() == Elem.size());
2551
2552 SmallVector<ConstantInt*,4> Consts(Elem.size());
2553 bool AllConst = getBuildVectorConstInts(Elem, VecTy, DAG, Consts);
2554
2555 unsigned First, Num = Elem.size();
2556 for (First = 0; First != Num; ++First) {
2557 if (!isUndef(Elem[First]))
2558 break;
2559 }
2560 if (First == Num)
2561 return DAG.getUNDEF(VecTy);
2562
2563 if (AllConst &&
2564 llvm::all_of(Consts, [](ConstantInt *CI) { return CI->isZero(); }))
2565 return getZero(dl, VecTy, DAG);
2566
2567 if (ElemTy == MVT::i16 || ElemTy == MVT::f16) {
2568 assert(Elem.size() == 2);
2569 if (AllConst) {
2570 // The 'Consts' array will have all values as integers regardless
2571 // of the vector element type.
2572 uint32_t V = (Consts[0]->getZExtValue() & 0xFFFF) |
2573 Consts[1]->getZExtValue() << 16;
2574 return DAG.getBitcast(VecTy, DAG.getConstant(V, dl, MVT::i32));
2575 }
2576 SDValue E0, E1;
2577 if (ElemTy == MVT::f16) {
2578 E0 = DAG.getZExtOrTrunc(DAG.getBitcast(MVT::i16, Elem[0]), dl, MVT::i32);
2579 E1 = DAG.getZExtOrTrunc(DAG.getBitcast(MVT::i16, Elem[1]), dl, MVT::i32);
2580 } else {
2581 E0 = Elem[0];
2582 E1 = Elem[1];
2583 }
2584 SDValue N = getInstr(Hexagon::A2_combine_ll, dl, MVT::i32, {E1, E0}, DAG);
2585 return DAG.getBitcast(VecTy, N);
2586 }
2587
2588 if (ElemTy == MVT::i8) {
2589 // First try generating a constant.
2590 if (AllConst) {
2591 uint32_t V = (Consts[0]->getZExtValue() & 0xFF) |
2592 (Consts[1]->getZExtValue() & 0xFF) << 8 |
2593 (Consts[2]->getZExtValue() & 0xFF) << 16 |
2594 Consts[3]->getZExtValue() << 24;
2595 return DAG.getBitcast(MVT::v4i8, DAG.getConstant(V, dl, MVT::i32));
2596 }
2597
2598 // Then try splat.
2599 bool IsSplat = true;
2600 for (unsigned i = First+1; i != Num; ++i) {
2601 if (Elem[i] == Elem[First] || isUndef(Elem[i]))
2602 continue;
2603 IsSplat = false;
2604 break;
2605 }
2606 if (IsSplat) {
2607 // Legalize the operand of SPLAT_VECTOR.
2608 SDValue Ext = DAG.getZExtOrTrunc(Elem[First], dl, MVT::i32);
2609 return DAG.getNode(ISD::SPLAT_VECTOR, dl, VecTy, Ext);
2610 }
2611
2612 // Generate
2613 // (zxtb(Elem[0]) | (zxtb(Elem[1]) << 8)) |
2614 // (zxtb(Elem[2]) | (zxtb(Elem[3]) << 8)) << 16
2615 assert(Elem.size() == 4);
2616 SDValue Vs[4];
2617 for (unsigned i = 0; i != 4; ++i) {
2618 Vs[i] = DAG.getZExtOrTrunc(Elem[i], dl, MVT::i32);
2619 Vs[i] = DAG.getZeroExtendInReg(Vs[i], dl, MVT::i8);
2620 }
2621 SDValue S8 = DAG.getConstant(8, dl, MVT::i32);
2622 SDValue T0 = DAG.getNode(ISD::SHL, dl, MVT::i32, {Vs[1], S8});
2623 SDValue T1 = DAG.getNode(ISD::SHL, dl, MVT::i32, {Vs[3], S8});
2624 SDValue B0 = DAG.getNode(ISD::OR, dl, MVT::i32, {Vs[0], T0});
2625 SDValue B1 = DAG.getNode(ISD::OR, dl, MVT::i32, {Vs[2], T1});
2626
2627 SDValue R = getInstr(Hexagon::A2_combine_ll, dl, MVT::i32, {B1, B0}, DAG);
2628 return DAG.getBitcast(MVT::v4i8, R);
2629 }
2630
2631#ifndef NDEBUG
2632 dbgs() << "VecTy: " << VecTy << '\n';
2633#endif
2634 llvm_unreachable("Unexpected vector element type");
2635}
2636
2637SDValue
2638HexagonTargetLowering::buildVector64(ArrayRef<SDValue> Elem, const SDLoc &dl,
2639 MVT VecTy, SelectionDAG &DAG) const {
2640 MVT ElemTy = VecTy.getVectorElementType();
2641 assert(VecTy.getVectorNumElements() == Elem.size());
2642
2643 SmallVector<ConstantInt*,8> Consts(Elem.size());
2644 bool AllConst = getBuildVectorConstInts(Elem, VecTy, DAG, Consts);
2645
2646 unsigned First, Num = Elem.size();
2647 for (First = 0; First != Num; ++First) {
2648 if (!isUndef(Elem[First]))
2649 break;
2650 }
2651 if (First == Num)
2652 return DAG.getUNDEF(VecTy);
2653
2654 if (AllConst &&
2655 llvm::all_of(Consts, [](ConstantInt *CI) { return CI->isZero(); }))
2656 return getZero(dl, VecTy, DAG);
2657
2658 // First try splat if possible.
2659 if (ElemTy == MVT::i16 || ElemTy == MVT::f16) {
2660 bool IsSplat = true;
2661 for (unsigned i = First+1; i != Num; ++i) {
2662 if (Elem[i] == Elem[First] || isUndef(Elem[i]))
2663 continue;
2664 IsSplat = false;
2665 break;
2666 }
2667 if (IsSplat) {
2668 // Legalize the operand of SPLAT_VECTOR
2669 SDValue S = ElemTy == MVT::f16 ? DAG.getBitcast(MVT::i16, Elem[First])
2670 : Elem[First];
2671 SDValue Ext = DAG.getZExtOrTrunc(S, dl, MVT::i32);
2672 return DAG.getNode(ISD::SPLAT_VECTOR, dl, VecTy, Ext);
2673 }
2674 }
2675
2676 // Then try constant.
2677 if (AllConst) {
2678 uint64_t Val = 0;
2679 unsigned W = ElemTy.getSizeInBits();
2680 uint64_t Mask = (1ull << W) - 1;
2681 for (unsigned i = 0; i != Num; ++i)
2682 Val = (Val << W) | (Consts[Num-1-i]->getZExtValue() & Mask);
2683 SDValue V0 = DAG.getConstant(Val, dl, MVT::i64);
2684 return DAG.getBitcast(VecTy, V0);
2685 }
2686
2687 // Build two 32-bit vectors and concatenate.
2688 MVT HalfTy = MVT::getVectorVT(ElemTy, Num/2);
2689 SDValue L = (ElemTy == MVT::i32)
2690 ? Elem[0]
2691 : buildVector32(Elem.take_front(Num/2), dl, HalfTy, DAG);
2692 SDValue H = (ElemTy == MVT::i32)
2693 ? Elem[1]
2694 : buildVector32(Elem.drop_front(Num/2), dl, HalfTy, DAG);
2695 return getCombine(H, L, dl, VecTy, DAG);
2696}
2697
2698SDValue
2699HexagonTargetLowering::extractVector(SDValue VecV, SDValue IdxV,
2700 const SDLoc &dl, MVT ValTy, MVT ResTy,
2701 SelectionDAG &DAG) const {
2702 MVT VecTy = ty(VecV);
2703 assert(!ValTy.isVector() ||
2704 VecTy.getVectorElementType() == ValTy.getVectorElementType());
2705 if (VecTy.getVectorElementType() == MVT::i1)
2706 return extractVectorPred(VecV, IdxV, dl, ValTy, ResTy, DAG);
2707
2708 unsigned VecWidth = VecTy.getSizeInBits();
2709 unsigned ValWidth = ValTy.getSizeInBits();
2710 unsigned ElemWidth = VecTy.getVectorElementType().getSizeInBits();
2711 assert((VecWidth % ElemWidth) == 0);
2712 assert(VecWidth == 32 || VecWidth == 64);
2713
2714 // Cast everything to scalar integer types.
2715 MVT ScalarTy = tyScalar(VecTy);
2716 VecV = DAG.getBitcast(ScalarTy, VecV);
2717
2718 SDValue WidthV = DAG.getConstant(ValWidth, dl, MVT::i32);
2719 SDValue ExtV;
2720
2721 if (auto *IdxN = dyn_cast<ConstantSDNode>(IdxV)) {
2722 unsigned Off = IdxN->getZExtValue() * ElemWidth;
2723 if (VecWidth == 64 && ValWidth == 32) {
2724 assert(Off == 0 || Off == 32);
2725 ExtV = Off == 0 ? LoHalf(VecV, DAG) : HiHalf(VecV, DAG);
2726 } else if (Off == 0 && (ValWidth % 8) == 0) {
2727 ExtV = DAG.getZeroExtendInReg(VecV, dl, tyScalar(ValTy));
2728 } else {
2729 SDValue OffV = DAG.getConstant(Off, dl, MVT::i32);
2730 // The return type of EXTRACTU must be the same as the type of the
2731 // input vector.
2732 ExtV = DAG.getNode(HexagonISD::EXTRACTU, dl, ScalarTy,
2733 {VecV, WidthV, OffV});
2734 }
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,
2739 DAG.getConstant(ElemWidth, dl, MVT::i32));
2740 ExtV = DAG.getNode(HexagonISD::EXTRACTU, dl, ScalarTy,
2741 {VecV, WidthV, OffV});
2742 }
2743
2744 // Cast ExtV to the requested result type.
2745 ExtV = DAG.getZExtOrTrunc(ExtV, dl, tyScalar(ResTy));
2746 ExtV = DAG.getBitcast(ResTy, ExtV);
2747 return ExtV;
2748}
2749
2750SDValue
2751HexagonTargetLowering::extractVectorPred(SDValue VecV, SDValue IdxV,
2752 const SDLoc &dl, MVT ValTy, MVT ResTy,
2753 SelectionDAG &DAG) const {
2754 // Special case for v{8,4,2}i1 (the only boolean vectors legal in Hexagon
2755 // without any coprocessors).
2756 MVT VecTy = ty(VecV);
2757 unsigned VecWidth = VecTy.getSizeInBits();
2758 unsigned ValWidth = ValTy.getSizeInBits();
2759 assert(VecWidth == VecTy.getVectorNumElements() &&
2760 "Vector elements should equal vector width size");
2761 assert(VecWidth == 8 || VecWidth == 4 || VecWidth == 2);
2762
2763 // Check if this is an extract of the lowest bit.
2764 if (isNullConstant(IdxV) && ValTy.getSizeInBits() == 1) {
2765 // Extracting the lowest bit is a no-op, but it changes the type,
2766 // so it must be kept as an operation to avoid errors related to
2767 // type mismatches.
2768 return DAG.getNode(HexagonISD::TYPECAST, dl, MVT::i1, VecV);
2769 }
2770
2771 // If the value extracted is a single bit, use tstbit.
2772 if (ValWidth == 1) {
2773 SDValue A0 = getInstr(Hexagon::C2_tfrpr, dl, MVT::i32, {VecV}, DAG);
2774 SDValue M0 = DAG.getConstant(8 / VecWidth, dl, MVT::i32);
2775 SDValue I0 = DAG.getNode(ISD::MUL, dl, MVT::i32, IdxV, M0);
2776 return DAG.getNode(HexagonISD::TSTBIT, dl, MVT::i1, A0, I0);
2777 }
2778
2779 // Each bool vector (v2i1, v4i1, v8i1) always occupies 8 bits in
2780 // a predicate register. The elements of the vector are repeated
2781 // in the register (if necessary) so that the total number is 8.
2782 // The extracted subvector will need to be expanded in such a way.
2783 unsigned Scale = VecWidth / ValWidth;
2784
2785 // Generate (p2d VecV) >> 8*Idx to move the interesting bytes to
2786 // position 0.
2787 assert(ty(IdxV) == MVT::i32);
2788 unsigned VecRep = 8 / VecWidth;
2789 SDValue S0 = DAG.getNode(ISD::MUL, dl, MVT::i32, IdxV,
2790 DAG.getConstant(8*VecRep, dl, MVT::i32));
2791 SDValue T0 = DAG.getNode(HexagonISD::P2D, dl, MVT::i64, VecV);
2792 SDValue T1 = DAG.getNode(ISD::SRL, dl, MVT::i64, T0, S0);
2793 while (Scale > 1) {
2794 // The longest possible subvector is at most 32 bits, so it is always
2795 // contained in the low subregister.
2796 T1 = LoHalf(T1, DAG);
2797 T1 = expandPredicate(T1, dl, DAG);
2798 Scale /= 2;
2799 }
2800
2801 return DAG.getNode(HexagonISD::D2P, dl, ResTy, T1);
2802}
2803
2804SDValue
2805HexagonTargetLowering::insertVector(SDValue VecV, SDValue ValV, SDValue IdxV,
2806 const SDLoc &dl, MVT ValTy,
2807 SelectionDAG &DAG) const {
2808 MVT VecTy = ty(VecV);
2809 if (VecTy.getVectorElementType() == MVT::i1)
2810 return insertVectorPred(VecV, ValV, IdxV, dl, ValTy, DAG);
2811
2812 unsigned VecWidth = VecTy.getSizeInBits();
2813 unsigned ValWidth = ValTy.getSizeInBits();
2814 assert(VecWidth == 32 || VecWidth == 64);
2815 assert((VecWidth % ValWidth) == 0);
2816
2817 // Cast everything to scalar integer types.
2818 MVT ScalarTy = MVT::getIntegerVT(VecWidth);
2819 // The actual type of ValV may be different than ValTy (which is related
2820 // to the vector type).
2821 unsigned VW = ty(ValV).getSizeInBits();
2822 ValV = DAG.getBitcast(MVT::getIntegerVT(VW), ValV);
2823 VecV = DAG.getBitcast(ScalarTy, VecV);
2824 if (VW != VecWidth)
2825 ValV = DAG.getAnyExtOrTrunc(ValV, dl, ScalarTy);
2826
2827 SDValue WidthV = DAG.getConstant(ValWidth, dl, MVT::i32);
2828 SDValue InsV;
2829
2830 if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(IdxV)) {
2831 unsigned W = C->getZExtValue() * ValWidth;
2832 SDValue OffV = DAG.getConstant(W, dl, MVT::i32);
2833 InsV = DAG.getNode(HexagonISD::INSERT, dl, ScalarTy,
2834 {VecV, ValV, WidthV, OffV});
2835 } else {
2836 if (ty(IdxV) != MVT::i32)
2837 IdxV = DAG.getZExtOrTrunc(IdxV, dl, MVT::i32);
2838 SDValue OffV = DAG.getNode(ISD::MUL, dl, MVT::i32, IdxV, WidthV);
2839 InsV = DAG.getNode(HexagonISD::INSERT, dl, ScalarTy,
2840 {VecV, ValV, WidthV, OffV});
2841 }
2842
2843 return DAG.getNode(ISD::BITCAST, dl, VecTy, InsV);
2844}
2845
2846SDValue
2847HexagonTargetLowering::insertVectorPred(SDValue VecV, SDValue ValV,
2848 SDValue IdxV, const SDLoc &dl,
2849 MVT ValTy, SelectionDAG &DAG) const {
2850 MVT VecTy = ty(VecV);
2851 unsigned VecLen = VecTy.getVectorNumElements();
2852
2853 if (ValTy == MVT::i1) {
2854 SDValue ToReg = getInstr(Hexagon::C2_tfrpr, dl, MVT::i32, {VecV}, DAG);
2855 SDValue Ext = DAG.getSExtOrTrunc(ValV, dl, MVT::i32);
2856 SDValue Width = DAG.getConstant(8 / VecLen, dl, MVT::i32);
2857 SDValue Idx = DAG.getNode(ISD::MUL, dl, MVT::i32, IdxV, Width);
2858 SDValue Ins =
2859 DAG.getNode(HexagonISD::INSERT, dl, MVT::i32, {ToReg, Ext, Width, Idx});
2860 return getInstr(Hexagon::C2_tfrrp, dl, VecTy, {Ins}, DAG);
2861 }
2862
2863 assert(ValTy.getVectorElementType() == MVT::i1);
2864 SDValue ValR = ValTy.isVector()
2865 ? DAG.getNode(HexagonISD::P2D, dl, MVT::i64, ValV)
2866 : DAG.getSExtOrTrunc(ValV, dl, MVT::i64);
2867
2868 unsigned Scale = VecLen / ValTy.getVectorNumElements();
2869 assert(Scale > 1);
2870
2871 for (unsigned R = Scale; R > 1; R /= 2) {
2872 ValR = contractPredicate(ValR, dl, DAG);
2873 ValR = getCombine(DAG.getUNDEF(MVT::i32), ValR, dl, MVT::i64, DAG);
2874 }
2875
2876 SDValue Width = DAG.getConstant(64 / Scale, dl, MVT::i32);
2877 SDValue Idx = DAG.getNode(ISD::MUL, dl, MVT::i32, IdxV, Width);
2878 SDValue VecR = DAG.getNode(HexagonISD::P2D, dl, MVT::i64, VecV);
2879 SDValue Ins =
2880 DAG.getNode(HexagonISD::INSERT, dl, MVT::i64, {VecR, ValR, Width, Idx});
2881 return DAG.getNode(HexagonISD::D2P, dl, VecTy, Ins);
2882}
2883
2884SDValue
2885HexagonTargetLowering::expandPredicate(SDValue Vec32, const SDLoc &dl,
2886 SelectionDAG &DAG) const {
2887 assert(ty(Vec32).getSizeInBits() == 32);
2888 if (isUndef(Vec32))
2889 return DAG.getUNDEF(MVT::i64);
2890 SDValue P = DAG.getBitcast(MVT::v4i8, Vec32);
2891 SDValue X = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::v4i16, P);
2892 return DAG.getBitcast(MVT::i64, X);
2893}
2894
2895SDValue
2896HexagonTargetLowering::contractPredicate(SDValue Vec64, const SDLoc &dl,
2897 SelectionDAG &DAG) const {
2898 assert(ty(Vec64).getSizeInBits() == 64);
2899 if (isUndef(Vec64))
2900 return DAG.getUNDEF(MVT::i32);
2901 // Collect even bytes:
2902 SDValue A = DAG.getBitcast(MVT::v8i8, Vec64);
2903 SDValue S = DAG.getVectorShuffle(MVT::v8i8, dl, A, DAG.getUNDEF(MVT::v8i8),
2904 {0, 2, 4, 6, 1, 3, 5, 7});
2905 return extractVector(S, DAG.getConstant(0, dl, MVT::i32), dl, MVT::v4i8,
2906 MVT::i32, DAG);
2907}
2908
2909SDValue
2910HexagonTargetLowering::getZero(const SDLoc &dl, MVT Ty, SelectionDAG &DAG)
2911 const {
2912 if (Ty.isVector()) {
2913 unsigned W = Ty.getSizeInBits();
2914 if (W <= 64)
2915 return DAG.getBitcast(Ty, DAG.getConstant(0, dl, MVT::getIntegerVT(W)));
2916 return DAG.getNode(ISD::SPLAT_VECTOR, dl, Ty, getZero(dl, MVT::i32, DAG));
2917 }
2918
2919 if (Ty.isInteger())
2920 return DAG.getConstant(0, dl, Ty);
2921 if (Ty.isFloatingPoint())
2922 return DAG.getConstantFP(0.0, dl, Ty);
2923 llvm_unreachable("Invalid type for zero");
2924}
2925
2926SDValue
2927HexagonTargetLowering::appendUndef(SDValue Val, MVT ResTy, SelectionDAG &DAG)
2928 const {
2929 MVT ValTy = ty(Val);
2931
2932 unsigned ValLen = ValTy.getVectorNumElements();
2933 unsigned ResLen = ResTy.getVectorNumElements();
2934 if (ValLen == ResLen)
2935 return Val;
2936
2937 const SDLoc &dl(Val);
2938 assert(ValLen < ResLen);
2939 assert(ResLen % ValLen == 0);
2940
2941 SmallVector<SDValue, 4> Concats = {Val};
2942 for (unsigned i = 1, e = ResLen / ValLen; i < e; ++i)
2943 Concats.push_back(DAG.getUNDEF(ValTy));
2944
2945 return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResTy, Concats);
2946}
2947
2948SDValue
2949HexagonTargetLowering::getCombine(SDValue Hi, SDValue Lo, const SDLoc &dl,
2950 MVT ResTy, SelectionDAG &DAG) const {
2951 MVT ElemTy = ty(Hi);
2952 assert(ElemTy == ty(Lo));
2953
2954 if (!ElemTy.isVector()) {
2955 assert(ElemTy.isScalarInteger());
2956 MVT PairTy = ElemTy.widenIntegerElementType();
2957 SDValue Pair = DAG.getNode(ISD::BUILD_PAIR, dl, PairTy, Lo, Hi);
2958 return DAG.getBitcast(ResTy, Pair);
2959 }
2960
2961 unsigned Width = ElemTy.getSizeInBits();
2962 MVT IntTy = MVT::getIntegerVT(Width);
2963 SDValue Pair =
2965 {DAG.getBitcast(IntTy, Lo), DAG.getBitcast(IntTy, Hi)});
2966 return DAG.getBitcast(ResTy, Pair);
2967}
2968
2969SDValue
2971 MVT VecTy = ty(Op);
2972 unsigned BW = VecTy.getSizeInBits();
2973 const SDLoc &dl(Op);
2975 for (unsigned i = 0, e = Op.getNumOperands(); i != e; ++i)
2976 Ops.push_back(Op.getOperand(i));
2977
2978 if (BW == 32)
2979 return buildVector32(Ops, dl, VecTy, DAG);
2980 if (BW == 64)
2981 return buildVector64(Ops, dl, VecTy, DAG);
2982
2983 if (VecTy == MVT::v8i1 || VecTy == MVT::v4i1 || VecTy == MVT::v2i1) {
2984 // Check if this is a special case or all-0 or all-1.
2985 bool All0 = true, All1 = true;
2986 for (SDValue P : Ops) {
2987 auto *CN = dyn_cast<ConstantSDNode>(P.getNode());
2988 if (CN == nullptr) {
2989 All0 = All1 = false;
2990 break;
2991 }
2992 uint32_t C = CN->getZExtValue();
2993 All0 &= (C == 0);
2994 All1 &= (C == 1);
2995 }
2996 if (All0)
2997 return DAG.getNode(HexagonISD::PFALSE, dl, VecTy);
2998 if (All1)
2999 return DAG.getNode(HexagonISD::PTRUE, dl, VecTy);
3000
3001 // For each i1 element in the resulting predicate register, put 1
3002 // shifted by the index of the element into a general-purpose register,
3003 // then or them together and transfer it back into a predicate register.
3004 SDValue Rs[8];
3005 SDValue Z = getZero(dl, MVT::i32, DAG);
3006 // Always produce 8 bits, repeat inputs if necessary.
3007 unsigned Rep = 8 / VecTy.getVectorNumElements();
3008 for (unsigned i = 0; i != 8; ++i) {
3009 SDValue S = DAG.getConstant(1ull << i, dl, MVT::i32);
3010 Rs[i] = DAG.getSelect(dl, MVT::i32, Ops[i/Rep], S, Z);
3011 }
3012 for (ArrayRef<SDValue> A(Rs); A.size() != 1; A = A.drop_back(A.size()/2)) {
3013 for (unsigned i = 0, e = A.size()/2; i != e; ++i)
3014 Rs[i] = DAG.getNode(ISD::OR, dl, MVT::i32, Rs[2*i], Rs[2*i+1]);
3015 }
3016 // Move the value directly to a predicate register.
3017 return getInstr(Hexagon::C2_tfrrp, dl, VecTy, {Rs[0]}, DAG);
3018 }
3019
3020 return SDValue();
3021}
3022
3023SDValue
3025 SelectionDAG &DAG) const {
3026 MVT VecTy = ty(Op);
3027 const SDLoc &dl(Op);
3028 if (VecTy.getSizeInBits() == 64) {
3029 assert(Op.getNumOperands() == 2);
3030 return getCombine(Op.getOperand(1), Op.getOperand(0), dl, VecTy, DAG);
3031 }
3032
3033 MVT ElemTy = VecTy.getVectorElementType();
3034 if (ElemTy == MVT::i1) {
3035 assert(VecTy == MVT::v2i1 || VecTy == MVT::v4i1 || VecTy == MVT::v8i1);
3036 MVT OpTy = ty(Op.getOperand(0));
3037 // Scale is how many times the operands need to be contracted to match
3038 // the representation in the target register.
3039 unsigned Scale = VecTy.getVectorNumElements() / OpTy.getVectorNumElements();
3040 assert(Scale == Op.getNumOperands() && Scale > 1);
3041
3042 // First, convert all bool vectors to integers, then generate pairwise
3043 // inserts to form values of doubled length. Up until there are only
3044 // two values left to concatenate, all of these values will fit in a
3045 // 32-bit integer, so keep them as i32 to use 32-bit inserts.
3046 SmallVector<SDValue,4> Words[2];
3047 unsigned IdxW = 0;
3048
3049 for (SDValue P : Op.getNode()->op_values()) {
3050 SDValue W = DAG.getNode(HexagonISD::P2D, dl, MVT::i64, P);
3051 for (unsigned R = Scale; R > 1; R /= 2) {
3052 W = contractPredicate(W, dl, DAG);
3053 W = getCombine(DAG.getUNDEF(MVT::i32), W, dl, MVT::i64, DAG);
3054 }
3055 W = LoHalf(W, DAG);
3056 Words[IdxW].push_back(W);
3057 }
3058
3059 while (Scale > 2) {
3060 SDValue WidthV = DAG.getConstant(64 / Scale, dl, MVT::i32);
3061 Words[IdxW ^ 1].clear();
3062
3063 for (unsigned i = 0, e = Words[IdxW].size(); i != e; i += 2) {
3064 SDValue W0 = Words[IdxW][i], W1 = Words[IdxW][i+1];
3065 // Insert W1 into W0 right next to the significant bits of W0.
3066 SDValue T = DAG.getNode(HexagonISD::INSERT, dl, MVT::i32,
3067 {W0, W1, WidthV, WidthV});
3068 Words[IdxW ^ 1].push_back(T);
3069 }
3070 IdxW ^= 1;
3071 Scale /= 2;
3072 }
3073
3074 // At this point there should only be two words left, and Scale should be 2.
3075 assert(Scale == 2 && Words[IdxW].size() == 2);
3076
3077 SDValue WW = getCombine(Words[IdxW][1], Words[IdxW][0], dl, MVT::i64, DAG);
3078 return DAG.getNode(HexagonISD::D2P, dl, VecTy, WW);
3079 }
3080
3081 return SDValue();
3082}
3083
3084SDValue
3086 SelectionDAG &DAG) const {
3087 SDValue Vec = Op.getOperand(0);
3088 MVT ElemTy = ty(Vec).getVectorElementType();
3089 return extractVector(Vec, Op.getOperand(1), SDLoc(Op), ElemTy, ty(Op), DAG);
3090}
3091
3092SDValue
3094 SelectionDAG &DAG) const {
3095 return extractVector(Op.getOperand(0), Op.getOperand(1), SDLoc(Op),
3096 ty(Op), ty(Op), DAG);
3097}
3098
3099SDValue
3101 SelectionDAG &DAG) const {
3102 return insertVector(Op.getOperand(0), Op.getOperand(1), Op.getOperand(2),
3103 SDLoc(Op), ty(Op).getVectorElementType(), DAG);
3104}
3105
3106SDValue
3108 SelectionDAG &DAG) const {
3109 SDValue ValV = Op.getOperand(1);
3110 return insertVector(Op.getOperand(0), ValV, Op.getOperand(2),
3111 SDLoc(Op), ty(ValV), DAG);
3112}
3113
3114bool
3116 // Assuming the caller does not have either a signext or zeroext modifier, and
3117 // only one value is accepted, any reasonable truncation is allowed.
3118 if (!Ty1->isIntegerTy() || !Ty2->isIntegerTy())
3119 return false;
3120
3121 // FIXME: in principle up to 64-bit could be made safe, but it would be very
3122 // fragile at the moment: any support for multiple value returns would be
3123 // liable to disallow tail calls involving i64 -> iN truncation in many cases.
3124 return Ty1->getPrimitiveSizeInBits() <= 32;
3125}
3126
3127SDValue
3129 MVT Ty = ty(Op);
3130 const SDLoc &dl(Op);
3131 LoadSDNode *LN = cast<LoadSDNode>(Op.getNode());
3132 MVT MemTy = LN->getMemoryVT().getSimpleVT();
3134
3135 bool LoadPred = MemTy == MVT::v2i1 || MemTy == MVT::v4i1 || MemTy == MVT::v8i1;
3136 if (LoadPred) {
3137 SDValue NL = DAG.getLoad(
3138 LN->getAddressingMode(), ISD::ZEXTLOAD, MVT::i32, dl, LN->getChain(),
3139 LN->getBasePtr(), LN->getOffset(), LN->getPointerInfo(),
3140 /*MemoryVT*/ MVT::i8, LN->getAlign(), LN->getMemOperand()->getFlags(),
3141 MMOMetadata(LN->getAAInfo(), LN->getRanges()));
3142 LN = cast<LoadSDNode>(NL.getNode());
3143 }
3144
3145 Align ClaimAlign = LN->getAlign();
3146 if (!validateConstPtrAlignment(LN->getBasePtr(), ClaimAlign, dl, DAG))
3147 return replaceMemWithUndef(Op, DAG);
3148
3149 // Call LowerUnalignedLoad for all loads, it recognizes loads that
3150 // don't need extra aligning.
3151 SDValue LU = LowerUnalignedLoad(SDValue(LN, 0), DAG);
3152 if (LoadPred) {
3153 SDValue TP = getInstr(Hexagon::C2_tfrrp, dl, MemTy, {LU}, DAG);
3154 if (ET == ISD::SEXTLOAD) {
3155 TP = DAG.getSExtOrTrunc(TP, dl, Ty);
3156 } else if (ET != ISD::NON_EXTLOAD) {
3157 TP = DAG.getZExtOrTrunc(TP, dl, Ty);
3158 }
3159 SDValue Ch = cast<LoadSDNode>(LU.getNode())->getChain();
3160 return DAG.getMergeValues({TP, Ch}, dl);
3161 }
3162 return LU;
3163}
3164
3165SDValue
3167 const SDLoc &dl(Op);
3168 StoreSDNode *SN = cast<StoreSDNode>(Op.getNode());
3169 SDValue Val = SN->getValue();
3170 MVT Ty = ty(Val);
3171
3172 if (Ty == MVT::v2i1 || Ty == MVT::v4i1 || Ty == MVT::v8i1) {
3173 // Store the exact predicate (all bits).
3174 SDValue TR = getInstr(Hexagon::C2_tfrpr, dl, MVT::i32, {Val}, DAG);
3175 SDValue NS = DAG.getTruncStore(SN->getChain(), dl, TR, SN->getBasePtr(),
3176 MVT::i8, SN->getMemOperand());
3177 if (SN->isIndexed()) {
3178 NS = DAG.getIndexedStore(NS, dl, SN->getBasePtr(), SN->getOffset(),
3179 SN->getAddressingMode());
3180 }
3181 SN = cast<StoreSDNode>(NS.getNode());
3182 }
3183
3184 Align ClaimAlign = SN->getAlign();
3185 if (!validateConstPtrAlignment(SN->getBasePtr(), ClaimAlign, dl, DAG))
3186 return replaceMemWithUndef(Op, DAG);
3187
3188 MVT StoreTy = SN->getMemoryVT().getSimpleVT();
3189 Align NeedAlign = Subtarget.getTypeAlignment(StoreTy);
3190 if (ClaimAlign < NeedAlign)
3191 return expandUnalignedStore(SN, DAG);
3192 return SDValue(SN, 0);
3193}
3194
3195SDValue
3197 const {
3198 LoadSDNode *LN = cast<LoadSDNode>(Op.getNode());
3199 MVT LoadTy = ty(Op);
3200 unsigned NeedAlign = Subtarget.getTypeAlignment(LoadTy).value();
3201 unsigned HaveAlign = LN->getAlign().value();
3202 if (HaveAlign >= NeedAlign)
3203 return Op;
3204
3205 const SDLoc &dl(Op);
3206 const DataLayout &DL = DAG.getDataLayout();
3207 LLVMContext &Ctx = *DAG.getContext();
3208
3209 // If the load aligning is disabled or the load can be broken up into two
3210 // smaller legal loads, do the default (target-independent) expansion.
3211 bool DoDefault = false;
3212 // Handle it in the default way if this is an indexed load.
3213 if (!LN->isUnindexed())
3214 DoDefault = true;
3215
3216 if (!AlignLoads) {
3218 *LN->getMemOperand()))
3219 return Op;
3220 DoDefault = true;
3221 }
3222 if (!DoDefault && (2 * HaveAlign) == NeedAlign) {
3223 // The PartTy is the equivalent of "getLoadableTypeOfSize(HaveAlign)".
3224 MVT PartTy = HaveAlign <= 8 ? MVT::getIntegerVT(8 * HaveAlign)
3225 : MVT::getVectorVT(MVT::i8, HaveAlign);
3226 DoDefault =
3227 allowsMemoryAccessForAlignment(Ctx, DL, PartTy, *LN->getMemOperand());
3228 }
3229 if (DoDefault) {
3230 std::pair<SDValue, SDValue> P = expandUnalignedLoad(LN, DAG);
3231 return DAG.getMergeValues({P.first, P.second}, dl);
3232 }
3233
3234 // The code below generates two loads, both aligned as NeedAlign, and
3235 // with the distance of NeedAlign between them. For that to cover the
3236 // bits that need to be loaded (and without overlapping), the size of
3237 // the loads should be equal to NeedAlign. This is true for all loadable
3238 // types, but add an assertion in case something changes in the future.
3239 assert(LoadTy.getSizeInBits() == 8*NeedAlign);
3240
3241 unsigned LoadLen = NeedAlign;
3242 SDValue Base = LN->getBasePtr();
3243 SDValue Chain = LN->getChain();
3244 auto BO = getBaseAndOffset(Base);
3245 unsigned BaseOpc = BO.first.getOpcode();
3246 if (BaseOpc == HexagonISD::VALIGNADDR && BO.second % LoadLen == 0)
3247 return Op;
3248
3249 if (BO.second % LoadLen != 0) {
3250 BO.first = DAG.getNode(ISD::ADD, dl, MVT::i32, BO.first,
3251 DAG.getConstant(BO.second % LoadLen, dl, MVT::i32));
3252 BO.second -= BO.second % LoadLen;
3253 }
3254 SDValue BaseNoOff = (BaseOpc != HexagonISD::VALIGNADDR)
3255 ? DAG.getNode(HexagonISD::VALIGNADDR, dl, MVT::i32, BO.first,
3256 DAG.getConstant(NeedAlign, dl, MVT::i32))
3257 : BO.first;
3258 SDValue Base0 =
3259 DAG.getMemBasePlusOffset(BaseNoOff, TypeSize::getFixed(BO.second), dl);
3260 SDValue Base1 = DAG.getMemBasePlusOffset(
3261 BaseNoOff, TypeSize::getFixed(BO.second + LoadLen), dl);
3262
3263 MachineMemOperand *WideMMO = nullptr;
3264 if (MachineMemOperand *MMO = LN->getMemOperand()) {
3266 WideMMO = MF.getMachineMemOperand(
3267 MMO->getPointerInfo(), MMO->getFlags(), 2 * LoadLen, Align(LoadLen),
3268 MMOMetadata(MMO->getAAInfo(), MMO->getRanges()), MMO->getSyncScopeID(),
3269 MMO->getSuccessOrdering(), MMO->getFailureOrdering());
3270 }
3271
3272 SDValue Load0 = DAG.getLoad(LoadTy, dl, Chain, Base0, WideMMO);
3273 SDValue Load1 = DAG.getLoad(LoadTy, dl, Chain, Base1, WideMMO);
3274
3275 SDValue Aligned = DAG.getNode(HexagonISD::VALIGN, dl, LoadTy,
3276 {Load1, Load0, BaseNoOff.getOperand(0)});
3277 SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
3278 Load0.getValue(1), Load1.getValue(1));
3279 SDValue M = DAG.getMergeValues({Aligned, NewChain}, dl);
3280 return M;
3281}
3282
3283SDValue
3285 SDValue X = Op.getOperand(0), Y = Op.getOperand(1);
3286 auto *CY = dyn_cast<ConstantSDNode>(Y);
3287 if (!CY)
3288 return SDValue();
3289
3290 const SDLoc &dl(Op);
3291 SDVTList VTs = Op.getNode()->getVTList();
3292 assert(VTs.NumVTs == 2);
3293 assert(VTs.VTs[1] == MVT::i1);
3294 unsigned Opc = Op.getOpcode();
3295
3296 if (CY) {
3297 uint64_t VY = CY->getZExtValue();
3298 assert(VY != 0 && "This should have been folded");
3299 // X +/- 1
3300 if (VY != 1)
3301 return SDValue();
3302
3303 if (Opc == ISD::UADDO) {
3304 SDValue Op = DAG.getNode(ISD::ADD, dl, VTs.VTs[0], {X, Y});
3305 SDValue Ov = DAG.getSetCC(dl, MVT::i1, Op, getZero(dl, ty(Op), DAG),
3306 ISD::SETEQ);
3307 return DAG.getMergeValues({Op, Ov}, dl);
3308 }
3309 if (Opc == ISD::USUBO) {
3310 SDValue Op = DAG.getNode(ISD::SUB, dl, VTs.VTs[0], {X, Y});
3311 SDValue Ov = DAG.getSetCC(dl, MVT::i1, Op,
3312 DAG.getAllOnesConstant(dl, ty(Op)), ISD::SETEQ);
3313 return DAG.getMergeValues({Op, Ov}, dl);
3314 }
3315 }
3316
3317 return SDValue();
3318}
3319
3321 SelectionDAG &DAG) const {
3322 const SDLoc &dl(Op);
3323 unsigned Opc = Op.getOpcode();
3324 SDValue X = Op.getOperand(0), Y = Op.getOperand(1), C = Op.getOperand(2);
3325
3326 if (Opc == ISD::UADDO_CARRY)
3327 return DAG.getNode(HexagonISD::ADDC, dl, Op.getNode()->getVTList(),
3328 { X, Y, C });
3329
3330 EVT CarryTy = C.getValueType();
3331 SDValue SubC = DAG.getNode(HexagonISD::SUBC, dl, Op.getNode()->getVTList(),
3332 { X, Y, DAG.getLogicalNOT(dl, C, CarryTy) });
3333 SDValue Out[] = { SubC.getValue(0),
3334 DAG.getLogicalNOT(dl, SubC.getValue(1), CarryTy) };
3335 return DAG.getMergeValues(Out, dl);
3336}
3337
3338SDValue
3340 SDValue Chain = Op.getOperand(0);
3341 SDValue Offset = Op.getOperand(1);
3342 SDValue Handler = Op.getOperand(2);
3343 SDLoc dl(Op);
3344 auto PtrVT = getPointerTy(DAG.getDataLayout());
3345
3346 // Mark function as containing a call to EH_RETURN.
3347 HexagonMachineFunctionInfo *FuncInfo =
3349 FuncInfo->setHasEHReturn();
3350
3351 unsigned OffsetReg = Hexagon::R28;
3352
3353 SDValue StoreAddr =
3354 DAG.getNode(ISD::ADD, dl, PtrVT, DAG.getRegister(Hexagon::R30, PtrVT),
3355 DAG.getIntPtrConstant(4, dl));
3356 Chain = DAG.getStore(Chain, dl, Handler, StoreAddr, MachinePointerInfo());
3357 Chain = DAG.getCopyToReg(Chain, dl, OffsetReg, Offset);
3358
3359 // Not needed we already use it as explicit input to EH_RETURN.
3360 // MF.getRegInfo().addLiveOut(OffsetReg);
3361
3362 return DAG.getNode(HexagonISD::EH_RETURN, dl, MVT::Other, Chain);
3363}
3364
3365SDValue
3367 unsigned Opc = Op.getOpcode();
3368 // Handle INLINEASM first.
3370 return LowerINLINEASM(Op, DAG);
3371
3372 if (isHvxOperation(Op.getNode(), DAG)) {
3373 // If HVX lowering returns nothing, try the default lowering.
3374 if (SDValue V = LowerHvxOperation(Op, DAG))
3375 return V;
3376 }
3377
3378 switch (Opc) {
3379 default:
3380#ifndef NDEBUG
3381 Op.getNode()->dumpr(&DAG);
3382#endif
3383 llvm_unreachable("Should not custom lower this!");
3384
3385 case ISD::FDIV:
3386 return LowerFDIV(Op, DAG);
3387 case ISD::CONCAT_VECTORS: return LowerCONCAT_VECTORS(Op, DAG);
3392 case ISD::BUILD_VECTOR: return LowerBUILD_VECTOR(Op, DAG);
3393 case ISD::VECTOR_SHUFFLE: return LowerVECTOR_SHUFFLE(Op, DAG);
3394 case ISD::BITCAST: return LowerBITCAST(Op, DAG);
3395 case ISD::LOAD: return LowerLoad(Op, DAG);
3396 case ISD::STORE: return LowerStore(Op, DAG);
3397 case ISD::UADDO:
3398 case ISD::USUBO: return LowerUAddSubO(Op, DAG);
3399 case ISD::UADDO_CARRY:
3400 case ISD::USUBO_CARRY: return LowerUAddSubOCarry(Op, DAG);
3401 case ISD::SRA:
3402 case ISD::SHL:
3403 case ISD::SRL: return LowerVECTOR_SHIFT(Op, DAG);
3404 case ISD::ROTL: return LowerROTL(Op, DAG);
3405 case ISD::ConstantPool: return LowerConstantPool(Op, DAG);
3406 case ISD::JumpTable: return LowerJumpTable(Op, DAG);
3407 case ISD::EH_RETURN: return LowerEH_RETURN(Op, DAG);
3408 case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG);
3409 case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
3411 case ISD::ATOMIC_FENCE: return LowerATOMIC_FENCE(Op, DAG);
3412 case ISD::GlobalAddress: return LowerGLOBALADDRESS(Op, DAG);
3413 case ISD::BlockAddress: return LowerBlockAddress(Op, DAG);
3415 case ISD::VACOPY: return LowerVACOPY(Op, DAG);
3416 case ISD::VASTART: return LowerVASTART(Op, DAG);
3418 case ISD::SETCC: return LowerSETCC(Op, DAG);
3419 case ISD::VSELECT: return LowerVSELECT(Op, DAG);
3421 case ISD::INTRINSIC_VOID: return LowerINTRINSIC_VOID(Op, DAG);
3422 case ISD::PREFETCH:
3423 return LowerPREFETCH(Op, DAG);
3424 case ISD::FMAXIMUM:
3425 case ISD::FMINIMUM:
3426 return LowerFMINFMAX(Op, DAG);
3427 break;
3428 }
3429
3430 return SDValue();
3431}
3432
3433void
3436 SelectionDAG &DAG) const {
3437 if (isHvxOperation(N, DAG)) {
3438 LowerHvxOperationWrapper(N, Results, DAG);
3439 if (!Results.empty())
3440 return;
3441 }
3442
3443 SDValue Op(N, 0);
3444 unsigned Opc = N->getOpcode();
3445
3446 switch (Opc) {
3447 case HexagonISD::SSAT:
3448 case HexagonISD::USAT:
3449 Results.push_back(opJoin(SplitVectorOp(Op, DAG), SDLoc(Op), DAG));
3450 break;
3451 case ISD::STORE:
3452 // We are only custom-lowering stores to verify the alignment of the
3453 // address if it is a compile-time constant. Since a store can be
3454 // modified during type-legalization (the value being stored may need
3455 // legalization), return empty Results here to indicate that we don't
3456 // really make any changes in the custom lowering.
3457 return;
3458 default:
3460 break;
3461 }
3462}
3463
3464void
3467 SelectionDAG &DAG) const {
3468 if (isHvxOperation(N, DAG)) {
3469 ReplaceHvxNodeResults(N, Results, DAG);
3470 if (!Results.empty())
3471 return;
3472 }
3473
3474 const SDLoc &dl(N);
3475 switch (N->getOpcode()) {
3476 case ISD::SRL:
3477 case ISD::SRA:
3478 case ISD::SHL:
3479 return;
3480 case ISD::BITCAST:
3481 // Handle a bitcast from v8i1 to i8.
3482 if (N->getValueType(0) == MVT::i8) {
3483 if (N->getOperand(0).getValueType() == MVT::v8i1) {
3484 SDValue P = getInstr(Hexagon::C2_tfrpr, dl, MVT::i32,
3485 N->getOperand(0), DAG);
3486 SDValue T = DAG.getAnyExtOrTrunc(P, dl, MVT::i8);
3487 Results.push_back(T);
3488 }
3489 }
3490 break;
3491 }
3492}
3493
3494SDValue
3496 DAGCombinerInfo &DCI) const {
3497 SDValue Op(N, 0);
3498 const SDLoc &dl(Op);
3499 unsigned Opc = Op.getOpcode();
3500
3501 // Combining transformations applicable for arbitrary vector sizes.
3502 if (DCI.isBeforeLegalizeOps()) {
3503 switch (Opc) {
3504 case ISD::VECREDUCE_ADD:
3505 if (SDValue V = splitVecReduceAdd(N, DCI.DAG))
3506 return V;
3507 if (SDValue V = expandVecReduceAdd(N, DCI.DAG))
3508 return V;
3509 return SDValue();
3513 if (SDValue V = splitExtendingPartialReduceMLA(N, DCI.DAG))
3514 return V;
3515 return SDValue();
3516 }
3517 } else {
3518 switch (Opc) {
3519 case ISD::VSELECT: {
3520 // (vselect (xor x, ptrue), v0, v1) -> (vselect x, v1, v0)
3521 SDValue Cond = Op.getOperand(0);
3522 if (Cond->getOpcode() == ISD::XOR) {
3523 SDValue C0 = Cond.getOperand(0), C1 = Cond.getOperand(1);
3524 if (C1->getOpcode() == HexagonISD::PTRUE) {
3525 SDValue VSel = DCI.DAG.getNode(ISD::VSELECT, dl, ty(Op), C0,
3526 Op.getOperand(2), Op.getOperand(1));
3527 return VSel;
3528 }
3529 }
3530 return SDValue();
3531 }
3532 }
3533 }
3534
3535 if (isHvxOperation(N, DCI.DAG)) {
3536 if (SDValue V = PerformHvxDAGCombine(N, DCI))
3537 return V;
3538 return SDValue();
3539 }
3540
3541 if (Opc == ISD::TRUNCATE) {
3542 SDValue Op0 = Op.getOperand(0);
3543 // fold (truncate (build pair x, y)) -> (truncate x) or x
3544 if (Op0.getOpcode() == ISD::BUILD_PAIR) {
3545 EVT TruncTy = Op.getValueType();
3546 SDValue Elem0 = Op0.getOperand(0);
3547 // if we match the low element of the pair, just return it.
3548 if (Elem0.getValueType() == TruncTy)
3549 return Elem0;
3550 // otherwise, if the low part is still too large, apply the truncate.
3551 if (Elem0.getValueType().bitsGT(TruncTy))
3552 return DCI.DAG.getNode(ISD::TRUNCATE, dl, TruncTy, Elem0);
3553 }
3554 }
3555
3556 if (DCI.isBeforeLegalizeOps())
3557 return SDValue();
3558
3559 switch (Opc) {
3560 case HexagonISD::P2D: {
3561 SDValue P = Op.getOperand(0);
3562 switch (P.getOpcode()) {
3563 case HexagonISD::PTRUE:
3564 return DCI.DAG.getAllOnesConstant(dl, ty(Op));
3565 case HexagonISD::PFALSE:
3566 return getZero(dl, ty(Op), DCI.DAG);
3567 default:
3568 break;
3569 }
3570 break;
3571 }
3572 case ISD::TRUNCATE: {
3573 SDValue Op0 = Op.getOperand(0);
3574 // fold (truncate (build pair x, y)) -> (truncate x) or x
3575 if (Op0.getOpcode() == ISD::BUILD_PAIR) {
3576 MVT TruncTy = ty(Op);
3577 SDValue Elem0 = Op0.getOperand(0);
3578 // if we match the low element of the pair, just return it.
3579 if (ty(Elem0) == TruncTy)
3580 return Elem0;
3581 // otherwise, if the low part is still too large, apply the truncate.
3582 if (ty(Elem0).bitsGT(TruncTy))
3583 return DCI.DAG.getNode(ISD::TRUNCATE, dl, TruncTy, Elem0);
3584 }
3585 break;
3586 }
3587 case ISD::OR: {
3588 // fold (or (shl xx, s), (zext y)) -> (COMBINE (shl xx, s-32), y)
3589 // if s >= 32
3590 auto fold0 = [&, this](SDValue Op) {
3591 if (ty(Op) != MVT::i64)
3592 return SDValue();
3593 SDValue Shl = Op.getOperand(0);
3594 SDValue Zxt = Op.getOperand(1);
3595 if (Shl.getOpcode() != ISD::SHL)
3596 std::swap(Shl, Zxt);
3597
3598 if (Shl.getOpcode() != ISD::SHL || Zxt.getOpcode() != ISD::ZERO_EXTEND)
3599 return SDValue();
3600
3601 SDValue Z = Zxt.getOperand(0);
3602 auto *Amt = dyn_cast<ConstantSDNode>(Shl.getOperand(1));
3603 if (Amt && Amt->getZExtValue() >= 32 && ty(Z).getSizeInBits() <= 32) {
3604 unsigned A = Amt->getZExtValue();
3605 SDValue S = Shl.getOperand(0);
3606 SDValue T0 = DCI.DAG.getNode(ISD::SHL, dl, ty(S), S,
3607 DCI.DAG.getConstant(A - 32, dl, MVT::i32));
3608 SDValue T1 = DCI.DAG.getZExtOrTrunc(T0, dl, MVT::i32);
3609 SDValue T2 = DCI.DAG.getZExtOrTrunc(Z, dl, MVT::i32);
3610 return DCI.DAG.getNode(HexagonISD::COMBINE, dl, MVT::i64, {T1, T2});
3611 }
3612 return SDValue();
3613 };
3614
3615 if (SDValue R = fold0(Op))
3616 return R;
3617 break;
3618 }
3619 }
3620
3621 return SDValue();
3622}
3623
3624/// Returns relocation base for the given PIC jumptable.
3625SDValue
3627 SelectionDAG &DAG) const {
3628 int Idx = cast<JumpTableSDNode>(Table)->getIndex();
3629 EVT VT = Table.getValueType();
3631 return DAG.getNode(HexagonISD::AT_PCREL, SDLoc(Table), VT, T);
3632}
3633
3634//===----------------------------------------------------------------------===//
3635// Inline Assembly Support
3636//===----------------------------------------------------------------------===//
3637
3640 if (Constraint.size() == 1) {
3641 switch (Constraint[0]) {
3642 case 'q':
3643 case 'v':
3644 if (Subtarget.useHVXOps())
3645 return C_RegisterClass;
3646 break;
3647 case 'a':
3648 return C_RegisterClass;
3649 default:
3650 break;
3651 }
3652 }
3653 return TargetLowering::getConstraintType(Constraint);
3654}
3655
3656std::pair<unsigned, const TargetRegisterClass*>
3658 const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const {
3659
3660 if (Constraint.size() == 1) {
3661 switch (Constraint[0]) {
3662 case 'r': // R0-R31
3663 switch (VT.SimpleTy) {
3664 default:
3665 return {0u, nullptr};
3666 case MVT::i1:
3667 case MVT::i8:
3668 case MVT::i16:
3669 case MVT::i32:
3670 case MVT::f32:
3671 return {0u, &Hexagon::IntRegsRegClass};
3672 case MVT::i64:
3673 case MVT::f64:
3674 return {0u, &Hexagon::DoubleRegsRegClass};
3675 }
3676 break;
3677 case 'a': // M0-M1
3678 if (VT != MVT::i32)
3679 return {0u, nullptr};
3680 return {0u, &Hexagon::ModRegsRegClass};
3681 case 'q': // q0-q3
3682 switch (VT.getSizeInBits()) {
3683 default:
3684 return {0u, nullptr};
3685 case 64:
3686 case 128:
3687 return {0u, &Hexagon::HvxQRRegClass};
3688 }
3689 break;
3690 case 'v': // V0-V31
3691 switch (VT.getSizeInBits()) {
3692 default:
3693 return {0u, nullptr};
3694 case 512:
3695 return {0u, &Hexagon::HvxVRRegClass};
3696 case 1024:
3697 if (Subtarget.hasV60Ops() && Subtarget.useHVX128BOps())
3698 return {0u, &Hexagon::HvxVRRegClass};
3699 return {0u, &Hexagon::HvxWRRegClass};
3700 case 2048:
3701 return {0u, &Hexagon::HvxWRRegClass};
3702 }
3703 break;
3704 default:
3705 return {0u, nullptr};
3706 }
3707 }
3708
3709 return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
3710}
3711
3712/// isFPImmLegal - Returns true if the target can instruction select the
3713/// specified FP immediate natively. If false, the legalizer will
3714/// materialize the FP immediate as a load from a constant pool.
3716 bool ForCodeSize) const {
3717 return true;
3718}
3719
3720/// Returns true if it is beneficial to convert a load of a constant
3721/// to just the constant itself.
3723 Type *Ty) const {
3724 if (!ConstantLoadsToImm)
3725 return false;
3726
3727 assert(Ty->isIntegerTy());
3728 unsigned BitSize = Ty->getPrimitiveSizeInBits();
3729 return (BitSize > 0 && BitSize <= 64);
3730}
3731
3732/// isLegalAddressingMode - Return true if the addressing mode represented by
3733/// AM is legal for this target, for a load/store of the specified type.
3735 const AddrMode &AM, Type *Ty,
3736 unsigned AS, Instruction *I) const {
3737 if (Ty->isSized()) {
3738 // When LSR detects uses of the same base address to access different
3739 // types (e.g. unions), it will assume a conservative type for these
3740 // uses:
3741 // LSR Use: Kind=Address of void in addrspace(4294967295), ...
3742 // The type Ty passed here would then be "void". Skip the alignment
3743 // checks, but do not return false right away, since that confuses
3744 // LSR into crashing.
3745 Align A = DL.getABITypeAlign(Ty);
3746 // The base offset must be a multiple of the alignment.
3747 if (!isAligned(A, AM.BaseOffs))
3748 return false;
3749 // The shifted offset must fit in 11 bits.
3750 if (!isInt<11>(AM.BaseOffs >> Log2(A)))
3751 return false;
3752 }
3753
3754 // No global is ever allowed as a base.
3755 if (AM.BaseGV)
3756 return false;
3757
3758 int Scale = AM.Scale;
3759 if (Scale < 0)
3760 Scale = -Scale;
3761 switch (Scale) {
3762 case 0: // No scale reg, "r+i", "r", or just "i".
3763 break;
3764 default: // No scaled addressing mode.
3765 return false;
3766 }
3767 return true;
3768}
3769
3770/// Return true if folding a constant offset with the given GlobalAddress is
3771/// legal. It is frequently not legal in PIC relocation models.
3773 const {
3774 return HTM.getRelocationModel() == Reloc::Static;
3775}
3776
3777/// isLegalICmpImmediate - Return true if the specified immediate is legal
3778/// icmp immediate, that is the target has icmp instructions which can compare
3779/// a register against the immediate without having to materialize the
3780/// immediate into a register.
3782 return Imm >= -512 && Imm <= 511;
3783}
3784
3785/// IsEligibleForTailCallOptimization - Check whether the call is eligible
3786/// for tail call optimization. Targets which want to do tail call
3787/// optimization should implement this function.
3789 SDValue Callee,
3790 CallingConv::ID CalleeCC,
3791 bool IsVarArg,
3792 bool IsCalleeStructRet,
3793 bool IsCallerStructRet,
3795 const SmallVectorImpl<SDValue> &OutVals,
3797 SelectionDAG& DAG) const {
3798 const Function &CallerF = DAG.getMachineFunction().getFunction();
3799 CallingConv::ID CallerCC = CallerF.getCallingConv();
3800 bool CCMatch = CallerCC == CalleeCC;
3801
3802 // ***************************************************************************
3803 // Look for obvious safe cases to perform tail call optimization that do not
3804 // require ABI changes.
3805 // ***************************************************************************
3806
3807 // If this is a tail call via a function pointer, then don't do it!
3808 if (!isa<GlobalAddressSDNode>(Callee) &&
3809 !isa<ExternalSymbolSDNode>(Callee)) {
3810 return false;
3811 }
3812
3813 // Do not optimize if the calling conventions do not match and the conventions
3814 // used are not C or Fast.
3815 if (!CCMatch) {
3816 bool R = (CallerCC == CallingConv::C || CallerCC == CallingConv::Fast);
3817 bool E = (CalleeCC == CallingConv::C || CalleeCC == CallingConv::Fast);
3818 // If R & E, then ok.
3819 if (!R || !E)
3820 return false;
3821 }
3822
3823 // Do not tail call optimize vararg calls.
3824 if (IsVarArg)
3825 return false;
3826
3827 // Also avoid tail call optimization if either caller or callee uses struct
3828 // return semantics.
3829 if (IsCalleeStructRet || IsCallerStructRet)
3830 return false;
3831
3832 // In addition to the cases above, we also disable Tail Call Optimization if
3833 // the calling convention code that at least one outgoing argument needs to
3834 // go on the stack. We cannot check that here because at this point that
3835 // information is not available.
3836 return true;
3837}
3838
3839/// Returns the target specific optimal type for load and store operations as
3840/// a result of memset, memcpy, and memmove lowering.
3841///
3842/// If DstAlign is zero that means it's safe to destination alignment can
3843/// satisfy any constraint. Similarly if SrcAlign is zero it means there isn't
3844/// a need to check it against alignment requirement, probably because the
3845/// source does not need to be loaded. If 'IsMemset' is true, that means it's
3846/// expanding a memset. If 'ZeroMemset' is true, that means it's a memset of
3847/// zero. 'MemcpyStrSrc' indicates whether the memcpy source is constant so it
3848/// does not need to be loaded. It returns EVT::Other if the type should be
3849/// determined using generic target-independent logic.
3851 LLVMContext &Context, const MemOp &Op,
3852 const AttributeList &FuncAttributes) const {
3853 if (Op.size() >= 8 && Op.isAligned(Align(8)))
3854 return MVT::i64;
3855 if (Op.size() >= 4 && Op.isAligned(Align(4)))
3856 return MVT::i32;
3857 if (Op.size() >= 2 && Op.isAligned(Align(2)))
3858 return MVT::i16;
3859 return MVT::Other;
3860}
3861
3862// The helpers below are versions of llvm::getShuffleReduction and
3863// llvm::getOrderedReduction, adapted to use during DAG passes and simplified as
3864// follows:
3865// - ICmp and FCmp are not handled;
3866// - in every step in getShuffleReduction, the input is split into halves (not
3867// pairwise).
3868
3870 SelectionDAG &DAG) {
3871 assert(Op != Instruction::ICmp && Op != Instruction::FCmp);
3872
3873 EVT VT = Vec.getValueType();
3874 EVT EltT = VT.getVectorElementType();
3875 unsigned VF = VT.getVectorNumElements();
3876 assert(VF > 0 &&
3877 "Reduction emission only supported for non-zero length vectors!");
3878
3879 SDLoc DL(Vec);
3880 SDValue Result = DAG.getExtractVectorElt(DL, EltT, Vec, 0);
3881 for (unsigned ExtractIdx = 1; ExtractIdx < VF; ++ExtractIdx) {
3882 SDValue Ext = DAG.getExtractVectorElt(DL, EltT, Vec, ExtractIdx);
3883 Result = DAG.getNode(Op, DL, EltT, {Result, Ext});
3884 }
3885
3886 return Result;
3887}
3888
3890 SelectionDAG &DAG) {
3891 assert(Op != Instruction::ICmp && Op != Instruction::FCmp);
3892
3893 EVT VT = Vec.getValueType();
3894 unsigned VF = VT.getVectorNumElements();
3895 if (VF == 0)
3896 llvm_unreachable("Vector must be non-zero length");
3897 // VF is a power of 2 so we can emit the reduction using log2(VF) shuffles
3898 // and vector ops, reducing the set of values being computed by half each
3899 // round.
3900 assert(isPowerOf2_32(VF) &&
3901 "Reduction emission only supported for pow2 vectors!");
3902
3903 SDLoc DL(Vec);
3904 // TODO: Is it correct to create double-vector shuffle and fill 3/4 of it with
3905 // undefs?
3906 SmallVector<int, 32> ShuffleMask(VF);
3907 for (unsigned i = VF; i > 1; i >>= 1) {
3908 // Move the upper half of the vector to the lower half.
3909 for (unsigned j = 0; j != i / 2; ++j)
3910 ShuffleMask[j] = i / 2 + j;
3911 // Fill the rest of the mask with undef.
3912 std::fill(&ShuffleMask[i / 2], ShuffleMask.end(), -1);
3913
3914 SDValue Shuf =
3915 DAG.getVectorShuffle(VT, DL, Vec, DAG.getUNDEF(VT), ShuffleMask);
3916
3917 Vec = DAG.getNode(Op, DL, VT, {Vec, Shuf});
3918 }
3919 // The result is in the first element of the vector.
3920 return DAG.getExtractVectorElt(DL, VT.getVectorElementType(), Vec, 0);
3921}
3922
3923SDValue HexagonTargetLowering::expandVecReduceAdd(SDNode *N,
3924 SelectionDAG &DAG) const {
3925 // Since we disabled automatic reduction expansion, generate log2 ladder code
3926 // if the vector is of a power-of-two length.
3927 SDValue Input = N->getOperand(0);
3929 return getShuffleReduction(Input, ISD::ADD, DAG);
3930 // Otherwise, reduction will be scalarized.
3931 return getOrderedReduction(Input, ISD::ADD, DAG);
3932}
3933
3935 LLVMContext &Context, const DataLayout &DL, EVT VT, unsigned AddrSpace,
3936 Align Alignment, MachineMemOperand::Flags Flags, unsigned *Fast) const {
3937 if (!VT.isSimple())
3938 return false;
3939 MVT SVT = VT.getSimpleVT();
3940 if (Subtarget.isHVXVectorType(SVT, true))
3941 return allowsHvxMemoryAccess(SVT, Flags, Fast);
3943 Context, DL, VT, AddrSpace, Alignment, Flags, Fast);
3944}
3945
3947 EVT VT, unsigned AddrSpace, Align Alignment, MachineMemOperand::Flags Flags,
3948 unsigned *Fast) const {
3949 if (!VT.isSimple())
3950 return false;
3951 MVT SVT = VT.getSimpleVT();
3952 if (Subtarget.isHVXVectorType(SVT, true))
3953 return allowsHvxMisalignedMemoryAccesses(SVT, Flags, Fast);
3954 if (Fast)
3955 *Fast = 0;
3956 return false;
3957}
3958
3959std::pair<const TargetRegisterClass*, uint8_t>
3960HexagonTargetLowering::findRepresentativeClass(const TargetRegisterInfo *TRI,
3961 MVT VT) const {
3962 if (Subtarget.isHVXVectorType(VT, true)) {
3963 unsigned BitWidth = VT.getSizeInBits();
3964 unsigned VecWidth = Subtarget.getVectorLength() * 8;
3965
3966 if (VT.getVectorElementType() == MVT::i1)
3967 return std::make_pair(&Hexagon::HvxQRRegClass, 1);
3968 if (BitWidth == VecWidth)
3969 return std::make_pair(&Hexagon::HvxVRRegClass, 1);
3970 assert(BitWidth == 2 * VecWidth);
3971 return std::make_pair(&Hexagon::HvxWRRegClass, 1);
3972 }
3973
3975}
3976
3978 SDNode *Load, ISD::LoadExtType ExtTy, EVT NewVT,
3979 std::optional<unsigned> ByteOffset) const {
3980 // TODO: This may be worth removing. Check regression tests for diffs.
3982 ByteOffset))
3983 return false;
3984
3985 auto *L = cast<LoadSDNode>(Load);
3986 std::pair<SDValue, int> BO = getBaseAndOffset(L->getBasePtr());
3987 // Small-data object, do not shrink.
3988 if (BO.first.getOpcode() == HexagonISD::CONST32_GP)
3989 return false;
3991 auto &HTM = static_cast<const HexagonTargetMachine &>(getTargetMachine());
3992 const auto *GO = dyn_cast_or_null<const GlobalObject>(GA->getGlobal());
3993 return !GO || !HTM.getObjFileLowering()->isGlobalInSmallSection(GO, HTM);
3994 }
3995 return true;
3996}
3997
3999 SDNode *Node) const {
4000 AdjustHvxInstrPostInstrSelection(MI, Node);
4001}
4002
4004 Type *ValueTy, Value *Addr,
4005 AtomicOrdering Ord) const {
4006 unsigned SZ = ValueTy->getPrimitiveSizeInBits();
4007 assert((SZ == 32 || SZ == 64) && "Only 32/64-bit atomic loads supported");
4008 Intrinsic::ID IntID = (SZ == 32) ? Intrinsic::hexagon_L2_loadw_locked
4009 : Intrinsic::hexagon_L4_loadd_locked;
4010
4011 Value *Call =
4012 Builder.CreateIntrinsic(IntID, Addr, /*FMFSource=*/nullptr, "larx");
4013
4014 return Builder.CreateBitCast(Call, ValueTy);
4015}
4016
4017/// Perform a store-conditional operation to Addr. Return the status of the
4018/// store. This should be 0 if the store succeeded, non-zero otherwise.
4020 Value *Val, Value *Addr,
4021 AtomicOrdering Ord) const {
4022 BasicBlock *BB = Builder.GetInsertBlock();
4023 Module *M = BB->getParent()->getParent();
4024 Type *Ty = Val->getType();
4025 unsigned SZ = Ty->getPrimitiveSizeInBits();
4026
4027 Type *CastTy = Builder.getIntNTy(SZ);
4028 assert((SZ == 32 || SZ == 64) && "Only 32/64-bit atomic stores supported");
4029 Intrinsic::ID IntID = (SZ == 32) ? Intrinsic::hexagon_S2_storew_locked
4030 : Intrinsic::hexagon_S4_stored_locked;
4031
4032 Val = Builder.CreateBitCast(Val, CastTy);
4033
4034 Value *Call = Builder.CreateIntrinsic(IntID, {Addr, Val},
4035 /*FMFSource=*/nullptr, "stcx");
4036 Value *Cmp = Builder.CreateICmpEQ(Call, Builder.getInt32(0), "");
4037 Value *Ext = Builder.CreateZExt(Cmp, Type::getInt32Ty(M->getContext()));
4038 return Ext;
4039}
4040
4043 // Do not expand loads and stores that don't exceed 64 bits.
4044 return LI->getType()->getPrimitiveSizeInBits() > 64
4047}
4048
4051 // Do not expand loads and stores that don't exceed 64 bits.
4052 return SI->getValueOperand()->getType()->getPrimitiveSizeInBits() > 64
4055}
4056
4062
4064 MachineInstr &MI, MachineBasicBlock *BB) const {
4065 switch (MI.getOpcode()) {
4066 case TargetOpcode::PATCHABLE_EVENT_CALL:
4067 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
4068 // These are lowered in the AsmPrinter.
4069 return BB;
4070 default:
4071 llvm_unreachable("Unexpected instruction with custom inserter");
4072 }
4073}
4074
4078 const TargetInstrInfo *TII) const {
4079 assert(MBBI->isCall() && MBBI->getCFIType() &&
4080 "Invalid call instruction for a KCFI check");
4081
4082 switch (MBBI->getOpcode()) {
4083 case Hexagon::J2_callr:
4084 case Hexagon::PS_callr_nr:
4085 break;
4086 default:
4087 llvm_unreachable("Unexpected CFI call opcode");
4088 }
4089
4090 MachineOperand &Target = MBBI->getOperand(0);
4091 assert(Target.isReg() && "Invalid target operand for an indirect call");
4092 Target.setIsRenamable(false);
4093
4094 return BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(Hexagon::KCFI_CHECK))
4095 .addReg(Target.getReg())
4096 .addImm(MBBI->getCFIType())
4097 .getInstr();
4098}
4099
4101 const Instruction &AndI) const {
4102 // Only sink 'and' mask to cmp use block if it is masking a single bit since
4103 // this will fold the and/cmp/br into a single tstbit instruction.
4105 if (!Mask)
4106 return false;
4107 return Mask->getValue().isPowerOf2();
4108}
4109
4110// Check if the result of the node is only used as a return value, as
4111// otherwise we can't perform a tail-call.
4113 SDValue &Chain) const {
4114 if (N->getNumValues() != 1)
4115 return false;
4116 if (!N->hasNUsesOfValue(1, 0))
4117 return false;
4118
4119 SDNode *Copy = *N->user_begin();
4120
4121 if (Copy->getOpcode() == ISD::BITCAST) {
4122 return isUsedByReturnOnly(Copy, Chain);
4123 }
4124
4125 if (Copy->getOpcode() != ISD::CopyToReg) {
4126 return false;
4127 }
4128
4129 // If the ISD::CopyToReg has a glue operand, we conservatively assume it
4130 // isn't safe to perform a tail call.
4131 if (Copy->getOperand(Copy->getNumOperands() - 1).getValueType() == MVT::Glue)
4132 return false;
4133
4134 // The copy must be used by a HexagonISD::RET_GLUE, and nothing else.
4135 bool HasRet = false;
4136 for (SDNode *Node : Copy->users()) {
4137 if (Node->getOpcode() != HexagonISD::RET_GLUE)
4138 return false;
4139 HasRet = true;
4140 }
4141 if (!HasRet)
4142 return false;
4143
4144 Chain = Copy->getOperand(0);
4145 return true;
4146}
4147
4149 const MachineFunction &MF) const {
4150 if (MF.getFunction().hasFnAttribute("probe-stack"))
4151 return MF.getFunction().getFnAttribute("probe-stack").getValueAsString() ==
4152 "inline-asm";
4153 return false;
4154}
4155
4157 Align StackAlign) const {
4158 const Function &Fn = MF.getFunction();
4159 unsigned StackProbeSize =
4160 Fn.getFnAttributeAsParsedInteger("stack-probe-size", 4096);
4161 // Round down to the stack alignment.
4162 StackProbeSize = alignDown(StackProbeSize, StackAlign.value());
4163 return StackProbeSize ? StackProbeSize : StackAlign.value();
4164}
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< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
const HexagonInstrInfo * TII
static cl::opt< bool > ConstantLoadsToImm("constant-loads-to-imm", cl::Hidden, cl::init(true), cl::desc("Convert constant loads to immediate values."))
static bool CC_SkipOdd(unsigned &ValNo, MVT &ValVT, MVT &LocVT, CCValAssign::LocInfo &LocInfo, ISD::ArgFlagsTy &ArgFlags, CCState &State)
static cl::opt< bool > AlignLoads("hexagon-align-loads", cl::Hidden, cl::init(false), cl::desc("Rewrite unaligned loads as a pair of aligned loads"))
static bool isBrevLdIntrinsic(const Value *Inst)
static Value * getUnderLyingObjectForBrevLdIntr(Value *V, int &Offset, bool &HasOffset)
static Value * getBrevLdObject(Value *V)
static cl::opt< bool > DisableArgsMinAlignment("hexagon-disable-args-min-alignment", cl::Hidden, cl::init(false), cl::desc("Disable minimum alignment of 1 for " "arguments passed by value on stack"))
static Value * returnEdge(const PHINode *PN, Value *IntrBaseVal)
static SDValue CreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain, ISD::ArgFlagsTy Flags, SelectionDAG &DAG, const SDLoc &dl)
CreateCopyOfByValArgument - Make a copy of an aggregate at address specified by "Src" to address "Dst...
static cl::opt< bool > EmitJumpTables("hexagon-emit-jump-tables", cl::init(true), cl::Hidden, cl::desc("Control jump table emission on Hexagon target"))
static cl::opt< int > MinimumJumpTables("minimum-jump-tables", cl::Hidden, cl::init(5), cl::desc("Set minimum jump tables"))
static cl::opt< bool > EnableHexSDNodeSched("enable-hexagon-sdnode-sched", cl::Hidden, cl::desc("Enable Hexagon SDNode scheduling"))
#define Hexagon_PointerSize
#define HEXAGON_LRFP_SIZE
#define HEXAGON_GOT_SYM_NAME
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define RegName(no)
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define G(x, y, z)
Definition MD5.cpp:55
#define H(x, y, z)
Definition MD5.cpp:56
std::pair< MCSymbol *, MachineModuleInfoImpl::StubValueTy > PairTy
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define T
#define T1
#define P(N)
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:1467
Class for arbitrary precision integers.
Definition APInt.h:78
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1565
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
Definition APInt.cpp:968
LLVM_ABI APInt reverseBits() const
Definition APInt.cpp:790
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:698
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
Definition Function.cpp:762
uint64_t getFnAttributeAsParsedInteger(StringRef Kind, uint64_t Default=0) const
For a string attribute Kind, parse attribute as an integer.
Definition Function.cpp:774
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:672
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition Function.cpp:727
const GlobalValue * getGlobal() const
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI const GlobalObject * getAliaseeObject() const
Definition Globals.cpp:521
Hexagon target-specific information for each MachineFunction.
Register getFrameRegister(const MachineFunction &MF) const override
const uint32_t * getCallPreservedMask(const MachineFunction &MF, CallingConv::ID) const override
bool isHVXVectorType(EVT VecTy, bool IncludeBool=false) const
unsigned getVectorLength() const
SDValue getPICJumpTableRelocBase(SDValue Table, SelectionDAG &DAG) const override
Returns relocation base for the given PIC jumptable.
SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const
SDValue LowerFMINFMAX(SDValue Op, SelectionDAG &DAG) const
MachineInstr * EmitKCFICheck(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator &MBBI, const TargetInstrInfo *TII) const override
SDValue LowerGLOBAL_OFFSET_TABLE(SDValue Op, SelectionDAG &DAG) const
bool isMaskAndCmp0FoldingBeneficial(const Instruction &AndI) const override
Return if the target supports combining a chain like:
SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const
void AdjustInstrPostInstrSelection(MachineInstr &MI, SDNode *Node) const override
This method should be implemented by targets that mark instructions with the 'hasPostISelHook' flag.
bool isTargetCanonicalConstantNode(SDValue Op) const override
Returns true if the given Opc is considered a canonical constant for the target, which should not be ...
ConstraintType getConstraintType(StringRef Constraint) const override
Given a constraint, return the type of constraint it is for this target.
bool isTruncateFree(Type *Ty1, Type *Ty2) const override
Return true if it's free to truncate a value of type FromTy to type ToTy.
MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
unsigned getStackProbeSize(const MachineFunction &MF, Align StackAlign) const
SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const
SDValue LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const
ExtractSubvectorCost getExtractSubvectorCost(EVT ResVT, EVT SrcVT, unsigned Index) const override
Return the cost of extracting a subvector of type ResVT from a vector of type SrcVT,...
SDValue LowerUAddSubO(SDValue Op, SelectionDAG &DAG) const
Value * emitLoadLinked(IRBuilderBase &Builder, Type *ValueTy, Value *Addr, AtomicOrdering Ord) const override
Perform a load-linked operation on Addr, returning a "Value *" with the corresponding pointee type.
bool isLegalICmpImmediate(int64_t Imm) const override
isLegalICmpImmediate - Return true if the specified immediate is legal icmp immediate,...
bool shouldReduceLoadWidth(SDNode *Load, ISD::LoadExtType ExtTy, EVT NewVT, std::optional< unsigned > ByteOffset) const override
Return true if it is profitable to reduce a load to a smaller type.
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
isLegalAddressingMode - Return true if the addressing mode represented by AM is legal for this target...
SDValue LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const
AtomicExpansionKind shouldExpandAtomicStoreInIR(StoreInst *SI) const override
Returns how the given (atomic) store should be expanded by the IR-level AtomicExpand pass into.
SDValue GetDynamicTLSAddr(SelectionDAG &DAG, SDValue Chain, GlobalAddressSDNode *GA, SDValue InGlue, EVT PtrVT, unsigned ReturnReg, unsigned char OperandGlues) const
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl< ISD::OutputArg > &Outs, const SmallVectorImpl< SDValue > &OutVals, const SDLoc &dl, SelectionDAG &DAG) const override
This hook must be implemented to lower outgoing return values, described by the Outs array,...
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override
This method will be invoked for all target nodes and for any target-independent nodes that the target...
SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const
bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, SDValue &Base, SDValue &Offset, ISD::MemIndexedMode &AM, SelectionDAG &DAG) const override
Returns true by value, base pointer and offset pointer and addressing mode by reference if this node ...
SDValue LowerUnalignedLoad(SDValue Op, SelectionDAG &DAG) const
SDValue LowerFDIV(SDValue Op, SelectionDAG &DAG) const
SDValue LowerVACOPY(SDValue Op, SelectionDAG &DAG) const
unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const override
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl< ISD::InputArg > &Ins, const SDLoc &dl, SelectionDAG &DAG, SmallVectorImpl< SDValue > &InVals) const override
This hook must be implemented to lower the incoming (formal) arguments, described by the Ins array,...
bool 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
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.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
A description of a memory reference used in the backend.
Flags
Flags values. These may be or'd together.
@ MOVolatile
The memory access is volatile.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
Flags getFlags() const
Return the raw flags of the source value,.
MachineOperand class - Representation of each machine instruction operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
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)
SDValue getGLOBAL_OFFSET_TABLE(EVT VT)
Return a GLOBAL_OFFSET_TABLE node. This does not have a useful SDLoc.
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false, SDNodeFlags Flags={})
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
LLVM_ABI SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align DstAlign, Align SrcAlign, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), BatchAAResults *BatchAA=nullptr)
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
LLVM_ABI SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, SDValue Offset, MachinePointerInfo PtrInfo, EVT SVT, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS, SDNodeFlags Flags=SDNodeFlags())
Helper function to make it easier to build Select's if you just have operands and don't want to check...
LLVM_ABI SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT)
Return the expression required to zero extend the Op value assuming it was the smaller SrcTy value.
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI SDValue getMemBasePlusOffset(SDValue Base, TypeSize Offset, const SDLoc &DL, const SDNodeFlags Flags=SDNodeFlags())
Returns sum of the base pointer and offset.
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI SDValue getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either sign-extending or trunca...
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const MMOMetadata &Metadata=MMOMetadata())
Loads are not normal binary operators: their result type is not determined by their operands,...
LLVM_ABI SDValue getIndexedStore(SDValue OrigStore, const SDLoc &dl, SDValue Base, SDValue Offset, ISD::MemIndexedMode AM)
LLVM_ABI SDValue getAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either any-extending or truncat...
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetBlockAddress(const BlockAddress *BA, EVT VT, int64_t Offset=0, unsigned TargetFlags=0)
LLVM_ABI void ReplaceAllUsesOfValueWith(SDValue From, SDValue To)
Replace any uses of From with To, leaving uses of other values produced by From.getNode() alone.
MachineFunction & getMachineFunction() const
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
SDValue getTargetConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offset=0, unsigned TargetFlags=0)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
LLVM_ABI SDValue getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1, SDValue N2, ArrayRef< int > Mask)
Return an ISD::VECTOR_SHUFFLE node.
LLVM_ABI SDValue getLogicalNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a logical NOT operation as (XOR Val, BooleanOne).
static void commuteMask(MutableArrayRef< int > Mask)
Change values in a shuffle permute mask assuming the two vector operands have swapped position.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
This class is used to represent ISD::STORE nodes.
const SDValue & getBasePtr() const
const SDValue & getOffset() const
const SDValue & getValue() const
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
TargetInstrInfo - Interface to description of machine instruction set.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
virtual bool shouldReduceLoadWidth(SDNode *Load, ISD::LoadExtType ExtTy, EVT NewVT, std::optional< unsigned > ByteOffset=std::nullopt) const
Return true if it is profitable to reduce a load to a smaller type.
LegalizeAction
This enum indicates whether operations are valid for a target, and if not, what action should be used...
unsigned MaxStoresPerMemcpyOptSize
Likewise for functions with the OptSize attribute.
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
const TargetMachine & getTargetMachine() const
virtual MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
LegalizeTypeAction
This enum indicates whether a types are legal for a target, and if not, what action should be used to...
void setIndexedLoadAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed load does or does not work with the specified type and indicate w...
void setPrefLoopAlignment(Align Alignment)
Set the target's preferred loop alignment.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
virtual unsigned getVectorTypeBreakdownForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const
Certain targets such as MIPS require that some types such as vectors are always broken down into scal...
void setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
unsigned MaxStoresPerMemsetOptSize
Likewise for functions with the OptSize attribute.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
unsigned MaxStoresPerMemmove
Specify maximum number of store instructions per memmove call.
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
unsigned MaxStoresPerMemmoveOptSize
Likewise for functions with the OptSize attribute.
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type.
void setIndexedStoreAction(ArrayRef< unsigned > IdxModes, MVT VT, LegalizeAction Action)
Indicate that the specified indexed store does or does not work with the specified type and indicate ...
ExtractSubvectorCost
Enum that specifies how expensive lowering an EXTRACT_SUBVECTOR is.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
void setPrefFunctionAlignment(Align Alignment)
Set the target's preferred function alignment.
unsigned MaxStoresPerMemset
Specify maximum number of store instructions per memset call.
void setMinimumJumpTableEntries(unsigned Val)
Indicate the minimum number of blocks to generate jump tables.
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
bool isPointerTy() const
True if this is an instance of PointerType.
Definition Type.h:282
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
LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
Definition Value.cpp:993
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
@ FMINNUM
FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, following IEEE-754 definition...
@ DYNAMIC_STACKALLOC
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary.
@ 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
@ FMINIMUM
FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0 as less than 0....
@ 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).
bool isIntEqualitySetCC(CondCode Code)
Return true if this is a setcc instruction that performs an equality comparison when used with intege...
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
initializer< Ty > init(const Ty &Val)
constexpr double e
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:578
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:166
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
RelativeUniformCounterPtr Values
Definition InstrProf.h:91
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
Definition Alignment.h:134
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
constexpr T alignDown(U Value, V Align, W Skew=0)
Returns the largest unsigned integer less than or equal to Value and is Skew mod Align.
Definition MathExtras.h:547
LLVM_ABI Value * getSplatValue(const Value *V)
Get splat value if the input is a splat vector or return nullptr.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
Definition bit.h:204
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI Value * getShuffleReduction(IRBuilderBase &Builder, Value *Src, unsigned Op, TargetTransformInfo::ReductionShuffle RS, RecurKind MinMaxKind=RecurKind::None)
Generates a vector reduction using shufflevectors to reduce the value.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:190
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
FormattedNumber format_hex(uint64_t N, unsigned Width, bool Upper=false)
format_hex - Output N as a fixed width hexadecimal.
Definition Format.h:164
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
AtomicOrdering
Atomic ordering for LLVM's memory model.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Definition MCRegister.h:21
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:880
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h: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
LLVM IR metadata carried by a MachineMemOperand.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Definition Alignment.h: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