47#include "llvm/IR/IntrinsicsHexagon.h"
69#define DEBUG_TYPE "hexagon-lowering"
73 cl::desc(
"Control jump table emission on Hexagon target"));
77 cl::desc(
"Enable Hexagon SDNode scheduling"));
80 cl::desc(
"Enable Fast Math processing"));
84 cl::desc(
"Set minimum jump tables"));
88 cl::desc(
"Max #stores to inline memcpy"));
92 cl::desc(
"Max #stores to inline memcpy"));
96 cl::desc(
"Max #stores to inline memmove"));
101 cl::desc(
"Max #stores to inline memmove"));
105 cl::desc(
"Max #stores to inline memset"));
109 cl::desc(
"Max #stores to inline memset"));
113 cl::desc(
"Rewrite unaligned loads as a pair of aligned loads"));
118 cl::desc(
"Disable minimum alignment of 1 for "
119 "arguments passed by value on stack"));
123 class HexagonCCState :
public CCState {
124 unsigned NumNamedVarArgParams = 0;
129 unsigned NumNamedArgs)
131 NumNamedVarArgParams(NumNamedArgs) {}
132 unsigned getNumNamedVarArgParams()
const {
return NumNamedVarArgParams; }
144 Hexagon::R0, Hexagon::R1, Hexagon::R2,
145 Hexagon::R3, Hexagon::R4, Hexagon::R5
147 const unsigned NumArgRegs = std::size(ArgRegs);
151 if (RegNum != NumArgRegs && RegNum % 2 == 1)
160#include "HexagonGenCallingConv.inc"
179 Chain, dl, Dst, Src, SizeNode, Flags.getNonZeroByValAlign(),
190 CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
193 return CCInfo.
CheckReturn(Outs, RetCC_Hexagon_HVX);
223 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
272 .
Case(
"r0", Hexagon::R0)
273 .
Case(
"r1", Hexagon::R1)
274 .
Case(
"r2", Hexagon::R2)
275 .
Case(
"r3", Hexagon::R3)
276 .
Case(
"r4", Hexagon::R4)
277 .
Case(
"r5", Hexagon::R5)
278 .
Case(
"r6", Hexagon::R6)
279 .
Case(
"r7", Hexagon::R7)
280 .
Case(
"r8", Hexagon::R8)
281 .
Case(
"r9", Hexagon::R9)
282 .
Case(
"r10", Hexagon::R10)
283 .
Case(
"r11", Hexagon::R11)
284 .
Case(
"r12", Hexagon::R12)
285 .
Case(
"r13", Hexagon::R13)
286 .
Case(
"r14", Hexagon::R14)
287 .
Case(
"r15", Hexagon::R15)
288 .
Case(
"r16", Hexagon::R16)
289 .
Case(
"r17", Hexagon::R17)
290 .
Case(
"r18", Hexagon::R18)
291 .
Case(
"r19", Hexagon::R19)
292 .
Case(
"r20", Hexagon::R20)
293 .
Case(
"r21", Hexagon::R21)
294 .
Case(
"r22", Hexagon::R22)
295 .
Case(
"r23", Hexagon::R23)
296 .
Case(
"r24", Hexagon::R24)
297 .
Case(
"r25", Hexagon::R25)
298 .
Case(
"r26", Hexagon::R26)
299 .
Case(
"r27", Hexagon::R27)
300 .
Case(
"r28", Hexagon::R28)
301 .
Case(
"r29", Hexagon::R29)
302 .
Case(
"r30", Hexagon::R30)
303 .
Case(
"r31", Hexagon::R31)
304 .
Case(
"r1:0", Hexagon::D0)
305 .
Case(
"r3:2", Hexagon::D1)
306 .
Case(
"r5:4", Hexagon::D2)
307 .
Case(
"r7:6", Hexagon::D3)
308 .
Case(
"r9:8", Hexagon::D4)
309 .
Case(
"r11:10", Hexagon::D5)
310 .
Case(
"r13:12", Hexagon::D6)
311 .
Case(
"r15:14", Hexagon::D7)
312 .
Case(
"r17:16", Hexagon::D8)
313 .
Case(
"r19:18", Hexagon::D9)
314 .
Case(
"r21:20", Hexagon::D10)
315 .
Case(
"r23:22", Hexagon::D11)
316 .
Case(
"r25:24", Hexagon::D12)
317 .
Case(
"r27:26", Hexagon::D13)
318 .
Case(
"r29:28", Hexagon::D14)
319 .
Case(
"r31:30", Hexagon::D15)
320 .
Case(
"sp", Hexagon::R29)
321 .
Case(
"fp", Hexagon::R30)
322 .
Case(
"lr", Hexagon::R31)
323 .
Case(
"p0", Hexagon::P0)
324 .
Case(
"p1", Hexagon::P1)
325 .
Case(
"p2", Hexagon::P2)
326 .
Case(
"p3", Hexagon::P3)
327 .
Case(
"sa0", Hexagon::SA0)
328 .
Case(
"lc0", Hexagon::LC0)
329 .
Case(
"sa1", Hexagon::SA1)
330 .
Case(
"lc1", Hexagon::LC1)
331 .
Case(
"m0", Hexagon::M0)
332 .
Case(
"m1", Hexagon::M1)
333 .
Case(
"usr", Hexagon::USR)
334 .
Case(
"ugp", Hexagon::UGP)
335 .
Case(
"cs0", Hexagon::CS0)
336 .
Case(
"cs1", Hexagon::CS1)
366 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
368 if (RVLocs[i].getValVT() == MVT::i1) {
378 Register PredR =
MRI.createVirtualRegister(&Hexagon::PredRegsRegClass);
390 RVLocs[i].getValVT(), Glue);
416 bool IsStructRet = Outs.
empty() ?
false : Outs[0].Flags.isSRet();
430 HexagonCCState CCInfo(CallConv, TreatAsVarArg, MF, ArgLocs, *DAG.
getContext(),
434 CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon_HVX);
436 CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon_Legacy);
438 CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon);
443 IsVarArg, IsStructRet, StructAttrFlag, Outs,
452 :
"Argument must be passed on stack. "
453 "Not eligible for Tail Call\n"));
456 unsigned NumBytes = CCInfo.getStackSize();
464 bool NeedsArgAlign =
false;
465 Align LargestAlignSeen;
467 for (
unsigned i = 0, e = ArgLocs.
size(); i != e; ++i) {
473 NeedsArgAlign |= ArgAlign;
499 StackPtr.getValueType());
502 LargestAlignSeen = std::max(
504 if (Flags.isByVal()) {
524 if (NeedsArgAlign && Subtarget.
hasV60Ops()) {
525 LLVM_DEBUG(
dbgs() <<
"Function needs byte stack align due to call args\n");
526 Align VecAlign = HRI.getSpillAlign(Hexagon::HvxVRRegClass);
527 LargestAlignSeen = std::max(LargestAlignSeen, VecAlign);
532 if (!MemOpChains.
empty())
546 for (
const auto &R : RegsToPass) {
547 Chain = DAG.
getCopyToReg(Chain, dl, R.first, R.second, Glue);
562 for (
const auto &R : RegsToPass) {
563 Chain = DAG.
getCopyToReg(Chain, dl, R.first, R.second, Glue);
578 dyn_cast<ExternalSymbolSDNode>(Callee)) {
590 for (
const auto &R : RegsToPass)
594 assert(Mask &&
"Missing call preserved mask for calling convention");
611 Chain = DAG.
getNode(OpCode, dl, NodeTys, Ops);
621 InVals, OutVals, Callee);
636 bool IsLegalType = VT == MVT::i8 || VT == MVT::i16 || VT == MVT::i32 ||
637 VT == MVT::i64 || VT == MVT::f32 || VT == MVT::f64 ||
638 VT == MVT::v2i16 || VT == MVT::v2i32 || VT == MVT::v4i8 ||
639 VT == MVT::v4i16 || VT == MVT::v8i8 ||
648 if (!isa<ConstantSDNode>(
Offset.getNode()))
652 int32_t V = cast<ConstantSDNode>(
Offset.getNode())->getSExtValue();
668 unsigned LR = HRI.getRARegister();
675 if (
Op.getOperand(NumOps-1).getValueType() == MVT::Glue)
680 unsigned NumVals = Flags.getNumOperandRegisters();
683 switch (Flags.getKind()) {
694 for (; NumVals; --NumVals, ++i) {
695 Register Reg = cast<RegisterSDNode>(
Op.getOperand(i))->getReg();
698 HMFI.setHasClobberLR(
true);
750 unsigned IntNo =
Op.getConstantOperandVal(1);
752 if (IntNo == Intrinsic::hexagon_prefetch) {
770 assert(AlignConst &&
"Non-constant Align in LowerDYNAMIC_STACKALLOC");
776 A = HFI.getStackAlign().value();
779 dbgs () << __func__ <<
" Align: " <<
A <<
" Size: ";
780 Size.getNode()->dump(&DAG);
805 HexagonCCState CCInfo(CallConv, TreatAsVarArg, MF, ArgLocs,
810 CCInfo.AnalyzeFormalArguments(Ins, CC_Hexagon_HVX);
812 CCInfo.AnalyzeFormalArguments(Ins, CC_Hexagon_Legacy);
814 CCInfo.AnalyzeFormalArguments(Ins, CC_Hexagon);
823 switch (RC.
getID()) {
824 case Hexagon::IntRegsRegClassID:
825 return Reg - Hexagon::R0 + 1;
826 case Hexagon::DoubleRegsRegClassID:
827 return (Reg - Hexagon::D0 + 1) * 2;
828 case Hexagon::HvxVRRegClassID:
829 return Reg - Hexagon::V0 + 1;
830 case Hexagon::HvxWRRegClassID:
831 return (Reg - Hexagon::W0 + 1) * 2;
838 HFL.FirstVarArgSavedReg = 0;
841 for (
unsigned i = 0, e = ArgLocs.
size(); i != e; ++i) {
844 bool ByVal = Flags.isByVal();
850 if (VA.
isRegLoc() && ByVal && Flags.getByValSize() <= 8)
854 (!ByVal || (ByVal && Flags.getByValSize() > 8));
883 HFL.FirstVarArgSavedReg = NextSingleReg(*RC, VA.
getLocReg());
889 unsigned ObjSize = Flags.isByVal()
890 ? Flags.getByValSize()
898 if (Flags.isByVal()) {
912 for (
int i = HFL.FirstVarArgSavedReg; i < 6; i++)
913 MRI.addLiveIn(Hexagon::R0+i);
917 HMFI.setFirstNamedArgFrameIndex(HMFI.getFirstNamedArgFrameIndex() - 1);
921 int NumVarArgRegs = 6 - HFL.FirstVarArgSavedReg;
922 bool RequiresPadding = (NumVarArgRegs & 1);
923 int RegSaveAreaSizePlusPadding = RequiresPadding
924 ? (NumVarArgRegs + 1) * 4
927 if (RegSaveAreaSizePlusPadding > 0) {
930 if (!(RegAreaStart % 8))
931 RegAreaStart = (RegAreaStart + 7) & -8;
933 int RegSaveAreaFrameIndex =
935 HMFI.setRegSavedAreaStartFrameIndex(RegSaveAreaFrameIndex);
938 int Offset = RegAreaStart + RegSaveAreaSizePlusPadding;
940 HMFI.setVarArgsFrameIndex(FI);
946 HMFI.setRegSavedAreaStartFrameIndex(FI);
947 HMFI.setVarArgsFrameIndex(FI);
956 HMFI.setVarArgsFrameIndex(FI);
969 const Value *SV = cast<SrcValueSDNode>(
Op.getOperand(2))->getValue();
989 SDValue SavedRegAreaStartFrameIndex =
990 DAG.
getFrameIndex(FuncInfo.getRegSavedAreaStartFrameIndex(), MVT::i32);
994 if (HFL.FirstVarArgSavedReg & 1)
995 SavedRegAreaStartFrameIndex =
1004 SavedRegAreaStartFrameIndex,
1036 const Value *DestSV = cast<SrcValueSDNode>(
Op.getOperand(3))->getValue();
1037 const Value *SrcSV = cast<SrcValueSDNode>(
Op.getOperand(4))->getValue();
1043 false,
false,
nullptr, std::nullopt,
1055 if (OpTy == MVT::v2i16 || OpTy == MVT::v4i8) {
1072 auto isSExtFree = [
this](
SDValue N) {
1073 switch (
N.getOpcode()) {
1079 EVT OrigTy = cast<VTSDNode>(
Op.getOperand(1))->getVT();
1085 return ThisBW >= OrigBW;
1094 if (OpTy == MVT::i8 || OpTy == MVT::i16) {
1096 bool IsNegative =
C &&
C->getAPIntValue().isNegative();
1097 if (IsNegative || isSExtFree(
LHS) || isSExtFree(
RHS))
1109 SDValue Op1 =
Op.getOperand(1), Op2 =
Op.getOperand(2);
1113 if (OpTy == MVT::v2i16 || OpTy == MVT::v4i8) {
1131 EVT ValTy =
Op.getValueType();
1134 bool isVTi1Type =
false;
1135 if (
auto *CV = dyn_cast<ConstantVector>(CPN->
getConstVal())) {
1136 if (cast<VectorType>(CV->getType())->getElementType()->isIntegerTy(1)) {
1139 unsigned VecLen = CV->getNumOperands();
1141 "conversion only supported for pow2 VectorSize");
1142 for (
unsigned i = 0; i < VecLen; ++i)
1158 else if (isVTi1Type)
1164 assert(cast<ConstantPoolSDNode>(
T)->getTargetFlags() == TF &&
1165 "Inconsistent target flag encountered");
1167 if (IsPositionIndependent)
1174 EVT VT =
Op.getValueType();
1175 int Idx = cast<JumpTableSDNode>(
Op)->getIndex();
1195 EVT VT =
Op.getValueType();
1197 unsigned Depth =
Op.getConstantOperandVal(0);
1217 EVT VT =
Op.getValueType();
1219 unsigned Depth =
Op.getConstantOperandVal(0);
1237 auto *GAN = cast<GlobalAddressSDNode>(
Op);
1239 auto *GV = GAN->getGlobal();
1240 int64_t
Offset = GAN->getOffset();
1248 if (GO && Subtarget.
useSmallData() && HLOF.isGlobalInSmallSection(GO, HTM))
1270 const BlockAddress *BA = cast<BlockAddressSDNode>(
Op)->getBlockAddress();
1296 unsigned char OperandFlags)
const {
1315 assert(Mask &&
"Missing call preserved mask for calling convention");
1350 if (IsPositionIndependent) {
1422 Hexagon::R0, Flags);
1559 for (
unsigned LegalIntOp :
1599 for (
unsigned IntExpOp :
1608 for (
unsigned FPExpOp :
1644 static const unsigned VectExpOps[] = {
1670 for (
unsigned VectExpOp : VectExpOps)
1684 if (VT.getVectorElementType() != MVT::i32) {
1708 for (
MVT NativeVT : {MVT::v8i1, MVT::v4i1, MVT::v2i1, MVT::v4i8,
1709 MVT::v8i8, MVT::v2i16, MVT::v4i16, MVT::v2i32}) {
1724 if (NativeVT.getVectorElementType() != MVT::i1) {
1731 for (
MVT VT : {MVT::v8i8, MVT::v4i16, MVT::v2i32}) {
1742 for (
MVT VT : {MVT::i16, MVT::i32, MVT::v4i8, MVT::i64, MVT::v8i8,
1743 MVT::v2i16, MVT::v4i16, MVT::v2i32}) {
1749 for (
MVT VT : {MVT::v2i1, MVT::v4i1, MVT::v8i1}) {
1755 for (
MVT VT : {MVT::v2i16, MVT::v4i8, MVT::v8i8, MVT::v2i32, MVT::v4i16,
1767 for (
MVT VT : {MVT::i1, MVT::v2i1, MVT::v4i1, MVT::v8i1}) {
1820 for (
MVT VT : {MVT::i8, MVT::i16, MVT::i32, MVT::i64, MVT::f32, MVT::f64,
1821 MVT::v2i16, MVT::v2i32, MVT::v4i8, MVT::v4i16, MVT::v8i8}) {
1849 initializeHVXLowering();
1869 setLibcallName(RTLIB::FPTOUINT_F32_I128,
"__hexagon_fixunssfti");
1870 setLibcallName(RTLIB::FPTOUINT_F64_I128,
"__hexagon_fixunsdfti");
1965HexagonTargetLowering::validateConstPtrAlignment(
SDValue Ptr,
Align NeedAlign,
1967 auto *CA = dyn_cast<ConstantSDNode>(
Ptr);
1970 unsigned Addr = CA->getZExtValue();
1973 if (HaveAlign >= NeedAlign)
1979 DiagnosticInfoMisalignedTrap(
StringRef M)
1985 return DI->
getKind() == DK_MisalignedTrap;
1993 <<
" has alignment " << HaveAlign.
value()
1994 <<
", but the memory access requires " << NeedAlign.
value();
1997 O <<
". The instruction has been replaced with a trap.";
2007 auto *
LS = cast<LSBaseSDNode>(
Op.getNode());
2008 assert(!
LS->isIndexed() &&
"Not expecting indexed ops on constant address");
2020 unsigned ID = cast<IntrinsicInst>(Inst)->getIntrinsicID();
2021 return (
ID == Intrinsic::hexagon_L2_loadrd_pbr ||
2022 ID == Intrinsic::hexagon_L2_loadri_pbr ||
2023 ID == Intrinsic::hexagon_L2_loadrh_pbr ||
2024 ID == Intrinsic::hexagon_L2_loadruh_pbr ||
2025 ID == Intrinsic::hexagon_L2_loadrb_pbr ||
2026 ID == Intrinsic::hexagon_L2_loadrub_pbr);
2035 V = cast<Operator>(V)->getOperand(0);
2037 V = cast<Instruction>(V)->getOperand(0);
2050 if (Blk == Parent) {
2055 BaseVal = BackEdgeVal;
2057 }
while ((BaseVal != BackEdgeVal) && (IntrBaseVal != BackEdgeVal));
2060 if (IntrBaseVal == BackEdgeVal)
2067 assert(
Idx >= 0 &&
"Unexpected index to incoming argument in PHI");
2075 Value *IntrBaseVal = V;
2082 }
while (BaseVal != V);
2085 if (
const PHINode *PN = dyn_cast<PHINode>(V))
2099 unsigned Intrinsic)
const {
2100 switch (Intrinsic) {
2101 case Intrinsic::hexagon_L2_loadrd_pbr:
2102 case Intrinsic::hexagon_L2_loadri_pbr:
2103 case Intrinsic::hexagon_L2_loadrh_pbr:
2104 case Intrinsic::hexagon_L2_loadruh_pbr:
2105 case Intrinsic::hexagon_L2_loadrb_pbr:
2106 case Intrinsic::hexagon_L2_loadrub_pbr: {
2108 auto &
DL =
I.getDataLayout();
2109 auto &Cont =
I.getCalledFunction()->getParent()->getContext();
2113 Type *ElTy =
I.getCalledFunction()->getReturnType()->getStructElementType(0);
2120 Info.align =
DL.getABITypeAlign(
Info.memVT.getTypeForEVT(Cont));
2124 case Intrinsic::hexagon_V6_vgathermw:
2125 case Intrinsic::hexagon_V6_vgathermw_128B:
2126 case Intrinsic::hexagon_V6_vgathermh:
2127 case Intrinsic::hexagon_V6_vgathermh_128B:
2128 case Intrinsic::hexagon_V6_vgathermhw:
2129 case Intrinsic::hexagon_V6_vgathermhw_128B:
2130 case Intrinsic::hexagon_V6_vgathermwq:
2131 case Intrinsic::hexagon_V6_vgathermwq_128B:
2132 case Intrinsic::hexagon_V6_vgathermhq:
2133 case Intrinsic::hexagon_V6_vgathermhq_128B:
2134 case Intrinsic::hexagon_V6_vgathermhwq:
2135 case Intrinsic::hexagon_V6_vgathermhwq_128B: {
2136 const Module &M = *
I.getParent()->getParent()->getParent();
2138 Type *VecTy =
I.getArgOperand(1)->getType();
2140 Info.ptrVal =
I.getArgOperand(0);
2143 MaybeAlign(M.getDataLayout().getTypeAllocSizeInBits(VecTy) / 8);
2156 return X.getValueType().isScalarInteger();
2176 unsigned DefinedValues)
const {
2181 unsigned Index)
const {
2213 unsigned Action = getPreferredHvxVectorAction(VT);
2219 if (ElemTy == MVT::i1)
2233 unsigned Action = getCustomHvxOperationAction(
Op);
2240std::pair<SDValue, int>
2241HexagonTargetLowering::getBaseAndOffset(
SDValue Addr)
const {
2244 if (
auto *CN = dyn_cast<const ConstantSDNode>(Op1.
getNode()))
2245 return {
Addr.getOperand(0), CN->getSExtValue() };
2255 const auto *SVN = cast<ShuffleVectorSDNode>(
Op);
2257 assert(AM.
size() <= 8 &&
"Unexpected shuffle mask");
2258 unsigned VecLen = AM.
size();
2262 "HVX shuffles should be legal");
2272 if (ty(Op0) != VecTy || ty(Op1) != VecTy)
2281 if (AM[
F] >=
int(VecLen)) {
2289 for (
int M : Mask) {
2291 for (
unsigned j = 0; j != ElemBytes; ++j)
2294 for (
unsigned j = 0; j != ElemBytes; ++j)
2307 for (
unsigned i = 0, e = ByteMask.
size(); i != e; ++i) {
2315 if (ByteMask.
size() == 4) {
2317 if (MaskIdx == (0x03020100 | MaskUnd))
2320 if (MaskIdx == (0x00010203 | MaskUnd)) {
2328 getCombine(Op1, Op0, dl, typeJoin({ty(Op1), ty(Op0)}), DAG);
2329 if (MaskIdx == (0x06040200 | MaskUnd))
2330 return getInstr(Hexagon::S2_vtrunehb, dl, VecTy, {Concat10}, DAG);
2331 if (MaskIdx == (0x07050301 | MaskUnd))
2332 return getInstr(Hexagon::S2_vtrunohb, dl, VecTy, {Concat10}, DAG);
2335 getCombine(Op0, Op1, dl, typeJoin({ty(Op0), ty(Op1)}), DAG);
2336 if (MaskIdx == (0x02000604 | MaskUnd))
2337 return getInstr(Hexagon::S2_vtrunehb, dl, VecTy, {Concat01}, DAG);
2338 if (MaskIdx == (0x03010705 | MaskUnd))
2339 return getInstr(Hexagon::S2_vtrunohb, dl, VecTy, {Concat01}, DAG);
2342 if (ByteMask.
size() == 8) {
2344 if (MaskIdx == (0x0706050403020100ull | MaskUnd))
2347 if (MaskIdx == (0x0001020304050607ull | MaskUnd)) {
2354 if (MaskIdx == (0x0d0c050409080100ull | MaskUnd))
2355 return getInstr(Hexagon::S2_shuffeh, dl, VecTy, {Op1, Op0}, DAG);
2356 if (MaskIdx == (0x0f0e07060b0a0302ull | MaskUnd))
2357 return getInstr(Hexagon::S2_shuffoh, dl, VecTy, {Op1, Op0}, DAG);
2358 if (MaskIdx == (0x0d0c090805040100ull | MaskUnd))
2359 return getInstr(Hexagon::S2_vtrunewh, dl, VecTy, {Op1, Op0}, DAG);
2360 if (MaskIdx == (0x0f0e0b0a07060302ull | MaskUnd))
2361 return getInstr(Hexagon::S2_vtrunowh, dl, VecTy, {Op1, Op0}, DAG);
2362 if (MaskIdx == (0x0706030205040100ull | MaskUnd)) {
2363 VectorPair
P = opSplit(Op0, dl, DAG);
2364 return getInstr(Hexagon::S2_packhl, dl, VecTy, {
P.second,
P.first}, DAG);
2368 if (MaskIdx == (0x0e060c040a020800ull | MaskUnd))
2369 return getInstr(Hexagon::S2_shuffeb, dl, VecTy, {Op1, Op0}, DAG);
2370 if (MaskIdx == (0x0f070d050b030901ull | MaskUnd))
2371 return getInstr(Hexagon::S2_shuffob, dl, VecTy, {Op1, Op0}, DAG);
2379 switch (
Op.getOpcode()) {
2381 if (
SDValue S = cast<BuildVectorSDNode>(
Op)->getSplatValue())
2385 return Op.getOperand(0);
2395 switch (
Op.getOpcode()) {
2409 if (
SDValue Sp = getSplatValue(
Op.getOperand(1), DAG))
2422 if (
SDValue S = getVectorShiftByInt(
Op, DAG))
2436 MVT ResTy = ty(Res);
2444 auto ShiftPartI8 = [&dl, &DAG,
this](
unsigned Opc,
SDValue V,
SDValue A) {
2454 return ShiftPartI8(Opc, Val, Amt);
2456 auto [LoV, HiV] = opSplit(Val, dl, DAG);
2458 {ShiftPartI8(Opc, LoV, Amt), ShiftPartI8(Opc, HiV, Amt)});
2463 if (isa<ConstantSDNode>(
Op.getOperand(1).getNode()))
2472 MVT InpTy = ty(InpV);
2477 if (InpTy == MVT::i8) {
2478 if (ResTy == MVT::v8i1) {
2481 return getInstr(Hexagon::C2_tfrrp, dl, ResTy, Ext, DAG);
2496 bool AllConst =
true;
2498 for (
unsigned i = 0, e = Values.
size(); i != e; ++i) {
2501 Consts[i] = ConstantInt::get(IntTy, 0);
2505 if (
auto *CN = dyn_cast<ConstantSDNode>(V.getNode())) {
2506 const ConstantInt *CI = CN->getConstantIntValue();
2508 }
else if (
auto *CN = dyn_cast<ConstantFPSDNode>(
V.getNode())) {
2509 const ConstantFP *CF = CN->getConstantFPValue();
2511 Consts[i] = ConstantInt::get(IntTy,
A.getZExtValue());
2526 bool AllConst = getBuildVectorConstInts(Elem, VecTy, DAG, Consts);
2530 if (!isUndef(Elem[
First]))
2538 return getZero(dl, VecTy, DAG);
2540 if (ElemTy == MVT::i16 || ElemTy == MVT::f16) {
2545 uint32_t V = (Consts[0]->getZExtValue() & 0xFFFF) |
2546 Consts[1]->getZExtValue() << 16;
2550 if (ElemTy == MVT::f16) {
2557 SDValue N = getInstr(Hexagon::A2_combine_ll, dl, MVT::i32, {E1, E0}, DAG);
2561 if (ElemTy == MVT::i8) {
2564 int32_t
V = (Consts[0]->getZExtValue() & 0xFF) |
2565 (Consts[1]->getZExtValue() & 0xFF) << 8 |
2566 (Consts[2]->getZExtValue() & 0xFF) << 16 |
2567 Consts[3]->getZExtValue() << 24;
2572 bool IsSplat =
true;
2573 for (
unsigned i =
First+1; i != Num; ++i) {
2574 if (Elem[i] == Elem[
First] || isUndef(Elem[i]))
2590 for (
unsigned i = 0; i != 4; ++i) {
2600 SDValue R = getInstr(Hexagon::A2_combine_ll, dl, MVT::i32, {B1, B0}, DAG);
2605 dbgs() <<
"VecTy: " << VecTy <<
'\n';
2617 bool AllConst = getBuildVectorConstInts(Elem, VecTy, DAG, Consts);
2621 if (!isUndef(Elem[
First]))
2629 return getZero(dl, VecTy, DAG);
2632 if (ElemTy == MVT::i16 || ElemTy == MVT::f16) {
2633 bool IsSplat =
true;
2634 for (
unsigned i =
First+1; i != Num; ++i) {
2635 if (Elem[i] == Elem[
First] || isUndef(Elem[i]))
2654 for (
unsigned i = 0; i != Num; ++i)
2655 Val = (Val << W) | (Consts[Num-1-i]->getZExtValue() &
Mask);
2664 : buildVector32(Elem.
take_front(Num/2), dl, HalfTy, DAG);
2667 : buildVector32(Elem.
drop_front(Num/2), dl, HalfTy, DAG);
2668 return getCombine(
H, L, dl, VecTy, DAG);
2675 MVT VecTy = ty(VecV);
2679 return extractVectorPred(VecV, IdxV, dl, ValTy, ResTy, DAG);
2684 assert((VecWidth % ElemWidth) == 0);
2685 assert(VecWidth == 32 || VecWidth == 64);
2688 MVT ScalarTy = tyScalar(VecTy);
2694 if (
auto *IdxN = dyn_cast<ConstantSDNode>(IdxV)) {
2695 unsigned Off = IdxN->getZExtValue() * ElemWidth;
2696 if (VecWidth == 64 && ValWidth == 32) {
2697 assert(Off == 0 || Off == 32);
2698 ExtV =
Off == 0 ? LoHalf(VecV, DAG) : HiHalf(VecV, DAG);
2699 }
else if (Off == 0 && (ValWidth % 8) == 0) {
2706 {VecV, WidthV, OffV});
2709 if (ty(IdxV) != MVT::i32)
2714 {VecV, WidthV, OffV});
2724HexagonTargetLowering::extractVectorPred(
SDValue VecV,
SDValue IdxV,
2729 MVT VecTy = ty(VecV);
2733 "Vector elements should equal vector width size");
2734 assert(VecWidth == 8 || VecWidth == 4 || VecWidth == 2);
2745 if (ValWidth == 1) {
2746 SDValue A0 = getInstr(Hexagon::C2_tfrpr, dl, MVT::i32, {VecV}, DAG);
2756 unsigned Scale = VecWidth / ValWidth;
2760 assert(ty(IdxV) == MVT::i32);
2761 unsigned VecRep = 8 / VecWidth;
2769 T1 = LoHalf(T1, DAG);
2770 T1 = expandPredicate(T1, dl, DAG);
2781 MVT VecTy = ty(VecV);
2783 return insertVectorPred(VecV, ValV, IdxV, dl, ValTy, DAG);
2787 assert(VecWidth == 32 || VecWidth == 64);
2788 assert((VecWidth % ValWidth) == 0);
2804 unsigned W =
C->getZExtValue() * ValWidth;
2807 {VecV, ValV, WidthV, OffV});
2809 if (ty(IdxV) != MVT::i32)
2813 {VecV, ValV, WidthV, OffV});
2820HexagonTargetLowering::insertVectorPred(
SDValue VecV,
SDValue ValV,
2823 MVT VecTy = ty(VecV);
2826 if (ValTy == MVT::i1) {
2827 SDValue ToReg = getInstr(Hexagon::C2_tfrpr, dl, MVT::i32, {VecV}, DAG);
2833 return getInstr(Hexagon::C2_tfrrp, dl, VecTy, {
Ins}, DAG);
2844 for (
unsigned R = Scale;
R > 1;
R /= 2) {
2845 ValR = contractPredicate(ValR, dl, DAG);
2846 ValR = getCombine(DAG.
getUNDEF(MVT::i32), ValR, dl, MVT::i64, DAG);
2858HexagonTargetLowering::expandPredicate(
SDValue Vec32,
const SDLoc &dl,
2860 assert(ty(Vec32).getSizeInBits() == 32);
2869HexagonTargetLowering::contractPredicate(
SDValue Vec64,
const SDLoc &dl,
2871 assert(ty(Vec64).getSizeInBits() == 64);
2877 {0, 2, 4, 6, 1, 3, 5, 7});
2878 return extractVector(S, DAG.
getConstant(0, dl, MVT::i32), dl, MVT::v4i8,
2902 MVT ValTy = ty(Val);
2907 if (ValLen == ResLen)
2910 const SDLoc &dl(Val);
2912 assert(ResLen % ValLen == 0);
2915 for (
unsigned i = 1, e = ResLen / ValLen; i <
e; ++i)
2924 MVT ElemTy = ty(
Hi);
2953 return buildVector32(Ops, dl, VecTy, DAG);
2955 return buildVector64(Ops, dl, VecTy, DAG);
2957 if (VecTy == MVT::v8i1 || VecTy == MVT::v4i1 || VecTy == MVT::v2i1) {
2959 bool All0 =
true, All1 =
true;
2961 auto *CN = dyn_cast<ConstantSDNode>(
P.getNode());
2962 if (CN ==
nullptr) {
2963 All0 = All1 =
false;
2979 SDValue Z = getZero(dl, MVT::i32, DAG);
2982 for (
unsigned i = 0; i != 8; ++i) {
2984 Rs[i] = DAG.
getSelect(dl, MVT::i32, Ops[i/Rep], S, Z);
2987 for (
unsigned i = 0, e =
A.size()/2; i != e; ++i)
2991 return getInstr(Hexagon::C2_tfrrp, dl, VecTy, {Rs[0]}, DAG);
3004 return getCombine(
Op.getOperand(1),
Op.getOperand(0), dl, VecTy, DAG);
3008 if (ElemTy == MVT::i1) {
3009 assert(VecTy == MVT::v2i1 || VecTy == MVT::v4i1 || VecTy == MVT::v8i1);
3010 MVT OpTy = ty(
Op.getOperand(0));
3023 for (
SDValue P :
Op.getNode()->op_values()) {
3025 for (
unsigned R = Scale; R > 1; R /= 2) {
3026 W = contractPredicate(W, dl, DAG);
3027 W = getCombine(DAG.
getUNDEF(MVT::i32), W, dl, MVT::i64, DAG);
3035 Words[IdxW ^ 1].
clear();
3037 for (
unsigned i = 0, e = Words[IdxW].
size(); i != e; i += 2) {
3038 SDValue W0 = Words[IdxW][i], W1 = Words[IdxW][i+1];
3041 {W0, W1, WidthV, WidthV});
3049 assert(Scale == 2 && Words[IdxW].
size() == 2);
3051 SDValue WW = getCombine(Words[IdxW][1], Words[IdxW][0], dl, MVT::i64, DAG);
3063 return extractVector(Vec,
Op.getOperand(1),
SDLoc(
Op), ElemTy, ty(
Op), DAG);
3069 return extractVector(
Op.getOperand(0),
Op.getOperand(1),
SDLoc(
Op),
3070 ty(
Op), ty(
Op), DAG);
3076 return insertVector(
Op.getOperand(0),
Op.getOperand(1),
Op.getOperand(2),
3084 return insertVector(
Op.getOperand(0), ValV,
Op.getOperand(2),
3109 bool LoadPred = MemTy == MVT::v2i1 || MemTy == MVT::v4i1 || MemTy == MVT::v8i1;
3116 LN = cast<LoadSDNode>(
NL.getNode());
3120 if (!validateConstPtrAlignment(LN->
getBasePtr(), ClaimAlign, dl, DAG))
3121 return replaceMemWithUndef(
Op, DAG);
3127 SDValue TP = getInstr(Hexagon::C2_tfrrp, dl, MemTy, {LU}, DAG);
3146 if (Ty == MVT::v2i1 || Ty == MVT::v4i1 || Ty == MVT::v8i1) {
3148 SDValue TR = getInstr(Hexagon::C2_tfrpr, dl, MVT::i32, {Val}, DAG);
3155 SN = cast<StoreSDNode>(NS.getNode());
3159 if (!validateConstPtrAlignment(SN->
getBasePtr(), ClaimAlign, dl, DAG))
3160 return replaceMemWithUndef(
Op, DAG);
3164 if (ClaimAlign < NeedAlign)
3173 MVT LoadTy = ty(
Op);
3176 if (HaveAlign >= NeedAlign)
3185 bool DoDefault =
false;
3196 if (!DoDefault && (2 * HaveAlign) == NeedAlign) {
3215 unsigned LoadLen = NeedAlign;
3218 auto BO = getBaseAndOffset(
Base);
3219 unsigned BaseOpc = BO.first.getOpcode();
3223 if (BO.second % LoadLen != 0) {
3225 DAG.
getConstant(BO.second % LoadLen, dl, MVT::i32));
3226 BO.second -= BO.second % LoadLen;
3241 MMO->getPointerInfo(), MMO->getFlags(), 2 * LoadLen,
Align(LoadLen),
3242 MMO->getAAInfo(), MMO->getRanges(), MMO->getSyncScopeID(),
3243 MMO->getSuccessOrdering(), MMO->getFailureOrdering());
3260 auto *CY = dyn_cast<ConstantSDNode>(
Y);
3268 unsigned Opc =
Op.getOpcode();
3272 assert(VY != 0 &&
"This should have been folded");
3297 unsigned Opc =
Op.getOpcode();
3304 EVT CarryTy =
C.getValueType();
3306 { X, Y, DAG.getLogicalNOT(dl, C, CarryTy) });
3325 unsigned OffsetReg = Hexagon::R28;
3341 unsigned Opc =
Op.getOpcode();
3347 if (isHvxOperation(
Op.getNode(), DAG)) {
3349 if (
SDValue V = LowerHvxOperation(
Op, DAG))
3356 Op.getNode()->dumpr(&DAG);
3358 errs() <<
"Error: check for a non-legal type in this operation\n";
3412 if (isHvxOperation(
N, DAG)) {
3413 LowerHvxOperationWrapper(
N,
Results, DAG);
3419 unsigned Opc =
N->getOpcode();
3443 if (isHvxOperation(
N, DAG)) {
3444 ReplaceHvxNodeResults(
N,
Results, DAG);
3450 switch (
N->getOpcode()) {
3457 if (
N->getValueType(0) == MVT::i8) {
3458 if (
N->getOperand(0).getValueType() == MVT::v8i1) {
3459 SDValue P = getInstr(Hexagon::C2_tfrpr, dl, MVT::i32,
3460 N->getOperand(0), DAG);
3472 if (isHvxOperation(
N, DCI.
DAG)) {
3473 if (
SDValue V = PerformHvxDAGCombine(
N, DCI))
3480 unsigned Opc =
Op.getOpcode();
3486 EVT TruncTy =
Op.getValueType();
3502 switch (
P.getOpcode()) {
3506 return getZero(dl, ty(
Op), DCI.
DAG);
3519 Op.getOperand(2),
Op.getOperand(1));
3527 MVT TruncTy = ty(
Op);
3530 if (ty(Elem0) == TruncTy)
3533 if (ty(Elem0).bitsGT(TruncTy))
3540 if (ty(
Op) != MVT::i64)
3551 auto *Amt = dyn_cast<ConstantSDNode>(Shl.
getOperand(1));
3552 if (Amt && Amt->getZExtValue() >= 32 && ty(Z).getSizeInBits() <= 32) {
3553 unsigned A = Amt->getZExtValue();
3575 int Idx = cast<JumpTableSDNode>(Table)->getIndex();
3587 if (Constraint.
size() == 1) {
3588 switch (Constraint[0]) {
3603std::pair<unsigned, const TargetRegisterClass*>
3607 if (Constraint.
size() == 1) {
3608 switch (Constraint[0]) {
3612 return {0u,
nullptr};
3618 return {0u, &Hexagon::IntRegsRegClass};
3621 return {0u, &Hexagon::DoubleRegsRegClass};
3626 return {0u,
nullptr};
3627 return {0u, &Hexagon::ModRegsRegClass};
3631 return {0u,
nullptr};
3634 return {0u, &Hexagon::HvxQRRegClass};
3640 return {0u,
nullptr};
3642 return {0u, &Hexagon::HvxVRRegClass};
3645 return {0u, &Hexagon::HvxVRRegClass};
3646 return {0u, &Hexagon::HvxWRRegClass};
3648 return {0u, &Hexagon::HvxWRRegClass};
3652 return {0u,
nullptr};
3663 bool ForCodeSize)
const {
3693 int Scale = AM.
Scale;
3717 return Imm >= -512 && Imm <= 511;
3727 bool IsCalleeStructRet,
3728 bool IsCallerStructRet,
3735 bool CCMatch = CallerCC == CalleeCC;
3743 if (!isa<GlobalAddressSDNode>(Callee) &&
3744 !isa<ExternalSymbolSDNode>(Callee)) {
3764 if (IsCalleeStructRet || IsCallerStructRet)
3787 if (
Op.size() >= 8 &&
Op.isAligned(
Align(8)))
3789 if (
Op.size() >= 4 &&
Op.isAligned(
Align(4)))
3791 if (
Op.size() >= 2 &&
Op.isAligned(
Align(2)))
3801 return allowsHvxMemoryAccess(SVT, Flags,
Fast);
3803 Context,
DL, VT, AddrSpace, Alignment, Flags,
Fast);
3808 unsigned *
Fast)
const {
3811 return allowsHvxMisalignedMemoryAccesses(SVT, Flags,
Fast);
3817std::pair<const TargetRegisterClass*, uint8_t>
3825 return std::make_pair(&Hexagon::HvxQRRegClass, 1);
3827 return std::make_pair(&Hexagon::HvxVRRegClass, 1);
3829 return std::make_pair(&Hexagon::HvxWRRegClass, 1);
3841 auto *L = cast<LoadSDNode>(Load);
3842 std::pair<SDValue,int> BO = getBaseAndOffset(L->getBasePtr());
3848 const auto *GO = dyn_cast_or_null<const GlobalObject>(GA->getGlobal());
3856 AdjustHvxInstrPostInstrSelection(
MI, Node);
3865 assert((SZ == 32 || SZ == 64) &&
"Only 32/64-bit atomic loads supported");
3866 Intrinsic::ID IntID = (SZ == 32) ? Intrinsic::hexagon_L2_loadw_locked
3867 : Intrinsic::hexagon_L4_loadd_locked;
3886 assert((SZ == 32 || SZ == 64) &&
"Only 32/64-bit atomic stores supported");
3887 Intrinsic::ID IntID = (SZ == 32) ? Intrinsic::hexagon_S2_storew_locked
3888 : Intrinsic::hexagon_S4_stored_locked;
3910 return SI->getValueOperand()->getType()->getPrimitiveSizeInBits() > 64
unsigned const MachineRegisterInfo * MRI
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis Results
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Analysis containing CSE Info
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
static cl::opt< int > MaxStoresPerMemcpyCL("max-store-memcpy", cl::Hidden, cl::init(6), cl::desc("Max #stores to inline memcpy"))
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 cl::opt< int > MaxStoresPerMemmoveOptSizeCL("max-store-memmove-Os", cl::Hidden, cl::init(4), cl::desc("Max #stores to inline memmove"))
static cl::opt< int > MaxStoresPerMemmoveCL("max-store-memmove", cl::Hidden, cl::init(6), cl::desc("Max #stores to inline memmove"))
static Value * getBrevLdObject(Value *V)
static cl::opt< int > MaxStoresPerMemsetCL("max-store-memset", cl::Hidden, cl::init(8), cl::desc("Max #stores to inline memset"))
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 cl::opt< int > MaxStoresPerMemcpyOptSizeCL("max-store-memcpy-Os", cl::Hidden, cl::init(4), cl::desc("Max #stores to inline memcpy"))
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< int > MaxStoresPerMemsetOptSizeCL("max-store-memset-Os", cl::Hidden, cl::init(4), cl::desc("Max #stores to inline memset"))
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"))
static cl::opt< bool > EnableFastMath("ffast-math", cl::Hidden, cl::desc("Enable Fast Math processing"))
#define Hexagon_PointerSize
#define HEXAGON_LRFP_SIZE
#define HEXAGON_GOT_SYM_NAME
std::pair< MCSymbol *, MachineModuleInfoImpl::StubValueTy > PairTy
unsigned const TargetRegisterInfo * TRI
Module.h This file contains the declarations for the Module class.
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
const char LLVMTargetMachineRef TM
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
APInt bitcastToAPInt() const
Class for arbitrary precision integers.
int64_t getSExtValue() const
Get sign extended value.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
ArrayRef< T > take_front(size_t N=1) const
Return a copy of *this with only the first N elements.
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
size_t size() const
size - Get the array size.
An instruction that atomically checks whether a specified value is in a memory location,...
LLVM Basic Block Representation.
const Function * getParent() const
Return the enclosing method, or null if none.
The address of a basic block.
CCState - This class holds information needed while lowering arguments and return values.
unsigned getFirstUnallocated(ArrayRef< MCPhysReg > Regs) const
getFirstUnallocated - Return the index of the first unallocated register in the set,...
void AnalyzeCallResult(const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn Fn)
AnalyzeCallResult - Analyze the return values of a call, incorporating info about the passed values i...
MCRegister AllocateReg(MCPhysReg Reg)
AllocateReg - Attempt to allocate one register.
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 ...
void AnalyzeReturn(const SmallVectorImpl< ISD::OutputArg > &Outs, CCAssignFn Fn)
AnalyzeReturn - Analyze the returned values of a return, incorporating info about the result values i...
CCValAssign - Represent assignment of one arg/retval to a location.
Register getLocReg() const
LocInfo getLocInfo() const
int64_t getLocMemOffset() const
FunctionType * getFunctionType() const
This class represents a function call, abstracting a target machine's calling convention.
ConstantFP - Floating Point Values [float, double].
const APFloat & getValueAPF() const
This is the shared class of boolean and integer constants.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
const APInt & getValue() const
Return the constant as an APInt value reference.
MachineConstantPoolValue * getMachineCPVal() const
bool isMachineConstantPoolEntry() const
const Constant * getConstVal() const
int64_t getSExtValue() const
static Constant * get(ArrayRef< Constant * > V)
This is an important base class in LLVM.
This class represents an Operation in the Expression.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
This is the base abstract class for diagnostic reporting in the backend.
Interface for custom diagnostic printing.
unsigned getNumParams() const
Return the number of fixed parameters this function type requires.
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
FunctionType * getFunctionType() const
Returns the FunctionType for me.
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
bool hasStructRetAttr() const
Determine if the function returns a structure through first or second pointer argument.
int64_t getOffset() const
const GlobalValue * getGlobal() const
Module * getParent()
Get the module that this global value is contained inside of...
const GlobalObject * getAliaseeObject() const
bool isValidAutoIncImm(const EVT VT, const int Offset) const
Hexagon target-specific information for each MachineFunction.
int getVarArgsFrameIndex()
void setFirstNamedArgFrameIndex(int v)
void setHasEHReturn(bool H=true)
Register getStackRegister() const
Register getFrameRegister(const MachineFunction &MF) const override
const uint32_t * getCallPreservedMask(const MachineFunction &MF, CallingConv::ID) const override
const HexagonInstrInfo * getInstrInfo() const override
const HexagonFrameLowering * getFrameLowering() const override
bool useSmallData() const