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