180 if (!
Subtarget.supportsMultiplication()) {
217 EVT VT =
Op.getValueType();
220 "Expected power-of-2 shift amount");
228 SDVTList ResTys = DAG.
getVTList(MVT::i16, MVT::i16);
235 uint64_t ShiftAmount =
N->getConstantOperandVal(1);
236 if (ShiftAmount == 16) {
241 switch (
Op.getOpcode()) {
254 switch (
Op.getOpcode()) {
274 switch (
Op.getOpcode()) {
278 return DAG.
getNode(AVRISD::LSLLOOP, dl, VT,
N->getOperand(0),
281 return DAG.
getNode(AVRISD::LSRLOOP, dl, VT,
N->getOperand(0),
284 SDValue Amt =
N->getOperand(1);
285 EVT AmtVT = Amt.getValueType();
288 return DAG.
getNode(AVRISD::ROLLOOP, dl, VT,
N->getOperand(0), Amt);
291 SDValue Amt =
N->getOperand(1);
292 EVT AmtVT = Amt.getValueType();
295 return DAG.
getNode(AVRISD::RORLOOP, dl, VT,
N->getOperand(0), Amt);
298 return DAG.
getNode(AVRISD::ASRLOOP, dl, VT,
N->getOperand(0),
303 uint64_t ShiftAmount =
N->getConstantOperandVal(1);
304 SDValue Victim =
N->getOperand(0);
306 switch (
Op.getOpcode()) {
330 if (
Op.getOpcode() ==
ISD::SHL && 4 <= ShiftAmount && ShiftAmount < 7) {
332 Victim = DAG.
getNode(AVRISD::SWAP, dl, VT, Victim);
336 }
else if (
Op.getOpcode() ==
ISD::SRL && 4 <= ShiftAmount &&
339 Victim = DAG.
getNode(AVRISD::SWAP, dl, VT, Victim);
343 }
else if (
Op.getOpcode() ==
ISD::SHL && ShiftAmount == 7) {
345 Victim = DAG.
getNode(AVRISD::LSLBN, dl, VT, Victim,
348 }
else if (
Op.getOpcode() ==
ISD::SRL && ShiftAmount == 7) {
350 Victim = DAG.
getNode(AVRISD::LSRBN, dl, VT, Victim,
353 }
else if (
Op.getOpcode() ==
ISD::SRA && ShiftAmount == 6) {
355 Victim = DAG.
getNode(AVRISD::ASRBN, dl, VT, Victim,
358 }
else if (
Op.getOpcode() ==
ISD::SRA && ShiftAmount == 7) {
360 Victim = DAG.
getNode(AVRISD::ASRBN, dl, VT, Victim,
363 }
else if (
Op.getOpcode() ==
ISD::ROTL && ShiftAmount == 3) {
365 Victim = DAG.
getNode(AVRISD::SWAP, dl, VT, Victim);
366 Victim = DAG.
getNode(AVRISD::ROR, dl, VT, Victim);
368 }
else if (
Op.getOpcode() ==
ISD::ROTR && ShiftAmount == 3) {
370 Victim = DAG.
getNode(AVRISD::SWAP, dl, VT, Victim);
371 Victim = DAG.
getNode(AVRISD::ROL, dl, VT, Victim);
373 }
else if (
Op.getOpcode() ==
ISD::ROTL && ShiftAmount == 7) {
375 Victim = DAG.
getNode(AVRISD::ROR, dl, VT, Victim);
377 }
else if (
Op.getOpcode() ==
ISD::ROTR && ShiftAmount == 7) {
379 Victim = DAG.
getNode(AVRISD::ROL, dl, VT, Victim);
384 Victim = DAG.
getNode(AVRISD::SWAP, dl, VT, Victim);
390 switch (ShiftAmount) {
392 Victim = DAG.
getNode(AVRISD::ASRWN, dl, VT, Victim,
397 Victim = DAG.
getNode(AVRISD::ASRWN, dl, VT, Victim,
402 Victim = DAG.
getNode(AVRISD::ASRWN, dl, VT, Victim,
409 if (4 <= ShiftAmount && ShiftAmount < 8)
410 switch (
Op.getOpcode()) {
412 Victim = DAG.
getNode(AVRISD::LSLWN, dl, VT, Victim,
417 Victim = DAG.
getNode(AVRISD::LSRWN, dl, VT, Victim,
424 else if (8 <= ShiftAmount && ShiftAmount < 12)
425 switch (
Op.getOpcode()) {
427 Victim = DAG.
getNode(AVRISD::LSLWN, dl, VT, Victim,
431 Opc8 = AVRISD::LSLHI;
434 Victim = DAG.
getNode(AVRISD::LSRWN, dl, VT, Victim,
438 Opc8 = AVRISD::LSRLO;
441 Victim = DAG.
getNode(AVRISD::ASRWN, dl, VT, Victim,
445 Opc8 = AVRISD::ASRLO;
450 else if (12 <= ShiftAmount)
451 switch (
Op.getOpcode()) {
453 Victim = DAG.
getNode(AVRISD::LSLWN, dl, VT, Victim,
457 Opc8 = AVRISD::LSLHI;
460 Victim = DAG.
getNode(AVRISD::LSRWN, dl, VT, Victim,
464 Opc8 = AVRISD::LSRLO;
467 Victim = DAG.
getNode(AVRISD::ASRWN, dl, VT, Victim,
471 Opc8 = AVRISD::ASRLO;
478 while (ShiftAmount--) {
479 Victim = DAG.
getNode(Opc8, dl, VT, Victim);
486 unsigned Opcode =
Op->getOpcode();
488 "Invalid opcode for Div/Rem lowering");
490 EVT VT =
Op->getValueType(0);
491 Type *Ty = VT.getTypeForEVT(*DAG.getContext());
494 switch (VT.getSimpleVT().SimpleTy) {
498 LC = IsSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
501 LC = IsSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
504 LC = IsSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
508 SDValue InChain = DAG.getEntryNode();
511 for (SDValue
const &
Value :
Op->op_values()) {
512 TargetLowering::ArgListEntry
Entry(
513 Value,
Value.getValueType().getTypeForEVT(*DAG.getContext()));
514 Entry.IsSExt = IsSigned;
515 Entry.IsZExt = !IsSigned;
516 Args.push_back(Entry);
519 RTLIB::LibcallImpl LCImpl = DAG.getLibcalls().getLibcallImpl(LC);
520 if (LCImpl == RTLIB::Unsupported)
524 DAG.getExternalSymbol(LCImpl,
getPointerTy(DAG.getDataLayout()));
529 TargetLowering::CallLoweringInfo CLI(DAG);
532 .setLibCallee(DAG.getLibcalls().getLibcallImplCallingConv(LCImpl), RetTy,
533 Callee, std::move(Args))
535 .setSExtResult(IsSigned)
536 .setZExtResult(!IsSigned);
538 std::pair<SDValue, SDValue> CallInfo =
LowerCallTo(CLI);
539 return CallInfo.first;
544 auto DL = DAG.getDataLayout();
557 auto DL = DAG.getDataLayout();
586SDValue AVRTargetLowering::getAVRCmp(SDValue
LHS, SDValue
RHS,
587 SelectionDAG &DAG, SDLoc
DL)
const {
588 assert((
LHS.getSimpleValueType() ==
RHS.getSimpleValueType()) &&
589 "LHS and RHS have different types");
590 assert(((
LHS.getSimpleValueType() == MVT::i16) ||
591 (
LHS.getSimpleValueType() == MVT::i8)) &&
592 "invalid comparison type");
601 DAG.getIntPtrConstant(0,
DL));
603 DAG.getIntPtrConstant(1,
DL));
604 SDValue RHSlo = (
Imm & 0xff) == 0
607 DAG.getIntPtrConstant(0,
DL));
608 SDValue RHShi = (
Imm & 0xff00) == 0
611 DAG.getIntPtrConstant(1,
DL));
612 Cmp = DAG.getNode(AVRISD::CMP,
DL, MVT::Glue, LHSlo, RHSlo);
613 Cmp = DAG.getNode(AVRISD::CMPC,
DL, MVT::Glue, LHShi, RHShi, Cmp);
618 SDValue LHSlo = (
Imm & 0xff) == 0
619 ? DAG.getRegister(
Subtarget.getZeroRegister(), MVT::i8)
621 DAG.getIntPtrConstant(0,
DL));
622 SDValue LHShi = (
Imm & 0xff00) == 0
623 ? DAG.getRegister(
Subtarget.getZeroRegister(), MVT::i8)
625 DAG.getIntPtrConstant(1,
DL));
627 DAG.getIntPtrConstant(0,
DL));
629 DAG.getIntPtrConstant(1,
DL));
630 Cmp = DAG.getNode(AVRISD::CMP,
DL, MVT::Glue, LHSlo, RHSlo);
631 Cmp = DAG.getNode(AVRISD::CMPC,
DL, MVT::Glue, LHShi, RHShi, Cmp);
634 Cmp = DAG.getNode(AVRISD::CMP,
DL, MVT::Glue,
LHS,
RHS);
646 EVT VT =
LHS.getValueType();
647 bool UseTest =
false;
660 switch (
C->getSExtValue()) {
672 LHS = DAG.getConstant(0,
DL, VT);
677 if (
C->getConstantIntValue()->isMaxValue(
true)) {
688 RHS = DAG.getSignedConstant(
C->getSExtValue() + 1,
DL, VT);
702 switch (
C->getSExtValue()) {
707 LHS = DAG.getConstant(0,
DL, VT);
732 if (
C->getConstantIntValue()->isMaxValue(
false)) {
736 RHS = DAG.getConstant(
C->getZExtValue() + 1,
DL, VT);
750 if (VT == MVT::i32) {
752 DAG.getIntPtrConstant(0,
DL));
754 DAG.getIntPtrConstant(1,
DL));
756 DAG.getIntPtrConstant(0,
DL));
758 DAG.getIntPtrConstant(1,
DL));
763 DAG.getIntPtrConstant(1,
DL));
764 Cmp = DAG.getNode(AVRISD::TST,
DL, MVT::Glue, Top);
766 Cmp = getAVRCmp(LHSlo, RHSlo, DAG,
DL);
767 Cmp = DAG.getNode(AVRISD::CMPC,
DL, MVT::Glue, LHShi, RHShi, Cmp);
769 }
else if (VT == MVT::i64) {
771 DAG.getIntPtrConstant(0,
DL));
773 DAG.getIntPtrConstant(1,
DL));
776 DAG.getIntPtrConstant(0,
DL));
778 DAG.getIntPtrConstant(1,
DL));
780 DAG.getIntPtrConstant(0,
DL));
782 DAG.getIntPtrConstant(1,
DL));
785 DAG.getIntPtrConstant(0,
DL));
787 DAG.getIntPtrConstant(1,
DL));
790 DAG.getIntPtrConstant(0,
DL));
792 DAG.getIntPtrConstant(1,
DL));
794 DAG.getIntPtrConstant(0,
DL));
796 DAG.getIntPtrConstant(1,
DL));
801 DAG.getIntPtrConstant(1,
DL));
802 Cmp = DAG.getNode(AVRISD::TST,
DL, MVT::Glue, Top);
804 Cmp = getAVRCmp(LHS0, RHS0, DAG,
DL);
805 Cmp = DAG.getNode(AVRISD::CMPC,
DL, MVT::Glue, LHS1, RHS1, Cmp);
806 Cmp = DAG.getNode(AVRISD::CMPC,
DL, MVT::Glue, LHS2, RHS2, Cmp);
807 Cmp = DAG.getNode(AVRISD::CMPC,
DL, MVT::Glue, LHS3, RHS3, Cmp);
809 }
else if (VT == MVT::i8 || VT == MVT::i16) {
812 Cmp = DAG.getNode(AVRISD::TST,
DL, MVT::Glue,
816 LHS, DAG.getIntPtrConstant(1,
DL)));
833 SDValue Chain =
Op.getOperand(0);
835 SDValue
LHS =
Op.getOperand(2);
836 SDValue
RHS =
Op.getOperand(3);
837 SDValue Dest =
Op.getOperand(4);
841 SDValue
Cmp = getAVRCmp(
LHS,
RHS, CC, TargetCC, DAG, dl);
843 return DAG.getNode(AVRISD::BRCOND, dl, MVT::Other, Chain, Dest, TargetCC,
848 SDValue
LHS =
Op.getOperand(0);
849 SDValue
RHS =
Op.getOperand(1);
850 SDValue TrueV =
Op.getOperand(2);
851 SDValue FalseV =
Op.getOperand(3);
856 SDValue
Cmp = getAVRCmp(
LHS,
RHS, CC, TargetCC, DAG, dl);
858 SDValue
Ops[] = {TrueV, FalseV, TargetCC,
Cmp};
860 return DAG.getNode(AVRISD::SELECT_CC, dl,
Op.getValueType(),
Ops);
864 SDValue
LHS =
Op.getOperand(0);
865 SDValue
RHS =
Op.getOperand(1);
870 SDValue
Cmp = getAVRCmp(
LHS,
RHS, CC, TargetCC, DAG,
DL);
872 SDValue TrueV = DAG.getConstant(1,
DL,
Op.getValueType());
873 SDValue FalseV = DAG.getConstant(0,
DL,
Op.getValueType());
874 SDValue
Ops[] = {TrueV, FalseV, TargetCC,
Cmp};
876 return DAG.getNode(AVRISD::SELECT_CC,
DL,
Op.getValueType(),
Ops);
881 const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
883 auto DL = DAG.getDataLayout();
888 SDValue FI = DAG.getFrameIndex(AFI->getVarArgsFrameIndex(),
getPointerTy(
DL));
890 return DAG.getStore(
Op.getOperand(0), dl, FI,
Op.getOperand(1),
891 MachinePointerInfo(SV));
896 SDValue ZeroReg = DAG.getRegister(
Subtarget.getZeroRegister(), MVT::i8);
912 SDNode *
N =
Op.getNode();
914 for (
unsigned I = 0;
I <
N->getNumOperands();
I++) {
915 SDValue Operand =
N->getOperand(
I);
916 if (Operand.getValueType() == MVT::Glue) {
921 Ops.push_back(Operand);
925 Ops.push_back(DAG.getTargetConstant(Flags, dl, MVT::i32));
926 Ops.push_back(ZeroReg);
933 SDValue
New = DAG.getNode(
N->getOpcode(), dl,
N->getVTList(),
Ops);
934 DAG.ReplaceAllUsesOfValueWith(
Op, New);
935 DAG.ReplaceAllUsesOfValueWith(
Op.getValue(1),
New.getValue(1));
941 switch (
Op.getOpcode()) {
949 return LowerShifts(
Op, DAG);
951 return LowerGlobalAddress(
Op, DAG);
953 return LowerBlockAddress(
Op, DAG);
955 return LowerBR_CC(
Op, DAG);
957 return LowerSELECT_CC(
Op, DAG);
959 return LowerSETCC(
Op, DAG);
961 return LowerVASTART(
Op, DAG);
964 return LowerDivRem(
Op, DAG);
966 return LowerINLINEASM(
Op, DAG);
968 return LowerFRAMEADDR(
Op, DAG);
970 return LowerRETURNADDR(
Op, DAG);
985 if (
Op.getConstantOperandVal(0) > 0)
1002SDValue AVRTargetLowering::LowerRETURNADDR(SDValue
Op,
1003 SelectionDAG &DAG)
const {
1018 if (
Op.getConstantOperandVal(0) > 0)
1024 MachineFrameInfo &MFI = MF.getFrameInfo();
1036 int PCWidth =
Subtarget.hasEIJMPCALL() ? 3 : 2;
1043 int FI = MFI.CreateFixedObject(2, PCWidth - 4,
true);
1044 SDValue Addr = DAG.getFrameIndex(FI, PtrVT);
1048 SDValue
Hi = DAG.getLoad(MVT::i8,
DL, DAG.getEntryNode(), Addr,
1051 DAG.getLoad(MVT::i8,
DL, DAG.getEntryNode(),
1055 SDValue Res = DAG.getTargetInsertSubreg(AVR::sub_lo,
DL, MVT::i16,
1056 DAG.getUNDEF(MVT::i16),
Lo);
1057 return DAG.getTargetInsertSubreg(AVR::sub_hi,
DL, MVT::i16, Res,
Hi);
1067 switch (
N->getOpcode()) {
1130 VT = LD->getMemoryVT();
1131 Op = LD->getBasePtr().getNode();
1138 VT = ST->getMemoryVT();
1139 Op = ST->getBasePtr().getNode();
1147 if (VT != MVT::i8 && VT != MVT::i16) {
1156 int RHSC =
RHS->getSExtValue();
1160 if ((VT == MVT::i16 && RHSC != -2) || (VT == MVT::i8 && RHSC != -1)) {
1164 Base =
Op->getOperand(0);
1187 VT = LD->getMemoryVT();
1188 Ptr = LD->getBasePtr();
1192 VT = ST->getMemoryVT();
1193 Ptr = ST->getBasePtr();
1201 if (VT == MVT::i16 && !
Subtarget.hasLowByteFirst())
1207 if (VT != MVT::i8 && VT != MVT::i16) {
1216 int RHSC =
RHS->getSExtValue();
1219 if ((VT == MVT::i16 && RHSC != 2) || (VT == MVT::i8 && RHSC != 1)) {
1229 Base =
Op->getOperand(0);
1254#define GET_CALLING_CONV_IMPL
1255#include "AVRGenCallingConv.inc"
1260 AVR::R25, AVR::R24, AVR::R23, AVR::R22, AVR::R21, AVR::R20,
1261 AVR::R19, AVR::R18, AVR::R17, AVR::R16, AVR::R15, AVR::R14,
1262 AVR::R13, AVR::R12, AVR::R11, AVR::R10, AVR::R9, AVR::R8};
1264 AVR::R22, AVR::R21, AVR::R20};
1266 AVR::R26R25, AVR::R25R24, AVR::R24R23, AVR::R23R22, AVR::R22R21,
1267 AVR::R21R20, AVR::R20R19, AVR::R19R18, AVR::R18R17, AVR::R17R16,
1268 AVR::R16R15, AVR::R15R14, AVR::R14R13, AVR::R13R12, AVR::R12R11,
1269 AVR::R11R10, AVR::R10R9, AVR::R9R8};
1271 AVR::R24R23, AVR::R23R22,
1272 AVR::R22R21, AVR::R21R20};
1275 "8-bit and 16-bit register arrays must be of equal length");
1277 "8-bit and 16-bit register arrays must be of equal length");
1283template <
typename ArgT>
1300 unsigned NumArgs = Args.size();
1303 int RegLastIdx = -1;
1305 bool UseStack =
false;
1306 for (
unsigned i = 0; i != NumArgs;) {
1307 MVT VT = Args[i].VT;
1312 unsigned ArgIndex = Args[i].OrigArgIndex;
1315 for (; j != NumArgs; ++j) {
1316 if (Args[j].OrigArgIndex != ArgIndex)
1318 TotalBytes += Args[j].VT.getStoreSize();
1321 TotalBytes =
alignTo(TotalBytes, 2);
1323 if (TotalBytes == 0)
1326 unsigned RegIdx = RegLastIdx + TotalBytes;
1327 RegLastIdx = RegIdx;
1329 if (RegIdx >= RegList8.
size()) {
1332 for (; i != j; ++i) {
1333 MVT VT = Args[i].VT;
1343 if (VT == MVT::i8) {
1345 }
else if (VT == MVT::i16) {
1349 "calling convention can only manage i8 and i16 types");
1351 assert(
Reg &&
"register not available in calling convention");
1362template <
typename ArgT>
1365 unsigned TotalBytes = 0;
1367 for (
const ArgT &Arg : Args) {
1368 TotalBytes += Arg.VT.getStoreSize();
1376template <
typename ArgT>
1379 unsigned NumArgs = Args.size();
1383 assert(TotalBytes <= 4 &&
1384 "return values greater than 4 bytes cannot be lowered on AVRTiny");
1386 assert(TotalBytes <= 8 &&
1387 "return values greater than 8 bytes cannot be lowered on AVR");
1402 if (TotalBytes > 4) {
1405 TotalBytes =
alignTo(TotalBytes, 2);
1409 int RegIdx = TotalBytes - 1;
1410 for (
unsigned i = 0; i != NumArgs; ++i) {
1411 MVT VT = Args[i].VT;
1413 if (VT == MVT::i8) {
1415 }
else if (VT == MVT::i16) {
1420 assert(
Reg &&
"register not available in calling convention");
1427SDValue AVRTargetLowering::LowerFormalArguments(
1429 const SmallVectorImpl<ISD::InputArg> &Ins,
const SDLoc &dl,
1430 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals)
const {
1432 MachineFrameInfo &MFI = MF.getFrameInfo();
1433 auto DL = DAG.getDataLayout();
1437 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
1442 CCInfo.AnalyzeFormalArguments(Ins, ArgCC_AVR_Vararg);
1449 for (CCValAssign &VA : ArgLocs) {
1452 if (VA.isRegLoc()) {
1453 EVT RegVT = VA.getLocVT();
1455 if (RegVT == MVT::i8) {
1456 RC = &AVR::GPR8RegClass;
1457 }
else if (RegVT == MVT::i16) {
1458 RC = &AVR::DREGSRegClass;
1464 ArgValue = DAG.getCopyFromReg(Chain, dl,
Reg, RegVT);
1472 switch (VA.getLocInfo()) {
1478 ArgValue = DAG.getNode(
ISD::BITCAST, dl, VA.getValVT(), ArgValue);
1482 DAG.getValueType(VA.getValVT()));
1483 ArgValue = DAG.getNode(
ISD::TRUNCATE, dl, VA.getValVT(), ArgValue);
1487 DAG.getValueType(VA.getValVT()));
1488 ArgValue = DAG.getNode(
ISD::TRUNCATE, dl, VA.getValVT(), ArgValue);
1492 InVals.push_back(ArgValue);
1497 EVT LocVT = VA.getLocVT();
1500 int FI = MFI.CreateFixedObject(LocVT.getSizeInBits() / 8,
1501 VA.getLocMemOffset(),
true);
1506 InVals.push_back(DAG.getLoad(LocVT, dl, Chain, FIN,
1514 unsigned StackSize = CCInfo.getStackSize();
1515 AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
1517 AFI->setVarArgsFrameIndex(MFI.CreateFixedObject(2, StackSize,
true));
1529 SelectionDAG &DAG = CLI.DAG;
1531 SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
1532 SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
1533 SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
1534 SDValue Chain = CLI.Chain;
1535 SDValue
Callee = CLI.Callee;
1536 bool &isTailCall = CLI.IsTailCall;
1538 bool isVarArg = CLI.IsVarArg;
1547 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
1555 const GlobalValue *GV =
G->getGlobal();
1559 DAG.getTargetGlobalAddress(GV,
DL,
getPointerTy(DAG.getDataLayout()));
1560 }
else if (
const ExternalSymbolSDNode *ES =
1562 Callee = DAG.getTargetExternalSymbol(ES->getSymbol(),
1568 CCInfo.AnalyzeCallOperands(Outs, ArgCC_AVR_Vararg);
1575 unsigned NumBytes = CCInfo.getStackSize();
1577 Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0,
DL);
1583 bool HasStackArgs =
false;
1584 for (AI = 0, AE = ArgLocs.size(); AI != AE; ++AI) {
1585 CCValAssign &VA = ArgLocs[AI];
1586 EVT RegVT = VA.getLocVT();
1587 SDValue Arg = OutVals[AI];
1590 switch (VA.getLocInfo()) {
1611 if (VA.isMemLoc()) {
1612 HasStackArgs =
true;
1618 RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
1629 for (; AI != AE; AI++) {
1630 CCValAssign &VA = ArgLocs[AI];
1631 SDValue Arg = OutVals[AI];
1636 SDValue PtrOff = DAG.getNode(
1638 DAG.getRegister(AVR::SP,
getPointerTy(DAG.getDataLayout())),
1639 DAG.getIntPtrConstant(VA.getLocMemOffset() + 1,
DL));
1641 MemOpChains.push_back(
1642 DAG.getStore(Chain,
DL, Arg, PtrOff,
1646 if (!MemOpChains.empty())
1654 for (
auto Reg : RegsToPass) {
1655 Chain = DAG.getCopyToReg(Chain,
DL,
Reg.first,
Reg.second, InGlue);
1656 InGlue = Chain.getValue(1);
1660 SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
1662 Ops.push_back(Chain);
1663 Ops.push_back(Callee);
1667 for (
auto Reg : RegsToPass) {
1668 Ops.push_back(DAG.getRegister(
Reg.first,
Reg.second.getValueType()));
1673 Ops.push_back(DAG.getRegister(
Subtarget.getZeroRegister(), MVT::i8));
1676 const TargetRegisterInfo *
TRI =
Subtarget.getRegisterInfo();
1677 const uint32_t *
Mask =
1678 TRI->getCallPreservedMask(DAG.getMachineFunction(), CallConv);
1679 assert(Mask &&
"Missing call preserved mask for calling convention");
1680 Ops.push_back(DAG.getRegisterMask(Mask));
1682 if (InGlue.getNode()) {
1683 Ops.push_back(InGlue);
1686 Chain = DAG.getNode(AVRISD::CALL,
DL, NodeTys,
Ops);
1687 InGlue = Chain.getValue(1);
1690 Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, InGlue,
DL);
1693 InGlue = Chain.getValue(1);
1698 return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins,
DL, DAG,
1705SDValue AVRTargetLowering::LowerCallResult(
1712 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
1717 CCInfo.AnalyzeCallResult(Ins, RetCC_AVR_BUILTIN);
1723 for (CCValAssign
const &RVLoc : RVLocs) {
1724 Chain = DAG.getCopyFromReg(Chain, dl, RVLoc.getLocReg(), RVLoc.getValVT(),
1727 InGlue = Chain.getValue(2);
1728 InVals.push_back(Chain.getValue(0));
1738bool AVRTargetLowering::CanLowerReturn(
1741 const Type *RetTy)
const {
1744 CCState CCInfo(CallConv, isVarArg, MF, RVLocs,
Context);
1745 return CCInfo.CheckReturn(Outs, RetCC_AVR_BUILTIN);
1749 return TotalBytes <= (unsigned)(
Subtarget.hasTinyEncoding() ? 4 : 8);
1762 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
1769 CCInfo.AnalyzeReturn(Outs, RetCC_AVR_BUILTIN);
1777 for (
unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
1778 CCValAssign &VA = RVLocs[i];
1779 assert(VA.isRegLoc() &&
"Can only return in registers!");
1781 Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Glue);
1784 Glue = Chain.getValue(1);
1785 RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
1790 if (MF.getFunction().getAttributes().hasFnAttr(Attribute::Naked)) {
1794 const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
1796 if (!AFI->isInterruptOrSignalHandler()) {
1801 RetOps.push_back(DAG.getRegister(
Subtarget.getZeroRegister(), MVT::i8));
1805 AFI->isInterruptOrSignalHandler() ? AVRISD::RETI_GLUE : AVRISD::RET_GLUE;
1809 if (Glue.getNode()) {
1810 RetOps.push_back(Glue);
1813 return DAG.getNode(RetOpc, dl, MVT::Other, RetOps);
1825 bool HasRepeatedOperand =
false;
1827 MachineRegisterInfo &RI =
F->getRegInfo();
1828 const TargetInstrInfo &
TII = *
Subtarget.getInstrInfo();
1831 switch (
MI.getOpcode()) {
1836 RC = &AVR::GPR8RegClass;
1837 HasRepeatedOperand =
true;
1841 RC = &AVR::DREGSRegClass;
1845 RC = &AVR::GPR8RegClass;
1849 RC = &AVR::DREGSRegClass;
1853 RC = &AVR::GPR8RegClass;
1857 RC = &AVR::DREGSRegClass;
1860 Opc =
Tiny ? AVR::ROLBRdR17 : AVR::ROLBRdR1;
1861 RC = &AVR::GPR8RegClass;
1865 RC = &AVR::DREGSRegClass;
1869 RC = &AVR::GPR8RegClass;
1873 RC = &AVR::DREGSRegClass;
1877 const BasicBlock *LLVM_BB = BB->getBasicBlock();
1880 for (
I = BB->getIterator();
I !=
F->end() && &(*
I) != BB; ++
I)
1886 MachineBasicBlock *LoopBB =
F->CreateMachineBasicBlock(LLVM_BB);
1887 MachineBasicBlock *CheckBB =
F->CreateMachineBasicBlock(LLVM_BB);
1888 MachineBasicBlock *RemBB =
F->CreateMachineBasicBlock(LLVM_BB);
1890 F->insert(
I, LoopBB);
1891 F->insert(
I, CheckBB);
1892 F->insert(
I, RemBB);
1898 RemBB->transferSuccessorsAndUpdatePHIs(BB);
1901 BB->addSuccessor(CheckBB);
1902 LoopBB->addSuccessor(CheckBB);
1903 CheckBB->addSuccessor(LoopBB);
1904 CheckBB->addSuccessor(RemBB);
1906 Register ShiftAmtReg = RI.createVirtualRegister(&AVR::GPR8RegClass);
1907 Register ShiftAmtReg2 = RI.createVirtualRegister(&AVR::GPR8RegClass);
1908 Register ShiftReg = RI.createVirtualRegister(RC);
1909 Register ShiftReg2 = RI.createVirtualRegister(RC);
1910 Register ShiftAmtSrcReg =
MI.getOperand(2).getReg();
1921 if (HasRepeatedOperand)
1922 ShiftMI.
addReg(ShiftReg);
1930 BuildMI(CheckBB, dl,
TII.get(AVR::PHI), ShiftReg)
1935 BuildMI(CheckBB, dl,
TII.get(AVR::PHI), ShiftAmtReg)
1940 BuildMI(CheckBB, dl,
TII.get(AVR::PHI), DstReg)
1946 BuildMI(CheckBB, dl,
TII.get(AVR::DECRd), ShiftAmtReg2).
addReg(ShiftAmtReg);
1949 MI.eraseFromParent();
1976 Register ZeroReg = MRI.createVirtualRegister(&AVR::GPR8RegClass);
1984 if (ShiftLeft && (ShiftAmt % 8) >= 6) {
1989 size_t ShiftRegsOffset = ShiftAmt / 8;
1990 size_t ShiftRegsSize = Regs.size() - ShiftRegsOffset;
1992 Regs.
slice(ShiftRegsOffset, ShiftRegsSize);
2000 Register LowByte = MRI.createVirtualRegister(&AVR::GPR8RegClass);
2004 if (ShiftAmt % 8 == 6) {
2006 Register NewLowByte = MRI.createVirtualRegister(&AVR::GPR8RegClass);
2008 LowByte = NewLowByte;
2012 for (
size_t I = 0;
I < Regs.size();
I++) {
2013 int ShiftRegsIdx =
I + 1;
2014 if (ShiftRegsIdx < (
int)ShiftRegs.
size()) {
2015 Regs[
I] = ShiftRegs[ShiftRegsIdx];
2016 }
else if (ShiftRegsIdx == (
int)ShiftRegs.
size()) {
2017 Regs[
I] = std::pair(LowByte, 0);
2019 Regs[
I] = std::pair(ZeroReg, 0);
2027 if (!ShiftLeft && (ShiftAmt % 8) >= 6) {
2030 size_t ShiftRegsSize = Regs.size() - (ShiftAmt / 8);
2032 Regs.
slice(0, ShiftRegsSize);
2041 Register HighByte = MRI.createVirtualRegister(&AVR::GPR8RegClass);
2043 if (ArithmeticShift) {
2061 if (ShiftAmt % 8 == 6) {
2064 Register NewExt = MRI.createVirtualRegister(&AVR::GPR8RegClass);
2072 for (
int I = Regs.size() - 1;
I >= 0;
I--) {
2073 int ShiftRegsIdx =
I - (Regs.size() - ShiftRegs.
size()) - 1;
2074 if (ShiftRegsIdx >= 0) {
2075 Regs[
I] = ShiftRegs[ShiftRegsIdx];
2076 }
else if (ShiftRegsIdx == -1) {
2077 Regs[
I] = std::pair(HighByte, 0);
2079 Regs[
I] = std::pair(ExtByte, 0);
2088 while (ShiftLeft && ShiftAmt >= 8) {
2090 for (
size_t I = 0;
I < Regs.size() - 1;
I++) {
2091 Regs[
I] = Regs[
I + 1];
2095 Regs[Regs.size() - 1] = std::pair(ZeroReg, 0);
2098 Regs = Regs.drop_back(1);
2105 if (!ShiftLeft && ShiftAmt >= 8) {
2106 if (ArithmeticShift) {
2108 ShrExtendReg = MRI.createVirtualRegister(&AVR::GPR8RegClass);
2109 Register Tmp = MRI.createVirtualRegister(&AVR::GPR8RegClass);
2111 .
addReg(Regs[0].first, {}, Regs[0].second)
2112 .addReg(Regs[0].first, {}, Regs[0].second);
2113 BuildMI(*BB,
MI, dl,
TII.get(AVR::SBCRdRr), ShrExtendReg)
2117 ShrExtendReg = ZeroReg;
2119 for (; ShiftAmt >= 8; ShiftAmt -= 8) {
2121 for (
size_t I = Regs.size() - 1;
I != 0;
I--) {
2122 Regs[
I] = Regs[
I - 1];
2126 Regs[0] = std::pair(ShrExtendReg, 0);
2129 Regs = Regs.drop_front(1);
2134 assert((ShiftAmt < 8) &&
"Unexpect shift amount");
2154 if (!ArithmeticShift && ShiftAmt >= 4) {
2156 for (
size_t I = 0;
I < Regs.size();
I++) {
2157 size_t Idx = ShiftLeft ?
I : Regs.size() -
I - 1;
2158 Register SwapReg = MRI.createVirtualRegister(&AVR::LD8RegClass);
2160 .
addReg(Regs[Idx].first, {}, Regs[Idx].second);
2162 Register R = MRI.createVirtualRegister(&AVR::GPR8RegClass);
2168 Register AndReg = MRI.createVirtualRegister(&AVR::LD8RegClass);
2171 .
addImm(ShiftLeft ? 0xf0 : 0x0f);
2173 Register R = MRI.createVirtualRegister(&AVR::GPR8RegClass);
2177 size_t PrevIdx = ShiftLeft ? Idx - 1 : Idx + 1;
2178 Regs[PrevIdx] = std::pair(R, 0);
2181 Regs[Idx] = std::pair(AndReg, 0);
2188 while (ShiftLeft && ShiftAmt) {
2190 for (ssize_t
I = Regs.size() - 1;
I >= 0;
I--) {
2191 Register Out = MRI.createVirtualRegister(&AVR::GPR8RegClass);
2194 if (
I == (ssize_t)Regs.size() - 1) {
2196 .
addReg(In, {}, InSubreg)
2197 .addReg(In, {}, InSubreg);
2200 .
addReg(In, {}, InSubreg)
2201 .addReg(In, {}, InSubreg);
2203 Regs[
I] = std::pair(Out, 0);
2207 while (!ShiftLeft && ShiftAmt) {
2209 for (
size_t I = 0;
I < Regs.size();
I++) {
2210 Register Out = MRI.createVirtualRegister(&AVR::GPR8RegClass);
2214 unsigned Opc = ArithmeticShift ? AVR::ASRRd : AVR::LSRRd;
2219 Regs[
I] = std::pair(Out, 0);
2224 if (ShiftAmt != 0) {
2231AVRTargetLowering::insertWideShift(MachineInstr &
MI,
2232 MachineBasicBlock *BB)
const {
2238 int64_t ShiftAmt =
MI.getOperand(4).getImm();
2240 switch (
MI.getOpcode()) {
2253 std::array<std::pair<Register, int>, 4>
Registers = {
2254 std::pair(
MI.getOperand(3).getReg(), AVR::sub_hi),
2255 std::pair(
MI.getOperand(3).getReg(), AVR::sub_lo),
2256 std::pair(
MI.getOperand(2).getReg(), AVR::sub_hi),
2257 std::pair(
MI.getOperand(2).getReg(), AVR::sub_lo),
2276 (
Opc !=
ISD::SRA || (ShiftAmt < 16 || ShiftAmt >= 22))) {
2278 BuildMI(*BB,
MI, dl,
TII.get(AVR::REG_SEQUENCE),
MI.getOperand(0).getReg())
2280 .addImm(AVR::sub_lo)
2282 .addImm(AVR::sub_hi);
2283 BuildMI(*BB,
MI, dl,
TII.get(AVR::REG_SEQUENCE),
MI.getOperand(1).getReg())
2285 .addImm(AVR::sub_lo)
2287 .addImm(AVR::sub_hi);
2290 BuildMI(*BB,
MI, dl,
TII.get(AVR::REG_SEQUENCE),
MI.getOperand(1).getReg())
2292 .addImm(AVR::sub_hi)
2294 .addImm(AVR::sub_lo);
2295 BuildMI(*BB,
MI, dl,
TII.get(AVR::REG_SEQUENCE),
MI.getOperand(0).getReg())
2297 .addImm(AVR::sub_hi)
2299 .addImm(AVR::sub_lo);
2303 MI.eraseFromParent();
2308 if (
I->getOpcode() == AVR::COPY) {
2309 Register SrcReg =
I->getOperand(1).getReg();
2310 return (SrcReg == AVR::R0 || SrcReg == AVR::R1);
2319MachineBasicBlock *AVRTargetLowering::insertMul(MachineInstr &
MI,
2320 MachineBasicBlock *BB)
const {
2328 BuildMI(*BB,
I,
MI.getDebugLoc(),
TII.get(AVR::EORRdRr), AVR::R1)
2338 const TargetInstrInfo &
TII = *
Subtarget.getInstrInfo();
2341 .
add(
MI.getOperand(0))
2343 MI.eraseFromParent();
2352 const TargetInstrInfo &
TII = *
Subtarget.getInstrInfo();
2366 (Width == 8) ? &AVR::GPR8RegClass : &AVR::DREGSNOZRegClass;
2367 unsigned LoadOpcode = (Width == 8) ? AVR::LDRdPtr : AVR::LDWRdPtr;
2368 unsigned StoreOpcode = (Width == 8) ? AVR::STPtrRr : AVR::STWPtrRr;
2376 BuildMI(*BB,
I, dl,
TII.get(LoadOpcode),
MI.getOperand(0).getReg())
2377 .
add(
MI.getOperand(1));
2383 .
add(
MI.getOperand(2));
2387 .
add(
MI.getOperand(1))
2396 MI.eraseFromParent();
2403 int Opc =
MI.getOpcode();
2419 return insertShift(
MI,
MBB, STI.hasTinyEncoding());
2423 return insertWideShift(
MI,
MBB);
2426 return insertMul(
MI,
MBB);
2428 return insertCopyZero(
MI,
MBB);
2429 case AVR::AtomicLoadAdd8:
2430 return insertAtomicArithmeticOp(
MI,
MBB, AVR::ADDRdRr, 8);
2431 case AVR::AtomicLoadAdd16:
2432 return insertAtomicArithmeticOp(
MI,
MBB, AVR::ADDWRdRr, 16);
2433 case AVR::AtomicLoadSub8:
2434 return insertAtomicArithmeticOp(
MI,
MBB, AVR::SUBRdRr, 8);
2435 case AVR::AtomicLoadSub16:
2436 return insertAtomicArithmeticOp(
MI,
MBB, AVR::SUBWRdRr, 16);
2437 case AVR::AtomicLoadAnd8:
2438 return insertAtomicArithmeticOp(
MI,
MBB, AVR::ANDRdRr, 8);
2439 case AVR::AtomicLoadAnd16:
2440 return insertAtomicArithmeticOp(
MI,
MBB, AVR::ANDWRdRr, 16);
2441 case AVR::AtomicLoadOr8:
2442 return insertAtomicArithmeticOp(
MI,
MBB, AVR::ORRdRr, 8);
2443 case AVR::AtomicLoadOr16:
2444 return insertAtomicArithmeticOp(
MI,
MBB, AVR::ORWRdRr, 16);
2445 case AVR::AtomicLoadXor8:
2446 return insertAtomicArithmeticOp(
MI,
MBB, AVR::EORRdRr, 8);
2447 case AVR::AtomicLoadXor16:
2448 return insertAtomicArithmeticOp(
MI,
MBB, AVR::EORWRdRr, 16);
2451 assert((
Opc == AVR::Select16 ||
Opc == AVR::Select8) &&
2452 "Unexpected instr type to insert");
2473 if (FallThrough !=
nullptr) {
2489 unsigned CallFrameSize =
TII.getCallFrameSizeAt(
MI);
2503 MBB->addSuccessor(falseMBB);
2504 MBB->addSuccessor(trueMBB);
2512 MI.getOperand(0).getReg())
2518 MI.eraseFromParent();
2528 if (Constraint.
size() == 1) {
2530 switch (Constraint[0]) {
2573 switch (ConstraintCode[0]) {
2584 Value *CallOperandVal =
info.CallOperandVal;
2589 if (!CallOperandVal) {
2594 switch (*constraint) {
2633 if ((
C->getSExtValue() >= -63) && (
C->getSExtValue() <= 0)) {
2640 if (
C->getZExtValue() == 2) {
2647 if (
C->getZExtValue() == 0) {
2661 if (
C->getSExtValue() == -1) {
2668 if ((
C->getZExtValue() == 8) || (
C->getZExtValue() == 16) ||
2669 (
C->getZExtValue() == 24)) {
2676 if (
C->getZExtValue() == 1) {
2683 if ((
C->getSExtValue() >= -6) && (
C->getSExtValue() <= 5)) {
2696std::pair<unsigned, const TargetRegisterClass *>
2700 if (Constraint.
size() == 1) {
2701 switch (Constraint[0]) {
2704 return std::make_pair(0U, &AVR::LD8loRegClass);
2705 else if (VT == MVT::i16)
2706 return std::make_pair(0U, &AVR::DREGSLD8loRegClass);
2709 if (VT == MVT::i8 || VT == MVT::i16)
2710 return std::make_pair(0U, &AVR::PTRDISPREGSRegClass);
2714 return std::make_pair(0U, &AVR::LD8RegClass);
2715 else if (VT == MVT::i16)
2716 return std::make_pair(0U, &AVR::DLDREGSRegClass);
2720 return std::make_pair(0U, &AVR::GPR8loRegClass);
2721 else if (VT == MVT::i16)
2722 return std::make_pair(0U, &AVR::DREGSloRegClass);
2725 if (VT == MVT::i8 || VT == MVT::i16)
2726 return std::make_pair(0U, &AVR::PTRREGSRegClass);
2729 return std::make_pair(0U, &AVR::GPRSPRegClass);
2732 return std::make_pair(0U, &AVR::GPR8RegClass);
2733 else if (VT == MVT::i16)
2734 return std::make_pair(0U, &AVR::DREGSRegClass);
2738 return std::make_pair(
unsigned(
Subtarget.getTmpRegister()),
2739 &AVR::GPR8RegClass);
2742 if (VT == MVT::i8 || VT == MVT::i16)
2743 return std::make_pair(0U, &AVR::IWREGSRegClass);
2747 if (VT == MVT::i8 || VT == MVT::i16)
2748 return std::make_pair(
unsigned(AVR::R27R26), &AVR::PTRREGSRegClass);
2752 if (VT == MVT::i8 || VT == MVT::i16)
2753 return std::make_pair(
unsigned(AVR::R29R28), &AVR::PTRREGSRegClass);
2757 if (VT == MVT::i8 || VT == MVT::i16)
2758 return std::make_pair(
unsigned(AVR::R31R30), &AVR::PTRREGSRegClass);
2766 Subtarget.getRegisterInfo(), Constraint, VT);
2771 std::vector<SDValue> &
Ops,
2775 EVT Ty =
Op.getValueType();
2778 if (Constraint.
size() != 1) {
2782 char ConstraintLetter = Constraint[0];
2783 switch (ConstraintLetter) {
2801 int64_t CVal64 =
C->getSExtValue();
2803 switch (ConstraintLetter) {
2810 if (CVal64 < -63 || CVal64 > 0)
2830 if (Ty.getSimpleVT() == MVT::i8) {
2841 if (CUVal64 != 8 && CUVal64 != 16 && CUVal64 != 24)
2851 if (CVal64 < -6 || CVal64 > 5)
2861 if (!FC || !FC->isZero())
2868 if (Result.getNode()) {
2869 Ops.push_back(Result);
2882 .
Case(
"r0", AVR::R0)
2883 .
Case(
"r1", AVR::R1)
2887 .
Case(
"r0", AVR::R1R0)
2888 .
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
const AVRRegisterInfo * getRegisterInfo() 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 setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
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.