LLVM: lib/Target/M68k/M68kISelLowering.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
23
41
42using namespace llvm;
43
44#define DEBUG_TYPE "M68k-isel"
45
46STATISTIC(NumTailCalls, "Number of tail calls");
47
51
52 MVT PtrVT = MVT::i32;
53
54
55
57
58 auto *RegInfo = Subtarget.getRegisterInfo();
60
61
65
70 }
71
72
79
82 if (Subtarget.atLeastM68020())
84 else
87
88 for (auto OP :
94 }
95
99 }
100
105 }
106
109
110
111 for (auto VT : {MVT::i8, MVT::i16, MVT::i32}) {
116 }
117
118
119 for (auto VT : {MVT::i8, MVT::i16, MVT::i32}) {
124 }
125
128
129 for (auto VT : {MVT::i8, MVT::i16, MVT::i32}) {
135 }
136
137 for (auto VT : {MVT::i8, MVT::i16, MVT::i32}) {
142 }
143
150
155
158
160
162
163
164
166 setOperationAction(ISD::ATOMIC_CMP_SWAP, {MVT::i8, MVT::i16, MVT::i32},
167 Subtarget.atLeastM68020() ? Legal : LibCall);
168
170
171
172
173
175 {
176 ISD::ATOMIC_LOAD_ADD,
177 ISD::ATOMIC_LOAD_SUB,
178 ISD::ATOMIC_LOAD_AND,
179 ISD::ATOMIC_LOAD_OR,
180 ISD::ATOMIC_LOAD_XOR,
181 ISD::ATOMIC_LOAD_NAND,
182 ISD::ATOMIC_LOAD_MIN,
183 ISD::ATOMIC_LOAD_MAX,
184 ISD::ATOMIC_LOAD_UMIN,
185 ISD::ATOMIC_LOAD_UMAX,
186 ISD::ATOMIC_SWAP,
187 },
188 {MVT::i8, MVT::i16, MVT::i32}, LibCall);
189
191}
192
195 return Subtarget.atLeastM68020()
198}
199
202 return M68k::D0;
203}
204
207 return M68k::D1;
208}
209
218
221
222 return MVT::i8;
223}
224
226 EVT Ty) const {
227 if (Ty.isSimple()) {
228 return Ty.getSimpleVT();
229 }
231}
232
233#include "M68kGenCallingConv.inc"
234
236
239 if (Outs.empty())
241
243 if (!Flags.isSRet())
245 if (Flags.isInReg())
248}
249
250
255
257 if (!Flags.isSRet())
259 if (Flags.isInReg())
262}
263
264
265
266
271
273 Chain, DL, Dst, Src, SizeNode, Flags.getNonZeroByValAlign(),
274 false, true,
276}
277
278
280
281
283 switch (CC) {
284
286 return true;
287 default:
289 }
290}
291
292
293
297
298
299
306
307 for (;;) {
308
312 continue;
313 }
320 continue;
321 }
322 }
323 break;
324 }
325
326 int FI = INT_MAX;
330 return false;
332 if (!Def)
333 return false;
334 if (!Flags.isByVal()) {
335 if (->isLoadFromStackSlot(*Def, FI))
336 return false;
337 } else {
338 unsigned Opcode = Def->getOpcode();
339 if ((Opcode == M68k::LEA32p || Opcode == M68k::LEA32f) &&
340 Def->getOperand(1).isFI()) {
341 FI = Def->getOperand(1).getIndex();
342 Bytes = Flags.getByValSize();
343 } else
344 return false;
345 }
347 if (Flags.isByVal())
348
349
350
351
352
353 return false;
354 SDValue Ptr = Ld->getBasePtr();
356 if (!FINode)
357 return false;
362 Bytes = Flags.getByValSize();
363 } else
364 return false;
365
366 assert(FI != INT_MAX);
368 return false;
369
371 return false;
372
374
375
376 if (Flags.isZExt() != MFI.isObjectZExt(FI) ||
378 return false;
379 }
380 }
381
383}
384
386M68kTargetLowering::getReturnAddressFrameIndex(SelectionDAG &DAG) const {
388 M68kMachineFunctionInfo *FuncInfo = MF.getInfo();
389 int ReturnAddrIndex = FuncInfo->getRAIndex();
390
391 if (ReturnAddrIndex == 0) {
392
393 unsigned SlotSize = Subtarget.getSlotSize();
395 SlotSize, -(int64_t)SlotSize, false);
396 FuncInfo->setRAIndex(ReturnAddrIndex);
397 }
398
400}
401
405 bool IsTailCall, int FPDiff,
408 OutRetAddr = getReturnAddressFrameIndex(DAG);
409
410
411 OutRetAddr = DAG.getLoad(VT, DL, Chain, OutRetAddr, MachinePointerInfo());
413}
414
415SDValue M68kTargetLowering::EmitTailCallStoreRetAddr(
417 EVT PtrVT, unsigned SlotSize, int FPDiff, const SDLoc &DL) const {
418 if (!FPDiff)
419 return Chain;
420
421
423 SlotSize, (int64_t)FPDiff - SlotSize, false);
424
426
428 Chain, DL, RetFI, NewFI,
430 return Chain;
431}
432
439 unsigned ArgIdx) const {
440
441 ISD::ArgFlagsTy Flags = Ins[ArgIdx].Flags;
442 EVT ValVT;
443
444
445
448 else
450
451
452
454 if (VA.getValVT() == MVT::i8) {
456 } else if (VA.getValVT() == MVT::i16) {
458 }
459
460
461
462
463
464
465
466
467
470 bool IsImmutable = !AlwaysUseMutable && .isByVal();
471
472 if (Flags.isByVal()) {
473 unsigned Bytes = Flags.getByValSize();
474 if (Bytes == 0)
475 Bytes = 1;
477
478
480 } else {
481 int FI =
483
484
489 }
490
491
492
493
496 ValVT, DL, Chain, FIN,
499 : Val;
500 }
501}
502
511 StackPtr, PtrOff);
512 if (Flags.isByVal())
514
516 Chain, DL, Arg, PtrOff,
518}
519
520
521
522
523
526 SelectionDAG &DAG = CLI.DAG;
528 SmallVectorImplISD::OutputArg &Outs = CLI.Outs;
529 SmallVectorImpl &OutVals = CLI.OutVals;
530 SmallVectorImplISD::InputArg &Ins = CLI.Ins;
535 bool IsVarArg = CLI.IsVarArg;
536
539 bool IsSibcall = false;
540 M68kMachineFunctionInfo *MFI = MF.getInfo();
541
542
545
547 if (Attr.getValueAsBool())
548 IsTailCall = false;
549
550
551
553 if (IsMustTail) {
554
555
556
557 IsTailCall = true;
558 } else if (IsTailCall) {
559
560 IsTailCall = IsEligibleForTailCallOptimization(
563 DAG);
564
565
566
568 IsSibcall = true;
569
570 if (IsTailCall)
571 ++NumTailCalls;
572 }
573
575 "Var args not supported with calling convention fastcc");
576
577
580 for (const auto &Arg : CLI.getArgs())
582 M68kCCState CCInfo(ArgTypes, CallConv, IsVarArg, MF, ArgLocs,
584 CCInfo.AnalyzeCallOperands(Outs, CC_M68k);
585
586
587 unsigned NumBytes = CCInfo.getAlignedCallFrameSize();
588 if (IsSibcall) {
589
590
591 NumBytes = 0;
594 NumBytes = GetAlignedArgumentStackSize(NumBytes, DAG);
595 }
596
597 int FPDiff = 0;
598 if (IsTailCall && !IsSibcall && !IsMustTail) {
599
601
602 FPDiff = NumBytesCallerPushed - NumBytes;
603
604
605
606 if (FPDiff < MFI->getTCReturnAddrDelta())
608 }
609
610 unsigned NumBytesToPush = NumBytes;
611 unsigned NumBytesToPop = NumBytes;
612
613
614
615
616 if (!Outs.empty() && Outs.back().Flags.isInAlloca()) {
617 NumBytesToPush = 0;
618 if (!ArgLocs.back().isMemLoc())
620 "parameter");
621 if (ArgLocs.back().getLocMemOffset() != 0)
622 report_fatal_error("any parameter with the inalloca attribute must be "
623 "the only memory argument");
624 }
625
626 if (!IsSibcall)
628 NumBytes - NumBytesToPush, DL);
629
631
632 if (IsTailCall && FPDiff)
633 Chain = EmitTailCallLoadRetAddr(DAG, RetFI, Chain, IsTailCall, FPDiff, DL);
634
638
639
640
641 const M68kRegisterInfo *RegInfo = Subtarget.getRegisterInfo();
642 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
643 ISD::ArgFlagsTy Flags = Outs[i].Flags;
644
645
646 if (Flags.isInAlloca())
647 continue;
648
649 CCValAssign &VA = ArgLocs[i];
651 SDValue Arg = OutVals[i];
652 bool IsByVal = Flags.isByVal();
653
654
656 default:
659 break;
662 break;
665 break;
668 break;
671 break;
673
677 Chain, DL, Arg, SpillSlot,
679 Arg = SpillSlot;
680 break;
681 }
682 }
683
686 } else if (!IsSibcall && (!IsTailCall || IsByVal)) {
691 }
693 LowerMemOpCallTo(Chain, StackPtr, Arg, DL, DAG, VA, Flags));
694 }
695 }
696
697 if (!MemOpChains.empty())
699
700
701
702
703
704 if (IsVarArg && IsMustTail) {
706 for (const auto &F : Forwards) {
708 RegsToPass.push_back(std::make_pair(unsigned(F.PReg), Val));
709 }
710 }
711
712
713
714
715 if (!IsSibcall && IsTailCall) {
716
717
718
719
720
721
723
726 int FI = 0;
727 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
728 CCValAssign &VA = ArgLocs[i];
730 continue;
732 SDValue Arg = OutVals[i];
733 ISD::ArgFlagsTy Flags = Outs[i].Flags;
734
735 if (Flags.isInAlloca())
736 continue;
737
739 uint32_t OpSize = (VA.getLocVT().getSizeInBits() + 7) / 8;
742
743 if (Flags.isByVal()) {
744
749 }
751 StackPtr, Source);
752
755 } else {
756
758 ArgChain, DL, Arg, FIN,
760 }
761 }
762
763 if (!MemOpChains2.empty())
765
766
767 Chain = EmitTailCallStoreRetAddr(DAG, MF, Chain, RetFI,
769 Subtarget.getSlotSize(), FPDiff, DL);
770 }
771
772
773
775 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
776 Chain = DAG.getCopyToReg(Chain, DL, RegsToPass[i].first,
777 RegsToPass[i].second, InGlue);
779 }
780
782
783
784
786
787
788
789 const GlobalValue *GV = G->getGlobal();
791 unsigned char OpFlags = Subtarget.classifyGlobalFunctionReference(GV);
792
795
797
798
801
802
806 }
807 }
810 unsigned char OpFlags =
811 Subtarget.classifyGlobalFunctionReference(nullptr, *Mod);
812
815 }
816
818
819 if (!IsSibcall && IsTailCall) {
820 Chain = DAG.getCALLSEQ_END(Chain, NumBytesToPop, 0, InGlue, DL);
822 }
823
824 Ops.push_back(Chain);
825 Ops.push_back(Callee);
826
827 if (IsTailCall)
829
830
831
832 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
834 RegsToPass[i].second.getValueType()));
835
836
838 assert(Mask && "Missing call preserved mask for calling convention");
839
841
843 Ops.push_back(InGlue);
844
845 if (IsTailCall) {
847 return DAG.getNode(M68kISD::TC_RETURN, DL, MVT::Other, Ops);
848 }
849
850
851 Chain = DAG.getNode(M68kISD::CALL, DL, {MVT::Other, MVT::Glue}, Ops);
853
854
855 unsigned NumBytesForCalleeToPop;
858 NumBytesForCalleeToPop = NumBytes;
860
861
862 NumBytesForCalleeToPop = 4;
863 } else {
864 NumBytesForCalleeToPop = 0;
865 }
866
868
869
870 NumBytesForCalleeToPop = NumBytes;
871 }
872
873
874 if (!IsSibcall) {
875 Chain = DAG.getCALLSEQ_END(Chain, NumBytesToPop, NumBytesForCalleeToPop,
876 InGlue, DL);
878 }
879
880
881
882 return LowerCallResult(Chain, InGlue, CallConv, IsVarArg, Ins, DL, DAG,
883 InVals);
884}
885
886SDValue M68kTargetLowering::LowerCallResult(
890
891
895 CCInfo.AnalyzeCallResult(Ins, RetCC_M68k);
896
897
898 for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
899 CCValAssign &VA = RVLocs[i];
901
902
906
909
912 }
913
914 return Chain;
915}
916
917
918
919
920
921SDValue M68kTargetLowering::LowerFormalArguments(
926 M68kMachineFunctionInfo *MMFI = MF.getInfo();
927
928
930
931
936 M68kCCState CCInfo(ArgTypes, CCID, IsVarArg, MF, ArgLocs, *DAG.getContext());
937
938 CCInfo.AnalyzeFormalArguments(Ins, CC_M68k);
939
940 unsigned LastVal = ~0U;
942 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
943 CCValAssign &VA = ArgLocs[i];
944 assert(VA.getValNo() != LastVal && "Same value in different locations");
945 (void)LastVal;
946
948
951 const TargetRegisterClass *RC;
952 if (RegVT == MVT::i32)
953 RC = &M68k::XR32RegClass;
954 else
956
959
960
961
962
971 }
972
975 }
976 } else {
978 ArgValue = LowerMemArgument(Chain, CCID, Ins, DL, DAG, VA, MFI, i);
979 }
980
981
982
984 ArgValue =
985 DAG.getLoad(VA.getValVT(), DL, Chain, ArgValue, MachinePointerInfo());
986
988 }
989
990 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
991
992
994 continue;
995
996
997
998
999 if (Ins[i].Flags.isSRet()) {
1001 if () {
1005 }
1008 break;
1009 }
1010 }
1011
1012 unsigned StackSize = CCInfo.getStackSize();
1013
1015 StackSize = GetAlignedArgumentStackSize(StackSize, DAG);
1016
1017
1018
1019
1020 if (MFI.hasVAStart()) {
1022 }
1023
1024 if (IsVarArg && MFI.hasMustTailInVarArgFunc()) {
1025
1027 MVT IntVT = MVT::i32;
1029
1030
1031
1032 SmallVectorImpl &Forwards =
1034 CCInfo.analyzeMustTailForwardedRegisters(Forwards, RegParmTypes, CC_M68k);
1035
1036
1037 for (ForwardedRegister &F : Forwards) {
1038
1042 }
1043 }
1044
1045
1049 } else {
1051
1054 }
1055
1057
1058 return Chain;
1059}
1060
1061
1062
1063
1064
1065bool M68kTargetLowering::CanLowerReturn(
1068 const Type *RetTy) const {
1070 CCState CCInfo(CCID, IsVarArg, MF, RVLocs, Context);
1071 return CCInfo.CheckReturn(Outs, RetCC_M68k);
1072}
1073
1076 bool IsVarArg,
1081 M68kMachineFunctionInfo *MFI = MF.getInfo();
1082
1084 CCState CCInfo(CCID, IsVarArg, MF, RVLocs, *DAG.getContext());
1085 CCInfo.AnalyzeReturn(Outs, RetCC_M68k);
1086
1089
1091
1094
1095
1096 for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
1097 CCValAssign &VA = RVLocs[i];
1098 assert(VA.isRegLoc() && "Can only return in registers!");
1099 SDValue ValToCopy = OutVals[i];
1101
1102
1110 else
1114
1118 }
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1154
1155
1156
1157 unsigned RetValReg = M68k::D0;
1158 Chain = DAG.getCopyToReg(Chain, DL, RetValReg, Val, Glue);
1160
1163 }
1164
1165 RetOps[0] = Chain;
1166
1167
1170
1171 return DAG.getNode(M68kISD::RET, DL, MVT::Other, RetOps);
1172}
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206unsigned
1207M68kTargetLowering::GetAlignedArgumentStackSize(unsigned StackSize,
1209 const TargetFrameLowering &TFI = *Subtarget.getFrameLowering();
1211 uint64_t AlignMask = StackAlignment - 1;
1212 int64_t Offset = StackSize;
1213 unsigned SlotSize = Subtarget.getSlotSize();
1214 if ((Offset & AlignMask) <= (StackAlignment - SlotSize)) {
1215
1216 Offset += ((StackAlignment - SlotSize) - (Offset & AlignMask));
1217 } else {
1218
1220 ((~AlignMask) & Offset) + StackAlignment + (StackAlignment - SlotSize);
1221 }
1223}
1224
1225
1226
1227bool M68kTargetLowering::IsEligibleForTailCallOptimization(
1229 bool IsCalleeStructRet, bool IsCallerStructRet, Type *RetTy,
1234 return false;
1235
1236
1239
1241 bool CCMatch = CallerCC == CalleeCC;
1242
1245 return true;
1246 return false;
1247 }
1248
1249
1250
1251
1252
1253
1254 const M68kRegisterInfo *RegInfo = Subtarget.getRegisterInfo();
1255 if (RegInfo->hasStackRealignment(MF))
1256 return false;
1257
1258
1259
1260 if (IsCalleeStructRet || IsCallerStructRet)
1261 return false;
1262
1263
1264
1266 if (IsVarArg && !Outs.empty()) {
1267
1269 CCState CCInfo(CalleeCC, IsVarArg, MF, ArgLocs, C);
1270
1271 CCInfo.AnalyzeCallOperands(Outs, CC_M68k);
1272 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i)
1273 if (!ArgLocs[i].isRegLoc())
1274 return false;
1275 }
1276
1277
1279 RetCC_M68k))
1280 return false;
1281
1282
1283 const M68kRegisterInfo *TRI = Subtarget.getRegisterInfo();
1284 const uint32_t *CallerPreserved = TRI->getCallPreservedMask(MF, CallerCC);
1285 if (!CCMatch) {
1286 const uint32_t *CalleePreserved = TRI->getCallPreservedMask(MF, CalleeCC);
1287 if (->regmaskSubsetEqual(CallerPreserved, CalleePreserved))
1288 return false;
1289 }
1290
1291 unsigned StackArgsSize = 0;
1292
1293
1294
1295 if (!Outs.empty()) {
1296
1297
1299 CCState CCInfo(CalleeCC, IsVarArg, MF, ArgLocs, C);
1300
1301 CCInfo.AnalyzeCallOperands(Outs, CC_M68k);
1302 StackArgsSize = CCInfo.getStackSize();
1303
1304 if (StackArgsSize) {
1305
1306
1308 const MachineRegisterInfo *MRI = &MF.getRegInfo();
1309 const M68kInstrInfo *TII = Subtarget.getInstrInfo();
1310 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
1311 CCValAssign &VA = ArgLocs[i];
1312 SDValue Arg = OutVals[i];
1313 ISD::ArgFlagsTy Flags = Outs[i].Flags;
1315 return false;
1318 TII, VA))
1319 return false;
1320 }
1321 }
1322 }
1323
1325
1326
1327
1328
1329
1332 PositionIndependent) {
1333 unsigned NumInRegs = 0;
1334
1335
1336 unsigned MaxInRegs = PositionIndependent ? 1 : 2;
1337
1338 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
1339 CCValAssign &VA = ArgLocs[i];
1341 continue;
1343 switch (Reg) {
1344 default:
1345 break;
1346 case M68k::A0:
1347 case M68k::A1:
1348 if (++NumInRegs == MaxInRegs)
1349 return false;
1350 break;
1351 }
1352 }
1353 }
1354
1355 const MachineRegisterInfo &MRI = MF.getRegInfo();
1357 return false;
1358 }
1359
1362
1363 if (unsigned BytesToPop =
1364 MF.getInfo()->getBytesToPopOnReturn()) {
1365
1366 bool CalleePopMatches = CalleeWillPop && BytesToPop == StackArgsSize;
1367 if (!CalleePopMatches)
1368 return false;
1369 } else if (CalleeWillPop && StackArgsSize > 0) {
1370
1371 return false;
1372 }
1373
1374 return true;
1375}
1376
1377
1378
1379
1380
1383 switch (Op.getOpcode()) {
1384 default:
1392 return LowerXALUO(Op, DAG);
1394 return LowerSETCC(Op, DAG);
1396 return LowerSETCCCARRY(Op, DAG);
1398 return LowerSELECT(Op, DAG);
1399 case ISD::BRCOND:
1400 return LowerBRCOND(Op, DAG);
1405 return LowerADDC_ADDE_SUBC_SUBE(Op, DAG);
1407 return LowerConstantPool(Op, DAG);
1409 return LowerGlobalAddress(Op, DAG);
1411 return LowerExternalSymbol(Op, DAG);
1413 return LowerBlockAddress(Op, DAG);
1415 return LowerJumpTable(Op, DAG);
1416 case ISD::VASTART:
1417 return LowerVASTART(Op, DAG);
1418 case ISD::DYNAMIC_STACKALLOC:
1419 return LowerDYNAMIC_STACKALLOC(Op, DAG);
1421 return LowerShiftLeftParts(Op, DAG);
1423 return LowerShiftRightParts(Op, DAG, true);
1425 return LowerShiftRightParts(Op, DAG, false);
1426 case ISD::ATOMIC_FENCE:
1427 return LowerATOMICFENCE(Op, DAG);
1429 return LowerGlobalTLSAddress(Op, DAG);
1430 }
1431}
1432
1436 ArgListTy &&ArgList) const {
1438 CallLoweringInfo CLI(DAG);
1444 std::move(ArgList));
1446}
1447
1450 unsigned TargetFlags) const {
1455
1457
1458 ArgListTy Args;
1459 Args.emplace_back(Arg, PtrTy);
1460 return LowerExternalSymbolCall(DAG, SDLoc(GA), "__tls_get_addr",
1461 std::move(Args));
1462}
1463
1465 return LowerExternalSymbolCall(DAG, Loc, "__m68k_read_tp", ArgListTy());
1466}
1467
1471}
1472
1479 return DAG.getNode(ISD::ADD, SDLoc(GA), MVT::i32, TGA, Addr);
1480}
1481
1485 SDValue Tp = getM68kReadTp(SDLoc(GA), DAG);
1493
1495}
1496
1499 SDValue Tp = getM68kReadTp(SDLoc(GA), DAG);
1503 return DAG.getNode(ISD::ADD, SDLoc(GA), MVT::i32, TGA, Tp);
1504}
1505
1506SDValue M68kTargetLowering::LowerGlobalTLSAddress(SDValue Op,
1508 assert(Subtarget.isTargetELF());
1509
1512
1513 switch (AccessModel) {
1515 return LowerTLSGeneralDynamic(GA, DAG);
1517 return LowerTLSLocalDynamic(GA, DAG);
1519 return LowerTLSInitialExec(GA, DAG);
1521 return LowerTLSLocalExec(GA, DAG);
1522 }
1523
1525}
1526
1529
1530
1531
1532
1533
1534 return VT.bitsLE(MVT::i32) || Subtarget.atLeastM68020();
1535}
1536
1538 switch (Opcode) {
1545 return true;
1546 default:
1547 return false;
1548 }
1549}
1550
1553 unsigned &CC) {
1555 EVT VT = N->getValueType(0);
1559
1560 unsigned TruncOp = 0;
1561 auto PromoteMULO = [&](unsigned ExtOp) {
1562
1563
1564
1565
1566 if (VT == MVT::i8) {
1569 VT = MVT::i16;
1571 }
1572 };
1573
1574 bool NoOverflow = false;
1575 unsigned BaseOp = 0;
1576 switch (Op.getOpcode()) {
1577 default:
1580 BaseOp = M68kISD::ADD;
1582 break;
1584 BaseOp = M68kISD::ADD;
1586 break;
1588 BaseOp = M68kISD::SUB;
1590 break;
1592 BaseOp = M68kISD::SUB;
1594 break;
1597 NoOverflow = VT != MVT::i32;
1600 break;
1603 NoOverflow = VT != MVT::i32;
1606 break;
1607 }
1608
1610 if (NoOverflow)
1612 else
1613
1614 VTs = DAG.getVTList(VT, MVT::i8);
1615
1618 if (TruncOp)
1619
1620 Result = DAG.getNode(TruncOp, DL, MVT::i8, Arith);
1621
1622 if (NoOverflow)
1624 else
1626}
1627
1629 SDNode *N = Op.getNode();
1631
1632
1633
1635 unsigned CC;
1637
1640
1641
1642 Overflow = CCR;
1643 } else {
1644
1645 Overflow = DAG.getNode(M68kISD::SETCC, DL, N->getValueType(1),
1647 }
1648
1650}
1651
1652
1653
1656
1657
1658
1659 if (Src.getValueType() == MVT::i8 || Src.getValueType() == MVT::i16)
1661
1662
1663
1664 if (Src.getValueType() != BitNo.getValueType())
1666
1667 SDValue BTST = DAG.getNode(M68kISD::BTST, DL, MVT::i8, Src, BitNo);
1668
1669
1671 return DAG.getNode(M68kISD::SETCC, DL, MVT::i8,
1673}
1674
1675
1684
1690
1691
1693 unsigned AndBitWidth = And.getValueSizeInBits();
1694 if (BitWidth > AndBitWidth) {
1696 if (Known.countMinLeadingZeros() < BitWidth - AndBitWidth)
1698 }
1699 LHS = Op1;
1701 }
1703 uint64_t AndRHSVal = AndRHS->getZExtValue();
1705
1709 }
1710
1711
1713 LHS = AndLHS;
1715 }
1716 }
1717
1718 if (LHS.getNode())
1720
1722}
1723
1725 switch (SetCCOpcode) {
1726 default:
1748 }
1749}
1750
1751
1752
1753
1757 if (!IsFP) {
1759 if (SetCCOpcode == ISD::SETGT && RHSC->isAllOnes()) {
1760
1763 }
1764 if (SetCCOpcode == ISD::SETLT && RHSC->isZero()) {
1765
1767 }
1768 if (SetCCOpcode == ISD::SETLT && RHSC->getZExtValue() == 1) {
1769
1772 }
1773 }
1774
1776 }
1777
1778
1779
1780
1782 SetCCOpcode = getSetCCSwappedOperands(SetCCOpcode);
1784 }
1785
1786 switch (SetCCOpcode) {
1787 default:
1788 break;
1794 break;
1795 }
1796
1797
1798
1799
1800
1801
1802
1803 switch (SetCCOpcode) {
1804 default:
1831 }
1832}
1833
1834
1837
1839 "Expected TRUNCATE to i1 node");
1840
1841 if (Op.getOperand(0).getOpcode() != ISD::SRL)
1843
1844 SDValue ShiftRight = Op.getOperand(0);
1846 CC, DL, DAG);
1847}
1848
1849
1852 ++UI) {
1854 unsigned UOpNo = UI->getOperandNo();
1856
1859 }
1860
1861 if (User->getOpcode() != ISD::BRCOND && User->getOpcode() != ISD::SETCC &&
1863 return true;
1864 }
1865 return false;
1866}
1867
1868SDValue M68kTargetLowering::EmitTest(SDValue Op, unsigned M68kCC,
1870
1871
1872
1873 bool NeedCF = false;
1874 bool NeedOF = false;
1875 switch (M68kCC) {
1876 default:
1877 break;
1882 NeedCF = true;
1883 break;
1890
1891
1892
1893 switch (Op->getOpcode()) {
1898 if (Op.getNode()->getFlags().hasNoSignedWrap())
1899 break;
1900 [[fallthrough]];
1901 }
1902 default:
1903 NeedOF = true;
1904 break;
1905 }
1906 break;
1907 }
1908 }
1909
1910
1911
1912 if (Op.getResNo() != 0 || NeedOF || NeedCF) {
1913
1914 return DAG.getNode(M68kISD::CMP, DL, MVT::i8,
1916 }
1917 unsigned Opcode = 0;
1918 unsigned NumOperands = 0;
1919
1920
1921
1922
1923 bool NeedTruncation = false;
1926 SDValue Arith = Op->getOperand(0);
1927
1930 default:
1931 break;
1937 NeedTruncation = true;
1938 ArithOp = Arith;
1939 }
1940 }
1941 }
1942
1943
1944
1945
1948 Opcode = M68kISD::ADD;
1949 NumOperands = 2;
1950 break;
1953
1954
1955
1959 EVT VT = Op.getValueType();
1961 unsigned ShAmt = Op->getConstantOperandVal(1);
1962 if (ShAmt >= BitWidth)
1963 break;
1967 if (.isSignedIntN(32))
1968 break;
1971 }
1972 break;
1973
1975
1976
1982 bool IsLegalAndnType = VT == MVT::i32 || VT == MVT::i64;
1983
1984
1985
1986 if ( !IsAndn || !IsLegalAndnType)
1987 break;
1988 }
1989 [[fallthrough]];
1993
1994
1995 for (const auto *U : Op.getNode()->users())
1996 if (U->getOpcode() == ISD::STORE)
1997 goto default_case;
1998
1999
2001 default:
2004 Opcode = M68kISD::SUB;
2005 break;
2007 Opcode = M68kISD::XOR;
2008 break;
2010 Opcode = M68kISD::AND;
2011 break;
2013 Opcode = M68kISD::OR;
2014 break;
2015 }
2016
2017 NumOperands = 2;
2018 break;
2019 case M68kISD::ADD:
2020 case M68kISD::SUB:
2021 case M68kISD::OR:
2022 case M68kISD::XOR:
2023 case M68kISD::AND:
2024 return SDValue(Op.getNode(), 1);
2025 default:
2026 default_case:
2027 break;
2028 }
2029
2030
2031
2032 if (NeedTruncation) {
2033 EVT VT = Op.getValueType();
2034 SDValue WideVal = Op->getOperand(0);
2036 unsigned ConvertedOp = 0;
2037
2038
2039
2041 default:
2042 break;
2044 ConvertedOp = M68kISD::ADD;
2045 break;
2047 ConvertedOp = M68kISD::SUB;
2048 break;
2050 ConvertedOp = M68kISD::AND;
2051 break;
2053 ConvertedOp = M68kISD::OR;
2054 break;
2056 ConvertedOp = M68kISD::XOR;
2057 break;
2058 }
2059
2060 if (ConvertedOp) {
2065 Op = DAG.getNode(ConvertedOp, DL, VT, V0, V1);
2066 }
2067 }
2068 }
2069
2070 if (Opcode == 0) {
2071
2072 return DAG.getNode(M68kISD::CMP, DL, MVT::i8,
2074 }
2075 SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::i8);
2077
2081}
2082
2083
2085 switch (M68kCC) {
2086 default:
2094 return true;
2099 return false;
2100 }
2101}
2102
2106 return EmitTest(Op0, M68kCC, DL, DAG);
2107
2109 "Unexpected comparison operation for MVT::i1 operands");
2110
2113
2114
2118 unsigned ExtendOp =
2120 Op0 = DAG.getNode(ExtendOp, DL, MVT::i32, Op0);
2121 Op1 = DAG.getNode(ExtendOp, DL, MVT::i32, Op1);
2122 }
2123
2127 }
2128 return DAG.getNode(M68kISD::CMP, DL, MVT::i8, Op0, Op1);
2129}
2130
2131
2132
2138 if (Op.getOpcode() == ISD::TRUNCATE && Op.getValueType() == MVT::i1)
2141}
2142
2144 MVT VT = Op.getSimpleValueType();
2145 assert(VT == MVT::i8 && "SetCC type must be 8-bit integer");
2146
2151
2152
2153
2154
2155
2156
2159 if (SDValue NewSetCC = LowerToBTST(Op0, CC, DL, DAG)) {
2160 if (VT == MVT::i1)
2162 return NewSetCC;
2163 }
2164 }
2165
2166
2167
2170
2171
2172
2173 if (Op0.getOpcode() == M68kISD::SETCC) {
2176 if (!Invert)
2177 return Op0;
2178
2181 DAG.getNode(M68kISD::SETCC, DL, MVT::i8,
2183 if (VT == MVT::i1)
2185 return SetCC;
2186 }
2187 }
2192 }
2196 }
2197 }
2198
2203
2204 SDValue CCR = EmitCmp(Op0, Op1, M68kCC, DL, DAG);
2205 return DAG.getNode(M68kISD::SETCC, DL, MVT::i8,
2207}
2208
2213 SDValue Carry = Op.getOperand(2);
2216
2217 assert(LHS.getSimpleValueType().isInteger() && "SETCCCARRY is integer only.");
2219
2222 Carry = DAG.getNode(M68kISD::ADD, DL, DAG.getVTList(CarryVT, MVT::i32), Carry,
2224
2225 SDVTList VTs = DAG.getVTList(LHS.getValueType(), MVT::i32);
2228
2229 return DAG.getNode(M68kISD::SETCC, DL, MVT::i8,
2231}
2232
2233
2235 unsigned Opc = Op.getNode()->getOpcode();
2236 if (Opc == M68kISD::CMP)
2237 return true;
2238 if (Op.getResNo() == 1 &&
2239 (Opc == M68kISD::ADD || Opc == M68kISD::SUB || Opc == M68kISD::ADDX ||
2240 Opc == M68kISD::SUBX || Opc == M68kISD::SMUL || Opc == M68kISD::UMUL ||
2241 Opc == M68kISD::OR || Opc == M68kISD::XOR || Opc == M68kISD::AND))
2242 return true;
2243
2244 if (Op.getResNo() == 2 && Opc == M68kISD::UMUL)
2245 return true;
2246
2247 return false;
2248}
2249
2252 return false;
2253
2256 unsigned Bits = V.getValueSizeInBits();
2259}
2260
2262 bool addTest = true;
2268
2270 if (SDValue NewCond = LowerSETCC(Cond, DAG))
2271 Cond = NewCond;
2272 }
2273
2274
2275
2276
2277
2278 if (Cond.getOpcode() == M68kISD::SETCC &&
2279 Cond.getOperand(1).getOpcode() == M68kISD::CMP &&
2282
2283 unsigned CondCode = Cond.getConstantOperandVal(0);
2284
2288
2290
2291
2292
2295
2297
2299 DAG.getNode(M68kISD::SUB, DL, VTs,
2301
2302 SDValue Res = DAG.getNode(M68kISD::SETCC_CARRY, DL, Op.getValueType(),
2305 return Res;
2306 }
2307
2308 Cmp = DAG.getNode(M68kISD::CMP, DL, MVT::i8,
2310
2311 SDValue Res =
2312 DAG.getNode(M68kISD::SETCC_CARRY, DL, Op.getValueType(),
2314
2317
2320 return Res;
2321 }
2322 }
2323
2324
2326 Cond.getOperand(0).getOpcode() == M68kISD::SETCC_CARRY &&
2329
2330
2331
2332 unsigned CondOpcode = Cond.getOpcode();
2333 if (CondOpcode == M68kISD::SETCC || CondOpcode == M68kISD::SETCC_CARRY) {
2335
2337 unsigned Opc = Cmp.getOpcode();
2338
2339 bool IllegalFPCMov = false;
2340
2341 if ((isM68kLogicalCmp(Cmp) && !IllegalFPCMov) || Opc == M68kISD::BTST) {
2343 addTest = false;
2344 }
2346
2348 unsigned CCode;
2351 addTest = false;
2352 }
2353
2354 if (addTest) {
2355
2358
2359
2360
2365 addTest = false;
2366 }
2367 }
2368 }
2369
2370 if (addTest) {
2373 }
2374
2375
2376
2377
2378
2379 if (Cond.getOpcode() == M68kISD::SUB) {
2381
2386 DAG.getNode(M68kISD::SETCC_CARRY, DL, Op.getValueType(),
2390 return Res;
2391 }
2392 }
2393
2394
2395
2396
2400 if (T1.getValueType() == T2.getValueType() &&
2401
2405 DAG.getNode(M68kISD::CMOV, DL, T1.getValueType(), T2, T1, CC, Cond);
2407 }
2408 }
2409
2410
2411
2412
2414 const APInt &C = Const->getAPIntValue();
2415 if (C.countr_zero() >= 5)
2416 return Op2;
2417 else if (C.countr_one() >= 5)
2418 return Op1;
2419 }
2420
2421
2422
2424 return DAG.getNode(M68kISD::CMOV, DL, Op.getValueType(), Ops);
2425}
2426
2427
2428
2432 return false;
2434 Op.getOperand(0).hasOneUse() &&
2436 Op.getOperand(1).hasOneUse());
2437}
2438
2439
2440
2443 return false;
2445 return Op.getOperand(0).getOpcode() == M68kISD::SETCC &&
2446 Op.getOperand(0).hasOneUse();
2447 return false;
2448}
2449
2451 bool AddTest = true;
2452 SDValue Chain = Op.getOperand(0);
2454 SDValue Dest = Op.getOperand(2);
2457 bool Inverted = false;
2458
2460
2463 Cond.getOperand(0).getResNo() == 1 &&
2468 Inverted = true;
2470 } else {
2471 if (SDValue NewCond = LowerSETCC(Cond, DAG))
2472 Cond = NewCond;
2473 }
2474 }
2475
2476
2478 Cond.getOperand(0).getOpcode() == M68kISD::SETCC_CARRY &&
2481
2482
2483
2484 unsigned CondOpcode = Cond.getOpcode();
2485 if (CondOpcode == M68kISD::SETCC || CondOpcode == M68kISD::SETCC_CARRY) {
2487
2489 unsigned Opc = Cmp.getOpcode();
2490
2493 AddTest = false;
2494 } else {
2496 default:
2497 break;
2500
2501
2502 Cond = Cond.getNode()->getOperand(1);
2503 AddTest = false;
2504 break;
2505 }
2506 }
2507 }
2508 CondOpcode = Cond.getOpcode();
2511 unsigned CCode;
2513
2514 if (Inverted)
2517
2518 AddTest = false;
2519 } else {
2520 unsigned CondOpc;
2523 if (CondOpc == ISD::OR) {
2524
2525
2526
2529 Chain = DAG.getNode(M68kISD::BRCOND, DL, Op.getValueType(), Chain,
2530 Dest, CC, Cmp);
2533 AddTest = false;
2534 }
2535 } else {
2536
2537
2538
2539
2540
2542 Op.getNode()->hasOneUse()) {
2547 SDNode *User = *Op.getNode()->user_begin();
2548
2549
2550
2551 if (User->getOpcode() == ISD::BR) {
2553 SDNode *NewBR =
2555 assert(NewBR == User);
2556 (void)NewBR;
2557 Dest = FalseBB;
2558
2559 Chain = DAG.getNode(M68kISD::BRCOND, DL, Op.getValueType(), Chain,
2560 Dest, CC, Cmp);
2566 AddTest = false;
2567 }
2568 }
2569 }
2571
2572
2573
2579 AddTest = false;
2580 }
2581 }
2582
2583 if (AddTest) {
2584
2587
2588
2589 if (Cond.hasOneUse()) {
2593 AddTest = false;
2594 }
2595 }
2596 }
2597
2598 if (AddTest) {
2601 Cond = EmitTest(Cond, MxCond, DL, DAG);
2602 }
2603 return DAG.getNode(M68kISD::BRCOND, DL, Op.getValueType(), Chain, Dest, CC,
2605}
2606
2607SDValue M68kTargetLowering::LowerADDC_ADDE_SUBC_SUBE(SDValue Op,
2609 MVT VT = Op.getNode()->getSimpleValueType(0);
2610
2611
2614
2615 SDVTList VTs = DAG.getVTList(VT, MVT::i8);
2616
2617 unsigned Opc;
2618 bool ExtraOp = false;
2619 switch (Op.getOpcode()) {
2620 default:
2623 Opc = M68kISD::ADD;
2624 break;
2626 Opc = M68kISD::ADDX;
2627 ExtraOp = true;
2628 break;
2630 Opc = M68kISD::SUB;
2631 break;
2633 Opc = M68kISD::SUBX;
2634 ExtraOp = true;
2635 break;
2636 }
2637
2638 if (!ExtraOp)
2639 return DAG.getNode(Opc, SDLoc(Op), VTs, Op.getOperand(0), Op.getOperand(1));
2640 return DAG.getNode(Opc, SDLoc(Op), VTs, Op.getOperand(0), Op.getOperand(1),
2641 Op.getOperand(2));
2642}
2643
2644
2645
2646
2647
2648
2649
2653
2654
2655
2656 unsigned char OpFlag = Subtarget.classifyLocalReference(nullptr);
2657
2658 unsigned WrapperKind = M68kISD::Wrapper;
2660 WrapperKind = M68kISD::WrapperPC;
2661 }
2662
2665 CP->getConstVal(), PtrVT, CP->getAlign(), CP->getOffset(), OpFlag);
2666
2667 SDLoc DL(CP);
2669
2670
2673 DAG.getNode(M68kISD::GLOBAL_BASE_REG, SDLoc(), PtrVT),
2674 Result);
2675 }
2676
2678}
2679
2683
2684
2685
2687 unsigned char OpFlag = Subtarget.classifyExternalReference(*Mod);
2688
2689 unsigned WrapperKind = M68kISD::Wrapper;
2691 WrapperKind = M68kISD::WrapperPC;
2692 }
2693
2696
2699
2700
2703 DAG.getNode(M68kISD::GLOBAL_BASE_REG, SDLoc(), PtrVT),
2704 Result);
2705 }
2706
2707
2708
2712 }
2713
2715}
2716
2719 unsigned char OpFlags = Subtarget.classifyBlockAddressReference();
2724
2725
2727
2729 Result = DAG.getNode(M68kISD::WrapperPC, DL, PtrVT, Result);
2730 } else {
2731 Result = DAG.getNode(M68kISD::Wrapper, DL, PtrVT, Result);
2732 }
2733
2734
2738 DAG.getNode(M68kISD::GLOBAL_BASE_REG, DL, PtrVT), Result);
2739 }
2740
2742}
2743
2744SDValue M68kTargetLowering::LowerGlobalAddress(const GlobalValue *GV,
2747 unsigned char OpFlags = Subtarget.classifyGlobalReference(GV);
2749
2750
2751
2756 } else {
2758 }
2759
2761 Result = DAG.getNode(M68kISD::WrapperPC, DL, PtrVT, Result);
2762 else
2763 Result = DAG.getNode(M68kISD::Wrapper, DL, PtrVT, Result);
2764
2765
2769 DAG.getNode(M68kISD::GLOBAL_BASE_REG, DL, PtrVT), Result);
2770 }
2771
2772
2773
2777 }
2778
2779
2780
2784 }
2785
2787}
2788
2793 return LowerGlobalAddress(GV, SDLoc(Op), Offset, DAG);
2794}
2795
2796
2797
2798
2799
2803
2804
2805
2806 unsigned char OpFlag = Subtarget.classifyLocalReference(nullptr);
2807
2808 unsigned WrapperKind = M68kISD::Wrapper;
2810 WrapperKind = M68kISD::WrapperPC;
2811 }
2812
2815 SDLoc DL(JT);
2817
2818
2821 DAG.getNode(M68kISD::GLOBAL_BASE_REG, SDLoc(), PtrVT),
2822 Result);
2823 }
2824
2826}
2827
2829 return Subtarget.getJumpTableEncoding();
2830}
2831
2834 unsigned uid, MCContext &Ctx) const {
2836}
2837
2841 return DAG.getNode(M68kISD::GLOBAL_BASE_REG, SDLoc(),
2843
2844
2845 return Table;
2846}
2847
2848
2853
2856 if (Constraint.size() > 0) {
2857 switch (Constraint[0]) {
2858 case 'a':
2859 case 'd':
2861 case 'I':
2862 case 'J':
2863 case 'K':
2864 case 'L':
2865 case 'M':
2866 case 'N':
2867 case 'O':
2868 case 'P':
2870 case 'C':
2871 if (Constraint.size() == 2)
2872 switch (Constraint[1]) {
2873 case '0':
2874 case 'i':
2875 case 'j':
2877 default:
2878 break;
2879 }
2880 break;
2881 case 'Q':
2882 case 'U':
2884 default:
2885 break;
2886 }
2887 }
2888
2890}
2891
2894 std::vector &Ops,
2897
2898 if (Constraint.size() == 1) {
2899
2900 switch (Constraint[0]) {
2901 case 'I':
2902 case 'J':
2903 case 'K':
2904 case 'L':
2905 case 'M':
2906 case 'N':
2907 case 'O':
2908 case 'P': {
2910 if ()
2911 return;
2912
2913 int64_t Val = C->getSExtValue();
2914 switch (Constraint[0]) {
2915 case 'I':
2916 if (Val > 0 && Val <= 8)
2917 break;
2918 return;
2919 case 'J':
2921 break;
2922 return;
2923 case 'K':
2924 if (Val < -0x80 || Val >= 0x80)
2925 break;
2926 return;
2927 case 'L':
2928 if (Val < 0 && Val >= -8)
2929 break;
2930 return;
2931 case 'M':
2932 if (Val < -0x100 || Val >= 0x100)
2933 break;
2934 return;
2935 case 'N':
2936 if (Val >= 24 && Val <= 31)
2937 break;
2938 return;
2939 case 'O':
2940 if (Val == 16)
2941 break;
2942 return;
2943 case 'P':
2944 if (Val >= 8 && Val <= 15)
2945 break;
2946 return;
2947 default:
2949 }
2950
2952 break;
2953 }
2954 default:
2955 break;
2956 }
2957 }
2958
2959 if (Constraint.size() == 2) {
2960 switch (Constraint[0]) {
2961 case 'C':
2962
2963 switch (Constraint[1]) {
2964 case '0':
2965 case 'i':
2966 case 'j': {
2968 if ()
2969 break;
2970
2971 int64_t Val = C->getSExtValue();
2972 switch (Constraint[1]) {
2973 case '0':
2974 if (!Val)
2975 break;
2976 return;
2977 case 'i':
2978 break;
2979 case 'j':
2981 break;
2982 return;
2983 default:
2985 }
2986
2988 break;
2989 }
2990 default:
2991 break;
2992 }
2993 break;
2994 default:
2995 break;
2996 }
2997 }
2998
2999 if (Result.getNode()) {
3000 Ops.push_back(Result);
3001 return;
3002 }
3003
3005}
3006
3007std::pair<unsigned, const TargetRegisterClass *>
3010 MVT VT) const {
3011 if (Constraint.size() == 1) {
3012 switch (Constraint[0]) {
3013 case 'r':
3014 case 'd':
3016 case MVT::i8:
3017 return std::make_pair(0U, &M68k::DR8RegClass);
3018 case MVT::i16:
3019 return std::make_pair(0U, &M68k::DR16RegClass);
3020 case MVT::i32:
3021 return std::make_pair(0U, &M68k::DR32RegClass);
3022 default:
3023 break;
3024 }
3025 break;
3026 case 'a':
3028 case MVT::i16:
3029 return std::make_pair(0U, &M68k::AR16RegClass);
3030 case MVT::i32:
3031 return std::make_pair(0U, &M68k::AR32RegClass);
3032 default:
3033 break;
3034 }
3035 break;
3036 default:
3037 break;
3038 }
3039 }
3040
3042}
3043
3044
3045
3049
3050
3051
3052
3054 switch (MI.getOpcode()) {
3055 case M68k::CMOV8d:
3056 case M68k::CMOV16d:
3057 case M68k::CMOV32r:
3058 return true;
3059
3060 default:
3061 return false;
3062 }
3063}
3064
3065
3066
3067
3068
3069
3073
3077 if (mi.readsRegister(M68k::CCR, nullptr))
3078 return false;
3080 break;
3081 }
3082
3083
3084
3085 if (miI == BB->end())
3086 for (const auto *SBB : BB->successors())
3087 if (SBB->isLiveIn(M68k::CCR))
3088 return false;
3089
3090
3091
3092 SelectItr->addRegisterKilled(M68k::CCR, TRI);
3093 return true;
3094}
3095
3097M68kTargetLowering::EmitLoweredSelect(MachineInstr &MI,
3099 const TargetInstrInfo *TII = Subtarget.getInstrInfo();
3101
3102
3103
3104
3105
3108
3109
3110
3111
3112
3113
3114
3115 MachineBasicBlock *ThisMBB = MBB;
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154 MachineInstr *CascadedCMOV = nullptr;
3155 MachineInstr *LastCMOV = &MI;
3160
3161
3162
3163
3164
3166
3168 (NextMIIt->getOperand(3).getImm() == CC ||
3169 NextMIIt->getOperand(3).getImm() == OppCC)) {
3170 LastCMOV = &*NextMIIt;
3171 ++NextMIIt;
3172 }
3173 }
3174
3175
3176
3177 if (LastCMOV == &MI && NextMIIt != MBB->end() &&
3178 NextMIIt->getOpcode() == MI.getOpcode() &&
3179 NextMIIt->getOperand(2).getReg() == MI.getOperand(2).getReg() &&
3180 NextMIIt->getOperand(1).getReg() == MI.getOperand(0).getReg() &&
3181 NextMIIt->getOperand(1).isKill()) {
3182 CascadedCMOV = &*NextMIIt;
3183 }
3184
3185 MachineBasicBlock *Jcc1MBB = nullptr;
3186
3187
3188
3189 if (CascadedCMOV) {
3190 Jcc1MBB = F->CreateMachineBasicBlock(BB);
3193 }
3194
3195 MachineBasicBlock *Copy0MBB = F->CreateMachineBasicBlock(BB);
3196 MachineBasicBlock *SinkMBB = F->CreateMachineBasicBlock(BB);
3197 F->insert(It, Copy0MBB);
3198 F->insert(It, SinkMBB);
3199
3200
3204
3205
3206
3207 const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
3208
3209 MachineInstr *LastCCRSUser = CascadedCMOV ? CascadedCMOV : LastCMOV;
3210 if (!LastCCRSUser->killsRegister(M68k::CCR, nullptr) &&
3214 }
3215
3216
3220
3221
3222 if (CascadedCMOV) {
3223
3225
3226
3227
3230 } else {
3232 }
3233
3234
3236
3237
3240
3241 if (CascadedCMOV) {
3245 }
3246
3247
3248
3249
3251
3252
3253
3254
3259 DenseMap<unsigned, std::pair<unsigned, unsigned>> RegRewriteTable;
3260 MachineInstrBuilder MIB;
3261
3262
3263
3264
3265
3266
3267
3268
3270 Register DestReg = MIIt->getOperand(0).getReg();
3271 Register Op1Reg = MIIt->getOperand(1).getReg();
3272 Register Op2Reg = MIIt->getOperand(2).getReg();
3273
3274
3275
3276
3277 if (MIIt->getOperand(3).getImm() == OppCC)
3279
3280 if (RegRewriteTable.find(Op1Reg) != RegRewriteTable.end())
3281 Op1Reg = RegRewriteTable[Op1Reg].first;
3282
3283 if (RegRewriteTable.find(Op2Reg) != RegRewriteTable.end())
3284 Op2Reg = RegRewriteTable[Op2Reg].second;
3285
3286 MIB =
3287 BuildMI(*SinkMBB, SinkInsertionPoint, DL, TII->get(M68k::PHI), DestReg)
3292
3293
3294 RegRewriteTable[DestReg] = std::make_pair(Op1Reg, Op2Reg);
3295 }
3296
3297
3298
3299 if (CascadedCMOV) {
3300 MIB.addReg(MI.getOperand(2).getReg()).addMBB(Jcc1MBB);
3301
3303 DL, TII->get(TargetOpcode::COPY),
3305 .addReg(MI.getOperand(0).getReg());
3307 }
3308
3309
3311 (MIIt++)->eraseFromParent();
3312
3313 return SinkMBB;
3314}
3315
3317M68kTargetLowering::EmitLoweredSegAlloca(MachineInstr &MI,
3319 llvm_unreachable("Cannot lower Segmented Stack Alloca with stack-split on");
3320}
3321
3325 switch (MI.getOpcode()) {
3326 default:
3328 case M68k::CMOV8d:
3329 case M68k::CMOV16d:
3330 case M68k::CMOV32r:
3331 return EmitLoweredSelect(MI, BB);
3332 case M68k::SALLOCA:
3333 return EmitLoweredSegAlloca(MI, BB);
3334 }
3335}
3336
3341
3344
3345
3346
3348 return DAG.getStore(Op.getOperand(0), DL, FR, Op.getOperand(1),
3350}
3351
3354
3357
3360 const SDValue AsmOperands[4] = {
3361 Op.getOperand(0),
3364 DAG.getDataLayout())),
3368 };
3369
3370 return DAG.getNode(ISD::INLINEASM, SDLoc(Op),
3371 DAG.getVTList(MVT::Other, MVT::Glue), AsmOperands);
3372}
3373
3374
3375
3376
3377
3378
3379SDValue M68kTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,
3383
3385
3386
3387 SDNode *Node = Op.getNode();
3388 SDValue Chain = Op.getOperand(0);
3390 unsigned Align = Op.getConstantOperandVal(2);
3391 EVT VT = Node->getValueType(0);
3392
3393
3394
3396
3398 if (SplitStack) {
3402 Register Vreg = MRI.createVirtualRegister(ARClass);
3404 Result = DAG.getNode(M68kISD::SEG_ALLOCA, DL, SPTy, Chain,
3406 } else {
3409 assert(SPReg && "Target cannot require DYNAMIC_STACKALLOC expansion and"
3410 " not tell us which reg is the stack pointer!");
3411
3413 Chain = SP.getValue(1);
3414 const TargetFrameLowering &TFI = *Subtarget.getFrameLowering();
3417 if (Align > StackAlign)
3421 }
3422
3424
3427}
3428
3434 SDValue Shamt = Op.getOperand(2);
3435 EVT VT = Lo.getValueType();
3436
3437
3438
3439
3440
3441
3442
3443
3448 SDValue ShamtMinusRegisterSize =
3450 SDValue RegisterSizeMinus1Shamt =
3452
3456 DAG.getNode(ISD::SRL, DL, VT, ShiftRight1Lo, RegisterSizeMinus1Shamt);
3460
3463
3466
3468}
3469
3471 bool IsSRA) const {
3475 SDValue Shamt = Op.getOperand(2);
3476 EVT VT = Lo.getValueType();
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3495
3500 SDValue ShamtMinusRegisterSize =
3502 SDValue RegisterSizeMinus1Shamt =
3504
3508 DAG.getNode(ISD::SHL, DL, VT, ShiftLeftHi1, RegisterSizeMinus1Shamt);
3512 DAG.getNode(ShiftRightOp, DL, VT, Hi, ShamtMinusRegisterSize);
3515
3518
3521
3523}
3524
3525
3526
3527
3528
3531 return DAG.getNode(M68kISD::SETCC, dl, MVT::i8,
3533}
3534
3535
3536
3538 if (CCR.getOpcode() == M68kISD::ADD) {
3548 if (Carry.getOpcode() == M68kISD::SETCC ||
3549 Carry.getOpcode() == M68kISD::SETCC_CARRY) {
3552 }
3553 }
3554 }
3555
3557}
3558
3559
3560
3561
3567 return Flags;
3568
3570}
3571
3572
3577 SDValue CCR = N->getOperand(1);
3578
3579
3581 return getSETCC(CC, Flags, DL, DAG);
3582
3584}
3589 SDValue CCR = N->getOperand(3);
3590
3591
3592
3593
3596 return DAG.getNode(M68kISD::BRCOND, DL, N->getVTList(), N->getOperand(0),
3597 N->getOperand(1), Cond, Flags);
3598 }
3599
3601}
3602
3605 MVT VT = N->getSimpleValueType(0);
3607 return DAG.getNode(M68kISD::SUBX, SDLoc(N), VTs, N->getOperand(0),
3608 N->getOperand(1), Flags);
3609 }
3610
3612}
3613
3614
3618 MVT VT = N->getSimpleValueType(0);
3620 return DAG.getNode(M68kISD::ADDX, SDLoc(N), VTs, N->getOperand(0),
3621 N->getOperand(1), Flags);
3622 }
3623
3625}
3626
3627SDValue M68kTargetLowering::PerformDAGCombine(SDNode *N,
3628 DAGCombinerInfo &DCI) const {
3629 SelectionDAG &DAG = DCI.DAG;
3630 switch (N->getOpcode()) {
3631 case M68kISD::SUBX:
3633 case M68kISD::ADDX:
3635 case M68kISD::SETCC:
3637 case M68kISD::BRCOND:
3639 }
3640
3642}
3643
3645 bool IsVarArg) const {
3646 if (Return)
3647 return RetCC_M68k_C;
3648 else
3649 return CC_M68k_C;
3650}
unsigned const MachineRegisterInfo * MRI
static SDValue getSETCC(AArch64CC::CondCode CC, SDValue NZCV, const SDLoc &DL, SelectionDAG &DAG)
Helper function to create 'CSET', which is equivalent to 'CSINC , WZR, WZR, invert()'.
static bool canGuaranteeTCO(CallingConv::ID CC, bool GuaranteeTailCalls)
Return true if the calling convention is one that we can guarantee TCO for.
static bool mayTailCallThisCC(CallingConv::ID CC)
Return true if we might ever do TCO for calls with this calling convention.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
const TargetInstrInfo & TII
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static SDValue CreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain, ISD::ArgFlagsTy Flags, SelectionDAG &DAG, const SDLoc &dl)
CreateCopyOfByValArgument - Make a copy of an aggregate at address specified by "Src" to address "Dst...
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
This file contains the custom routines for the M68k Calling Convention that aren't done by tablegen.
static SDValue LowerTruncateToBTST(SDValue Op, ISD::CondCode CC, const SDLoc &DL, SelectionDAG &DAG)
Definition M68kISelLowering.cpp:1835
static void lowerOverflowArithmetic(SDValue Op, SelectionDAG &DAG, SDValue &Result, SDValue &CCR, unsigned &CC)
Definition M68kISelLowering.cpp:1551
static SDValue combineADDX(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI)
Definition M68kISelLowering.cpp:3615
static bool isAndOrOfSetCCs(SDValue Op, unsigned &Opc)
Return true if node is an ISD::AND or ISD::OR of two M68k::SETcc nodes each of which has no other use...
Definition M68kISelLowering.cpp:2429
static bool hasNonFlagsUse(SDValue Op)
return true if Op has a use that doesn't just read flags.
Definition M68kISelLowering.cpp:1850
static bool isM68kCCUnsigned(unsigned M68kCC)
Return true if the condition is an unsigned comparison operation.
Definition M68kISelLowering.cpp:2084
static StructReturnType callIsStructReturn(const SmallVectorImpl< ISD::OutputArg > &Outs)
Definition M68kISelLowering.cpp:238
static bool isXor1OfSetCC(SDValue Op)
Return true if node is an ISD::XOR of a M68kISD::SETCC and 1 and that the SETCC node has a single use...
Definition M68kISelLowering.cpp:2441
static SDValue LowerAndToBTST(SDValue And, ISD::CondCode CC, const SDLoc &DL, SelectionDAG &DAG)
Result of 'and' is compared against zero. Change to a BTST node if possible.
Definition M68kISelLowering.cpp:1676
static SDValue combineM68kBrCond(SDNode *N, SelectionDAG &DAG, const M68kSubtarget &Subtarget)
Definition M68kISelLowering.cpp:3585
static M68k::CondCode TranslateIntegerM68kCC(ISD::CondCode SetCCOpcode)
Definition M68kISelLowering.cpp:1724
static StructReturnType argsAreStructReturn(const SmallVectorImpl< ISD::InputArg > &Ins)
Determines whether a function uses struct return semantics.
Definition M68kISelLowering.cpp:252
static bool isCMOVPseudo(MachineInstr &MI)
Definition M68kISelLowering.cpp:3053
static bool shouldGuaranteeTCO(CallingConv::ID CC, bool GuaranteedTailCallOpt)
Return true if the function is being made into a tailcall target by changing its ABI.
Definition M68kISelLowering.cpp:294
static bool isM68kLogicalCmp(SDValue Op)
Return true if opcode is a M68k logical comparison.
Definition M68kISelLowering.cpp:2234
static SDValue combineM68kSetCC(SDNode *N, SelectionDAG &DAG, const M68kSubtarget &Subtarget)
Definition M68kISelLowering.cpp:3573
static SDValue combineSetCCCCR(SDValue CCR, M68k::CondCode &CC, SelectionDAG &DAG, const M68kSubtarget &Subtarget)
Optimize a CCR definition used according to the condition code CC into a simpler CCR value,...
Definition M68kISelLowering.cpp:3562
static SDValue combineCarryThroughADD(SDValue CCR)
Definition M68kISelLowering.cpp:3537
static bool isOverflowArithmetic(unsigned Opcode)
Definition M68kISelLowering.cpp:1537
static bool MatchingStackOffset(SDValue Arg, unsigned Offset, ISD::ArgFlagsTy Flags, MachineFrameInfo &MFI, const MachineRegisterInfo *MRI, const M68kInstrInfo *TII, const CCValAssign &VA)
Return true if the given stack call argument is already available in the same position (relatively) o...
Definition M68kISelLowering.cpp:300
static SDValue getBitTestCondition(SDValue Src, SDValue BitNo, ISD::CondCode CC, const SDLoc &DL, SelectionDAG &DAG)
Create a BTST (Bit Test) node - Test bit BitNo in Src and set condition according to equal/not-equal ...
Definition M68kISelLowering.cpp:1654
StructReturnType
Definition M68kISelLowering.cpp:235
@ NotStructReturn
Definition M68kISelLowering.cpp:235
@ RegStructReturn
Definition M68kISelLowering.cpp:235
@ StackStructReturn
Definition M68kISelLowering.cpp:235
static bool isTruncWithZeroHighBitsInput(SDValue V, SelectionDAG &DAG)
Definition M68kISelLowering.cpp:2250
static bool checkAndUpdateCCRKill(MachineBasicBlock::iterator SelectItr, MachineBasicBlock *BB, const TargetRegisterInfo *TRI)
Definition M68kISelLowering.cpp:3070
static SDValue combineSUBX(SDNode *N, SelectionDAG &DAG)
Definition M68kISelLowering.cpp:3603
static unsigned TranslateM68kCC(ISD::CondCode SetCCOpcode, const SDLoc &DL, bool IsFP, SDValue &LHS, SDValue &RHS, SelectionDAG &DAG)
Do a one-to-one translation of a ISD::CondCode to the M68k-specific condition code,...
Definition M68kISelLowering.cpp:1754
This file defines the interfaces that M68k uses to lower LLVM code into a selection DAG.
This file contains the declarations of the M68k MCAsmInfo properties.
This file declares the M68k specific subclass of MachineFunctionInfo.
This file declares the M68k specific subclass of TargetSubtargetInfo.
This file declares the M68k specific subclass of TargetMachine.
This file contains declarations for M68k ELF object file lowering.
Machine Check Debug Module
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static constexpr MCPhysReg SPReg
const SmallVectorImpl< MachineOperand > & Cond
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
an instruction that atomically reads a memory location, combines it with another value,...
static LLVM_ABI bool resultsCompatible(CallingConv::ID CalleeCC, CallingConv::ID CallerCC, MachineFunction &MF, LLVMContext &C, const SmallVectorImpl< ISD::InputArg > &Ins, CCAssignFn CalleeFn, CCAssignFn CallerFn)
Returns true if the results of the two calling conventions are compatible.
CCValAssign - Represent assignment of one arg/retval to a location.
Register getLocReg() const
LocInfo getLocInfo() const
int64_t getLocMemOffset() const
unsigned getValNo() const
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
This is an important base class in LLVM.
A parsed version of the target data layout string in and methods for querying it.
iterator find(const_arg_type_t< KeyT > Val)
iterator_range< arg_iterator > args()
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
bool hasStructRetAttr() const
Determine if the function returns a structure through first or second pointer argument.
int64_t getOffset() const
const GlobalValue * getGlobal() const
bool hasDLLImportStorageClass() const
Module * getParent()
Get the module that this global value is contained inside of...
This is an important class for using LLVM in a threaded context.
void setVarArgsFrameIndex(int Index)
void setSRetReturnReg(unsigned Reg)
SmallVectorImpl< ForwardedRegister > & getForwardedMustTailRegParms()
void setBytesToPopOnReturn(unsigned bytes)
unsigned getBytesToPopOnReturn() const
unsigned getSRetReturnReg() const
void setRAIndex(int Index)
int getVarArgsFrameIndex() const
void setArgumentStackSize(unsigned size)
void setTCReturnAddrDelta(int delta)
const uint32_t * getCallPreservedMask(const MachineFunction &MF, CallingConv::ID) const override
unsigned getStackRegister() const
const M68kRegisterInfo * getRegisterInfo() const override
ConstraintType getConstraintType(StringRef ConstraintStr) const override
Given a constraint, return the type of constraint it is for this target.
Definition M68kISelLowering.cpp:2855
void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const override
Lower the specified operand into the Ops vector.
Definition M68kISelLowering.cpp:2892
MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const override
This method should be implemented by targets that mark instructions with the 'usesCustomInserter' fla...
Definition M68kISelLowering.cpp:3323
virtual MVT getScalarShiftAmountTy(const DataLayout &, EVT) const override
EVT is not used in-tree, but is used by out-of-tree target.
Definition M68kISelLowering.cpp:225
const MCExpr * LowerCustomJumpTableEntry(const MachineJumpTableInfo *MJTI, const MachineBasicBlock *MBB, unsigned uid, MCContext &Ctx) const override
Definition M68kISelLowering.cpp:2832
SDValue getPICJumpTableRelocBase(SDValue Table, SelectionDAG &DAG) const override
Returns relocation base for the given PIC jumptable.
Definition M68kISelLowering.cpp:2838
const MCExpr * getPICJumpTableRelocBaseExpr(const MachineFunction *MF, unsigned JTI, MCContext &Ctx) const override
This returns the relocation base for the given PIC jumptable, the same as getPICJumpTableRelocBase,...
Definition M68kISelLowering.cpp:2849
AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *RMW) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
Definition M68kISelLowering.cpp:194
Register getExceptionPointerRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception address on entry to an ...
Definition M68kISelLowering.cpp:201
CCAssignFn * getCCAssignFn(CallingConv::ID CC, bool Return, bool IsVarArg) const
Definition M68kISelLowering.cpp:3644
M68kTargetLowering(const M68kTargetMachine &TM, const M68kSubtarget &STI)
Definition M68kISelLowering.cpp:48
InlineAsm::ConstraintCode getInlineAsmMemConstraint(StringRef ConstraintCode) const override
Definition M68kISelLowering.cpp:211
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override
Provide custom lowering hooks for some operations.
Definition M68kISelLowering.cpp:1381
EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override
Return the value type to use for ISD::SETCC.
Definition M68kISelLowering.cpp:219
unsigned getJumpTableEncoding() const override
Return the entry encoding for a jump table in the current function.
Definition M68kISelLowering.cpp:2828
std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override
Given a physical register constraint (e.g.
Definition M68kISelLowering.cpp:3008
Register getExceptionSelectorRegister(const Constant *PersonalityFn) const override
If a physical register, this returns the register that receives the exception typeid on entry to a la...
Definition M68kISelLowering.cpp:206
Context object for machine code objects.
Base class for the full range of assembler expressions which are needed for parsing.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
static auto integer_valuetypes()
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
static MVT getIntegerVT(unsigned BitWidth)
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
void setCallFrameSize(unsigned N)
Set the call frame size on entry to this basic block.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< succ_iterator > successors()
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.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
void setObjectZExt(int ObjectIdx, bool IsZExt)
void setObjectSExt(int ObjectIdx, bool IsSExt)
void setHasTailCall(bool V=true)
bool isObjectZExt(int ObjectIdx) const
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
bool isObjectSExt(int ObjectIdx) const
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MCSymbol * getJTISymbol(unsigned JTI, MCContext &Ctx, bool isLinkerPrivate=false) const
getJTISymbol - Return the MCSymbol for the specified non-empty jump table.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
bool shouldSplitStack() const
Should we be emitting segmented stack stuff for the function.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Register addLiveIn(MCRegister PReg, const TargetRegisterClass *RC)
addLiveIn - Add the specified physical register as a live-in value and create a corresponding virtual...
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
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
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
bool readsRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr reads the specified register.
bool killsRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr kills the specified register.
bool definesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr fully defines the specified register.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
@ EK_Custom32
EK_Custom32 - Each entry is a 32-bit value that is custom lowered by the TargetLowering::LowerCustomJ...
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
Class to represent pointers.
static LLVM_ABI PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
Wrapper class representing virtual and physical registers.
static constexpr bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
This class provides iterator support for SDUse operands that use a specific SDNode.
Represents one node in the SelectionDAG.
bool hasOneUse() const
Return true if there is exactly one use of this node.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
const SDValue & getOperand(unsigned Num) const
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
uint64_t getConstantOperandVal(unsigned i) const
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
unsigned getOpcode() const
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned TargetFlags=0)
LLVM_ABI SDValue getStackArgumentTokenFactor(SDValue Chain)
Compute a TokenFactor to force all the incoming stack arguments to be loaded from the stack.
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)
LLVM_ABI SDValue getMergeValues(ArrayRef< SDValue > Ops, const SDLoc &dl)
Create a MERGE_VALUES node from the given operands.
LLVM_ABI SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
SDValue getSetCC(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS, ISD::CondCode Cond, SDValue Chain=SDValue(), bool IsSignaling=false)
Helper function to make it easier to build SetCC's if you just have an ISD::CondCode instead of an SD...
LLVM_ABI SDValue getRegister(Register Reg, EVT VT)
LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)
Loads are not normal binary operators: their result type is not determined by their operands,...
SDValue getGLOBAL_OFFSET_TABLE(EVT VT)
Return a GLOBAL_OFFSET_TABLE node. This does not have a useful SDLoc.
LLVM_ABI SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align Alignment, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), BatchAAResults *BatchAA=nullptr)
LLVM_ABI SDValue getNOT(const SDLoc &DL, SDValue Val, EVT VT)
Create a bitwise NOT operation as (XOR Val, -1).
const TargetLowering & getTargetLoweringInfo() const
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned TargetFlags=0)
SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, const SDLoc &DL)
Return a new CALLSEQ_END node, which always must have a glue result (to ensure it's not CSE'd).
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, Register Reg, EVT VT)
const DataLayout & getDataLayout() const
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
SDValue getSignedTargetConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
LLVM_ABI SDValue getMDNode(const MDNode *MD)
Return an MDNodeSDNode which holds an MDNode.
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
SDValue getCALLSEQ_START(SDValue Chain, uint64_t InSize, uint64_t OutSize, const SDLoc &DL)
Return a new CALLSEQ_START node, that starts new call frame, in which InSize bytes are set up inside ...
LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)
const TargetMachine & getTarget() const
LLVM_ABI SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
LLVM_ABI SDValue getValueType(EVT)
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)
SDValue getTargetBlockAddress(const BlockAddress *BA, EVT VT, int64_t Offset=0, unsigned TargetFlags=0)
MachineFunction & getMachineFunction() const
LLVM_ABI SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
LLVM_ABI KnownBits computeKnownBits(SDValue Op, unsigned Depth=0) const
Determine which bits of Op are known to be either zero or one and return them in Known.
LLVM_ABI SDValue getRegisterMask(const uint32_t *RegMask)
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
LLVMContext * getContext() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
LLVM_ABI SDValue CreateStackTemporary(TypeSize Bytes, Align Alignment)
Create a stack temporary based on the size in bytes and the alignment.
LLVM_ABI SDNode * UpdateNodeOperands(SDNode *N, SDValue Op)
Mutate the specified node in-place to have the specified operands.
SDValue getTargetConstantPool(const Constant *C, EVT VT, MaybeAlign Align=std::nullopt, int Offset=0, unsigned TargetFlags=0)
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
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)
unsigned getStackAlignment() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
unsigned getCallFrameSizeAt(MachineInstr &MI) const
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
const TargetMachine & getTargetMachine() const
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
Register getStackPointerRegisterToSaveRestore() const
If a physical register, this specifies the register that llvm.savestack/llvm.restorestack should save...
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.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
MVT getProgramPointerTy(const DataLayout &DL) const
Return the type for code pointers, which is determined by the program address space specified through...
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...
bool isOperationLegal(unsigned Op, EVT VT) const
Return true if the specified operation is legal on this target.
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
@ ZeroOrNegativeOneBooleanContent
void setStackPointerRegisterToSaveRestore(Register R)
If set to a physical register, this specifies the register that llvm.savestack/llvm....
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
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
virtual MVT getPointerMemTy(const DataLayout &DL, uint32_t AS=0) const
Return the in-memory pointer type for the given address space, defaults to the pointer type from the ...
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.
bool parametersInCSRMatch(const MachineRegisterInfo &MRI, const uint32_t *CallerPreservedMask, const SmallVectorImpl< CCValAssign > &ArgLocs, const SmallVectorImpl< SDValue > &OutVals) const
Check whether parameters to a call that are passed in callee saved registers are the same as from the...
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
bool isPositionIndependent() const
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
TargetLowering(const TargetLowering &)=delete
virtual void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector< SDValue > &Ops, SelectionDAG &DAG) const
Lower the specified operand into the Ops vector.
TLSModel::Model getTLSModel(const GlobalValue *GV) const
Returns the TLS model which should be used for the given global variable.
unsigned GuaranteedTailCallOpt
GuaranteedTailCallOpt - This flag is enabled when -tailcallopt is specified on the commandline.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getOperandNo() const
Return the operand # of this use in its User.
User * getUser() const
Returns the User that contains this Use.
LLVM Value Representation.
bool hasOneUse() const
Return true if there is exactly one use of this value.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
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.
@ M68k_INTR
Used for M68k interrupt routines.
@ Swift
Calling convention for Swift.
@ M68k_RTD
Used for M68k rtd-based CC (similar to X86's stdcall).
@ C
The default llvm calling convention, compatible with C.
LLVM_ABI CondCode getSetCCInverse(CondCode Operation, bool isIntegerLike)
Return the operation corresponding to !(X op Y), where 'op' is a valid SetCC operation.
bool isNON_EXTLoad(const SDNode *N)
Returns true if the specified node is a non-extending load.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ MERGE_VALUES
MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...
@ 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.
@ 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.
@ SIGN_EXTEND
Conversion operators.
@ SETCCCARRY
Like SetCC, ops #0 and #1 are the LHS and RHS operands to compare, but op #2 is a boolean indicating ...
@ SSUBO
Same for subtraction.
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ BasicBlock
Various leaf nodes.
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ SADDO
RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition.
@ 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) ...
@ SMULO
Same for multiplication.
@ 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.
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ 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...
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
static bool isPCRelBlockReference(unsigned char Flag)
Return True if the Block is referenced using PC.
static bool isGlobalRelativeToPICBase(unsigned char TargetFlag)
Return true if the specified global value reference is relative to a 32-bit PIC base (M68kISD::GLOBAL...
static bool isGlobalStubReference(unsigned char TargetFlag)
Return true if the specified TargetFlag operand is a reference to a stub for a global,...
static bool isPCRelGlobalReference(unsigned char Flag)
Return True if the specified GlobalValue requires PC addressing mode.
@ MO_TLSLDM
On a symbol operand, this indicates that the immediate is the offset to the slot in GOT which stores ...
@ MO_TLSLE
On a symbol operand, this indicates that the immediate is the offset to the variable within in the th...
@ MO_TLSGD
On a symbol operand, this indicates that the immediate is the offset to the slot in GOT which stores ...
@ MO_GOTPCREL
On a symbol operand this indicates that the immediate is offset to the GOT entry for the symbol name ...
@ MO_TLSIE
On a symbol operand, this indicates that the immediate is the offset to the variable within the threa...
@ MO_TLSLD
On a symbol operand, this indicates that the immediate is the offset to variable within the thread lo...
static bool isDirectGlobalReference(unsigned char Flag)
Return True if the specified GlobalValue is a direct reference for a symbol.
static bool IsSETCC(unsigned SETCC)
static unsigned GetCondBranchFromCond(M68k::CondCode CC)
bool isCalleePop(CallingConv::ID CallingConv, bool IsVarArg, bool GuaranteeTCO)
Determines whether the callee is required to pop its own arguments.
Definition M68kISelLowering.cpp:3046
static M68k::CondCode GetOppositeBranchCondition(M68k::CondCode CC)
@ User
could "use" a pointer
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
unsigned Log2_64_Ceil(uint64_t Value)
Return the ceil log base 2 of the specified value, 64 if the value is zero.
bool CCAssignFn(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
CCAssignFn - This function assigns a location for Val, updating State to reflect the change.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
LLVM_ABI bool isBitwiseNot(SDValue V, bool AllowUndefs=false)
Returns true if V is a bitwise not operation.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
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 - Return true if the parameter to the template is an instance of one of the template type argu...
@ Mod
The access may modify the value stored in memory.
@ Xor
Bitwise or logical XOR of integers.
@ Sub
Subtraction of integers.
DWARFExpression::Operation Op
constexpr unsigned BitWidth
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
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.
uint64_t getScalarSizeInBits() const
bool isVector() const
Return true if this is a vector value type.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool bitsLE(EVT VT) const
Return true if this has no more bits than VT.
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.
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 a list of ValueType's that has been intern'd by a SelectionDAG.
This structure contains all information that is necessary for lowering calls.
CallLoweringInfo & setLibCallee(CallingConv::ID CC, Type *ResultType, SDValue Target, ArgListTy &&ArgsList)
SmallVector< ISD::InputArg, 32 > Ins
CallLoweringInfo & setDebugLoc(const SDLoc &dl)
SmallVector< ISD::OutputArg, 32 > Outs
SmallVector< SDValue, 32 > OutVals
Type * RetTy
Same as OrigRetTy, or partially legalized for soft float libcalls.
CallLoweringInfo & setChain(SDValue InChain)