179 if (!
Subtarget.supportsMultiplication()) {
216 EVT VT =
Op.getValueType();
219 "Expected power-of-2 shift amount");
227 SDVTList ResTys = DAG.
getVTList(MVT::i16, MVT::i16);
234 uint64_t ShiftAmount =
N->getConstantOperandVal(1);
235 if (ShiftAmount == 16) {
240 switch (
Op.getOpcode()) {
253 switch (
Op.getOpcode()) {
273 switch (
Op.getOpcode()) {
277 return DAG.
getNode(AVRISD::LSLLOOP, dl, VT,
N->getOperand(0),
280 return DAG.
getNode(AVRISD::LSRLOOP, dl, VT,
N->getOperand(0),
283 SDValue Amt =
N->getOperand(1);
284 EVT AmtVT = Amt.getValueType();
287 return DAG.
getNode(AVRISD::ROLLOOP, dl, VT,
N->getOperand(0), Amt);
290 SDValue Amt =
N->getOperand(1);
291 EVT AmtVT = Amt.getValueType();
294 return DAG.
getNode(AVRISD::RORLOOP, dl, VT,
N->getOperand(0), Amt);
297 return DAG.
getNode(AVRISD::ASRLOOP, dl, VT,
N->getOperand(0),
302 uint64_t ShiftAmount =
N->getConstantOperandVal(1);
303 SDValue Victim =
N->getOperand(0);
305 switch (
Op.getOpcode()) {
329 if (
Op.getOpcode() ==
ISD::SHL && 4 <= ShiftAmount && ShiftAmount < 7) {
331 Victim = DAG.
getNode(AVRISD::SWAP, dl, VT, Victim);
335 }
else if (
Op.getOpcode() ==
ISD::SRL && 4 <= ShiftAmount &&
338 Victim = DAG.
getNode(AVRISD::SWAP, dl, VT, Victim);
342 }
else if (
Op.getOpcode() ==
ISD::SHL && ShiftAmount == 7) {
344 Victim = DAG.
getNode(AVRISD::LSLBN, dl, VT, Victim,
347 }
else if (
Op.getOpcode() ==
ISD::SRL && ShiftAmount == 7) {
349 Victim = DAG.
getNode(AVRISD::LSRBN, dl, VT, Victim,
352 }
else if (
Op.getOpcode() ==
ISD::SRA && ShiftAmount == 6) {
354 Victim = DAG.
getNode(AVRISD::ASRBN, dl, VT, Victim,
357 }
else if (
Op.getOpcode() ==
ISD::SRA && ShiftAmount == 7) {
359 Victim = DAG.
getNode(AVRISD::ASRBN, dl, VT, Victim,
362 }
else if (
Op.getOpcode() ==
ISD::ROTL && ShiftAmount == 3) {
364 Victim = DAG.
getNode(AVRISD::SWAP, dl, VT, Victim);
365 Victim = DAG.
getNode(AVRISD::ROR, dl, VT, Victim);
367 }
else if (
Op.getOpcode() ==
ISD::ROTR && ShiftAmount == 3) {
369 Victim = DAG.
getNode(AVRISD::SWAP, dl, VT, Victim);
370 Victim = DAG.
getNode(AVRISD::ROL, dl, VT, Victim);
372 }
else if (
Op.getOpcode() ==
ISD::ROTL && ShiftAmount == 7) {
374 Victim = DAG.
getNode(AVRISD::ROR, dl, VT, Victim);
376 }
else if (
Op.getOpcode() ==
ISD::ROTR && ShiftAmount == 7) {
378 Victim = DAG.
getNode(AVRISD::ROL, dl, VT, Victim);
383 Victim = DAG.
getNode(AVRISD::SWAP, dl, VT, Victim);
389 switch (ShiftAmount) {
391 Victim = DAG.
getNode(AVRISD::ASRWN, dl, VT, Victim,
396 Victim = DAG.
getNode(AVRISD::ASRWN, dl, VT, Victim,
401 Victim = DAG.
getNode(AVRISD::ASRWN, dl, VT, Victim,
408 if (4 <= ShiftAmount && ShiftAmount < 8)
409 switch (
Op.getOpcode()) {
411 Victim = DAG.
getNode(AVRISD::LSLWN, dl, VT, Victim,
416 Victim = DAG.
getNode(AVRISD::LSRWN, dl, VT, Victim,
423 else if (8 <= ShiftAmount && ShiftAmount < 12)
424 switch (
Op.getOpcode()) {
426 Victim = DAG.
getNode(AVRISD::LSLWN, dl, VT, Victim,
430 Opc8 = AVRISD::LSLHI;
433 Victim = DAG.
getNode(AVRISD::LSRWN, dl, VT, Victim,
437 Opc8 = AVRISD::LSRLO;
440 Victim = DAG.
getNode(AVRISD::ASRWN, dl, VT, Victim,
444 Opc8 = AVRISD::ASRLO;
449 else if (12 <= ShiftAmount)
450 switch (
Op.getOpcode()) {
452 Victim = DAG.
getNode(AVRISD::LSLWN, dl, VT, Victim,
456 Opc8 = AVRISD::LSLHI;
459 Victim = DAG.
getNode(AVRISD::LSRWN, dl, VT, Victim,
463 Opc8 = AVRISD::LSRLO;
466 Victim = DAG.
getNode(AVRISD::ASRWN, dl, VT, Victim,
470 Opc8 = AVRISD::ASRLO;
477 while (ShiftAmount--) {
478 Victim = DAG.
getNode(Opc8, dl, VT, Victim);
485 unsigned Opcode =
Op->getOpcode();
487 "Invalid opcode for Div/Rem lowering");
489 EVT VT =
Op->getValueType(0);
490 Type *Ty = VT.getTypeForEVT(*DAG.getContext());
493 switch (VT.getSimpleVT().SimpleTy) {
497 LC = IsSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
500 LC = IsSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
503 LC = IsSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
507 SDValue InChain = DAG.getEntryNode();
510 for (SDValue
const &
Value :
Op->op_values()) {
511 TargetLowering::ArgListEntry
Entry(
512 Value,
Value.getValueType().getTypeForEVT(*DAG.getContext()));
513 Entry.IsSExt = IsSigned;
514 Entry.IsZExt = !IsSigned;
515 Args.push_back(Entry);
518 RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
519 if (LCImpl == RTLIB::Unsupported)
523 DAG.getExternalSymbol(LCImpl,
getPointerTy(DAG.getDataLayout()));
528 TargetLowering::CallLoweringInfo CLI(DAG);
531 .setLibCallee(DAG.getLibcalls().getLibcallImplCallingConv(LCImpl), RetTy,
532 Callee, std::move(Args))
534 .setSExtResult(IsSigned)
535 .setZExtResult(!IsSigned);
537 std::pair<SDValue, SDValue> CallInfo =
LowerCallTo(CLI);
538 return CallInfo.first;
543 auto DL = DAG.getDataLayout();
556 auto DL = DAG.getDataLayout();
585SDValue AVRTargetLowering::getAVRCmp(SDValue
LHS, SDValue
RHS,
586 SelectionDAG &DAG, SDLoc
DL)
const {
587 assert((
LHS.getSimpleValueType() ==
RHS.getSimpleValueType()) &&
588 "LHS and RHS have different types");
589 assert(((
LHS.getSimpleValueType() == MVT::i16) ||
590 (
LHS.getSimpleValueType() == MVT::i8)) &&
591 "invalid comparison type");
600 DAG.getIntPtrConstant(0,
DL));
602 DAG.getIntPtrConstant(1,
DL));
603 SDValue RHSlo = (
Imm & 0xff) == 0
606 DAG.getIntPtrConstant(0,
DL));
607 SDValue RHShi = (
Imm & 0xff00) == 0
610 DAG.getIntPtrConstant(1,
DL));
611 Cmp = DAG.getNode(AVRISD::CMP,
DL, MVT::Glue, LHSlo, RHSlo);
612 Cmp = DAG.getNode(AVRISD::CMPC,
DL, MVT::Glue, LHShi, RHShi, Cmp);
617 SDValue LHSlo = (
Imm & 0xff) == 0
618 ? DAG.getRegister(
Subtarget.getZeroRegister(), MVT::i8)
620 DAG.getIntPtrConstant(0,
DL));
621 SDValue LHShi = (
Imm & 0xff00) == 0
622 ? DAG.getRegister(
Subtarget.getZeroRegister(), MVT::i8)
624 DAG.getIntPtrConstant(1,
DL));
626 DAG.getIntPtrConstant(0,
DL));
628 DAG.getIntPtrConstant(1,
DL));
629 Cmp = DAG.getNode(AVRISD::CMP,
DL, MVT::Glue, LHSlo, RHSlo);
630 Cmp = DAG.getNode(AVRISD::CMPC,
DL, MVT::Glue, LHShi, RHShi, Cmp);
633 Cmp = DAG.getNode(AVRISD::CMP,
DL, MVT::Glue,
LHS,
RHS);
645 EVT VT =
LHS.getValueType();
646 bool UseTest =
false;
659 switch (
C->getSExtValue()) {
671 LHS = DAG.getConstant(0,
DL, VT);
676 if (
C->getConstantIntValue()->isMaxValue(
true)) {
687 RHS = DAG.getSignedConstant(
C->getSExtValue() + 1,
DL, VT);
701 switch (
C->getSExtValue()) {
706 LHS = DAG.getConstant(0,
DL, VT);
731 if (
C->getConstantIntValue()->isMaxValue(
false)) {
735 RHS = DAG.getConstant(
C->getZExtValue() + 1,
DL, VT);
749 if (VT == MVT::i32) {
751 DAG.getIntPtrConstant(0,
DL));
753 DAG.getIntPtrConstant(1,
DL));
755 DAG.getIntPtrConstant(0,
DL));
757 DAG.getIntPtrConstant(1,
DL));
762 DAG.getIntPtrConstant(1,
DL));
763 Cmp = DAG.getNode(AVRISD::TST,
DL, MVT::Glue, Top);
765 Cmp = getAVRCmp(LHSlo, RHSlo, DAG,
DL);
766 Cmp = DAG.getNode(AVRISD::CMPC,
DL, MVT::Glue, LHShi, RHShi, Cmp);
768 }
else if (VT == MVT::i64) {
770 DAG.getIntPtrConstant(0,
DL));
772 DAG.getIntPtrConstant(1,
DL));
775 DAG.getIntPtrConstant(0,
DL));
777 DAG.getIntPtrConstant(1,
DL));
779 DAG.getIntPtrConstant(0,
DL));
781 DAG.getIntPtrConstant(1,
DL));
784 DAG.getIntPtrConstant(0,
DL));
786 DAG.getIntPtrConstant(1,
DL));
789 DAG.getIntPtrConstant(0,
DL));
791 DAG.getIntPtrConstant(1,
DL));
793 DAG.getIntPtrConstant(0,
DL));
795 DAG.getIntPtrConstant(1,
DL));
800 DAG.getIntPtrConstant(1,
DL));
801 Cmp = DAG.getNode(AVRISD::TST,
DL, MVT::Glue, Top);
803 Cmp = getAVRCmp(LHS0, RHS0, DAG,
DL);
804 Cmp = DAG.getNode(AVRISD::CMPC,
DL, MVT::Glue, LHS1, RHS1, Cmp);
805 Cmp = DAG.getNode(AVRISD::CMPC,
DL, MVT::Glue, LHS2, RHS2, Cmp);
806 Cmp = DAG.getNode(AVRISD::CMPC,
DL, MVT::Glue, LHS3, RHS3, Cmp);
808 }
else if (VT == MVT::i8 || VT == MVT::i16) {
811 Cmp = DAG.getNode(AVRISD::TST,
DL, MVT::Glue,
815 LHS, DAG.getIntPtrConstant(1,
DL)));
832 SDValue Chain =
Op.getOperand(0);
834 SDValue
LHS =
Op.getOperand(2);
835 SDValue
RHS =
Op.getOperand(3);
836 SDValue Dest =
Op.getOperand(4);
840 SDValue
Cmp = getAVRCmp(
LHS,
RHS, CC, TargetCC, DAG, dl);
842 return DAG.getNode(AVRISD::BRCOND, dl, MVT::Other, Chain, Dest, TargetCC,
847 SDValue
LHS =
Op.getOperand(0);
848 SDValue
RHS =
Op.getOperand(1);
849 SDValue TrueV =
Op.getOperand(2);
850 SDValue FalseV =
Op.getOperand(3);
855 SDValue
Cmp = getAVRCmp(
LHS,
RHS, CC, TargetCC, DAG, dl);
857 SDValue
Ops[] = {TrueV, FalseV, TargetCC,
Cmp};
859 return DAG.getNode(AVRISD::SELECT_CC, dl,
Op.getValueType(),
Ops);
863 SDValue
LHS =
Op.getOperand(0);
864 SDValue
RHS =
Op.getOperand(1);
869 SDValue
Cmp = getAVRCmp(
LHS,
RHS, CC, TargetCC, DAG,
DL);
871 SDValue TrueV = DAG.getConstant(1,
DL,
Op.getValueType());
872 SDValue FalseV = DAG.getConstant(0,
DL,
Op.getValueType());
873 SDValue
Ops[] = {TrueV, FalseV, TargetCC,
Cmp};
875 return DAG.getNode(AVRISD::SELECT_CC,
DL,
Op.getValueType(),
Ops);
880 const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
882 auto DL = DAG.getDataLayout();
887 SDValue FI = DAG.getFrameIndex(AFI->getVarArgsFrameIndex(),
getPointerTy(
DL));
889 return DAG.getStore(
Op.getOperand(0), dl, FI,
Op.getOperand(1),
890 MachinePointerInfo(SV));
895 SDValue ZeroReg = DAG.getRegister(
Subtarget.getZeroRegister(), MVT::i8);
911 SDNode *
N =
Op.getNode();
913 for (
unsigned I = 0;
I <
N->getNumOperands();
I++) {
914 SDValue Operand =
N->getOperand(
I);
915 if (Operand.getValueType() == MVT::Glue) {
920 Ops.push_back(Operand);
924 Ops.push_back(DAG.getTargetConstant(Flags, dl, MVT::i32));
925 Ops.push_back(ZeroReg);
932 SDValue
New = DAG.getNode(
N->getOpcode(), dl,
N->getVTList(),
Ops);
933 DAG.ReplaceAllUsesOfValueWith(
Op, New);
934 DAG.ReplaceAllUsesOfValueWith(
Op.getValue(1),
New.getValue(1));
940 switch (
Op.getOpcode()) {
948 return LowerShifts(
Op, DAG);
950 return LowerGlobalAddress(
Op, DAG);
952 return LowerBlockAddress(
Op, DAG);
954 return LowerBR_CC(
Op, DAG);
956 return LowerSELECT_CC(
Op, DAG);
958 return LowerSETCC(
Op, DAG);
960 return LowerVASTART(
Op, DAG);
963 return LowerDivRem(
Op, DAG);
965 return LowerINLINEASM(
Op, DAG);
967 return LowerFRAMEADDR(
Op, DAG);
969 return LowerRETURNADDR(
Op, DAG);
984 if (
Op.getConstantOperandVal(0) > 0)
1000SDValue AVRTargetLowering::LowerRETURNADDR(SDValue
Op,
1001 SelectionDAG &DAG)
const {
1016 if (
Op.getConstantOperandVal(0) > 0)
1022 MachineFrameInfo &MFI = MF.getFrameInfo();
1034 int PCWidth =
Subtarget.hasEIJMPCALL() ? 3 : 2;
1041 int FI = MFI.CreateFixedObject(2, PCWidth - 4,
true);
1042 SDValue Addr = DAG.getFrameIndex(FI, PtrVT);
1046 SDValue
Hi = DAG.getLoad(MVT::i8,
DL, DAG.getEntryNode(), Addr,
1049 DAG.getLoad(MVT::i8,
DL, DAG.getEntryNode(),
1053 SDValue Res = DAG.getTargetInsertSubreg(AVR::sub_lo,
DL, MVT::i16,
1054 DAG.getUNDEF(MVT::i16),
Lo);
1055 return DAG.getTargetInsertSubreg(AVR::sub_hi,
DL, MVT::i16, Res,
Hi);
1065 switch (
N->getOpcode()) {
1128 VT = LD->getMemoryVT();
1129 Op = LD->getBasePtr().getNode();
1136 VT = ST->getMemoryVT();
1137 Op = ST->getBasePtr().getNode();
1145 if (VT != MVT::i8 && VT != MVT::i16) {
1154 int RHSC =
RHS->getSExtValue();
1158 if ((VT == MVT::i16 && RHSC != -2) || (VT == MVT::i8 && RHSC != -1)) {
1162 Base =
Op->getOperand(0);
1185 VT = LD->getMemoryVT();
1186 Ptr = LD->getBasePtr();
1190 VT = ST->getMemoryVT();
1191 Ptr = ST->getBasePtr();
1199 if (VT == MVT::i16 && !
Subtarget.hasLowByteFirst())
1205 if (VT != MVT::i8 && VT != MVT::i16) {
1214 int RHSC =
RHS->getSExtValue();
1217 if ((VT == MVT::i16 && RHSC != 2) || (VT == MVT::i8 && RHSC != 1)) {
1227 Base =
Op->getOperand(0);
1252#define GET_CALLING_CONV_IMPL
1253#include "AVRGenCallingConv.inc"
1258 AVR::R25, AVR::R24, AVR::R23, AVR::R22, AVR::R21, AVR::R20,
1259 AVR::R19, AVR::R18, AVR::R17, AVR::R16, AVR::R15, AVR::R14,
1260 AVR::R13, AVR::R12, AVR::R11, AVR::R10, AVR::R9, AVR::R8};
1262 AVR::R22, AVR::R21, AVR::R20};
1264 AVR::R26R25, AVR::R25R24, AVR::R24R23, AVR::R23R22, AVR::R22R21,
1265 AVR::R21R20, AVR::R20R19, AVR::R19R18, AVR::R18R17, AVR::R17R16,
1266 AVR::R16R15, AVR::R15R14, AVR::R14R13, AVR::R13R12, AVR::R12R11,
1267 AVR::R11R10, AVR::R10R9, AVR::R9R8};
1269 AVR::R24R23, AVR::R23R22,
1270 AVR::R22R21, AVR::R21R20};
1273 "8-bit and 16-bit register arrays must be of equal length");
1275 "8-bit and 16-bit register arrays must be of equal length");
1281template <
typename ArgT>
1298 unsigned NumArgs = Args.size();
1301 int RegLastIdx = -1;
1303 bool UseStack =
false;
1304 for (
unsigned i = 0; i != NumArgs;) {
1305 MVT VT = Args[i].VT;
1310 unsigned ArgIndex = Args[i].OrigArgIndex;
1313 for (; j != NumArgs; ++j) {
1314 if (Args[j].OrigArgIndex != ArgIndex)
1316 TotalBytes += Args[j].VT.getStoreSize();
1319 TotalBytes =
alignTo(TotalBytes, 2);
1321 if (TotalBytes == 0)
1324 unsigned RegIdx = RegLastIdx + TotalBytes;
1325 RegLastIdx = RegIdx;
1327 if (RegIdx >= RegList8.
size()) {
1330 for (; i != j; ++i) {
1331 MVT VT = Args[i].VT;
1341 if (VT == MVT::i8) {
1343 }
else if (VT == MVT::i16) {
1347 "calling convention can only manage i8 and i16 types");
1349 assert(
Reg &&
"register not available in calling convention");
1360template <
typename ArgT>
1363 unsigned TotalBytes = 0;
1365 for (
const ArgT &Arg : Args) {
1366 TotalBytes += Arg.VT.getStoreSize();
1374template <
typename ArgT>
1377 unsigned NumArgs = Args.size();
1381 assert(TotalBytes <= 4 &&
1382 "return values greater than 4 bytes cannot be lowered on AVRTiny");
1384 assert(TotalBytes <= 8 &&
1385 "return values greater than 8 bytes cannot be lowered on AVR");
1400 if (TotalBytes > 4) {
1403 TotalBytes =
alignTo(TotalBytes, 2);
1407 int RegIdx = TotalBytes - 1;
1408 for (
unsigned i = 0; i != NumArgs; ++i) {
1409 MVT VT = Args[i].VT;
1411 if (VT == MVT::i8) {
1413 }
else if (VT == MVT::i16) {
1418 assert(
Reg &&
"register not available in calling convention");
1425SDValue AVRTargetLowering::LowerFormalArguments(
1427 const SmallVectorImpl<ISD::InputArg> &Ins,
const SDLoc &dl,
1428 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals)
const {
1430 MachineFrameInfo &MFI = MF.getFrameInfo();
1431 auto DL = DAG.getDataLayout();
1435 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
1440 CCInfo.AnalyzeFormalArguments(Ins, ArgCC_AVR_Vararg);
1447 for (CCValAssign &VA : ArgLocs) {
1450 if (VA.isRegLoc()) {
1451 EVT RegVT = VA.getLocVT();
1453 if (RegVT == MVT::i8) {
1454 RC = &AVR::GPR8RegClass;
1455 }
else if (RegVT == MVT::i16) {
1456 RC = &AVR::DREGSRegClass;
1462 ArgValue = DAG.getCopyFromReg(Chain, dl,
Reg, RegVT);
1470 switch (VA.getLocInfo()) {
1476 ArgValue = DAG.getNode(
ISD::BITCAST, dl, VA.getValVT(), ArgValue);
1480 DAG.getValueType(VA.getValVT()));
1481 ArgValue = DAG.getNode(
ISD::TRUNCATE, dl, VA.getValVT(), ArgValue);
1485 DAG.getValueType(VA.getValVT()));
1486 ArgValue = DAG.getNode(
ISD::TRUNCATE, dl, VA.getValVT(), ArgValue);
1490 InVals.push_back(ArgValue);
1495 EVT LocVT = VA.getLocVT();
1498 int FI = MFI.CreateFixedObject(LocVT.getSizeInBits() / 8,
1499 VA.getLocMemOffset(),
true);
1504 InVals.push_back(DAG.getLoad(LocVT, dl, Chain, FIN,
1512 unsigned StackSize = CCInfo.getStackSize();
1513 AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
1515 AFI->setVarArgsFrameIndex(MFI.CreateFixedObject(2, StackSize,
true));
1527 SelectionDAG &DAG = CLI.DAG;
1529 SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
1530 SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
1531 SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
1532 SDValue Chain = CLI.Chain;
1533 SDValue
Callee = CLI.Callee;
1534 bool &isTailCall = CLI.IsTailCall;
1536 bool isVarArg = CLI.IsVarArg;
1545 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
1553 const GlobalValue *GV =
G->getGlobal();
1557 DAG.getTargetGlobalAddress(GV,
DL,
getPointerTy(DAG.getDataLayout()));
1558 }
else if (
const ExternalSymbolSDNode *ES =
1560 Callee = DAG.getTargetExternalSymbol(ES->getSymbol(),
1566 CCInfo.AnalyzeCallOperands(Outs, ArgCC_AVR_Vararg);
1573 unsigned NumBytes = CCInfo.getStackSize();
1575 Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0,
DL);
1581 bool HasStackArgs =
false;
1582 for (AI = 0, AE = ArgLocs.size(); AI != AE; ++AI) {
1583 CCValAssign &VA = ArgLocs[AI];
1584 EVT RegVT = VA.getLocVT();
1585 SDValue Arg = OutVals[AI];
1588 switch (VA.getLocInfo()) {
1609 if (VA.isMemLoc()) {
1610 HasStackArgs =
true;
1616 RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
1627 for (; AI != AE; AI++) {
1628 CCValAssign &VA = ArgLocs[AI];
1629 SDValue Arg = OutVals[AI];
1634 SDValue PtrOff = DAG.getNode(
1636 DAG.getRegister(AVR::SP,
getPointerTy(DAG.getDataLayout())),
1637 DAG.getIntPtrConstant(VA.getLocMemOffset() + 1,
DL));
1639 MemOpChains.push_back(
1640 DAG.getStore(Chain,
DL, Arg, PtrOff,
1644 if (!MemOpChains.empty())
1652 for (
auto Reg : RegsToPass) {
1653 Chain = DAG.getCopyToReg(Chain,
DL,
Reg.first,
Reg.second, InGlue);
1654 InGlue = Chain.getValue(1);
1658 SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
1660 Ops.push_back(Chain);
1661 Ops.push_back(Callee);
1665 for (
auto Reg : RegsToPass) {
1666 Ops.push_back(DAG.getRegister(
Reg.first,
Reg.second.getValueType()));
1671 Ops.push_back(DAG.getRegister(
Subtarget.getZeroRegister(), MVT::i8));
1674 const TargetRegisterInfo *
TRI =
Subtarget.getRegisterInfo();
1675 const uint32_t *
Mask =
1676 TRI->getCallPreservedMask(DAG.getMachineFunction(), CallConv);
1677 assert(Mask &&
"Missing call preserved mask for calling convention");
1678 Ops.push_back(DAG.getRegisterMask(Mask));
1680 if (InGlue.getNode()) {
1681 Ops.push_back(InGlue);
1684 Chain = DAG.getNode(AVRISD::CALL,
DL, NodeTys,
Ops);
1685 InGlue = Chain.getValue(1);
1688 Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, InGlue,
DL);
1691 InGlue = Chain.getValue(1);
1696 return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins,
DL, DAG,
1703SDValue AVRTargetLowering::LowerCallResult(
1710 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
1715 CCInfo.AnalyzeCallResult(Ins, RetCC_AVR_BUILTIN);
1721 for (CCValAssign
const &RVLoc : RVLocs) {
1722 Chain = DAG.getCopyFromReg(Chain, dl, RVLoc.getLocReg(), RVLoc.getValVT(),
1725 InGlue = Chain.getValue(2);
1726 InVals.push_back(Chain.getValue(0));
1736bool AVRTargetLowering::CanLowerReturn(
1739 const Type *RetTy)
const {
1742 CCState CCInfo(CallConv, isVarArg, MF, RVLocs,
Context);
1743 return CCInfo.CheckReturn(Outs, RetCC_AVR_BUILTIN);
1747 return TotalBytes <= (unsigned)(
Subtarget.hasTinyEncoding() ? 4 : 8);
1760 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
1767 CCInfo.AnalyzeReturn(Outs, RetCC_AVR_BUILTIN);
1775 for (
unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
1776 CCValAssign &VA = RVLocs[i];
1777 assert(VA.isRegLoc() &&
"Can only return in registers!");
1779 Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Glue);
1782 Glue = Chain.getValue(1);
1783 RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
1788 if (MF.getFunction().getAttributes().hasFnAttr(Attribute::Naked)) {
1792 const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
1794 if (!AFI->isInterruptOrSignalHandler()) {
1799 RetOps.push_back(DAG.getRegister(
Subtarget.getZeroRegister(), MVT::i8));
1803 AFI->isInterruptOrSignalHandler() ? AVRISD::RETI_GLUE : AVRISD::RET_GLUE;
1807 if (Glue.getNode()) {
1808 RetOps.push_back(Glue);
1811 return DAG.getNode(RetOpc, dl, MVT::Other, RetOps);
1823 bool HasRepeatedOperand =
false;
1825 MachineRegisterInfo &RI =
F->getRegInfo();
1826 const TargetInstrInfo &
TII = *
Subtarget.getInstrInfo();
1829 switch (
MI.getOpcode()) {
1834 RC = &AVR::GPR8RegClass;
1835 HasRepeatedOperand =
true;
1839 RC = &AVR::DREGSRegClass;
1843 RC = &AVR::GPR8RegClass;
1847 RC = &AVR::DREGSRegClass;
1851 RC = &AVR::GPR8RegClass;
1855 RC = &AVR::DREGSRegClass;
1858 Opc =
Tiny ? AVR::ROLBRdR17 : AVR::ROLBRdR1;
1859 RC = &AVR::GPR8RegClass;
1863 RC = &AVR::DREGSRegClass;
1867 RC = &AVR::GPR8RegClass;
1871 RC = &AVR::DREGSRegClass;
1875 const BasicBlock *LLVM_BB = BB->getBasicBlock();
1878 for (
I = BB->getIterator();
I !=
F->end() && &(*
I) != BB; ++
I)
1884 MachineBasicBlock *LoopBB =
F->CreateMachineBasicBlock(LLVM_BB);
1885 MachineBasicBlock *CheckBB =
F->CreateMachineBasicBlock(LLVM_BB);
1886 MachineBasicBlock *RemBB =
F->CreateMachineBasicBlock(LLVM_BB);
1888 F->insert(
I, LoopBB);
1889 F->insert(
I, CheckBB);
1890 F->insert(
I, RemBB);
1896 RemBB->transferSuccessorsAndUpdatePHIs(BB);
1899 BB->addSuccessor(CheckBB);
1900 LoopBB->addSuccessor(CheckBB);
1901 CheckBB->addSuccessor(LoopBB);
1902 CheckBB->addSuccessor(RemBB);
1904 Register ShiftAmtReg = RI.createVirtualRegister(&AVR::GPR8RegClass);
1905 Register ShiftAmtReg2 = RI.createVirtualRegister(&AVR::GPR8RegClass);
1906 Register ShiftReg = RI.createVirtualRegister(RC);
1907 Register ShiftReg2 = RI.createVirtualRegister(RC);
1908 Register ShiftAmtSrcReg =
MI.getOperand(2).getReg();
1919 if (HasRepeatedOperand)
1920 ShiftMI.
addReg(ShiftReg);
1928 BuildMI(CheckBB, dl,
TII.get(AVR::PHI), ShiftReg)
1933 BuildMI(CheckBB, dl,
TII.get(AVR::PHI), ShiftAmtReg)
1938 BuildMI(CheckBB, dl,
TII.get(AVR::PHI), DstReg)
1944 BuildMI(CheckBB, dl,
TII.get(AVR::DECRd), ShiftAmtReg2).
addReg(ShiftAmtReg);
1947 MI.eraseFromParent();
1974 Register ZeroReg = MRI.createVirtualRegister(&AVR::GPR8RegClass);
1982 if (ShiftLeft && (ShiftAmt % 8) >= 6) {
1987 size_t ShiftRegsOffset = ShiftAmt / 8;
1988 size_t ShiftRegsSize = Regs.size() - ShiftRegsOffset;
1990 Regs.
slice(ShiftRegsOffset, ShiftRegsSize);
1998 Register LowByte = MRI.createVirtualRegister(&AVR::GPR8RegClass);
2002 if (ShiftAmt % 8 == 6) {
2004 Register NewLowByte = MRI.createVirtualRegister(&AVR::GPR8RegClass);
2006 LowByte = NewLowByte;
2010 for (
size_t I = 0;
I < Regs.size();
I++) {
2011 int ShiftRegsIdx =
I + 1;
2012 if (ShiftRegsIdx < (
int)ShiftRegs.
size()) {
2013 Regs[
I] = ShiftRegs[ShiftRegsIdx];
2014 }
else if (ShiftRegsIdx == (
int)ShiftRegs.
size()) {
2015 Regs[
I] = std::pair(LowByte, 0);
2017 Regs[
I] = std::pair(ZeroReg, 0);
2025 if (!ShiftLeft && (ShiftAmt % 8) >= 6) {
2028 size_t ShiftRegsSize = Regs.size() - (ShiftAmt / 8);
2030 Regs.
slice(0, ShiftRegsSize);
2039 Register HighByte = MRI.createVirtualRegister(&AVR::GPR8RegClass);
2041 if (ArithmeticShift) {
2059 if (ShiftAmt % 8 == 6) {
2062 Register NewExt = MRI.createVirtualRegister(&AVR::GPR8RegClass);
2070 for (
int I = Regs.size() - 1;
I >= 0;
I--) {
2071 int ShiftRegsIdx =
I - (Regs.size() - ShiftRegs.
size()) - 1;
2072 if (ShiftRegsIdx >= 0) {
2073 Regs[
I] = ShiftRegs[ShiftRegsIdx];
2074 }
else if (ShiftRegsIdx == -1) {
2075 Regs[
I] = std::pair(HighByte, 0);
2077 Regs[
I] = std::pair(ExtByte, 0);
2086 while (ShiftLeft && ShiftAmt >= 8) {
2088 for (
size_t I = 0;
I < Regs.size() - 1;
I++) {
2089 Regs[
I] = Regs[
I + 1];
2093 Regs[Regs.size() - 1] = std::pair(ZeroReg, 0);
2096 Regs = Regs.drop_back(1);
2103 if (!ShiftLeft && ShiftAmt >= 8) {
2104 if (ArithmeticShift) {
2106 ShrExtendReg = MRI.createVirtualRegister(&AVR::GPR8RegClass);
2107 Register Tmp = MRI.createVirtualRegister(&AVR::GPR8RegClass);
2109 .
addReg(Regs[0].first, {}, Regs[0].second)
2110 .addReg(Regs[0].first, {}, Regs[0].second);
2111 BuildMI(*BB,
MI, dl,
TII.get(AVR::SBCRdRr), ShrExtendReg)
2115 ShrExtendReg = ZeroReg;
2117 for (; ShiftAmt >= 8; ShiftAmt -= 8) {
2119 for (
size_t I = Regs.size() - 1;
I != 0;
I--) {
2120 Regs[
I] = Regs[
I - 1];
2124 Regs[0] = std::pair(ShrExtendReg, 0);
2127 Regs = Regs.drop_front(1);
2132 assert((ShiftAmt < 8) &&
"Unexpect shift amount");
2152 if (!ArithmeticShift && ShiftAmt >= 4) {
2154 for (
size_t I = 0;
I < Regs.size();
I++) {
2155 size_t Idx = ShiftLeft ?
I : Regs.size() -
I - 1;
2156 Register SwapReg = MRI.createVirtualRegister(&AVR::LD8RegClass);
2158 .
addReg(Regs[Idx].first, {}, Regs[Idx].second);
2160 Register R = MRI.createVirtualRegister(&AVR::GPR8RegClass);
2166 Register AndReg = MRI.createVirtualRegister(&AVR::LD8RegClass);
2169 .
addImm(ShiftLeft ? 0xf0 : 0x0f);
2171 Register R = MRI.createVirtualRegister(&AVR::GPR8RegClass);
2175 size_t PrevIdx = ShiftLeft ? Idx - 1 : Idx + 1;
2176 Regs[PrevIdx] = std::pair(R, 0);
2179 Regs[Idx] = std::pair(AndReg, 0);
2186 while (ShiftLeft && ShiftAmt) {
2188 for (ssize_t
I = Regs.size() - 1;
I >= 0;
I--) {
2189 Register Out = MRI.createVirtualRegister(&AVR::GPR8RegClass);
2192 if (
I == (ssize_t)Regs.size() - 1) {
2194 .
addReg(In, {}, InSubreg)
2195 .addReg(In, {}, InSubreg);
2198 .
addReg(In, {}, InSubreg)
2199 .addReg(In, {}, InSubreg);
2201 Regs[
I] = std::pair(Out, 0);
2205 while (!ShiftLeft && ShiftAmt) {
2207 for (
size_t I = 0;
I < Regs.size();
I++) {
2208 Register Out = MRI.createVirtualRegister(&AVR::GPR8RegClass);
2212 unsigned Opc = ArithmeticShift ? AVR::ASRRd : AVR::LSRRd;
2217 Regs[
I] = std::pair(Out, 0);
2222 if (ShiftAmt != 0) {
2229AVRTargetLowering::insertWideShift(MachineInstr &
MI,
2230 MachineBasicBlock *BB)
const {
2236 int64_t ShiftAmt =
MI.getOperand(4).getImm();
2238 switch (
MI.getOpcode()) {
2251 std::array<std::pair<Register, int>, 4>
Registers = {
2252 std::pair(
MI.getOperand(3).getReg(), AVR::sub_hi),
2253 std::pair(
MI.getOperand(3).getReg(), AVR::sub_lo),
2254 std::pair(
MI.getOperand(2).getReg(), AVR::sub_hi),
2255 std::pair(
MI.getOperand(2).getReg(), AVR::sub_lo),
2273 (
Opc !=
ISD::SRA || (ShiftAmt < 16 || ShiftAmt >= 22))) {
2275 BuildMI(*BB,
MI, dl,
TII.get(AVR::REG_SEQUENCE),
MI.getOperand(0).getReg())
2277 .addImm(AVR::sub_lo)
2279 .addImm(AVR::sub_hi);
2280 BuildMI(*BB,
MI, dl,
TII.get(AVR::REG_SEQUENCE),
MI.getOperand(1).getReg())
2282 .addImm(AVR::sub_lo)
2284 .addImm(AVR::sub_hi);
2287 BuildMI(*BB,
MI, dl,
TII.get(AVR::REG_SEQUENCE),
MI.getOperand(1).getReg())
2289 .addImm(AVR::sub_hi)
2291 .addImm(AVR::sub_lo);
2292 BuildMI(*BB,
MI, dl,
TII.get(AVR::REG_SEQUENCE),
MI.getOperand(0).getReg())
2294 .addImm(AVR::sub_hi)
2296 .addImm(AVR::sub_lo);
2300 MI.eraseFromParent();
2305 if (
I->getOpcode() == AVR::COPY) {
2306 Register SrcReg =
I->getOperand(1).getReg();
2307 return (SrcReg == AVR::R0 || SrcReg == AVR::R1);
2316MachineBasicBlock *AVRTargetLowering::insertMul(MachineInstr &
MI,
2317 MachineBasicBlock *BB)
const {
2325 BuildMI(*BB,
I,
MI.getDebugLoc(),
TII.get(AVR::EORRdRr), AVR::R1)
2335 const TargetInstrInfo &
TII = *
Subtarget.getInstrInfo();
2338 .
add(
MI.getOperand(0))
2340 MI.eraseFromParent();
2349 const TargetInstrInfo &
TII = *
Subtarget.getInstrInfo();
2363 (Width == 8) ? &AVR::GPR8RegClass : &AVR::DREGSNOZRegClass;
2364 unsigned LoadOpcode = (Width == 8) ? AVR::LDRdPtr : AVR::LDWRdPtr;
2365 unsigned StoreOpcode = (Width == 8) ? AVR::STPtrRr : AVR::STWPtrRr;
2373 BuildMI(*BB,
I, dl,
TII.get(LoadOpcode),
MI.getOperand(0).getReg())
2374 .
add(
MI.getOperand(1));
2380 .
add(
MI.getOperand(2));
2384 .
add(
MI.getOperand(1))
2393 MI.eraseFromParent();
2400 int Opc =
MI.getOpcode();
2416 return insertShift(
MI,
MBB, STI.hasTinyEncoding());
2420 return insertWideShift(
MI,
MBB);
2423 return insertMul(
MI,
MBB);
2425 return insertCopyZero(
MI,
MBB);
2426 case AVR::AtomicLoadAdd8:
2427 return insertAtomicArithmeticOp(
MI,
MBB, AVR::ADDRdRr, 8);
2428 case AVR::AtomicLoadAdd16:
2429 return insertAtomicArithmeticOp(
MI,
MBB, AVR::ADDWRdRr, 16);
2430 case AVR::AtomicLoadSub8:
2431 return insertAtomicArithmeticOp(
MI,
MBB, AVR::SUBRdRr, 8);
2432 case AVR::AtomicLoadSub16:
2433 return insertAtomicArithmeticOp(
MI,
MBB, AVR::SUBWRdRr, 16);
2434 case AVR::AtomicLoadAnd8:
2435 return insertAtomicArithmeticOp(
MI,
MBB, AVR::ANDRdRr, 8);
2436 case AVR::AtomicLoadAnd16:
2437 return insertAtomicArithmeticOp(
MI,
MBB, AVR::ANDWRdRr, 16);
2438 case AVR::AtomicLoadOr8:
2439 return insertAtomicArithmeticOp(
MI,
MBB, AVR::ORRdRr, 8);
2440 case AVR::AtomicLoadOr16:
2441 return insertAtomicArithmeticOp(
MI,
MBB, AVR::ORWRdRr, 16);
2442 case AVR::AtomicLoadXor8:
2443 return insertAtomicArithmeticOp(
MI,
MBB, AVR::EORRdRr, 8);
2444 case AVR::AtomicLoadXor16:
2445 return insertAtomicArithmeticOp(
MI,
MBB, AVR::EORWRdRr, 16);
2448 assert((
Opc == AVR::Select16 ||
Opc == AVR::Select8) &&
2449 "Unexpected instr type to insert");
2470 if (FallThrough !=
nullptr) {
2486 unsigned CallFrameSize =
TII.getCallFrameSizeAt(
MI);
2500 MBB->addSuccessor(falseMBB);
2501 MBB->addSuccessor(trueMBB);
2509 MI.getOperand(0).getReg())
2515 MI.eraseFromParent();
2525 if (Constraint.
size() == 1) {
2527 switch (Constraint[0]) {
2570 switch (ConstraintCode[0]) {
2581 Value *CallOperandVal =
info.CallOperandVal;
2586 if (!CallOperandVal) {
2591 switch (*constraint) {
2630 if ((
C->getSExtValue() >= -63) && (
C->getSExtValue() <= 0)) {
2637 if (
C->getZExtValue() == 2) {
2644 if (
C->getZExtValue() == 0) {
2658 if (
C->getSExtValue() == -1) {
2665 if ((
C->getZExtValue() == 8) || (
C->getZExtValue() == 16) ||
2666 (
C->getZExtValue() == 24)) {
2673 if (
C->getZExtValue() == 1) {
2680 if ((
C->getSExtValue() >= -6) && (
C->getSExtValue() <= 5)) {
2693std::pair<unsigned, const TargetRegisterClass *>
2697 if (Constraint.
size() == 1) {
2698 switch (Constraint[0]) {
2701 return std::make_pair(0U, &AVR::LD8loRegClass);
2702 else if (VT == MVT::i16)
2703 return std::make_pair(0U, &AVR::DREGSLD8loRegClass);
2706 if (VT == MVT::i8 || VT == MVT::i16)
2707 return std::make_pair(0U, &AVR::PTRDISPREGSRegClass);
2711 return std::make_pair(0U, &AVR::LD8RegClass);
2712 else if (VT == MVT::i16)
2713 return std::make_pair(0U, &AVR::DLDREGSRegClass);
2717 return std::make_pair(0U, &AVR::GPR8loRegClass);
2718 else if (VT == MVT::i16)
2719 return std::make_pair(0U, &AVR::DREGSloRegClass);
2722 if (VT == MVT::i8 || VT == MVT::i16)
2723 return std::make_pair(0U, &AVR::PTRREGSRegClass);
2726 return std::make_pair(0U, &AVR::GPRSPRegClass);
2729 return std::make_pair(0U, &AVR::GPR8RegClass);
2730 else if (VT == MVT::i16)
2731 return std::make_pair(0U, &AVR::DREGSRegClass);
2735 return std::make_pair(
unsigned(
Subtarget.getTmpRegister()),
2736 &AVR::GPR8RegClass);
2739 if (VT == MVT::i8 || VT == MVT::i16)
2740 return std::make_pair(0U, &AVR::IWREGSRegClass);
2744 if (VT == MVT::i8 || VT == MVT::i16)
2745 return std::make_pair(
unsigned(AVR::R27R26), &AVR::PTRREGSRegClass);
2749 if (VT == MVT::i8 || VT == MVT::i16)
2750 return std::make_pair(
unsigned(AVR::R29R28), &AVR::PTRREGSRegClass);
2754 if (VT == MVT::i8 || VT == MVT::i16)
2755 return std::make_pair(
unsigned(AVR::R31R30), &AVR::PTRREGSRegClass);
2763 Subtarget.getRegisterInfo(), Constraint, VT);
2768 std::vector<SDValue> &
Ops,
2772 EVT Ty =
Op.getValueType();
2775 if (Constraint.
size() != 1) {
2779 char ConstraintLetter = Constraint[0];
2780 switch (ConstraintLetter) {
2798 int64_t CVal64 =
C->getSExtValue();
2800 switch (ConstraintLetter) {
2807 if (CVal64 < -63 || CVal64 > 0)
2827 if (Ty.getSimpleVT() == MVT::i8) {
2838 if (CUVal64 != 8 && CUVal64 != 16 && CUVal64 != 24)
2848 if (CVal64 < -6 || CVal64 > 5)
2858 if (!FC || !FC->isZero())
2865 if (Result.getNode()) {
2866 Ops.push_back(Result);
2879 .
Case(
"r0", AVR::R0)
2880 .
Case(
"r1", AVR::R1)
2884 .
Case(
"r0", AVR::R1R0)
2885 .
Case(
"sp", AVR::SP)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Reserve WWM Registers
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis Results
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const HexagonInstrInfo * TII
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Register const TargetRegisterInfo * TRI
Promote Memory to Register
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
Utilities related to the AVR instruction set.
A specific AVR target MCU.
Register getZeroRegister() const
const AVRInstrInfo * getInstrInfo() const override
void ReplaceNodeResults(SDNode *N, SmallVectorImpl< SDValue > &Results, SelectionDAG &DAG) const override
Replace a node with an illegal result type with a new node built out of custom code.
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 getPreIndexedAddressParts(SDNode *N, 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 the node's...
std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override
Given a physical register constraint (e.g.
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
ConstraintType getConstraintType(StringRef Constraint) const override
Given a constraint, return the type of constraint it is for this target.
const AVRSubtarget & Subtarget
InlineAsm::ConstraintCode getInlineAsmMemConstraint(StringRef ConstraintCode) const override
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, unsigned AS, Instruction *I=nullptr) const override
Return true if the addressing mode represented by AM is legal for this target, for a load/store of th...
ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &info, const char *constraint) const override
Examine constraint string and operand type and determine a weight value.
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override
Return true if folding a constant offset with the given GlobalAddress is legal.
Register getRegisterByName(const char *RegName, LLT VT, const MachineFunction &MF) const override
Return the register ID of the name passed in.
AVRTargetLowering(const AVRTargetMachine &TM, const AVRSubtarget &STI)
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const override
Lower the specified operand into the Ops vector.
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the ValueType of the result of SETCC operations.
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 ...
A generic AVR implementation.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
LLVM Basic Block Representation.
CCState - This class holds information needed while lowering arguments and return values.
MCRegister AllocateReg(MCPhysReg Reg)
AllocateReg - Attempt to allocate one register.
LLVMContext & getContext() const
int64_t AllocateStack(unsigned Size, Align Alignment)
AllocateStack - Allocate a chunk of stack space with the specified size and alignment.
void addLoc(const CCValAssign &V)
static CCValAssign getReg(unsigned ValNo, MVT ValVT, MCRegister Reg, MVT LocVT, LocInfo HTP, bool IsCustom=false)
static CCValAssign getMem(unsigned ValNo, MVT ValVT, int64_t Offset, MVT LocVT, LocInfo HTP, bool IsCustom=false)
ConstantFP - Floating Point Values [float, double].
This is the shared class of boolean and integer constants.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
LLVM_ABI Align getABITypeAlign(Type *Ty) const
Returns the minimum ABI-required alignment for the specified type.
LLVM_ABI TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
This is an important class for using LLVM in a threaded context.
This class is used to represent ISD::LOAD nodes.
static auto integer_valuetypes()
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
void setCallFrameSize(unsigned N)
Set the call frame size on entry to this basic block.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
void setFrameAddressIsTaken(bool T)
void setReturnAddressIsTaken(bool s)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
BasicBlockListType::iterator iterator
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
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.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
MutableArrayRef< T > slice(size_t N, size_t M) const
Chop off the first N elements of the array, and keep M elements in the array.
Wrapper class representing virtual and physical registers.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDValue getValue(unsigned R) const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
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 getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
MachineFunction & getMachineFunction() const
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This class is used to represent ISD::STORE nodes.
Represent a constant reference to a string, i.e.
constexpr size_t size() const
Get the string size.
A switch()-like statement whose cases are string literals.
StringSwitch & Case(StringLiteral S, T Value)
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
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...
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 setMinFunctionAlignment(Align Alignment)
Set the target's minimum function alignment.
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose.
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 ...
void setSupportsUnalignedAtomics(bool UnalignedSupported)
Sets whether unaligned atomic operations are supported.
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 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 ...
@ ZeroOrOneBooleanContent
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
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...
std::vector< ArgListEntry > ArgListTy
void setSchedulingPreference(Sched::Preference Pref)
Specify the target scheduling preference.
virtual InlineAsm::ConstraintCode getInlineAsmMemConstraint(StringRef ConstraintCode) const
virtual ConstraintType getConstraintType(StringRef Constraint) const
Given a constraint, return the type of constraint it is for this target.
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
virtual ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &info, const char *constraint) const
Examine constraint string and operand type and determine a weight value.
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 LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetInstrInfo * getInstrInfo() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static constexpr TypeSize getFixed(ScalarTy ExactSize)
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
CondCodes
AVR specific condition codes.
@ COND_SH
Unsigned same or higher.
@ COND_GE
Greater than or equal.
bool isProgramMemoryAccess(MemSDNode const *N)
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.
@ AVR_BUILTIN
Used for special AVR rtlib functions which have an "optimized" convention to preserve registers.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ 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.
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ BSWAP
Byte Swap and Counting operators.
@ VAEND
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE.
@ ADDC
Carry-setting nodes for multiple precision addition and subtraction.
@ ADD
Simple integer binary arithmetic operators.
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
@ 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.
@ SIGN_EXTEND
Conversion operators.
@ BR_CC
BR_CC - Conditional branch.
@ BR_JT
BR_JT - Jumptable branch.
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ EXTRACT_ELEMENT
EXTRACT_ELEMENT - This is used to get the lower or upper (determined by a Constant,...
@ VACOPY
VACOPY - VACOPY has 5 operands: an input chain, a destination pointer, a source pointer,...
@ BasicBlock
Various leaf nodes.
@ MULHU
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
@ SHL
Shift and rotation operations.
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ SELECT_CC
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
@ ATOMIC_CMP_SWAP
Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) For double-word atomic operations: ValLo,...
@ 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 ...
@ FRAMEADDR
FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and llvm.returnaddress on the DAG.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ ADDE
Carry-using nodes for multiple precision addition and subtraction.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ ATOMIC_SWAP
Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN,...
@ INLINEASM
INLINEASM - Represents an inline asm block.
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ VAARG
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
@ BRCOND
BRCOND - Conditional branch.
@ SHL_PARTS
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations.
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
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,...
This is an optimization pass for GlobalISel generic memory operations.
static void analyzeReturnValues(const SmallVectorImpl< ArgT > &Args, CCState &CCInfo, bool Tiny)
Analyze incoming and outgoing value of returning from a function.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
@ Undef
Value of the register doesn't matter.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
static const MCPhysReg RegList16Tiny[]
constexpr bool has_single_bit(T Value) noexcept
static const MCPhysReg RegList8Tiny[]
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
static void analyzeArguments(TargetLowering::CallLoweringInfo *CLI, const Function *F, const DataLayout *TD, const SmallVectorImpl< ArgT > &Args, SmallVectorImpl< CCValAssign > &ArgLocs, CCState &CCInfo, bool Tiny)
Analyze incoming and outgoing function arguments.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
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...
static const MCPhysReg RegList16AVR[]
@ Sub
Subtraction of integers.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
static unsigned getTotalArgumentsSizeInBytes(const SmallVectorImpl< ArgT > &Args)
Count the total number of bytes needed to pass or return these arguments.
DWARFExpression::Operation Op
static AVRCC::CondCodes intCCToAVRCC(ISD::CondCode CC)
IntCCToAVRCC - Convert a DAG integer condition code to an AVR CC.
ArrayRef(const T &OneElt) -> ArrayRef< T >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
static bool isCopyMulResult(MachineBasicBlock::iterator const &I)
static void insertMultibyteShift(MachineInstr &MI, MachineBasicBlock *BB, MutableArrayRef< std::pair< Register, int > > Regs, ISD::NodeType Opc, int64_t ShiftAmt)
static const MCPhysReg RegList8AVR[]
Registers for calling conventions, ordered in reverse as required by ABI.
MCRegisterClass TargetRegisterClass
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
bool isVector() const
Return true if this is a vector value type.
LLVM_ABI Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
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 represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg + ScalableOffset*...
This contains information for each constraint that we are lowering.
This structure contains all information that is necessary for lowering calls.