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