177 if (!
Subtarget.supportsMultiplication()) {
214 EVT VT =
Op.getValueType();
217 "Expected power-of-2 shift amount");
220 if (!isa<ConstantSDNode>(
N->getOperand(1))) {
225 SDVTList ResTys = DAG.
getVTList(MVT::i16, MVT::i16);
232 uint64_t ShiftAmount =
N->getConstantOperandVal(1);
233 if (ShiftAmount == 16) {
238 switch (
Op.getOpcode()) {
251 switch (
Op.getOpcode()) {
270 if (!isa<ConstantSDNode>(
N->getOperand(1))) {
271 switch (
Op.getOpcode()) {
275 return DAG.
getNode(AVRISD::LSLLOOP, dl, VT,
N->getOperand(0),
278 return DAG.
getNode(AVRISD::LSRLOOP, dl, VT,
N->getOperand(0),
281 SDValue Amt =
N->getOperand(1);
282 EVT AmtVT = Amt.getValueType();
285 return DAG.
getNode(AVRISD::ROLLOOP, dl, VT,
N->getOperand(0), Amt);
288 SDValue Amt =
N->getOperand(1);
289 EVT AmtVT = Amt.getValueType();
292 return DAG.
getNode(AVRISD::RORLOOP, dl, VT,
N->getOperand(0), Amt);
295 return DAG.
getNode(AVRISD::ASRLOOP, dl, VT,
N->getOperand(0),
300 uint64_t ShiftAmount =
N->getConstantOperandVal(1);
301 SDValue Victim =
N->getOperand(0);
303 switch (
Op.getOpcode()) {
327 if (
Op.getOpcode() ==
ISD::SHL && 4 <= ShiftAmount && ShiftAmount < 7) {
329 Victim = DAG.
getNode(AVRISD::SWAP, dl, VT, Victim);
333 }
else if (
Op.getOpcode() ==
ISD::SRL && 4 <= ShiftAmount &&
336 Victim = DAG.
getNode(AVRISD::SWAP, dl, VT, Victim);
340 }
else if (
Op.getOpcode() ==
ISD::SHL && ShiftAmount == 7) {
342 Victim = DAG.
getNode(AVRISD::LSLBN, dl, VT, Victim,
345 }
else if (
Op.getOpcode() ==
ISD::SRL && ShiftAmount == 7) {
347 Victim = DAG.
getNode(AVRISD::LSRBN, dl, VT, Victim,
350 }
else if (
Op.getOpcode() ==
ISD::SRA && ShiftAmount == 6) {
352 Victim = DAG.
getNode(AVRISD::ASRBN, dl, VT, Victim,
355 }
else if (
Op.getOpcode() ==
ISD::SRA && ShiftAmount == 7) {
357 Victim = DAG.
getNode(AVRISD::ASRBN, dl, VT, Victim,
360 }
else if (
Op.getOpcode() ==
ISD::ROTL && ShiftAmount == 3) {
362 Victim = DAG.
getNode(AVRISD::SWAP, dl, VT, Victim);
363 Victim = DAG.
getNode(AVRISD::ROR, dl, VT, Victim);
365 }
else if (
Op.getOpcode() ==
ISD::ROTR && ShiftAmount == 3) {
367 Victim = DAG.
getNode(AVRISD::SWAP, dl, VT, Victim);
368 Victim = DAG.
getNode(AVRISD::ROL, dl, VT, Victim);
370 }
else if (
Op.getOpcode() ==
ISD::ROTL && ShiftAmount == 7) {
372 Victim = DAG.
getNode(AVRISD::ROR, dl, VT, Victim);
374 }
else if (
Op.getOpcode() ==
ISD::ROTR && ShiftAmount == 7) {
376 Victim = DAG.
getNode(AVRISD::ROL, dl, VT, Victim);
381 Victim = DAG.
getNode(AVRISD::SWAP, dl, VT, Victim);
387 switch (ShiftAmount) {
389 Victim = DAG.
getNode(AVRISD::ASRWN, dl, VT, Victim,
394 Victim = DAG.
getNode(AVRISD::ASRWN, dl, VT, Victim,
399 Victim = DAG.
getNode(AVRISD::ASRWN, dl, VT, Victim,
406 if (4 <= ShiftAmount && ShiftAmount < 8)
407 switch (
Op.getOpcode()) {
409 Victim = DAG.
getNode(AVRISD::LSLWN, dl, VT, Victim,
414 Victim = DAG.
getNode(AVRISD::LSRWN, dl, VT, Victim,
421 else if (8 <= ShiftAmount && ShiftAmount < 12)
422 switch (
Op.getOpcode()) {
424 Victim = DAG.
getNode(AVRISD::LSLWN, dl, VT, Victim,
428 Opc8 = AVRISD::LSLHI;
431 Victim = DAG.
getNode(AVRISD::LSRWN, dl, VT, Victim,
435 Opc8 = AVRISD::LSRLO;
438 Victim = DAG.
getNode(AVRISD::ASRWN, dl, VT, Victim,
442 Opc8 = AVRISD::ASRLO;
447 else if (12 <= ShiftAmount)
448 switch (
Op.getOpcode()) {
450 Victim = DAG.
getNode(AVRISD::LSLWN, dl, VT, Victim,
454 Opc8 = AVRISD::LSLHI;
457 Victim = DAG.
getNode(AVRISD::LSRWN, dl, VT, Victim,
461 Opc8 = AVRISD::LSRLO;
464 Victim = DAG.
getNode(AVRISD::ASRWN, dl, VT, Victim,
468 Opc8 = AVRISD::ASRLO;
475 while (ShiftAmount--) {
476 Victim = DAG.
getNode(Opc8, dl, VT, Victim);
482SDValue AVRTargetLowering::LowerDivRem(SDValue
Op, SelectionDAG &DAG)
const {
483 unsigned Opcode =
Op->getOpcode();
485 "Invalid opcode for Div/Rem lowering");
487 EVT VT =
Op->getValueType(0);
488 Type *Ty = VT.getTypeForEVT(*DAG.getContext());
491 switch (VT.getSimpleVT().SimpleTy) {
495 LC = IsSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
498 LC = IsSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
501 LC = IsSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
505 SDValue InChain = DAG.getEntryNode();
508 for (SDValue
const &Value :
Op->op_values()) {
509 TargetLowering::ArgListEntry
Entry(
510 Value,
Value.getValueType().getTypeForEVT(*DAG.getContext()));
511 Entry.IsSExt = IsSigned;
512 Entry.IsZExt = !IsSigned;
513 Args.push_back(Entry);
522 TargetLowering::CallLoweringInfo CLI(DAG);
527 .setSExtResult(IsSigned)
528 .setZExtResult(!IsSigned);
530 std::pair<SDValue, SDValue> CallInfo =
LowerCallTo(CLI);
531 return CallInfo.first;
534SDValue AVRTargetLowering::LowerGlobalAddress(SDValue
Op,
535 SelectionDAG &DAG)
const {
536 auto DL = DAG.getDataLayout();
538 const GlobalValue *GV = cast<GlobalAddressSDNode>(
Op)->getGlobal();
539 int64_t
Offset = cast<GlobalAddressSDNode>(
Op)->getOffset();
547SDValue AVRTargetLowering::LowerBlockAddress(SDValue
Op,
548 SelectionDAG &DAG)
const {
549 auto DL = DAG.getDataLayout();
550 const BlockAddress *BA = cast<BlockAddressSDNode>(
Op)->getBlockAddress();
578SDValue AVRTargetLowering::getAVRCmp(SDValue
LHS, SDValue
RHS,
579 SelectionDAG &DAG, SDLoc
DL)
const {
580 assert((
LHS.getSimpleValueType() ==
RHS.getSimpleValueType()) &&
581 "LHS and RHS have different types");
582 assert(((
LHS.getSimpleValueType() == MVT::i16) ||
583 (
LHS.getSimpleValueType() == MVT::i8)) &&
584 "invalid comparison type");
588 if (
LHS.getSimpleValueType() == MVT::i16 && isa<ConstantSDNode>(
RHS)) {
593 DAG.getIntPtrConstant(0,
DL));
595 DAG.getIntPtrConstant(1,
DL));
596 SDValue RHSlo = (Imm & 0xff) == 0
599 DAG.getIntPtrConstant(0,
DL));
600 SDValue RHShi = (Imm & 0xff00) == 0
603 DAG.getIntPtrConstant(1,
DL));
604 Cmp = DAG.getNode(AVRISD::CMP,
DL, MVT::Glue, LHSlo, RHSlo);
605 Cmp = DAG.getNode(AVRISD::CMPC,
DL, MVT::Glue, LHShi, RHShi, Cmp);
606 }
else if (
RHS.getSimpleValueType() == MVT::i16 && isa<ConstantSDNode>(
LHS)) {
610 SDValue LHSlo = (
Imm & 0xff) == 0
613 DAG.getIntPtrConstant(0,
DL));
614 SDValue LHShi = (
Imm & 0xff00) == 0
617 DAG.getIntPtrConstant(1,
DL));
619 DAG.getIntPtrConstant(0,
DL));
621 DAG.getIntPtrConstant(1,
DL));
622 Cmp = DAG.getNode(AVRISD::CMP,
DL, MVT::Glue, LHSlo, RHSlo);
623 Cmp = DAG.getNode(AVRISD::CMPC,
DL, MVT::Glue, LHShi, RHShi, Cmp);
626 Cmp = DAG.getNode(AVRISD::CMP,
DL, MVT::Glue,
LHS,
RHS);
635 SDValue &AVRcc, SelectionDAG &DAG,
638 EVT VT =
LHS.getValueType();
639 bool UseTest =
false;
651 if (
const ConstantSDNode *
C = dyn_cast<ConstantSDNode>(
RHS)) {
652 switch (
C->getSExtValue()) {
664 LHS = DAG.getConstant(0,
DL, VT);
671 RHS = DAG.getSignedConstant(
C->getSExtValue() + 1,
DL, VT);
684 if (
const ConstantSDNode *
C = dyn_cast<ConstantSDNode>(
RHS)) {
685 switch (
C->getSExtValue()) {
690 LHS = DAG.getConstant(0,
DL, VT);
714 if (
const ConstantSDNode *
C = dyn_cast<ConstantSDNode>(
RHS)) {
717 assert((!
C->isAllOnes()) &&
"integer overflow in comparison transform");
718 RHS = DAG.getConstant(
C->getZExtValue() + 1,
DL, VT);
731 if (VT == MVT::i32) {
733 DAG.getIntPtrConstant(0,
DL));
735 DAG.getIntPtrConstant(1,
DL));
737 DAG.getIntPtrConstant(0,
DL));
739 DAG.getIntPtrConstant(1,
DL));
744 DAG.getIntPtrConstant(1,
DL));
745 Cmp = DAG.getNode(AVRISD::TST,
DL, MVT::Glue, Top);
747 Cmp = getAVRCmp(LHSlo, RHSlo, DAG,
DL);
748 Cmp = DAG.getNode(AVRISD::CMPC,
DL, MVT::Glue, LHShi, RHShi, Cmp);
750 }
else if (VT == MVT::i64) {
752 DAG.getIntPtrConstant(0,
DL));
754 DAG.getIntPtrConstant(1,
DL));
757 DAG.getIntPtrConstant(0,
DL));
759 DAG.getIntPtrConstant(1,
DL));
761 DAG.getIntPtrConstant(0,
DL));
763 DAG.getIntPtrConstant(1,
DL));
766 DAG.getIntPtrConstant(0,
DL));
768 DAG.getIntPtrConstant(1,
DL));
771 DAG.getIntPtrConstant(0,
DL));
773 DAG.getIntPtrConstant(1,
DL));
775 DAG.getIntPtrConstant(0,
DL));
777 DAG.getIntPtrConstant(1,
DL));
782 DAG.getIntPtrConstant(1,
DL));
783 Cmp = DAG.getNode(AVRISD::TST,
DL, MVT::Glue, Top);
785 Cmp = getAVRCmp(LHS0, RHS0, DAG,
DL);
786 Cmp = DAG.getNode(AVRISD::CMPC,
DL, MVT::Glue, LHS1, RHS1, Cmp);
787 Cmp = DAG.getNode(AVRISD::CMPC,
DL, MVT::Glue, LHS2, RHS2, Cmp);
788 Cmp = DAG.getNode(AVRISD::CMPC,
DL, MVT::Glue, LHS3, RHS3, Cmp);
790 }
else if (VT == MVT::i8 || VT == MVT::i16) {
793 Cmp = DAG.getNode(AVRISD::TST,
DL, MVT::Glue,
797 LHS, DAG.getIntPtrConstant(1,
DL)));
813SDValue AVRTargetLowering::LowerBR_CC(SDValue
Op, SelectionDAG &DAG)
const {
814 SDValue Chain =
Op.getOperand(0);
816 SDValue
LHS =
Op.getOperand(2);
817 SDValue
RHS =
Op.getOperand(3);
818 SDValue Dest =
Op.getOperand(4);
822 SDValue
Cmp = getAVRCmp(
LHS,
RHS, CC, TargetCC, DAG, dl);
824 return DAG.getNode(AVRISD::BRCOND, dl, MVT::Other, Chain, Dest, TargetCC,
828SDValue AVRTargetLowering::LowerSELECT_CC(SDValue
Op, SelectionDAG &DAG)
const {
829 SDValue
LHS =
Op.getOperand(0);
830 SDValue
RHS =
Op.getOperand(1);
831 SDValue TrueV =
Op.getOperand(2);
832 SDValue FalseV =
Op.getOperand(3);
837 SDValue
Cmp = getAVRCmp(
LHS,
RHS, CC, TargetCC, DAG, dl);
839 SDValue Ops[] = {TrueV, FalseV, TargetCC,
Cmp};
841 return DAG.getNode(AVRISD::SELECT_CC, dl,
Op.getValueType(), Ops);
844SDValue AVRTargetLowering::LowerSETCC(SDValue
Op, SelectionDAG &DAG)
const {
845 SDValue
LHS =
Op.getOperand(0);
846 SDValue
RHS =
Op.getOperand(1);
851 SDValue
Cmp = getAVRCmp(
LHS,
RHS, CC, TargetCC, DAG,
DL);
853 SDValue TrueV = DAG.getConstant(1,
DL,
Op.getValueType());
854 SDValue FalseV = DAG.getConstant(0,
DL,
Op.getValueType());
855 SDValue Ops[] = {TrueV, FalseV, TargetCC,
Cmp};
857 return DAG.getNode(AVRISD::SELECT_CC,
DL,
Op.getValueType(), Ops);
860SDValue AVRTargetLowering::LowerVASTART(SDValue
Op, SelectionDAG &DAG)
const {
861 const MachineFunction &MF = DAG.getMachineFunction();
862 const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
863 const Value *SV = cast<SrcValueSDNode>(
Op.getOperand(2))->getValue();
864 auto DL = DAG.getDataLayout();
869 SDValue FI = DAG.getFrameIndex(AFI->getVarArgsFrameIndex(),
getPointerTy(
DL));
871 return DAG.getStore(
Op.getOperand(0), dl, FI,
Op.getOperand(1),
872 MachinePointerInfo(SV));
876SDValue AVRTargetLowering::LowerINLINEASM(SDValue
Op, SelectionDAG &DAG)
const {
892 SmallVector<SDValue, 8> Ops;
893 SDNode *
N =
Op.getNode();
895 for (
unsigned I = 0;
I <
N->getNumOperands();
I++) {
896 SDValue Operand =
N->getOperand(
I);
897 if (Operand.getValueType() == MVT::Glue) {
902 Ops.push_back(Operand);
906 Ops.push_back(DAG.getTargetConstant(Flags, dl, MVT::i32));
907 Ops.push_back(ZeroReg);
914 SDValue
New = DAG.getNode(
N->getOpcode(), dl,
N->getVTList(), Ops);
915 DAG.ReplaceAllUsesOfValueWith(
Op, New);
916 DAG.ReplaceAllUsesOfValueWith(
Op.getValue(1),
New.getValue(1));
922 switch (
Op.getOpcode()) {
930 return LowerShifts(
Op, DAG);
932 return LowerGlobalAddress(
Op, DAG);
934 return LowerBlockAddress(
Op, DAG);
936 return LowerBR_CC(
Op, DAG);
938 return LowerSELECT_CC(
Op, DAG);
940 return LowerSETCC(
Op, DAG);
942 return LowerVASTART(
Op, DAG);
945 return LowerDivRem(
Op, DAG);
947 return LowerINLINEASM(
Op, DAG);
960 switch (
N->getOpcode()) {
1022 if (
const LoadSDNode *LD = dyn_cast<LoadSDNode>(
N)) {
1023 VT = LD->getMemoryVT();
1024 Op = LD->getBasePtr().getNode();
1030 }
else if (
const StoreSDNode *ST = dyn_cast<StoreSDNode>(
N)) {
1031 VT = ST->getMemoryVT();
1032 Op = ST->getBasePtr().getNode();
1040 if (VT != MVT::i8 && VT != MVT::i16) {
1049 int RHSC =
RHS->getSExtValue();
1053 if ((VT == MVT::i16 && RHSC != -2) || (VT == MVT::i8 && RHSC != -1)) {
1057 Base =
Op->getOperand(0);
1079 if (
const LoadSDNode *LD = dyn_cast<LoadSDNode>(
N)) {
1080 VT = LD->getMemoryVT();
1081 Ptr = LD->getBasePtr();
1084 }
else if (
const StoreSDNode *ST = dyn_cast<StoreSDNode>(
N)) {
1085 VT = ST->getMemoryVT();
1086 Ptr = ST->getBasePtr();
1094 if (VT == MVT::i16 && !
Subtarget.hasLowByteFirst())
1100 if (VT != MVT::i8 && VT != MVT::i16) {
1109 int RHSC =
RHS->getSExtValue();
1112 if ((VT == MVT::i16 && RHSC != 2) || (VT == MVT::i8 && RHSC != 1)) {
1118 if (
const LoadSDNode *LD = dyn_cast<LoadSDNode>(
N))
1122 Base =
Op->getOperand(0);
1147#include "AVRGenCallingConv.inc"
1152 AVR::R25, AVR::R24, AVR::R23, AVR::R22, AVR::R21, AVR::R20,
1153 AVR::R19, AVR::R18, AVR::R17, AVR::R16, AVR::R15, AVR::R14,
1154 AVR::R13, AVR::R12, AVR::R11, AVR::R10, AVR::R9, AVR::R8};
1156 AVR::R22, AVR::R21, AVR::R20};
1158 AVR::R26R25, AVR::R25R24, AVR::R24R23, AVR::R23R22, AVR::R22R21,
1159 AVR::R21R20, AVR::R20R19, AVR::R19R18, AVR::R18R17, AVR::R17R16,
1160 AVR::R16R15, AVR::R15R14, AVR::R14R13, AVR::R13R12, AVR::R12R11,
1161 AVR::R11R10, AVR::R10R9, AVR::R9R8};
1163 AVR::R24R23, AVR::R23R22,
1164 AVR::R22R21, AVR::R21R20};
1167 "8-bit and 16-bit register arrays must be of equal length");
1169 "8-bit and 16-bit register arrays must be of equal length");
1175template <
typename ArgT>
1192 unsigned NumArgs = Args.size();
1195 int RegLastIdx = -1;
1197 bool UseStack =
false;
1198 for (
unsigned i = 0; i != NumArgs;) {
1199 MVT VT = Args[i].VT;
1204 unsigned ArgIndex = Args[i].OrigArgIndex;
1207 for (; j != NumArgs; ++j) {
1208 if (Args[j].OrigArgIndex != ArgIndex)
1210 TotalBytes += Args[j].VT.getStoreSize();
1213 TotalBytes =
alignTo(TotalBytes, 2);
1215 if (TotalBytes == 0)
1218 unsigned RegIdx = RegLastIdx + TotalBytes;
1219 RegLastIdx = RegIdx;
1221 if (RegIdx >= RegList8.
size()) {
1224 for (; i != j; ++i) {
1225 MVT VT = Args[i].VT;
1235 if (VT == MVT::i8) {
1237 }
else if (VT == MVT::i16) {
1241 "calling convention can only manage i8 and i16 types");
1243 assert(
Reg &&
"register not available in calling convention");
1254template <
typename ArgT>
1257 unsigned TotalBytes = 0;
1259 for (
const ArgT &Arg : Args) {
1260 TotalBytes += Arg.VT.getStoreSize();
1268template <
typename ArgT>
1271 unsigned NumArgs = Args.size();
1275 assert(TotalBytes <= 4 &&
1276 "return values greater than 4 bytes cannot be lowered on AVRTiny");
1278 assert(TotalBytes <= 8 &&
1279 "return values greater than 8 bytes cannot be lowered on AVR");
1294 if (TotalBytes > 4) {
1297 TotalBytes =
alignTo(TotalBytes, 2);
1301 int RegIdx = TotalBytes - 1;
1302 for (
unsigned i = 0; i != NumArgs; ++i) {
1303 MVT VT = Args[i].VT;
1305 if (VT == MVT::i8) {
1307 }
else if (VT == MVT::i16) {
1312 assert(
Reg &&
"register not available in calling convention");
1319SDValue AVRTargetLowering::LowerFormalArguments(
1321 const SmallVectorImpl<ISD::InputArg> &Ins,
const SDLoc &dl,
1322 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals)
const {
1323 MachineFunction &MF = DAG.getMachineFunction();
1324 MachineFrameInfo &MFI = MF.getFrameInfo();
1325 auto DL = DAG.getDataLayout();
1328 SmallVector<CCValAssign, 16> ArgLocs;
1329 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
1334 CCInfo.AnalyzeFormalArguments(Ins, ArgCC_AVR_Vararg);
1341 for (CCValAssign &VA : ArgLocs) {
1344 if (VA.isRegLoc()) {
1345 EVT RegVT = VA.getLocVT();
1346 const TargetRegisterClass *RC;
1347 if (RegVT == MVT::i8) {
1348 RC = &AVR::GPR8RegClass;
1349 }
else if (RegVT == MVT::i16) {
1350 RC = &AVR::DREGSRegClass;
1356 ArgValue = DAG.getCopyFromReg(Chain, dl,
Reg, RegVT);
1364 switch (VA.getLocInfo()) {
1370 ArgValue = DAG.getNode(
ISD::BITCAST, dl, VA.getValVT(), ArgValue);
1374 DAG.getValueType(VA.getValVT()));
1375 ArgValue = DAG.getNode(
ISD::TRUNCATE, dl, VA.getValVT(), ArgValue);
1379 DAG.getValueType(VA.getValVT()));
1380 ArgValue = DAG.getNode(
ISD::TRUNCATE, dl, VA.getValVT(), ArgValue);
1384 InVals.push_back(ArgValue);
1389 EVT LocVT = VA.getLocVT();
1392 int FI = MFI.CreateFixedObject(LocVT.getSizeInBits() / 8,
1393 VA.getLocMemOffset(),
true);
1398 InVals.push_back(DAG.getLoad(LocVT, dl, Chain, FIN,
1406 unsigned StackSize = CCInfo.getStackSize();
1407 AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
1409 AFI->setVarArgsFrameIndex(MFI.CreateFixedObject(2, StackSize,
true));
1419SDValue AVRTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
1420 SmallVectorImpl<SDValue> &InVals)
const {
1421 SelectionDAG &DAG = CLI.DAG;
1423 SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
1424 SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
1425 SmallVectorImpl<ISD::InputArg> &
Ins = CLI.Ins;
1426 SDValue Chain = CLI.Chain;
1427 SDValue
Callee = CLI.Callee;
1428 bool &isTailCall = CLI.IsTailCall;
1430 bool isVarArg = CLI.IsVarArg;
1432 MachineFunction &MF = DAG.getMachineFunction();
1438 SmallVector<CCValAssign, 16> ArgLocs;
1439 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
1446 if (
const GlobalAddressSDNode *
G = dyn_cast<GlobalAddressSDNode>(Callee)) {
1447 const GlobalValue *GV =
G->getGlobal();
1448 if (isa<Function>(GV))
1449 F = cast<Function>(GV);
1451 DAG.getTargetGlobalAddress(GV,
DL,
getPointerTy(DAG.getDataLayout()));
1452 }
else if (
const ExternalSymbolSDNode *ES =
1453 dyn_cast<ExternalSymbolSDNode>(Callee)) {
1454 Callee = DAG.getTargetExternalSymbol(ES->getSymbol(),
1460 CCInfo.AnalyzeCallOperands(Outs, ArgCC_AVR_Vararg);
1467 unsigned NumBytes = CCInfo.getStackSize();
1469 Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0,
DL);
1471 SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass;
1475 bool HasStackArgs =
false;
1476 for (AI = 0, AE = ArgLocs.size(); AI != AE; ++AI) {
1477 CCValAssign &VA = ArgLocs[AI];
1478 EVT RegVT = VA.getLocVT();
1479 SDValue Arg = OutVals[AI];
1482 switch (VA.getLocInfo()) {
1503 if (VA.isMemLoc()) {
1504 HasStackArgs =
true;
1510 RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
1520 SmallVector<SDValue, 8> MemOpChains;
1521 for (; AI != AE; AI++) {
1522 CCValAssign &VA = ArgLocs[AI];
1523 SDValue Arg = OutVals[AI];
1528 SDValue PtrOff = DAG.getNode(
1530 DAG.getRegister(AVR::SP,
getPointerTy(DAG.getDataLayout())),
1531 DAG.getIntPtrConstant(VA.getLocMemOffset() + 1,
DL));
1533 MemOpChains.push_back(
1534 DAG.getStore(Chain,
DL, Arg, PtrOff,
1538 if (!MemOpChains.empty())
1546 for (
auto Reg : RegsToPass) {
1547 Chain = DAG.getCopyToReg(Chain,
DL,
Reg.first,
Reg.second, InGlue);
1548 InGlue = Chain.getValue(1);
1552 SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
1553 SmallVector<SDValue, 8> Ops;
1554 Ops.push_back(Chain);
1555 Ops.push_back(Callee);
1559 for (
auto Reg : RegsToPass) {
1560 Ops.push_back(DAG.getRegister(
Reg.first,
Reg.second.getValueType()));
1570 TRI->getCallPreservedMask(DAG.getMachineFunction(), CallConv);
1571 assert(Mask &&
"Missing call preserved mask for calling convention");
1572 Ops.push_back(DAG.getRegisterMask(Mask));
1574 if (InGlue.getNode()) {
1575 Ops.push_back(InGlue);
1578 Chain = DAG.getNode(AVRISD::CALL,
DL, NodeTys, Ops);
1579 InGlue = Chain.getValue(1);
1582 Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, InGlue,
DL);
1585 InGlue = Chain.getValue(1);
1590 return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins,
DL, DAG,
1597SDValue AVRTargetLowering::LowerCallResult(
1598 SDValue Chain, SDValue InGlue,
CallingConv::ID CallConv,
bool isVarArg,
1599 const SmallVectorImpl<ISD::InputArg> &Ins,
const SDLoc &dl,
1600 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals)
const {
1603 SmallVector<CCValAssign, 16> RVLocs;
1604 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
1609 CCInfo.AnalyzeCallResult(Ins, RetCC_AVR_BUILTIN);
1615 for (CCValAssign
const &RVLoc : RVLocs) {
1616 Chain = DAG.getCopyFromReg(Chain, dl, RVLoc.getLocReg(), RVLoc.getValVT(),
1619 InGlue = Chain.getValue(2);
1620 InVals.push_back(Chain.getValue(0));
1630bool AVRTargetLowering::CanLowerReturn(
1632 const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context,
1633 const Type *
RetTy)
const {
1635 SmallVector<CCValAssign, 16> RVLocs;
1636 CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context);
1637 return CCInfo.CheckReturn(Outs, RetCC_AVR_BUILTIN);
1645AVRTargetLowering::LowerReturn(SDValue Chain,
CallingConv::ID CallConv,
1647 const SmallVectorImpl<ISD::OutputArg> &Outs,
1648 const SmallVectorImpl<SDValue> &OutVals,
1649 const SDLoc &dl, SelectionDAG &DAG)
const {
1651 SmallVector<CCValAssign, 16> RVLocs;
1654 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
1657 MachineFunction &MF = DAG.getMachineFunction();
1661 CCInfo.AnalyzeReturn(Outs, RetCC_AVR_BUILTIN);
1667 SmallVector<SDValue, 4> RetOps(1, Chain);
1669 for (
unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
1670 CCValAssign &VA = RVLocs[i];
1671 assert(VA.isRegLoc() &&
"Can only return in registers!");
1673 Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Glue);
1676 Glue = Chain.getValue(1);
1677 RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
1682 if (MF.getFunction().getAttributes().hasFnAttr(Attribute::Naked)) {
1686 const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
1688 if (!AFI->isInterruptOrSignalHandler()) {
1697 AFI->isInterruptOrSignalHandler() ? AVRISD::RETI_GLUE : AVRISD::RET_GLUE;
1701 if (Glue.getNode()) {
1702 RetOps.push_back(Glue);
1705 return DAG.getNode(RetOpc, dl, MVT::Other, RetOps);
1712MachineBasicBlock *AVRTargetLowering::insertShift(MachineInstr &
MI,
1713 MachineBasicBlock *BB,
1716 const TargetRegisterClass *RC;
1717 bool HasRepeatedOperand =
false;
1718 MachineFunction *
F = BB->getParent();
1719 MachineRegisterInfo &RI =
F->getRegInfo();
1723 switch (
MI.getOpcode()) {
1728 RC = &AVR::GPR8RegClass;
1729 HasRepeatedOperand =
true;
1733 RC = &AVR::DREGSRegClass;
1737 RC = &AVR::GPR8RegClass;
1741 RC = &AVR::DREGSRegClass;
1745 RC = &AVR::GPR8RegClass;
1749 RC = &AVR::DREGSRegClass;
1752 Opc =
Tiny ? AVR::ROLBRdR17 : AVR::ROLBRdR1;
1753 RC = &AVR::GPR8RegClass;
1757 RC = &AVR::DREGSRegClass;
1761 RC = &AVR::GPR8RegClass;
1765 RC = &AVR::DREGSRegClass;
1769 const BasicBlock *LLVM_BB = BB->getBasicBlock();
1772 for (
I = BB->getIterator();
I !=
F->end() && &(*
I) != BB; ++
I)
1778 MachineBasicBlock *LoopBB =
F->CreateMachineBasicBlock(LLVM_BB);
1779 MachineBasicBlock *CheckBB =
F->CreateMachineBasicBlock(LLVM_BB);
1780 MachineBasicBlock *RemBB =
F->CreateMachineBasicBlock(LLVM_BB);
1782 F->insert(
I, LoopBB);
1783 F->insert(
I, CheckBB);
1784 F->insert(
I, RemBB);
1790 RemBB->transferSuccessorsAndUpdatePHIs(BB);
1793 BB->addSuccessor(CheckBB);
1794 LoopBB->addSuccessor(CheckBB);
1795 CheckBB->addSuccessor(LoopBB);
1796 CheckBB->addSuccessor(RemBB);
1798 Register ShiftAmtReg = RI.createVirtualRegister(&AVR::GPR8RegClass);
1799 Register ShiftAmtReg2 = RI.createVirtualRegister(&AVR::GPR8RegClass);
1800 Register ShiftReg = RI.createVirtualRegister(RC);
1801 Register ShiftReg2 = RI.createVirtualRegister(RC);
1802 Register ShiftAmtSrcReg =
MI.getOperand(2).getReg();
1813 if (HasRepeatedOperand)
1814 ShiftMI.
addReg(ShiftReg);
1822 BuildMI(CheckBB, dl,
TII.get(AVR::PHI), ShiftReg)
1827 BuildMI(CheckBB, dl,
TII.get(AVR::PHI), ShiftAmtReg)
1832 BuildMI(CheckBB, dl,
TII.get(AVR::PHI), DstReg)
1838 BuildMI(CheckBB, dl,
TII.get(AVR::DECRd), ShiftAmtReg2).
addReg(ShiftAmtReg);
1841 MI.eraseFromParent();
1868 Register ZeroReg =
MRI.createVirtualRegister(&AVR::GPR8RegClass);
1876 if (ShiftLeft && (ShiftAmt % 8) >= 6) {
1881 size_t ShiftRegsOffset = ShiftAmt / 8;
1882 size_t ShiftRegsSize = Regs.size() - ShiftRegsOffset;
1884 Regs.
slice(ShiftRegsOffset, ShiftRegsSize);
1892 Register LowByte =
MRI.createVirtualRegister(&AVR::GPR8RegClass);
1896 if (ShiftAmt % 8 == 6) {
1898 Register NewLowByte =
MRI.createVirtualRegister(&AVR::GPR8RegClass);
1900 LowByte = NewLowByte;
1904 for (
size_t I = 0;
I < Regs.size();
I++) {
1905 int ShiftRegsIdx =
I + 1;
1906 if (ShiftRegsIdx < (
int)ShiftRegs.
size()) {
1907 Regs[
I] = ShiftRegs[ShiftRegsIdx];
1908 }
else if (ShiftRegsIdx == (
int)ShiftRegs.
size()) {
1909 Regs[
I] = std::pair(LowByte, 0);
1911 Regs[
I] = std::pair(ZeroReg, 0);
1919 if (!ShiftLeft && (ShiftAmt % 8) >= 6) {
1922 size_t ShiftRegsSize = Regs.size() - (ShiftAmt / 8);
1924 Regs.
slice(0, ShiftRegsSize);
1933 Register HighByte =
MRI.createVirtualRegister(&AVR::GPR8RegClass);
1935 if (ArithmeticShift) {
1953 if (ShiftAmt % 8 == 6) {
1956 Register NewExt =
MRI.createVirtualRegister(&AVR::GPR8RegClass);
1964 for (
int I = Regs.size() - 1;
I >= 0;
I--) {
1965 int ShiftRegsIdx =
I - (Regs.size() - ShiftRegs.
size()) - 1;
1966 if (ShiftRegsIdx >= 0) {
1967 Regs[
I] = ShiftRegs[ShiftRegsIdx];
1968 }
else if (ShiftRegsIdx == -1) {
1969 Regs[
I] = std::pair(HighByte, 0);
1971 Regs[
I] = std::pair(ExtByte, 0);
1980 while (ShiftLeft && ShiftAmt >= 8) {
1982 for (
size_t I = 0;
I < Regs.size() - 1;
I++) {
1983 Regs[
I] = Regs[
I + 1];
1987 Regs[Regs.size() - 1] = std::pair(ZeroReg, 0);
1990 Regs = Regs.drop_back(1);
1997 if (!ShiftLeft && ShiftAmt >= 8) {
1998 if (ArithmeticShift) {
2000 ShrExtendReg =
MRI.createVirtualRegister(&AVR::GPR8RegClass);
2001 Register Tmp =
MRI.createVirtualRegister(&AVR::GPR8RegClass);
2003 .
addReg(Regs[0].first, 0, Regs[0].second)
2004 .
addReg(Regs[0].first, 0, Regs[0].second);
2005 BuildMI(*BB,
MI, dl,
TII.get(AVR::SBCRdRr), ShrExtendReg)
2009 ShrExtendReg = ZeroReg;
2011 for (; ShiftAmt >= 8; ShiftAmt -= 8) {
2013 for (
size_t I = Regs.size() - 1;
I != 0;
I--) {
2014 Regs[
I] = Regs[
I - 1];
2018 Regs[0] = std::pair(ShrExtendReg, 0);
2021 Regs = Regs.drop_front(1);
2026 assert((ShiftAmt < 8) &&
"Unexpect shift amount");
2046 if (!ArithmeticShift && ShiftAmt >= 4) {
2048 for (
size_t I = 0;
I < Regs.size();
I++) {
2049 size_t Idx = ShiftLeft ?
I : Regs.size() -
I - 1;
2050 Register SwapReg =
MRI.createVirtualRegister(&AVR::LD8RegClass);
2054 Register R =
MRI.createVirtualRegister(&AVR::GPR8RegClass);
2060 Register AndReg =
MRI.createVirtualRegister(&AVR::LD8RegClass);
2063 .
addImm(ShiftLeft ? 0xf0 : 0x0f);
2065 Register R =
MRI.createVirtualRegister(&AVR::GPR8RegClass);
2069 size_t PrevIdx = ShiftLeft ?
Idx - 1 :
Idx + 1;
2070 Regs[PrevIdx] = std::pair(R, 0);
2073 Regs[
Idx] = std::pair(AndReg, 0);
2080 while (ShiftLeft && ShiftAmt) {
2082 for (ssize_t
I = Regs.size() - 1;
I >= 0;
I--) {
2083 Register Out =
MRI.createVirtualRegister(&AVR::GPR8RegClass);
2086 if (
I == (ssize_t)Regs.size() - 1) {
2089 .
addReg(In, 0, InSubreg);
2093 .
addReg(In, 0, InSubreg);
2095 Regs[
I] = std::pair(Out, 0);
2099 while (!ShiftLeft && ShiftAmt) {
2101 for (
size_t I = 0;
I < Regs.size();
I++) {
2102 Register Out =
MRI.createVirtualRegister(&AVR::GPR8RegClass);
2106 unsigned Opc = ArithmeticShift ? AVR::ASRRd : AVR::LSRRd;
2111 Regs[
I] = std::pair(Out, 0);
2116 if (ShiftAmt != 0) {
2123AVRTargetLowering::insertWideShift(MachineInstr &
MI,
2124 MachineBasicBlock *BB)
const {
2126 const DebugLoc &dl =
MI.getDebugLoc();
2130 int64_t ShiftAmt =
MI.getOperand(4).getImm();
2132 switch (
MI.getOpcode()) {
2145 std::array<std::pair<Register, int>, 4>
Registers = {
2146 std::pair(
MI.getOperand(3).getReg(), AVR::sub_hi),
2147 std::pair(
MI.getOperand(3).getReg(), AVR::sub_lo),
2148 std::pair(
MI.getOperand(2).getReg(), AVR::sub_hi),
2149 std::pair(
MI.getOperand(2).getReg(), AVR::sub_lo),
2167 (
Opc !=
ISD::SRA || (ShiftAmt < 16 || ShiftAmt >= 22))) {
2169 BuildMI(*BB,
MI, dl,
TII.get(AVR::REG_SEQUENCE),
MI.getOperand(0).getReg())
2174 BuildMI(*BB,
MI, dl,
TII.get(AVR::REG_SEQUENCE),
MI.getOperand(1).getReg())
2181 BuildMI(*BB,
MI, dl,
TII.get(AVR::REG_SEQUENCE),
MI.getOperand(1).getReg())
2186 BuildMI(*BB,
MI, dl,
TII.get(AVR::REG_SEQUENCE),
MI.getOperand(0).getReg())
2194 MI.eraseFromParent();
2199 if (
I->getOpcode() == AVR::COPY) {
2200 Register SrcReg =
I->getOperand(1).getReg();
2201 return (SrcReg == AVR::R0 || SrcReg == AVR::R1);
2210MachineBasicBlock *AVRTargetLowering::insertMul(MachineInstr &
MI,
2211 MachineBasicBlock *BB)
const {
2219 BuildMI(*BB,
I,
MI.getDebugLoc(),
TII.get(AVR::EORRdRr), AVR::R1)
2227AVRTargetLowering::insertCopyZero(MachineInstr &
MI,
2228 MachineBasicBlock *BB)
const {
2232 .
add(
MI.getOperand(0))
2234 MI.eraseFromParent();
2240MachineBasicBlock *AVRTargetLowering::insertAtomicArithmeticOp(
2241 MachineInstr &
MI, MachineBasicBlock *BB,
unsigned Opcode,
int Width)
const {
2242 MachineRegisterInfo &
MRI = BB->getParent()->getRegInfo();
2256 const TargetRegisterClass *RC =
2257 (Width == 8) ? &AVR::GPR8RegClass : &AVR::DREGSRegClass;
2258 unsigned LoadOpcode = (Width == 8) ? AVR::LDRdPtr : AVR::LDWRdPtr;
2259 unsigned StoreOpcode = (Width == 8) ? AVR::STPtrRr : AVR::STWPtrRr;
2267 BuildMI(*BB,
I, dl,
TII.get(LoadOpcode),
MI.getOperand(0).getReg())
2268 .
add(
MI.getOperand(1));
2274 .
add(
MI.getOperand(2));
2278 .
add(
MI.getOperand(1))
2287 MI.eraseFromParent();
2294 int Opc =
MI.getOpcode();
2310 return insertShift(
MI,
MBB, STI.hasTinyEncoding());
2314 return insertWideShift(
MI,
MBB);
2317 return insertMul(
MI,
MBB);
2319 return insertCopyZero(
MI,
MBB);
2320 case AVR::AtomicLoadAdd8:
2321 return insertAtomicArithmeticOp(
MI,
MBB, AVR::ADDRdRr, 8);
2322 case AVR::AtomicLoadAdd16:
2323 return insertAtomicArithmeticOp(
MI,
MBB, AVR::ADDWRdRr, 16);
2324 case AVR::AtomicLoadSub8:
2325 return insertAtomicArithmeticOp(
MI,
MBB, AVR::SUBRdRr, 8);
2326 case AVR::AtomicLoadSub16:
2327 return insertAtomicArithmeticOp(
MI,
MBB, AVR::SUBWRdRr, 16);
2328 case AVR::AtomicLoadAnd8:
2329 return insertAtomicArithmeticOp(
MI,
MBB, AVR::ANDRdRr, 8);
2330 case AVR::AtomicLoadAnd16:
2331 return insertAtomicArithmeticOp(
MI,
MBB, AVR::ANDWRdRr, 16);
2332 case AVR::AtomicLoadOr8:
2333 return insertAtomicArithmeticOp(
MI,
MBB, AVR::ORRdRr, 8);
2334 case AVR::AtomicLoadOr16:
2335 return insertAtomicArithmeticOp(
MI,
MBB, AVR::ORWRdRr, 16);
2336 case AVR::AtomicLoadXor8:
2337 return insertAtomicArithmeticOp(
MI,
MBB, AVR::EORRdRr, 8);
2338 case AVR::AtomicLoadXor16:
2339 return insertAtomicArithmeticOp(
MI,
MBB, AVR::EORWRdRr, 16);
2342 assert((
Opc == AVR::Select16 ||
Opc == AVR::Select8) &&
2343 "Unexpected instr type to insert");
2364 if (FallThrough !=
nullptr) {
2380 unsigned CallFrameSize =
TII.getCallFrameSizeAt(
MI);
2394 MBB->addSuccessor(falseMBB);
2395 MBB->addSuccessor(trueMBB);
2403 MI.getOperand(0).getReg())
2409 MI.eraseFromParent();
2419 if (Constraint.
size() == 1) {
2421 switch (Constraint[0]) {
2464 switch (ConstraintCode[0]) {
2475 Value *CallOperandVal =
info.CallOperandVal;
2480 if (!CallOperandVal) {
2485 switch (*constraint) {
2509 if (
const ConstantFP *
C = dyn_cast<ConstantFP>(CallOperandVal)) {
2516 if (
const ConstantInt *
C = dyn_cast<ConstantInt>(CallOperandVal)) {
2517 if (isUInt<6>(
C->getZExtValue())) {
2523 if (
const ConstantInt *
C = dyn_cast<ConstantInt>(CallOperandVal)) {
2524 if ((
C->getSExtValue() >= -63) && (
C->getSExtValue() <= 0)) {
2530 if (
const ConstantInt *
C = dyn_cast<ConstantInt>(CallOperandVal)) {
2531 if (
C->getZExtValue() == 2) {
2537 if (
const ConstantInt *
C = dyn_cast<ConstantInt>(CallOperandVal)) {
2538 if (
C->getZExtValue() == 0) {
2544 if (
const ConstantInt *
C = dyn_cast<ConstantInt>(CallOperandVal)) {
2545 if (isUInt<8>(
C->getZExtValue())) {
2551 if (
const ConstantInt *
C = dyn_cast<ConstantInt>(CallOperandVal)) {
2552 if (
C->getSExtValue() == -1) {
2558 if (
const ConstantInt *
C = dyn_cast<ConstantInt>(CallOperandVal)) {
2559 if ((
C->getZExtValue() == 8) || (
C->getZExtValue() == 16) ||
2560 (
C->getZExtValue() == 24)) {
2566 if (
const ConstantInt *
C = dyn_cast<ConstantInt>(CallOperandVal)) {
2567 if (
C->getZExtValue() == 1) {
2573 if (
const ConstantInt *
C = dyn_cast<ConstantInt>(CallOperandVal)) {
2574 if ((
C->getSExtValue() >= -6) && (
C->getSExtValue() <= 5)) {
2587std::pair<unsigned, const TargetRegisterClass *>
2591 if (Constraint.
size() == 1) {
2592 switch (Constraint[0]) {
2595 return std::make_pair(0U, &AVR::LD8loRegClass);
2596 else if (VT == MVT::i16)
2597 return std::make_pair(0U, &AVR::DREGSLD8loRegClass);
2600 if (VT == MVT::i8 || VT == MVT::i16)
2601 return std::make_pair(0U, &AVR::PTRDISPREGSRegClass);
2605 return std::make_pair(0U, &AVR::LD8RegClass);
2606 else if (VT == MVT::i16)
2607 return std::make_pair(0U, &AVR::DLDREGSRegClass);
2611 return std::make_pair(0U, &AVR::GPR8loRegClass);
2612 else if (VT == MVT::i16)
2613 return std::make_pair(0U, &AVR::DREGSloRegClass);
2616 if (VT == MVT::i8 || VT == MVT::i16)
2617 return std::make_pair(0U, &AVR::PTRREGSRegClass);
2620 return std::make_pair(0U, &AVR::GPRSPRegClass);
2623 return std::make_pair(0U, &AVR::GPR8RegClass);
2624 else if (VT == MVT::i16)
2625 return std::make_pair(0U, &AVR::DREGSRegClass);
2630 &AVR::GPR8RegClass);
2633 if (VT == MVT::i8 || VT == MVT::i16)
2634 return std::make_pair(0U, &AVR::IWREGSRegClass);
2638 if (VT == MVT::i8 || VT == MVT::i16)
2639 return std::make_pair(
unsigned(AVR::R27R26), &AVR::PTRREGSRegClass);
2643 if (VT == MVT::i8 || VT == MVT::i16)
2644 return std::make_pair(
unsigned(AVR::R29R28), &AVR::PTRREGSRegClass);
2648 if (VT == MVT::i8 || VT == MVT::i16)
2649 return std::make_pair(
unsigned(AVR::R31R30), &AVR::PTRREGSRegClass);
2662 std::vector<SDValue> &Ops,
2666 EVT Ty =
Op.getValueType();
2669 if (Constraint.
size() != 1) {
2673 char ConstraintLetter = Constraint[0];
2674 switch (ConstraintLetter) {
2692 int64_t CVal64 =
C->getSExtValue();
2694 switch (ConstraintLetter) {
2696 if (!isUInt<6>(CUVal64))
2701 if (CVal64 < -63 || CVal64 > 0)
2716 if (!isUInt<8>(CUVal64))
2732 if (CUVal64 != 8 && CUVal64 != 16 && CUVal64 != 24)
2742 if (CVal64 < -6 || CVal64 > 5)
2752 if (!FC || !FC->isZero())
2759 if (Result.getNode()) {
2760 Ops.push_back(Result);
2773 .
Case(
"r0", AVR::R0)
2774 .
Case(
"r1", AVR::R1)
2778 .
Case(
"r0", AVR::R1R0)
2779 .
Case(
"sp", AVR::SP)
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis Results
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
const HexagonInstrInfo * TII
Register const TargetRegisterInfo * TRI
SI Pre allocate WWM Registers
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 getTmpRegister() const
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.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - 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.
This class represents an Operation in the Expression.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
LLVM_ABI Align getABITypeAlign(Type *Ty) const
Returns the minimum ABI-required alignment for the specified type.
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
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
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)
CreateMachineBasicBlock - Allocate a new MachineBasicBlock.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
MutableArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - 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.
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)
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.
StringRef - Represent a constant reference to a string, i.e.
constexpr size_t size() const
size - 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...
CallingConv::ID getLibcallCallingConv(RTLIB::Libcall Call) const
Get the CallingConv that should be used for the specified libcall.
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...
const char * getLibcallName(RTLIB::Libcall Call) const
Get the libcall routine name for the specified libcall.
std::vector< ArgListEntry > ArgListTy
void setSchedulingPreference(Sched::Preference Pref)
Specify the target scheduling preference.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
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.
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...
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.
@ C
The default llvm calling convention, compatible with C.
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 ...
@ 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,...
@ Undef
Value of the register doesn't matter.
Type
MessagePack types as defined in the standard, with the exception of Integer being divided into a sign...
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.
static const MCPhysReg RegList16Tiny[]
static const MCPhysReg RegList8Tiny[]
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
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.
static const MCPhysReg RegList16AVR[]
@ Sub
Subtraction of integers.
static unsigned getTotalArgumentsSizeInBytes(const SmallVectorImpl< ArgT > &Args)
Count the total number of bytes needed to pass or return these arguments.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
DWARFExpression::Operation Op
static AVRCC::CondCodes intCCToAVRCC(ISD::CondCode CC)
IntCCToAVRCC - Convert a DAG integer condition code to an AVR CC.
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.
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.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
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.