70#define DEBUG_TYPE "si-load-store-opt"
78 S_BUFFER_LOAD_SGPR_IMM,
97 unsigned char NumVAddrs = 0;
100 bool SOffset =
false;
108const unsigned MaxAddressRegs = 12 + 1 + 1;
110class SILoadStoreOptimizer {
119 InstClassEnum InstClass;
124 int AddrIdx[MaxAddressRegs];
126 unsigned NumAddresses;
129 bool hasSameBaseAddress(
const CombineInfo &CI) {
130 if (NumAddresses != CI.NumAddresses)
134 for (
unsigned i = 0; i < NumAddresses; i++) {
137 if (AddrReg[i]->isImm() || AddrRegNext.
isImm()) {
138 if (AddrReg[i]->isImm() != AddrRegNext.
isImm() ||
156 for (
unsigned i = 0; i < NumAddresses; ++i) {
165 if (!AddrOp->
isReg())
171 AddrOp->
getReg() != AMDGPU::SGPR_NULL)
176 if (
MRI.hasOneNonDBGUse(AddrOp->
getReg()))
190 struct BaseRegisters {
194 unsigned LoSubReg = 0;
195 unsigned HiSubReg = 0;
197 bool UseV64Pattern =
false;
199 bool UseScratchVGPRPattern =
false;
221 static bool dmasksCanBeCombined(
const CombineInfo &CI,
223 const CombineInfo &Paired);
224 static bool offsetsCanBeCombined(CombineInfo &CI,
const GCNSubtarget &STI,
225 CombineInfo &Paired,
bool Modify =
false);
226 static bool widthsFit(
const GCNSubtarget &STI,
const CombineInfo &CI,
227 const CombineInfo &Paired);
228 unsigned getNewOpcode(
const CombineInfo &CI,
const CombineInfo &Paired);
229 static std::pair<unsigned, unsigned> getSubRegIdxs(
const CombineInfo &CI,
230 const CombineInfo &Paired);
232 getTargetRegisterClass(
const CombineInfo &CI,
233 const CombineInfo &Paired)
const;
236 CombineInfo *checkAndPrepareMerge(CombineInfo &CI, CombineInfo &Paired);
238 void copyToDestRegs(CombineInfo &CI, CombineInfo &Paired,
242 Register copyFromSrcRegs(CombineInfo &CI, CombineInfo &Paired,
246 unsigned read2Opcode(
unsigned EltSize,
bool GDS)
const;
247 unsigned read2ST64Opcode(
unsigned EltSize,
bool GDS)
const;
249 mergeRead2Pair(CombineInfo &CI, CombineInfo &Paired,
252 unsigned write2Opcode(
unsigned EltSize,
bool GDS)
const;
253 unsigned write2ST64Opcode(
unsigned EltSize,
bool GDS)
const;
254 unsigned getWrite2Opcode(
const CombineInfo &CI)
const;
257 mergeWrite2Pair(CombineInfo &CI, CombineInfo &Paired,
260 mergeImagePair(CombineInfo &CI, CombineInfo &Paired,
263 mergeSMemLoadImmPair(CombineInfo &CI, CombineInfo &Paired,
266 mergeBufferLoadPair(CombineInfo &CI, CombineInfo &Paired,
269 mergeBufferStorePair(CombineInfo &CI, CombineInfo &Paired,
272 mergeTBufferLoadPair(CombineInfo &CI, CombineInfo &Paired,
275 mergeTBufferStorePair(CombineInfo &CI, CombineInfo &Paired,
278 mergeFlatLoadPair(CombineInfo &CI, CombineInfo &Paired,
281 mergeFlatStorePair(CombineInfo &CI, CombineInfo &Paired,
285 int32_t NewOffset)
const;
286 void updateAsyncLDSAddress(
MachineInstr &
MI, int32_t OffsetDiff)
const;
291 MemAddress &Addr)
const;
293 MemAddress &Addr)
const;
302 std::list<std::list<CombineInfo> > &MergeableInsts)
const;
307 std::list<std::list<CombineInfo>> &MergeableInsts)
const;
310 const CombineInfo &Paired);
312 static InstClassEnum getCommonInstClass(
const CombineInfo &CI,
313 const CombineInfo &Paired);
315 bool optimizeInstsWithSameBaseAddr(std::list<CombineInfo> &MergeList,
316 bool &OptimizeListAgain);
317 bool optimizeBlock(std::list<std::list<CombineInfo> > &MergeableInsts);
332 StringRef getPassName()
const override {
return "SI Load Store Optimizer"; }
347 const unsigned Opc =
MI.getOpcode();
353 if (
TII.isImage(
MI)) {
355 TII.getNamedOperand(
MI, AMDGPU::OpName::dmask)->getImm();
363 case AMDGPU::S_BUFFER_LOAD_DWORD_IMM:
364 case AMDGPU::S_BUFFER_LOAD_DWORD_SGPR_IMM:
365 case AMDGPU::S_LOAD_DWORD_IMM:
366 case AMDGPU::GLOBAL_LOAD_DWORD:
367 case AMDGPU::GLOBAL_LOAD_DWORD_SADDR:
368 case AMDGPU::GLOBAL_STORE_DWORD:
369 case AMDGPU::GLOBAL_STORE_DWORD_SADDR:
370 case AMDGPU::FLAT_LOAD_DWORD:
371 case AMDGPU::FLAT_STORE_DWORD:
372 case AMDGPU::FLAT_LOAD_DWORD_SADDR:
373 case AMDGPU::FLAT_STORE_DWORD_SADDR:
375 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM:
376 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM:
377 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM_ec:
378 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM_ec:
379 case AMDGPU::S_LOAD_DWORDX2_IMM:
380 case AMDGPU::S_LOAD_DWORDX2_IMM_ec:
381 case AMDGPU::GLOBAL_LOAD_DWORDX2:
382 case AMDGPU::GLOBAL_LOAD_DWORDX2_SADDR:
383 case AMDGPU::GLOBAL_STORE_DWORDX2:
384 case AMDGPU::GLOBAL_STORE_DWORDX2_SADDR:
385 case AMDGPU::FLAT_LOAD_DWORDX2:
386 case AMDGPU::FLAT_STORE_DWORDX2:
387 case AMDGPU::FLAT_LOAD_DWORDX2_SADDR:
388 case AMDGPU::FLAT_STORE_DWORDX2_SADDR:
390 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM:
391 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM:
392 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM_ec:
393 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM_ec:
394 case AMDGPU::S_LOAD_DWORDX3_IMM:
395 case AMDGPU::S_LOAD_DWORDX3_IMM_ec:
396 case AMDGPU::GLOBAL_LOAD_DWORDX3:
397 case AMDGPU::GLOBAL_LOAD_DWORDX3_SADDR:
398 case AMDGPU::GLOBAL_STORE_DWORDX3:
399 case AMDGPU::GLOBAL_STORE_DWORDX3_SADDR:
400 case AMDGPU::FLAT_LOAD_DWORDX3:
401 case AMDGPU::FLAT_STORE_DWORDX3:
402 case AMDGPU::FLAT_LOAD_DWORDX3_SADDR:
403 case AMDGPU::FLAT_STORE_DWORDX3_SADDR:
405 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM:
406 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM:
407 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM_ec:
408 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM_ec:
409 case AMDGPU::S_LOAD_DWORDX4_IMM:
410 case AMDGPU::S_LOAD_DWORDX4_IMM_ec:
411 case AMDGPU::GLOBAL_LOAD_DWORDX4:
412 case AMDGPU::GLOBAL_LOAD_DWORDX4_SADDR:
413 case AMDGPU::GLOBAL_STORE_DWORDX4:
414 case AMDGPU::GLOBAL_STORE_DWORDX4_SADDR:
415 case AMDGPU::FLAT_LOAD_DWORDX4:
416 case AMDGPU::FLAT_STORE_DWORDX4:
417 case AMDGPU::FLAT_LOAD_DWORDX4_SADDR:
418 case AMDGPU::FLAT_STORE_DWORDX4_SADDR:
420 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM:
421 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM:
422 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM_ec:
423 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM_ec:
424 case AMDGPU::S_LOAD_DWORDX8_IMM:
425 case AMDGPU::S_LOAD_DWORDX8_IMM_ec:
427 case AMDGPU::DS_READ_B32:
428 case AMDGPU::DS_READ_B32_gfx9:
429 case AMDGPU::DS_WRITE_B32:
430 case AMDGPU::DS_WRITE_B32_gfx9:
432 case AMDGPU::DS_READ_B64:
433 case AMDGPU::DS_READ_B64_gfx9:
434 case AMDGPU::DS_WRITE_B64:
435 case AMDGPU::DS_WRITE_B64_gfx9:
450 case AMDGPU::BUFFER_LOAD_DWORD_BOTHEN:
451 case AMDGPU::BUFFER_LOAD_DWORD_BOTHEN_exact:
452 case AMDGPU::BUFFER_LOAD_DWORD_IDXEN:
453 case AMDGPU::BUFFER_LOAD_DWORD_IDXEN_exact:
454 case AMDGPU::BUFFER_LOAD_DWORD_OFFEN:
455 case AMDGPU::BUFFER_LOAD_DWORD_OFFEN_exact:
456 case AMDGPU::BUFFER_LOAD_DWORD_OFFSET:
457 case AMDGPU::BUFFER_LOAD_DWORD_OFFSET_exact:
458 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_BOTHEN:
459 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_BOTHEN_exact:
460 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_IDXEN:
461 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_IDXEN_exact:
462 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_OFFEN:
463 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_OFFEN_exact:
464 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_OFFSET:
465 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_OFFSET_exact:
467 case AMDGPU::BUFFER_STORE_DWORD_BOTHEN:
468 case AMDGPU::BUFFER_STORE_DWORD_BOTHEN_exact:
469 case AMDGPU::BUFFER_STORE_DWORD_IDXEN:
470 case AMDGPU::BUFFER_STORE_DWORD_IDXEN_exact:
471 case AMDGPU::BUFFER_STORE_DWORD_OFFEN:
472 case AMDGPU::BUFFER_STORE_DWORD_OFFEN_exact:
473 case AMDGPU::BUFFER_STORE_DWORD_OFFSET:
474 case AMDGPU::BUFFER_STORE_DWORD_OFFSET_exact:
475 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_BOTHEN:
476 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_BOTHEN_exact:
477 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_IDXEN:
478 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_IDXEN_exact:
479 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_OFFEN:
480 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_OFFEN_exact:
481 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_OFFSET:
482 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_OFFSET_exact:
495 if (
TII.get(
Opc).mayStore() || !
TII.get(
Opc).mayLoad() ||
504 case AMDGPU::TBUFFER_LOAD_FORMAT_X_BOTHEN:
505 case AMDGPU::TBUFFER_LOAD_FORMAT_X_BOTHEN_exact:
506 case AMDGPU::TBUFFER_LOAD_FORMAT_X_IDXEN:
507 case AMDGPU::TBUFFER_LOAD_FORMAT_X_IDXEN_exact:
508 case AMDGPU::TBUFFER_LOAD_FORMAT_X_OFFEN:
509 case AMDGPU::TBUFFER_LOAD_FORMAT_X_OFFEN_exact:
510 case AMDGPU::TBUFFER_LOAD_FORMAT_X_OFFSET:
511 case AMDGPU::TBUFFER_LOAD_FORMAT_X_OFFSET_exact:
512 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_BOTHEN:
513 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_BOTHEN_exact:
514 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_IDXEN:
515 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_IDXEN_exact:
516 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_OFFEN:
517 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_OFFEN_exact:
518 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_OFFSET:
519 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_OFFSET_exact:
521 case AMDGPU::TBUFFER_STORE_FORMAT_X_OFFEN:
522 case AMDGPU::TBUFFER_STORE_FORMAT_X_OFFEN_exact:
523 case AMDGPU::TBUFFER_STORE_FORMAT_X_OFFSET:
524 case AMDGPU::TBUFFER_STORE_FORMAT_X_OFFSET_exact:
525 case AMDGPU::TBUFFER_STORE_FORMAT_X_VBUFFER_OFFEN:
526 case AMDGPU::TBUFFER_STORE_FORMAT_X_VBUFFER_OFFEN_exact:
527 case AMDGPU::TBUFFER_STORE_FORMAT_X_VBUFFER_OFFSET:
528 case AMDGPU::TBUFFER_STORE_FORMAT_X_VBUFFER_OFFSET_exact:
529 return TBUFFER_STORE;
533 case AMDGPU::S_BUFFER_LOAD_DWORD_IMM:
534 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM:
535 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM:
536 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM:
537 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM:
538 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM_ec:
539 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM_ec:
540 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM_ec:
541 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM_ec:
542 return S_BUFFER_LOAD_IMM;
543 case AMDGPU::S_BUFFER_LOAD_DWORD_SGPR_IMM:
544 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM:
545 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM:
546 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM:
547 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM:
548 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM_ec:
549 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM_ec:
550 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM_ec:
551 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM_ec:
552 return S_BUFFER_LOAD_SGPR_IMM;
553 case AMDGPU::S_LOAD_DWORD_IMM:
554 case AMDGPU::S_LOAD_DWORDX2_IMM:
555 case AMDGPU::S_LOAD_DWORDX3_IMM:
556 case AMDGPU::S_LOAD_DWORDX4_IMM:
557 case AMDGPU::S_LOAD_DWORDX8_IMM:
558 case AMDGPU::S_LOAD_DWORDX2_IMM_ec:
559 case AMDGPU::S_LOAD_DWORDX3_IMM_ec:
560 case AMDGPU::S_LOAD_DWORDX4_IMM_ec:
561 case AMDGPU::S_LOAD_DWORDX8_IMM_ec:
563 case AMDGPU::DS_READ_B32:
564 case AMDGPU::DS_READ_B32_gfx9:
565 case AMDGPU::DS_READ_B64:
566 case AMDGPU::DS_READ_B64_gfx9:
568 case AMDGPU::DS_WRITE_B32:
569 case AMDGPU::DS_WRITE_B32_gfx9:
570 case AMDGPU::DS_WRITE_B64:
571 case AMDGPU::DS_WRITE_B64_gfx9:
573 case AMDGPU::GLOBAL_LOAD_DWORD:
574 case AMDGPU::GLOBAL_LOAD_DWORDX2:
575 case AMDGPU::GLOBAL_LOAD_DWORDX3:
576 case AMDGPU::GLOBAL_LOAD_DWORDX4:
577 case AMDGPU::FLAT_LOAD_DWORD:
578 case AMDGPU::FLAT_LOAD_DWORDX2:
579 case AMDGPU::FLAT_LOAD_DWORDX3:
580 case AMDGPU::FLAT_LOAD_DWORDX4:
582 case AMDGPU::GLOBAL_LOAD_DWORD_SADDR:
583 case AMDGPU::GLOBAL_LOAD_DWORDX2_SADDR:
584 case AMDGPU::GLOBAL_LOAD_DWORDX3_SADDR:
585 case AMDGPU::GLOBAL_LOAD_DWORDX4_SADDR:
586 return GLOBAL_LOAD_SADDR;
587 case AMDGPU::GLOBAL_STORE_DWORD:
588 case AMDGPU::GLOBAL_STORE_DWORDX2:
589 case AMDGPU::GLOBAL_STORE_DWORDX3:
590 case AMDGPU::GLOBAL_STORE_DWORDX4:
591 case AMDGPU::FLAT_STORE_DWORD:
592 case AMDGPU::FLAT_STORE_DWORDX2:
593 case AMDGPU::FLAT_STORE_DWORDX3:
594 case AMDGPU::FLAT_STORE_DWORDX4:
596 case AMDGPU::GLOBAL_STORE_DWORD_SADDR:
597 case AMDGPU::GLOBAL_STORE_DWORDX2_SADDR:
598 case AMDGPU::GLOBAL_STORE_DWORDX3_SADDR:
599 case AMDGPU::GLOBAL_STORE_DWORDX4_SADDR:
600 return GLOBAL_STORE_SADDR;
601 case AMDGPU::FLAT_LOAD_DWORD_SADDR:
602 case AMDGPU::FLAT_LOAD_DWORDX2_SADDR:
603 case AMDGPU::FLAT_LOAD_DWORDX3_SADDR:
604 case AMDGPU::FLAT_LOAD_DWORDX4_SADDR:
605 return FLAT_LOAD_SADDR;
606 case AMDGPU::FLAT_STORE_DWORD_SADDR:
607 case AMDGPU::FLAT_STORE_DWORDX2_SADDR:
608 case AMDGPU::FLAT_STORE_DWORDX3_SADDR:
609 case AMDGPU::FLAT_STORE_DWORDX4_SADDR:
610 return FLAT_STORE_SADDR;
625 return Info->BaseOpcode;
630 case AMDGPU::DS_READ_B32:
631 case AMDGPU::DS_READ_B32_gfx9:
632 case AMDGPU::DS_READ_B64:
633 case AMDGPU::DS_READ_B64_gfx9:
634 case AMDGPU::DS_WRITE_B32:
635 case AMDGPU::DS_WRITE_B32_gfx9:
636 case AMDGPU::DS_WRITE_B64:
637 case AMDGPU::DS_WRITE_B64_gfx9:
639 case AMDGPU::S_BUFFER_LOAD_DWORD_IMM:
640 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM:
641 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM:
642 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM:
643 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM:
644 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM_ec:
645 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM_ec:
646 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM_ec:
647 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM_ec:
648 return AMDGPU::S_BUFFER_LOAD_DWORD_IMM;
649 case AMDGPU::S_BUFFER_LOAD_DWORD_SGPR_IMM:
650 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM:
651 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM:
652 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM:
653 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM:
654 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM_ec:
655 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM_ec:
656 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM_ec:
657 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM_ec:
658 return AMDGPU::S_BUFFER_LOAD_DWORD_SGPR_IMM;
659 case AMDGPU::S_LOAD_DWORD_IMM:
660 case AMDGPU::S_LOAD_DWORDX2_IMM:
661 case AMDGPU::S_LOAD_DWORDX3_IMM:
662 case AMDGPU::S_LOAD_DWORDX4_IMM:
663 case AMDGPU::S_LOAD_DWORDX8_IMM:
664 case AMDGPU::S_LOAD_DWORDX2_IMM_ec:
665 case AMDGPU::S_LOAD_DWORDX3_IMM_ec:
666 case AMDGPU::S_LOAD_DWORDX4_IMM_ec:
667 case AMDGPU::S_LOAD_DWORDX8_IMM_ec:
668 return AMDGPU::S_LOAD_DWORD_IMM;
669 case AMDGPU::GLOBAL_LOAD_DWORD:
670 case AMDGPU::GLOBAL_LOAD_DWORDX2:
671 case AMDGPU::GLOBAL_LOAD_DWORDX3:
672 case AMDGPU::GLOBAL_LOAD_DWORDX4:
673 case AMDGPU::FLAT_LOAD_DWORD:
674 case AMDGPU::FLAT_LOAD_DWORDX2:
675 case AMDGPU::FLAT_LOAD_DWORDX3:
676 case AMDGPU::FLAT_LOAD_DWORDX4:
677 return AMDGPU::FLAT_LOAD_DWORD;
678 case AMDGPU::GLOBAL_LOAD_DWORD_SADDR:
679 case AMDGPU::GLOBAL_LOAD_DWORDX2_SADDR:
680 case AMDGPU::GLOBAL_LOAD_DWORDX3_SADDR:
681 case AMDGPU::GLOBAL_LOAD_DWORDX4_SADDR:
682 return AMDGPU::GLOBAL_LOAD_DWORD_SADDR;
683 case AMDGPU::GLOBAL_STORE_DWORD:
684 case AMDGPU::GLOBAL_STORE_DWORDX2:
685 case AMDGPU::GLOBAL_STORE_DWORDX3:
686 case AMDGPU::GLOBAL_STORE_DWORDX4:
687 case AMDGPU::FLAT_STORE_DWORD:
688 case AMDGPU::FLAT_STORE_DWORDX2:
689 case AMDGPU::FLAT_STORE_DWORDX3:
690 case AMDGPU::FLAT_STORE_DWORDX4:
691 return AMDGPU::FLAT_STORE_DWORD;
692 case AMDGPU::GLOBAL_STORE_DWORD_SADDR:
693 case AMDGPU::GLOBAL_STORE_DWORDX2_SADDR:
694 case AMDGPU::GLOBAL_STORE_DWORDX3_SADDR:
695 case AMDGPU::GLOBAL_STORE_DWORDX4_SADDR:
696 return AMDGPU::GLOBAL_STORE_DWORD_SADDR;
697 case AMDGPU::FLAT_LOAD_DWORD_SADDR:
698 case AMDGPU::FLAT_LOAD_DWORDX2_SADDR:
699 case AMDGPU::FLAT_LOAD_DWORDX3_SADDR:
700 case AMDGPU::FLAT_LOAD_DWORDX4_SADDR:
701 return AMDGPU::FLAT_LOAD_DWORD_SADDR;
702 case AMDGPU::FLAT_STORE_DWORD_SADDR:
703 case AMDGPU::FLAT_STORE_DWORDX2_SADDR:
704 case AMDGPU::FLAT_STORE_DWORDX3_SADDR:
705 case AMDGPU::FLAT_STORE_DWORDX4_SADDR:
706 return AMDGPU::FLAT_STORE_DWORD_SADDR;
717SILoadStoreOptimizer::getCommonInstClass(
const CombineInfo &CI,
718 const CombineInfo &Paired) {
719 assert(CI.InstClass == Paired.InstClass);
721 if ((CI.InstClass == FLAT_LOAD || CI.InstClass == FLAT_STORE) &&
723 return (CI.InstClass == FLAT_STORE) ? GLOBAL_STORE : GLOBAL_LOAD;
737 Result.SOffset =
true;
743 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
744 if (VAddr0Idx >= 0) {
745 AMDGPU::OpName RsrcName =
746 TII.isMIMG(
Opc) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
747 int RsrcIdx = AMDGPU::getNamedOperandIdx(
Opc, RsrcName);
748 Result.NumVAddrs = RsrcIdx - VAddr0Idx;
765 Result.SOffset =
true;
773 case AMDGPU::S_BUFFER_LOAD_DWORD_SGPR_IMM:
774 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM:
775 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM:
776 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM:
777 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM:
778 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM_ec:
779 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM_ec:
780 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM_ec:
781 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM_ec:
782 Result.SOffset =
true;
784 case AMDGPU::S_BUFFER_LOAD_DWORD_IMM:
785 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM:
786 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM:
787 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM:
788 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM:
789 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM_ec:
790 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM_ec:
791 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM_ec:
792 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM_ec:
793 case AMDGPU::S_LOAD_DWORD_IMM:
794 case AMDGPU::S_LOAD_DWORDX2_IMM:
795 case AMDGPU::S_LOAD_DWORDX3_IMM:
796 case AMDGPU::S_LOAD_DWORDX4_IMM:
797 case AMDGPU::S_LOAD_DWORDX8_IMM:
798 case AMDGPU::S_LOAD_DWORDX2_IMM_ec:
799 case AMDGPU::S_LOAD_DWORDX3_IMM_ec:
800 case AMDGPU::S_LOAD_DWORDX4_IMM_ec:
801 case AMDGPU::S_LOAD_DWORDX8_IMM_ec:
804 case AMDGPU::DS_READ_B32:
805 case AMDGPU::DS_READ_B64:
806 case AMDGPU::DS_READ_B32_gfx9:
807 case AMDGPU::DS_READ_B64_gfx9:
808 case AMDGPU::DS_WRITE_B32:
809 case AMDGPU::DS_WRITE_B64:
810 case AMDGPU::DS_WRITE_B32_gfx9:
811 case AMDGPU::DS_WRITE_B64_gfx9:
814 case AMDGPU::GLOBAL_LOAD_DWORD_SADDR:
815 case AMDGPU::GLOBAL_LOAD_DWORDX2_SADDR:
816 case AMDGPU::GLOBAL_LOAD_DWORDX3_SADDR:
817 case AMDGPU::GLOBAL_LOAD_DWORDX4_SADDR:
818 case AMDGPU::GLOBAL_STORE_DWORD_SADDR:
819 case AMDGPU::GLOBAL_STORE_DWORDX2_SADDR:
820 case AMDGPU::GLOBAL_STORE_DWORDX3_SADDR:
821 case AMDGPU::GLOBAL_STORE_DWORDX4_SADDR:
822 case AMDGPU::FLAT_LOAD_DWORD_SADDR:
823 case AMDGPU::FLAT_LOAD_DWORDX2_SADDR:
824 case AMDGPU::FLAT_LOAD_DWORDX3_SADDR:
825 case AMDGPU::FLAT_LOAD_DWORDX4_SADDR:
826 case AMDGPU::FLAT_STORE_DWORD_SADDR:
827 case AMDGPU::FLAT_STORE_DWORDX2_SADDR:
828 case AMDGPU::FLAT_STORE_DWORDX3_SADDR:
829 case AMDGPU::FLAT_STORE_DWORDX4_SADDR:
832 case AMDGPU::GLOBAL_LOAD_DWORD:
833 case AMDGPU::GLOBAL_LOAD_DWORDX2:
834 case AMDGPU::GLOBAL_LOAD_DWORDX3:
835 case AMDGPU::GLOBAL_LOAD_DWORDX4:
836 case AMDGPU::GLOBAL_STORE_DWORD:
837 case AMDGPU::GLOBAL_STORE_DWORDX2:
838 case AMDGPU::GLOBAL_STORE_DWORDX3:
839 case AMDGPU::GLOBAL_STORE_DWORDX4:
840 case AMDGPU::FLAT_LOAD_DWORD:
841 case AMDGPU::FLAT_LOAD_DWORDX2:
842 case AMDGPU::FLAT_LOAD_DWORDX3:
843 case AMDGPU::FLAT_LOAD_DWORDX4:
844 case AMDGPU::FLAT_STORE_DWORD:
845 case AMDGPU::FLAT_STORE_DWORDX2:
846 case AMDGPU::FLAT_STORE_DWORDX3:
847 case AMDGPU::FLAT_STORE_DWORDX4:
854 const SILoadStoreOptimizer &LSO) {
856 unsigned Opc =
MI->getOpcode();
857 InstClass = getInstClass(
Opc, *LSO.TII);
859 if (InstClass == UNKNOWN)
862 DataRC = LSO.getDataRegClass(*
MI);
867 (
Opc == AMDGPU::DS_READ_B64 ||
Opc == AMDGPU::DS_READ_B64_gfx9) ? 8
872 (
Opc == AMDGPU::DS_WRITE_B64 ||
Opc == AMDGPU::DS_WRITE_B64_gfx9) ? 8
875 case S_BUFFER_LOAD_IMM:
876 case S_BUFFER_LOAD_SGPR_IMM:
885 if (InstClass == MIMG) {
890 int OffsetIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::offset);
891 Offset =
I->getOperand(OffsetIdx).getImm();
894 if (InstClass == TBUFFER_LOAD || InstClass == TBUFFER_STORE) {
898 EltSize = Info->BitsPerComp / 8;
901 Width = getOpcodeWidth(*
I, *LSO.TII);
903 if ((InstClass == DS_READ) || (InstClass == DS_WRITE)) {
906 }
else if (InstClass != MIMG) {
910 AddressRegs Regs = getRegs(
Opc, *LSO.TII);
914 for (
unsigned J = 0; J < Regs.NumVAddrs; J++)
915 AddrIdx[NumAddresses++] =
916 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0) + J;
918 AddrIdx[NumAddresses++] =
919 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::addr);
921 AddrIdx[NumAddresses++] =
922 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::sbase);
924 AddrIdx[NumAddresses++] = AMDGPU::getNamedOperandIdx(
925 Opc, isVIMAGEorVSAMPLE ? AMDGPU::OpName::rsrc : AMDGPU::OpName::srsrc);
927 AddrIdx[NumAddresses++] =
928 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::soffset);
930 AddrIdx[NumAddresses++] =
931 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::saddr);
933 AddrIdx[NumAddresses++] =
934 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr);
936 AddrIdx[NumAddresses++] = AMDGPU::getNamedOperandIdx(
937 Opc, isVIMAGEorVSAMPLE ? AMDGPU::OpName::samp : AMDGPU::OpName::ssamp);
938 assert(NumAddresses <= MaxAddressRegs);
940 for (
unsigned J = 0; J < NumAddresses; J++)
941 AddrReg[J] = &
I->getOperand(AddrIdx[J]);
947 "SI Load Store Optimizer",
false,
false)
952char SILoadStoreOptimizerLegacy::ID = 0;
959 for (
const auto &
Op :
MI.operands()) {
963 RegDefs.insert(Op.getReg());
965 RegUses.insert(Op.getReg());
969bool SILoadStoreOptimizer::canSwapInstructions(
970 const DenseSet<Register> &ARegDefs,
const DenseSet<Register> &ARegUses,
971 const MachineInstr &
A,
const MachineInstr &
B)
const {
972 if (
A.mayLoadOrStore() &&
B.mayLoadOrStore() &&
973 (
A.mayStore() ||
B.mayStore()) &&
A.mayAlias(AA,
B,
true))
975 for (
const auto &BOp :
B.operands()) {
978 if ((BOp.isDef() || BOp.readsReg()) && ARegDefs.
contains(BOp.getReg()))
980 if (BOp.isDef() && ARegUses.
contains(BOp.getReg()))
989SILoadStoreOptimizer::combineKnownAdjacentMMOs(
const CombineInfo &CI,
990 const CombineInfo &Paired) {
991 const MachineMemOperand *MMOa = *CI.I->memoperands_begin();
992 const MachineMemOperand *MMOb = *Paired.I->memoperands_begin();
1010bool SILoadStoreOptimizer::dmasksCanBeCombined(
const CombineInfo &CI,
1011 const SIInstrInfo &
TII,
1012 const CombineInfo &Paired) {
1013 assert(CI.InstClass == MIMG);
1016 const auto *TFEOp =
TII.getNamedOperand(*CI.I, AMDGPU::OpName::tfe);
1017 const auto *LWEOp =
TII.getNamedOperand(*CI.I, AMDGPU::OpName::lwe);
1019 if ((TFEOp && TFEOp->getImm()) || (LWEOp && LWEOp->getImm()))
1023 AMDGPU::OpName OperandsToMatch[] = {
1024 AMDGPU::OpName::cpol, AMDGPU::OpName::d16, AMDGPU::OpName::unorm,
1025 AMDGPU::OpName::da, AMDGPU::OpName::r128, AMDGPU::OpName::a16,
1026 AMDGPU::OpName::dim};
1028 for (AMDGPU::OpName
op : OperandsToMatch) {
1029 int Idx = AMDGPU::getNamedOperandIdx(CI.I->getOpcode(),
op);
1030 if (AMDGPU::getNamedOperandIdx(Paired.I->getOpcode(),
op) != Idx)
1033 CI.I->getOperand(Idx).getImm() != Paired.I->getOperand(Idx).getImm())
1038 unsigned MaxMask = std::max(CI.DMask, Paired.DMask);
1039 unsigned MinMask = std::min(CI.DMask, Paired.DMask);
1045 if ((1u << AllowedBitsForMin) <= MinMask)
1052 unsigned ComponentCount,
1054 if (ComponentCount > 4)
1073 return NewFormatInfo->
Format;
1086bool SILoadStoreOptimizer::offsetsCanBeCombined(CombineInfo &CI,
1087 const GCNSubtarget &STI,
1088 CombineInfo &Paired,
1090 assert(CI.InstClass != MIMG);
1094 if (CI.Offset == Paired.Offset)
1097 if (CI.GDS != Paired.GDS)
1101 if ((CI.Offset % CI.EltSize != 0) || (Paired.Offset % CI.EltSize != 0))
1104 if (CI.InstClass == TBUFFER_LOAD || CI.InstClass == TBUFFER_STORE) {
1106 const llvm::AMDGPU::GcnBufferFormatInfo *Info0 =
1108 const llvm::AMDGPU::GcnBufferFormatInfo *Info1 =
1120 unsigned NumCombinedComponents = CI.Width + Paired.Width;
1121 if (NumCombinedComponents == 3 && CI.EltSize <= 2)
1122 NumCombinedComponents = 4;
1130 unsigned ElemIndex0 = CI.Offset / CI.EltSize;
1131 unsigned ElemIndex1 = Paired.Offset / Paired.EltSize;
1132 if (ElemIndex0 + CI.Width != ElemIndex1 &&
1133 ElemIndex1 + Paired.Width != ElemIndex0)
1139 unsigned MergedBytes = CI.EltSize * NumCombinedComponents;
1140 unsigned RequiredAlign = std::min(MergedBytes, 4u);
1141 unsigned MinOff = std::min(CI.Offset, Paired.Offset);
1142 if (MinOff % RequiredAlign != 0)
1148 uint32_t EltOffset0 = CI.Offset / CI.EltSize;
1149 uint32_t EltOffset1 = Paired.Offset / CI.EltSize;
1154 if ((CI.InstClass != DS_READ) && (CI.InstClass != DS_WRITE)) {
1155 if (EltOffset0 + CI.Width != EltOffset1 &&
1156 EltOffset1 + Paired.Width != EltOffset0)
1162 if (CI.InstClass == S_LOAD_IMM || CI.InstClass == S_BUFFER_LOAD_IMM ||
1163 CI.InstClass == S_BUFFER_LOAD_SGPR_IMM) {
1169 if (CI.Width != Paired.Width &&
1170 (CI.Width < Paired.Width) == (CI.Offset < Paired.Offset))
1178 if ((EltOffset0 % 64 == 0) && (EltOffset1 % 64) == 0 &&
1181 CI.Offset = EltOffset0 / 64;
1182 Paired.Offset = EltOffset1 / 64;
1191 CI.Offset = EltOffset0;
1192 Paired.Offset = EltOffset1;
1198 uint32_t Min = std::min(EltOffset0, EltOffset1);
1199 uint32_t
Max = std::max(EltOffset0, EltOffset1);
1202 if (((Max - Min) & ~Mask) == 0) {
1211 CI.BaseOff = BaseOff * CI.EltSize;
1212 CI.Offset = (EltOffset0 - BaseOff) / 64;
1213 Paired.Offset = (EltOffset1 - BaseOff) / 64;
1225 CI.BaseOff = BaseOff * CI.EltSize;
1226 CI.Offset = EltOffset0 - BaseOff;
1227 Paired.Offset = EltOffset1 - BaseOff;
1235bool SILoadStoreOptimizer::widthsFit(
const GCNSubtarget &STM,
1236 const CombineInfo &CI,
1237 const CombineInfo &Paired) {
1238 const unsigned Width = (CI.Width + Paired.Width);
1239 switch (CI.InstClass) {
1242 case S_BUFFER_LOAD_IMM:
1243 case S_BUFFER_LOAD_SGPR_IMM:
1253 return STM.hasScalarDwordx3Loads();
1259SILoadStoreOptimizer::getDataRegClass(
const MachineInstr &
MI)
const {
1260 if (
const auto *Dst =
TII->getNamedOperand(
MI, AMDGPU::OpName::vdst)) {
1261 return TRI->getRegClassForReg(*
MRI, Dst->getReg());
1263 if (
const auto *Src =
TII->getNamedOperand(
MI, AMDGPU::OpName::vdata)) {
1264 return TRI->getRegClassForReg(*
MRI, Src->getReg());
1266 if (
const auto *Src =
TII->getNamedOperand(
MI, AMDGPU::OpName::data0)) {
1267 return TRI->getRegClassForReg(*
MRI, Src->getReg());
1269 if (
const auto *Dst =
TII->getNamedOperand(
MI, AMDGPU::OpName::sdst)) {
1270 return TRI->getRegClassForReg(*
MRI, Dst->getReg());
1272 if (
const auto *Src =
TII->getNamedOperand(
MI, AMDGPU::OpName::sdata)) {
1273 return TRI->getRegClassForReg(*
MRI, Src->getReg());
1280SILoadStoreOptimizer::CombineInfo *
1281SILoadStoreOptimizer::checkAndPrepareMerge(CombineInfo &CI,
1282 CombineInfo &Paired) {
1285 if (CI.InstClass == UNKNOWN || Paired.InstClass == UNKNOWN)
1287 assert(CI.InstClass == Paired.InstClass);
1289 if (getInstSubclass(CI.I->getOpcode(), *
TII) !=
1290 getInstSubclass(Paired.I->getOpcode(), *
TII))
1295 if (CI.InstClass == MIMG) {
1296 if (!dmasksCanBeCombined(CI, *
TII, Paired))
1299 if (!widthsFit(*STM, CI, Paired) || !offsetsCanBeCombined(CI, *STM, Paired))
1303 DenseSet<Register> RegDefs;
1304 DenseSet<Register> RegUses;
1306 if (CI.I->mayLoad()) {
1310 if (!canSwapInstructions(RegDefs, RegUses, *Paired.I, *
MBBI))
1318 if (!canSwapInstructions(RegDefs, RegUses, *CI.I, *
MBBI))
1328 if (CI.InstClass == DS_READ || CI.InstClass == DS_WRITE) {
1329 if (STM->hasNeedsAligned2addrDS() &&
1330 (CI.I->memoperands_empty() ||
1331 (*CI.I->memoperands_begin())->getAlign().value() < CI.Width * 4))
1333 offsetsCanBeCombined(CI, *STM, Paired,
true);
1336 if (CI.InstClass == DS_WRITE) {
1344 const MachineOperand *Data0 =
1345 TII->getNamedOperand(*CI.I, AMDGPU::OpName::data0);
1346 const MachineOperand *Data1 =
1347 TII->getNamedOperand(*Paired.I, AMDGPU::OpName::data0);
1349 const MCInstrDesc &Write2Opc =
TII->get(getWrite2Opcode(CI));
1350 int Data0Idx = AMDGPU::getNamedOperandIdx(Write2Opc.
getOpcode(),
1351 AMDGPU::OpName::data0);
1352 int Data1Idx = AMDGPU::getNamedOperandIdx(Write2Opc.
getOpcode(),
1353 AMDGPU::OpName::data1);
1359 if (
unsigned SubReg = Data0->
getSubReg()) {
1364 if (
unsigned SubReg = Data1->
getSubReg()) {
1382void SILoadStoreOptimizer::copyToDestRegs(
1383 CombineInfo &CI, CombineInfo &Paired,
1385 AMDGPU::OpName OpName,
Register DestReg)
const {
1386 MachineBasicBlock *
MBB = CI.I->getParent();
1388 auto [SubRegIdx0, SubRegIdx1] = getSubRegIdxs(CI, Paired);
1391 const MCInstrDesc &CopyDesc =
TII->get(TargetOpcode::COPY);
1392 auto *Dest0 =
TII->getNamedOperand(*CI.I, OpName);
1393 auto *Dest1 =
TII->getNamedOperand(*Paired.I, OpName);
1398 Dest0->setIsEarlyClobber(
false);
1399 Dest1->setIsEarlyClobber(
false);
1403 .
addReg(DestReg, {}, SubRegIdx0);
1406 .
addReg(DestReg, {}, SubRegIdx1);
1412SILoadStoreOptimizer::copyFromSrcRegs(CombineInfo &CI, CombineInfo &Paired,
1415 AMDGPU::OpName OpName)
const {
1416 MachineBasicBlock *
MBB = CI.I->getParent();
1418 auto [SubRegIdx0, SubRegIdx1] = getSubRegIdxs(CI, Paired);
1424 const auto *
Src0 =
TII->getNamedOperand(*CI.I, OpName);
1425 const auto *
Src1 =
TII->getNamedOperand(*Paired.I, OpName);
1427 BuildMI(*
MBB, InsertBefore,
DL,
TII->get(AMDGPU::REG_SEQUENCE), SrcReg)
1436unsigned SILoadStoreOptimizer::read2Opcode(
unsigned EltSize,
bool GDS)
const {
1438 return (EltSize == 4) ? AMDGPU::DS_READ2_B32 : AMDGPU::DS_READ2_B64;
1439 return (EltSize == 4) ? AMDGPU::DS_READ2_B32_gfx9 : AMDGPU::DS_READ2_B64_gfx9;
1442unsigned SILoadStoreOptimizer::read2ST64Opcode(
unsigned EltSize,
1445 return (EltSize == 4) ? AMDGPU::DS_READ2ST64_B32 : AMDGPU::DS_READ2ST64_B64;
1447 return (EltSize == 4) ? AMDGPU::DS_READ2ST64_B32_gfx9
1448 : AMDGPU::DS_READ2ST64_B64_gfx9;
1452SILoadStoreOptimizer::mergeRead2Pair(CombineInfo &CI, CombineInfo &Paired,
1454 MachineBasicBlock *
MBB = CI.I->getParent();
1458 const auto *AddrReg =
TII->getNamedOperand(*CI.I, AMDGPU::OpName::addr);
1460 unsigned NewOffset0 = std::min(CI.Offset, Paired.Offset);
1461 unsigned NewOffset1 = std::max(CI.Offset, Paired.Offset);
1462 unsigned Opc = CI.UseST64 ? read2ST64Opcode(CI.EltSize, CI.GDS)
1463 : read2Opcode(CI.EltSize, CI.GDS);
1466 (NewOffset0 != NewOffset1) &&
"Computed offset doesn't fit");
1468 const MCInstrDesc &Read2Desc =
TII->get(
Opc);
1477 unsigned BaseSubReg = AddrReg->getSubReg();
1485 TII->getAddNoCarry(*
MBB, InsertBefore,
DL, BaseReg)
1487 .addReg(AddrReg->getReg(), {}, BaseSubReg)
1492 MachineInstrBuilder Read2 =
1494 .
addReg(BaseReg, {}, BaseSubReg)
1500 copyToDestRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdst, DestReg);
1502 CI.I->eraseFromParent();
1503 Paired.I->eraseFromParent();
1509unsigned SILoadStoreOptimizer::write2Opcode(
unsigned EltSize,
bool GDS)
const {
1511 return (EltSize == 4) ? AMDGPU::DS_WRITE2_B32 : AMDGPU::DS_WRITE2_B64;
1512 return (EltSize == 4) ? AMDGPU::DS_WRITE2_B32_gfx9
1513 : AMDGPU::DS_WRITE2_B64_gfx9;
1516unsigned SILoadStoreOptimizer::write2ST64Opcode(
unsigned EltSize,
1519 return (EltSize == 4) ? AMDGPU::DS_WRITE2ST64_B32
1520 : AMDGPU::DS_WRITE2ST64_B64;
1522 return (EltSize == 4) ? AMDGPU::DS_WRITE2ST64_B32_gfx9
1523 : AMDGPU::DS_WRITE2ST64_B64_gfx9;
1526unsigned SILoadStoreOptimizer::getWrite2Opcode(
const CombineInfo &CI)
const {
1527 return CI.UseST64 ? write2ST64Opcode(CI.EltSize, CI.GDS)
1528 : write2Opcode(CI.EltSize, CI.GDS);
1532 CombineInfo &CI, CombineInfo &Paired,
1534 MachineBasicBlock *
MBB = CI.I->getParent();
1538 const MachineOperand *AddrReg =
1539 TII->getNamedOperand(*CI.I, AMDGPU::OpName::addr);
1540 const MachineOperand *Data0 =
1541 TII->getNamedOperand(*CI.I, AMDGPU::OpName::data0);
1542 const MachineOperand *Data1 =
1543 TII->getNamedOperand(*Paired.I, AMDGPU::OpName::data0);
1545 unsigned NewOffset0 = CI.Offset;
1546 unsigned NewOffset1 = Paired.Offset;
1547 unsigned Opc = getWrite2Opcode(CI);
1549 if (NewOffset0 > NewOffset1) {
1556 (NewOffset0 != NewOffset1) &&
"Computed offset doesn't fit");
1558 const MCInstrDesc &Write2Desc =
TII->get(
Opc);
1563 unsigned BaseSubReg = AddrReg->
getSubReg();
1571 TII->getAddNoCarry(*
MBB, InsertBefore,
DL, BaseReg)
1573 .addReg(AddrReg->
getReg(), {}, BaseSubReg)
1578 MachineInstrBuilder Write2 =
BuildMI(*
MBB, InsertBefore,
DL, Write2Desc)
1579 .
addReg(BaseReg, {}, BaseSubReg)
1585 .cloneMergedMemRefs({&*CI.I, &*Paired.I});
1587 CI.I->eraseFromParent();
1588 Paired.I->eraseFromParent();
1590 LLVM_DEBUG(
dbgs() <<
"Inserted write2 inst: " << *Write2 <<
'\n');
1595SILoadStoreOptimizer::mergeImagePair(CombineInfo &CI, CombineInfo &Paired,
1597 MachineBasicBlock *
MBB = CI.I->getParent();
1601 const unsigned Opcode = getNewOpcode(CI, Paired);
1606 unsigned MergedDMask = CI.DMask | Paired.DMask;
1608 AMDGPU::getNamedOperandIdx(CI.I->getOpcode(), AMDGPU::OpName::dmask);
1610 auto MIB =
BuildMI(*
MBB, InsertBefore,
DL,
TII->get(Opcode), DestReg);
1611 for (
unsigned I = 1,
E = (*CI.I).getNumOperands();
I !=
E; ++
I) {
1613 MIB.addImm(MergedDMask);
1615 MIB.add((*CI.I).getOperand(
I));
1621 assert(CI.I->hasOneMemOperand() && Paired.I->hasOneMemOperand());
1623 MachineInstr *
New = MIB.addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1625 copyToDestRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdata, DestReg);
1627 CI.I->eraseFromParent();
1628 Paired.I->eraseFromParent();
1633 CombineInfo &CI, CombineInfo &Paired,
1635 MachineBasicBlock *
MBB = CI.I->getParent();
1639 const unsigned Opcode = getNewOpcode(CI, Paired);
1644 unsigned MergedOffset = std::min(CI.Offset, Paired.Offset);
1649 assert(CI.I->hasOneMemOperand() && Paired.I->hasOneMemOperand());
1651 MachineInstrBuilder
New =
1653 .
add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::sbase));
1654 if (CI.InstClass == S_BUFFER_LOAD_SGPR_IMM)
1655 New.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::soffset));
1656 New.addImm(MergedOffset);
1657 New.addImm(CI.CPol).addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1659 copyToDestRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::sdst, DestReg);
1661 CI.I->eraseFromParent();
1662 Paired.I->eraseFromParent();
1667 CombineInfo &CI, CombineInfo &Paired,
1669 MachineBasicBlock *
MBB = CI.I->getParent();
1674 const unsigned Opcode = getNewOpcode(CI, Paired);
1680 unsigned MergedOffset = std::min(CI.Offset, Paired.Offset);
1682 auto MIB =
BuildMI(*
MBB, InsertBefore,
DL,
TII->get(Opcode), DestReg);
1684 AddressRegs Regs = getRegs(Opcode, *
TII);
1687 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr));
1692 assert(CI.I->hasOneMemOperand() && Paired.I->hasOneMemOperand());
1695 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::srsrc))
1696 .add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::soffset))
1697 .addImm(MergedOffset)
1700 .addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1702 copyToDestRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdata, DestReg);
1704 CI.I->eraseFromParent();
1705 Paired.I->eraseFromParent();
1710 CombineInfo &CI, CombineInfo &Paired,
1712 MachineBasicBlock *
MBB = CI.I->getParent();
1717 const unsigned Opcode = getNewOpcode(CI, Paired);
1723 unsigned MergedOffset = std::min(CI.Offset, Paired.Offset);
1725 auto MIB =
BuildMI(*
MBB, InsertBefore,
DL,
TII->get(Opcode), DestReg);
1727 AddressRegs Regs = getRegs(Opcode, *
TII);
1730 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr));
1735 unsigned NumCombinedComponents = CI.Width + Paired.Width;
1736 if (NumCombinedComponents == 3 && CI.EltSize <= 2)
1737 NumCombinedComponents = 4;
1738 unsigned JoinedFormat =
1744 assert(CI.I->hasOneMemOperand() && Paired.I->hasOneMemOperand());
1747 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::srsrc))
1748 .add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::soffset))
1749 .addImm(MergedOffset)
1750 .addImm(JoinedFormat)
1753 .addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1755 copyToDestRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdata, DestReg);
1757 CI.I->eraseFromParent();
1758 Paired.I->eraseFromParent();
1763 CombineInfo &CI, CombineInfo &Paired,
1765 MachineBasicBlock *
MBB = CI.I->getParent();
1769 const unsigned Opcode = getNewOpcode(CI, Paired);
1772 copyFromSrcRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdata);
1776 AddressRegs Regs = getRegs(Opcode, *
TII);
1779 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr));
1784 unsigned NumCombinedComponents = CI.Width + Paired.Width;
1785 if (NumCombinedComponents == 3 && CI.EltSize <= 2)
1786 NumCombinedComponents = 4;
1787 unsigned JoinedFormat =
1793 assert(CI.I->hasOneMemOperand() && Paired.I->hasOneMemOperand());
1796 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::srsrc))
1797 .add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::soffset))
1798 .addImm(std::min(CI.Offset, Paired.Offset))
1799 .addImm(JoinedFormat)
1802 .addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1804 CI.I->eraseFromParent();
1805 Paired.I->eraseFromParent();
1810 CombineInfo &CI, CombineInfo &Paired,
1812 MachineBasicBlock *
MBB = CI.I->getParent();
1817 const unsigned Opcode = getNewOpcode(CI, Paired);
1822 auto MIB =
BuildMI(*
MBB, InsertBefore,
DL,
TII->get(Opcode), DestReg);
1824 if (
auto *SAddr =
TII->getNamedOperand(*CI.I, AMDGPU::OpName::saddr))
1828 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr))
1829 .addImm(std::min(CI.Offset, Paired.Offset))
1831 .addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1833 copyToDestRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdst, DestReg);
1835 CI.I->eraseFromParent();
1836 Paired.I->eraseFromParent();
1841 CombineInfo &CI, CombineInfo &Paired,
1843 MachineBasicBlock *
MBB = CI.I->getParent();
1848 const unsigned Opcode = getNewOpcode(CI, Paired);
1851 copyFromSrcRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdata);
1854 .
add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr))
1857 if (
auto *SAddr =
TII->getNamedOperand(*CI.I, AMDGPU::OpName::saddr))
1861 MIB.addImm(std::min(CI.Offset, Paired.Offset))
1863 .addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1865 CI.I->eraseFromParent();
1866 Paired.I->eraseFromParent();
1875 (MMOs.
size() != 1 || MMOs[0]->
getAlign().value() < Width * 4);
1878unsigned SILoadStoreOptimizer::getNewOpcode(
const CombineInfo &CI,
1879 const CombineInfo &Paired) {
1880 const unsigned Width = CI.Width + Paired.Width;
1881 const CombineInfo &Leading = Paired < CI ? Paired : CI;
1884 const bool NeedsConstrainedOpc =
1887 switch (getCommonInstClass(CI, Paired)) {
1889 assert(CI.InstClass == BUFFER_LOAD || CI.InstClass == BUFFER_STORE);
1900 case S_BUFFER_LOAD_IMM: {
1905 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM_ec
1906 : AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM;
1908 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM_ec
1909 : AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM;
1911 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM_ec
1912 : AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM;
1914 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM_ec
1915 : AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM;
1918 case S_BUFFER_LOAD_SGPR_IMM: {
1923 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM_ec
1924 : AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM;
1926 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM_ec
1927 : AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM;
1929 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM_ec
1930 : AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM;
1932 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM_ec
1933 : AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM;
1941 return NeedsConstrainedOpc ? AMDGPU::S_LOAD_DWORDX2_IMM_ec
1942 : AMDGPU::S_LOAD_DWORDX2_IMM;
1944 return NeedsConstrainedOpc ? AMDGPU::S_LOAD_DWORDX3_IMM_ec
1945 : AMDGPU::S_LOAD_DWORDX3_IMM;
1947 return NeedsConstrainedOpc ? AMDGPU::S_LOAD_DWORDX4_IMM_ec
1948 : AMDGPU::S_LOAD_DWORDX4_IMM;
1950 return NeedsConstrainedOpc ? AMDGPU::S_LOAD_DWORDX8_IMM_ec
1951 : AMDGPU::S_LOAD_DWORDX8_IMM;
1959 return AMDGPU::GLOBAL_LOAD_DWORDX2;
1961 return AMDGPU::GLOBAL_LOAD_DWORDX3;
1963 return AMDGPU::GLOBAL_LOAD_DWORDX4;
1965 case GLOBAL_LOAD_SADDR:
1970 return AMDGPU::GLOBAL_LOAD_DWORDX2_SADDR;
1972 return AMDGPU::GLOBAL_LOAD_DWORDX3_SADDR;
1974 return AMDGPU::GLOBAL_LOAD_DWORDX4_SADDR;
1981 return AMDGPU::GLOBAL_STORE_DWORDX2;
1983 return AMDGPU::GLOBAL_STORE_DWORDX3;
1985 return AMDGPU::GLOBAL_STORE_DWORDX4;
1987 case GLOBAL_STORE_SADDR:
1992 return AMDGPU::GLOBAL_STORE_DWORDX2_SADDR;
1994 return AMDGPU::GLOBAL_STORE_DWORDX3_SADDR;
1996 return AMDGPU::GLOBAL_STORE_DWORDX4_SADDR;
2003 return AMDGPU::FLAT_LOAD_DWORDX2;
2005 return AMDGPU::FLAT_LOAD_DWORDX3;
2007 return AMDGPU::FLAT_LOAD_DWORDX4;
2014 return AMDGPU::FLAT_STORE_DWORDX2;
2016 return AMDGPU::FLAT_STORE_DWORDX3;
2018 return AMDGPU::FLAT_STORE_DWORDX4;
2020 case FLAT_LOAD_SADDR:
2025 return AMDGPU::FLAT_LOAD_DWORDX2_SADDR;
2027 return AMDGPU::FLAT_LOAD_DWORDX3_SADDR;
2029 return AMDGPU::FLAT_LOAD_DWORDX4_SADDR;
2031 case FLAT_STORE_SADDR:
2036 return AMDGPU::FLAT_STORE_DWORDX2_SADDR;
2038 return AMDGPU::FLAT_STORE_DWORDX3_SADDR;
2040 return AMDGPU::FLAT_STORE_DWORDX4_SADDR;
2049std::pair<unsigned, unsigned>
2050SILoadStoreOptimizer::getSubRegIdxs(
const CombineInfo &CI,
2051 const CombineInfo &Paired) {
2052 assert((CI.InstClass != MIMG ||
2054 CI.Width + Paired.Width)) &&
2060 static const unsigned Idxs[5][4] = {
2061 {AMDGPU::sub0, AMDGPU::sub0_sub1, AMDGPU::sub0_sub1_sub2, AMDGPU::sub0_sub1_sub2_sub3},
2062 {AMDGPU::sub1, AMDGPU::sub1_sub2, AMDGPU::sub1_sub2_sub3, AMDGPU::sub1_sub2_sub3_sub4},
2063 {AMDGPU::sub2, AMDGPU::sub2_sub3, AMDGPU::sub2_sub3_sub4, AMDGPU::sub2_sub3_sub4_sub5},
2064 {AMDGPU::sub3, AMDGPU::sub3_sub4, AMDGPU::sub3_sub4_sub5, AMDGPU::sub3_sub4_sub5_sub6},
2065 {AMDGPU::sub4, AMDGPU::sub4_sub5, AMDGPU::sub4_sub5_sub6, AMDGPU::sub4_sub5_sub6_sub7},
2068 assert(CI.Width >= 1 && CI.Width <= 4);
2069 assert(Paired.Width >= 1 && Paired.Width <= 4);
2072 Idx1 = Idxs[0][Paired.Width - 1];
2073 Idx0 = Idxs[Paired.Width][CI.Width - 1];
2075 Idx0 = Idxs[0][CI.Width - 1];
2076 Idx1 = Idxs[CI.Width][Paired.Width - 1];
2079 return {Idx0, Idx1};
2083SILoadStoreOptimizer::getTargetRegisterClass(
const CombineInfo &CI,
2084 const CombineInfo &Paired)
const {
2085 if (CI.InstClass == S_BUFFER_LOAD_IMM ||
2086 CI.InstClass == S_BUFFER_LOAD_SGPR_IMM || CI.InstClass == S_LOAD_IMM) {
2087 switch (CI.Width + Paired.Width) {
2091 return &AMDGPU::SReg_64_XEXECRegClass;
2093 return &AMDGPU::SGPR_96RegClass;
2095 return &AMDGPU::SGPR_128RegClass;
2097 return &AMDGPU::SGPR_256RegClass;
2099 return &AMDGPU::SGPR_512RegClass;
2105 unsigned BitWidth = 32 * (CI.Width + Paired.Width);
2106 return TRI->isAGPRClass(getDataRegClass(*CI.I))
2112 CombineInfo &CI, CombineInfo &Paired,
2114 MachineBasicBlock *
MBB = CI.I->getParent();
2118 const unsigned Opcode = getNewOpcode(CI, Paired);
2121 copyFromSrcRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdata);
2125 AddressRegs Regs = getRegs(Opcode, *
TII);
2128 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr));
2134 assert(CI.I->hasOneMemOperand() && Paired.I->hasOneMemOperand());
2137 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::srsrc))
2138 .add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::soffset))
2139 .addImm(std::min(CI.Offset, Paired.Offset))
2142 .addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
2144 CI.I->eraseFromParent();
2145 Paired.I->eraseFromParent();
2150SILoadStoreOptimizer::createRegOrImm(int32_t Val, MachineInstr &
MI)
const {
2151 APInt
V(32, Val,
true);
2152 if (
TII->isInlineConstant(
V))
2157 BuildMI(*
MI.getParent(),
MI.getIterator(),
MI.getDebugLoc(),
2158 TII->get(AMDGPU::S_MOV_B32),
Reg)
2166Register SILoadStoreOptimizer::computeBase(MachineInstr &
MI,
2167 const MemAddress &Addr)
const {
2175 if (Addr.Base.UseV64Pattern) {
2177 TII->getRegClass(
TII->get(AMDGPU::V_ADD_U64_e64), 0));
2181 MachineInstr *MovOffset =
2185 MachineInstr *
Add64 =
2199 if (Addr.Base.UseScratchVGPRPattern) {
2201 createRegOrImm(
static_cast<int32_t
>(Addr.Offset),
MI);
2204 MachineInstr *
Add32 =
2206 .
addReg(Addr.Base.LoReg, {}, Addr.Base.LoSubReg)
2216 assert((
TRI->getRegSizeInBits(Addr.Base.LoReg, *
MRI) == 32 ||
2217 Addr.Base.LoSubReg) &&
2218 "Expected 32-bit Base-Register-Low!!");
2220 assert((
TRI->getRegSizeInBits(Addr.Base.HiReg, *
MRI) == 32 ||
2221 Addr.Base.HiSubReg) &&
2222 "Expected 32-bit Base-Register-Hi!!");
2224 MachineOperand OffsetLo = createRegOrImm(
static_cast<int32_t
>(Addr.Offset),
MI);
2225 MachineOperand OffsetHi =
2226 createRegOrImm(
static_cast<int32_t
>(Addr.Offset >> 32),
MI);
2228 const auto *CarryRC =
TRI->getWaveMaskRegClass();
2234 MachineInstr *LoHalf =
2236 .
addReg(CarryReg, RegState::Define)
2237 .
addReg(Addr.Base.LoReg, {}, Addr.Base.LoSubReg)
2241 MachineInstr *HiHalf =
2243 .
addReg(DeadCarryReg, RegState::Define | RegState::Dead)
2244 .
addReg(Addr.Base.HiReg, {}, Addr.Base.HiSubReg)
2250 MachineInstr *FullBase =
2261 dbgs() <<
" " << *HiHalf <<
"\n";
2262 dbgs() <<
" " << *FullBase <<
"\n\n";);
2268void SILoadStoreOptimizer::updateBaseAndOffset(MachineInstr &
MI,
2270 int32_t NewOffset)
const {
2271 auto *
Base =
TII->getNamedOperand(
MI, AMDGPU::OpName::vaddr);
2272 Base->setReg(NewBase);
2273 Base->setIsKill(
false);
2274 TII->getNamedOperand(
MI, AMDGPU::OpName::offset)->setImm(NewOffset);
2280bool SILoadStoreOptimizer::processBaseWithConstOffset64(
2281 MachineInstr *AddDef,
const MachineOperand &
Base, MemAddress &Addr)
const {
2285 MachineOperand *
Src0 =
TII->getNamedOperand(*AddDef, AMDGPU::OpName::src0);
2286 MachineOperand *
Src1 =
TII->getNamedOperand(*AddDef, AMDGPU::OpName::src1);
2288 const MachineOperand *BaseOp =
nullptr;
2290 auto Offset =
TII->getImmOrMaterializedImm(*
MRI, *Src1);
2301 Addr.Base.LoReg = BaseOp->
getReg();
2302 Addr.Base.UseV64Pattern =
true;
2310bool SILoadStoreOptimizer::processBaseWithConstOffset32(
2311 MachineInstr *AddDef, MemAddress &Addr)
const {
2313 if (
TII->getNamedOperand(*AddDef, AMDGPU::OpName::clamp)->getImm())
2316 MachineOperand *
Src0 =
TII->getNamedOperand(*AddDef, AMDGPU::OpName::src0);
2317 MachineOperand *
Src1 =
TII->getNamedOperand(*AddDef, AMDGPU::OpName::src1);
2319 const MachineOperand *BaseOp =
nullptr;
2320 std::optional<int64_t>
Offset;
2322 if ((
Offset =
TII->getImmOrMaterializedImm(*
MRI, *Src1))) {
2324 }
else if ((
Offset =
TII->getImmOrMaterializedImm(*
MRI, *Src0))) {
2335 Addr.Base.LoReg = BaseOp->
getReg();
2336 Addr.Base.LoSubReg = BaseOp->
getSubReg();
2337 Addr.Base.UseScratchVGPRPattern =
true;
2360void SILoadStoreOptimizer::processBaseWithConstOffset(
const MachineOperand &
Base,
2361 MemAddress &Addr)
const {
2370 if (
Def->getOpcode() == AMDGPU::V_ADD_U64_e64) {
2371 if (processBaseWithConstOffset64(Def,
Base, Addr))
2377 if (
Def->getOpcode() == AMDGPU::V_ADD_U32_e64 &&
2379 if (processBaseWithConstOffset32(Def, Addr))
2384 if (
Def->getOpcode() != AMDGPU::REG_SEQUENCE ||
Def->getNumOperands() != 5)
2387 MachineOperand BaseLo =
Def->getOperand(1);
2388 MachineOperand BaseHi =
Def->getOperand(3);
2395 if (!BaseLoDef || BaseLoDef->
getOpcode() != AMDGPU::V_ADD_CO_U32_e64 ||
2396 !BaseHiDef || BaseHiDef->
getOpcode() != AMDGPU::V_ADDC_U32_e64)
2399 MachineOperand *
Src0 =
TII->getNamedOperand(*BaseLoDef, AMDGPU::OpName::src0);
2400 MachineOperand *
Src1 =
TII->getNamedOperand(*BaseLoDef, AMDGPU::OpName::src1);
2402 auto Offset0P =
TII->getImmOrMaterializedImm(*
MRI, *Src0);
2406 if (!(Offset0P =
TII->getImmOrMaterializedImm(*
MRI, *Src1)))
2411 if (!BaseLo.
isReg())
2414 Src0 =
TII->getNamedOperand(*BaseHiDef, AMDGPU::OpName::src0);
2415 Src1 =
TII->getNamedOperand(*BaseHiDef, AMDGPU::OpName::src1);
2420 if (!
Src1->isImm() ||
Src0->isImm())
2426 if (!BaseHi.
isReg())
2429 Addr.Base.LoReg = BaseLo.
getReg();
2430 Addr.Base.HiReg = BaseHi.
getReg();
2431 Addr.Base.LoSubReg = BaseLo.
getSubReg();
2432 Addr.Base.HiSubReg = BaseHi.
getSubReg();
2433 Addr.Offset = (*Offset0P & 0x00000000ffffffff) | (Offset1 << 32);
2440void SILoadStoreOptimizer::updateAsyncLDSAddress(MachineInstr &
MI,
2441 int32_t OffsetDiff)
const {
2442 if (!
TII->usesASYNC_CNT(
MI) || OffsetDiff == 0)
2445 MachineOperand *LDSAddr =
TII->getNamedOperand(
MI, AMDGPU::OpName::vdst);
2447 LDSAddr =
TII->getNamedOperand(
MI, AMDGPU::OpName::vdata);
2462bool SILoadStoreOptimizer::promoteConstantOffsetToImm(
2464 MemInfoMap &Visited,
2465 SmallPtrSet<MachineInstr *, 4> &
AnchorList)
const {
2471 !
TII->getNamedOperand(
MI, AMDGPU::OpName::vaddr))
2476 TII->getNamedOperand(
MI, AMDGPU::OpName::saddr))
2486 : AMDGPU::FlatAddrSpace::FLAT;
2487 bool AllowNegativeOffset =
2488 TII->allowNegativeFlatOffset(FlatVariant) && !
TII->usesASYNC_CNT(
MI);
2492 bool IsOffsetU16 =
TII->usesASYNC_CNT(
MI);
2499 if (
TII->getNamedOperand(
MI, AMDGPU::OpName::offset)->getImm()) {
2505 MachineOperand &
Base = *
TII->getNamedOperand(
MI, AMDGPU::OpName::vaddr);
2506 auto [It,
Inserted] = Visited.try_emplace(&
MI);
2509 processBaseWithConstOffset(
Base, MAddr);
2514 if (MAddr.Offset == 0) {
2515 LLVM_DEBUG(
dbgs() <<
" Failed to extract constant-offset or there are no"
2516 " constant offsets that can be promoted.\n";);
2522 <<
"} Offset: " << MAddr.Offset <<
"\n\n";);
2549 MachineInstr *AnchorInst =
nullptr;
2550 MemAddress AnchorAddr;
2551 uint32_t MaxDist = std::numeric_limits<uint32_t>::min();
2553 bool MIIsAnchor =
false;
2562 MachineInstr &MINext = *
MBBI;
2566 TII->getNamedOperand(MINext, AMDGPU::OpName::offset)->getImm())
2569 const MachineOperand &BaseNext =
2570 *
TII->getNamedOperand(MINext, AMDGPU::OpName::vaddr);
2571 MemAddress MAddrNext;
2572 auto [It,
Inserted] = Visited.try_emplace(&MINext);
2574 processBaseWithConstOffset(BaseNext, MAddrNext);
2575 It->second = MAddrNext;
2577 MAddrNext = It->second;
2579 if (MAddrNext.Base.LoReg != MAddr.Base.LoReg ||
2580 MAddrNext.Base.HiReg != MAddr.Base.HiReg ||
2581 MAddrNext.Base.LoSubReg != MAddr.Base.LoSubReg ||
2582 MAddrNext.Base.HiSubReg != MAddr.Base.HiSubReg)
2585 InstsWCommonBase.
emplace_back(&MINext, MAddrNext.Offset);
2587 if (AllowNegativeOffset) {
2588 int64_t Dist = MAddr.Offset - MAddrNext.Offset;
2589 TargetLoweringBase::AddrMode AM;
2592 if (
TLI->isLegalFlatAddressingMode(AM, AS) &&
2593 (uint32_t)std::abs(Dist) > MaxDist) {
2594 MaxDist = std::abs(Dist);
2596 AnchorAddr = MAddrNext;
2597 AnchorInst = &MINext;
2605 if (!AllowNegativeOffset && !InstsWCommonBase.
empty()) {
2606 for (
auto &[Inst,
Offset] : InstsWCommonBase) {
2607 int64_t Dist = MAddr.Offset -
Offset;
2608 TargetLoweringBase::AddrMode AM;
2611 if (Dist >= 0 &&
TLI->isLegalFlatAddressingMode(AM, AS) &&
2613 (!AnchorInst ||
Offset < AnchorAddr.Offset)) {
2614 AnchorAddr = Visited[Inst];
2623 LLVM_DEBUG(
dbgs() <<
" Anchor-Inst(with max-distance from Offset): ";
2624 AnchorInst->
dump());
2626 << AnchorAddr.Offset <<
"\n\n");
2631 int32_t OffsetDiff = MAddr.Offset - AnchorAddr.Offset;
2632 updateBaseAndOffset(
MI,
Base, OffsetDiff);
2633 updateAsyncLDSAddress(
MI, OffsetDiff);
2636 for (
auto [OtherMI, OtherOffset] : InstsWCommonBase) {
2637 TargetLoweringBase::AddrMode AM;
2639 AM.
BaseOffs = OtherOffset - AnchorAddr.Offset;
2641 if (
TLI->isLegalFlatAddressingMode(AM, AS) &&
2642 (AllowNegativeOffset || AM.
BaseOffs >= 0) &&
2646 int32_t OtherOffsetDiff = OtherOffset - AnchorAddr.Offset;
2647 updateBaseAndOffset(*OtherMI,
Base, OtherOffsetDiff);
2648 updateAsyncLDSAddress(*OtherMI, OtherOffsetDiff);
2657 LLVM_DEBUG(
dbgs() <<
" MI is anchor (smallest offset); promoting "
2658 "candidates relative to MI's base.\n");
2661 bool AnyPromoted =
false;
2663 for (
auto [OtherMI, OtherOffset] : InstsWCommonBase) {
2664 int64_t Dist = OtherOffset - MAddr.Offset;
2665 TargetLoweringBase::AddrMode AM;
2668 if (Dist >= 0 &&
TLI->isLegalFlatAddressingMode(AM, AS) &&
2672 updateBaseAndOffset(*OtherMI,
Base, Dist);
2673 updateAsyncLDSAddress(*OtherMI, Dist);
2680 TII->getNamedOperand(
MI, AMDGPU::OpName::vaddr)->setIsKill(
false);
2689void SILoadStoreOptimizer::addInstToMergeableList(
const CombineInfo &CI,
2690 std::list<std::list<CombineInfo> > &MergeableInsts)
const {
2691 for (std::list<CombineInfo> &AddrList : MergeableInsts) {
2692 if (AddrList.front().InstClass == CI.InstClass &&
2693 AddrList.front().hasSameBaseAddress(CI)) {
2694 AddrList.emplace_back(CI);
2700 MergeableInsts.emplace_back(1, CI);
2703std::pair<MachineBasicBlock::iterator, bool>
2704SILoadStoreOptimizer::collectMergeableInsts(
2706 MemInfoMap &Visited, SmallPtrSet<MachineInstr *, 4> &
AnchorList,
2707 std::list<std::list<CombineInfo>> &MergeableInsts)
const {
2713 for (; BlockI !=
End; ++BlockI) {
2714 MachineInstr &
MI = *BlockI;
2718 if (promoteConstantOffsetToImm(
MI, Visited,
AnchorList))
2723 if (
MI.hasOrderedMemoryRef() ||
MI.hasUnmodeledSideEffects()) {
2731 const InstClassEnum InstClass = getInstClass(
MI.getOpcode(), *
TII);
2732 if (InstClass == UNKNOWN)
2737 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::swz);
2738 if (Swizzled != -1 &&
MI.getOperand(Swizzled).getImm())
2741 if (InstClass == TBUFFER_LOAD || InstClass == TBUFFER_STORE) {
2744 dbgs() <<
"Skip tbuffer combine: relaxed OOB mode not enabled\n");
2748 const MachineOperand *Fmt =
2749 TII->getNamedOperand(
MI, AMDGPU::OpName::format);
2754 }
else if (InstClass == MIMG) {
2757 const auto *TFEOp =
TII->getNamedOperand(
MI, AMDGPU::OpName::tfe);
2758 if (TFEOp && TFEOp->getImm())
2761 const auto *LWEOp =
TII->getNamedOperand(
MI, AMDGPU::OpName::lwe);
2762 if (LWEOp && LWEOp->getImm())
2767 CI.setMI(
MI, *
this);
2770 if (!CI.hasMergeableAddress(*
MRI))
2785 for (std::list<std::list<CombineInfo>>::iterator
I = MergeableInsts.begin(),
2786 E = MergeableInsts.end();
I !=
E;) {
2788 std::list<CombineInfo> &MergeList = *
I;
2789 if (MergeList.size() <= 1) {
2793 I = MergeableInsts.erase(
I);
2801 [] (
const CombineInfo &
A,
const CombineInfo &
B) {
2802 return A.Offset <
B.Offset;
2813bool SILoadStoreOptimizer::optimizeBlock(
2814 std::list<std::list<CombineInfo> > &MergeableInsts) {
2817 for (std::list<std::list<CombineInfo>>::iterator
I = MergeableInsts.begin(),
2818 E = MergeableInsts.end();
I !=
E;) {
2819 std::list<CombineInfo> &MergeList = *
I;
2821 bool OptimizeListAgain =
false;
2822 if (!optimizeInstsWithSameBaseAddr(MergeList, OptimizeListAgain)) {
2826 I = MergeableInsts.erase(
I);
2834 if (!OptimizeListAgain) {
2835 I = MergeableInsts.erase(
I);
2838 OptimizeAgain =
true;
2844SILoadStoreOptimizer::optimizeInstsWithSameBaseAddr(
2845 std::list<CombineInfo> &MergeList,
2846 bool &OptimizeListAgain) {
2847 if (MergeList.empty())
2852 for (
auto I = MergeList.begin(),
Next = std::next(
I);
Next != MergeList.end();
2853 Next = std::next(
I)) {
2858 if ((*First).Order > (*Second).Order)
2860 CombineInfo &CI = *
First;
2861 CombineInfo &Paired = *Second;
2863 CombineInfo *Where = checkAndPrepareMerge(CI, Paired);
2871 LLVM_DEBUG(
dbgs() <<
"Merging: " << *CI.I <<
" with: " << *Paired.I);
2874 switch (CI.InstClass) {
2879 NewMI = mergeRead2Pair(CI, Paired, Where->I);
2882 NewMI = mergeWrite2Pair(CI, Paired, Where->I);
2884 case S_BUFFER_LOAD_IMM:
2885 case S_BUFFER_LOAD_SGPR_IMM:
2887 NewMI = mergeSMemLoadImmPair(CI, Paired, Where->I);
2888 OptimizeListAgain |= CI.Width + Paired.Width < 8;
2891 NewMI = mergeBufferLoadPair(CI, Paired, Where->I);
2892 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2895 NewMI = mergeBufferStorePair(CI, Paired, Where->I);
2896 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2899 NewMI = mergeImagePair(CI, Paired, Where->I);
2900 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2903 NewMI = mergeTBufferLoadPair(CI, Paired, Where->I);
2904 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2907 NewMI = mergeTBufferStorePair(CI, Paired, Where->I);
2908 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2911 case FLAT_LOAD_SADDR:
2913 case GLOBAL_LOAD_SADDR:
2914 NewMI = mergeFlatLoadPair(CI, Paired, Where->I);
2915 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2918 case FLAT_STORE_SADDR:
2920 case GLOBAL_STORE_SADDR:
2921 NewMI = mergeFlatStorePair(CI, Paired, Where->I);
2922 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2925 CI.setMI(NewMI, *
this);
2926 CI.Order = Where->Order;
2930 MergeList.erase(Second);
2936bool SILoadStoreOptimizerLegacy::runOnMachineFunction(
MachineFunction &MF) {
2939 return SILoadStoreOptimizer(
2940 &getAnalysis<AAResultsWrapperPass>().getAAResults())
2964 for (MachineBasicBlock &
MBB : MF) {
2968 bool CollectModified;
2969 std::list<std::list<CombineInfo>> MergeableInsts;
2973 std::tie(SectionEnd, CollectModified) =
2979 OptimizeAgain =
false;
2981 }
while (OptimizeAgain);
3003 bool Changed = SILoadStoreOptimizer(&
AA).run(MF);
const TargetLowering & TLI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
INITIALIZE_PASS(AMDGPUImageIntrinsicOptimizer, DEBUG_TYPE, "AMDGPU Image Intrinsic Optimizer", false, false) char AMDGPUImageIntrinsicOptimizer void addInstToMergeableList(IntrinsicInst *II, SmallVector< SmallVector< IntrinsicInst *, 4 > > &MergeableInsts, const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr)
BasicBlock::iterator collectMergeableInsts(BasicBlock::iterator I, BasicBlock::iterator E, SmallVector< SmallVector< IntrinsicInst *, 4 > > &MergeableInsts)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
AMD GCN specific subclass of TargetSubtarget.
const HexagonInstrInfo * TII
static MaybeAlign getAlign(Value *Ptr)
std::pair< Instruction::BinaryOps, Value * > OffsetOp
Find all possible pairs (BinOp, RHS) that BinOp V, RHS can be simplified.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
MachineRegisterInfo & MRI
static uint32_t mostAlignedValueInRange(uint32_t Lo, uint32_t Hi)
static bool needsConstrainedOpcode(const GCNSubtarget &STM, ArrayRef< MachineMemOperand * > MMOs, unsigned Width)
static void addDefsUsesToList(const MachineInstr &MI, DenseSet< Register > &RegDefs, DenseSet< Register > &RegUses)
static unsigned getBufferFormatWithCompCount(unsigned OldFormat, unsigned ComponentCount, const GCNSubtarget &STI)
static bool optimizeBlock(BasicBlock &BB, bool &ModifiedDT, const TargetTransformInfo &TTI, const DataLayout &DL, bool HasBranchDivergence, DomTreeUpdater *DTU)
A manager for alias analyses.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
Represents analyses that only rely on functions' control flow.
static LLVM_ABI DebugLoc getMergedLocation(DebugLoc LocA, DebugLoc LocB)
When two instructions are combined into a single instruction we also need to combine the original loc...
Implements a dense probed hash-table based set.
bool hasOptNone() const
Do not optimize this function (-O0).
bool loadStoreOptEnabled() const
const SIInstrInfo * getInstrInfo() const override
bool hasDwordx3LoadStores() const
const SITargetLowering * getTargetLowering() const override
bool hasRelaxedTBufferOOBMode() const
bool ldsRequiresM0Init() const
Return if most LDS instructions have an m0 use that require m0 to be initialized.
bool hasFlatScratchSVSSwizzleBug() const
bool isXNACKEnabled() const
const HexagonRegisterInfo & getRegisterInfo() const
TypeSize getValue() const
unsigned getOpcode() const
Return the opcode number for this descriptor.
An RAII based helper class to modify MachineFunctionProperties when running pass.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
Properties which a MachineFunction may have at a given point in time.
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.
Function & getFunction()
Return the LLVM function that this machine code represents.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
const MachineInstrBuilder & cloneMergedMemRefs(ArrayRef< const MachineInstr * > OtherMIs) const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
LLVM_ABI void dump() const
A description of a memory reference used in the backend.
LocationSize getSize() const
Return the size in bytes of the memory reference.
unsigned getAddrSpace() const
const MachinePointerInfo & getPointerInfo() const
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
LLVM_ABI LLVM_READONLY MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Wrapper class representing virtual and physical registers.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
static bool isFLATScratch(const MachineInstr &MI)
static bool isVIMAGE(const MachineInstr &MI)
static bool isFLATGlobal(const MachineInstr &MI)
static bool isVSAMPLE(const MachineInstr &MI)
static bool isFLAT(const MachineInstr &MI)
LLVM_READONLY MachineOperand * getNamedOperand(MachineInstr &MI, AMDGPU::OpName OperandName) const
Returns the operand named Op.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
reference emplace_back(ArgTypes &&... Args)
Represent a constant reference to a string, i.e.
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ PRIVATE_ADDRESS
Address space for private memory.
LLVM_READONLY const MIMGInfo * getMIMGInfo(unsigned Opc)
uint64_t convertSMRDOffsetUnits(const MCSubtargetInfo &ST, uint64_t ByteOffset)
Convert ByteOffset to dwords if the subtarget uses dword SMRD immediate offsets.
bool getMTBUFHasSrsrc(unsigned Opc)
int getMTBUFElements(unsigned Opc)
bool getMTBUFHasSoffset(unsigned Opc)
int getMUBUFOpcode(unsigned BaseOpc, unsigned Elements)
int getMUBUFBaseOpcode(unsigned Opc)
LLVM_READONLY bool hasNamedOperand(uint32_t Opcode, OpName NamedIdx)
int getMTBUFBaseOpcode(unsigned Opc)
bool getMUBUFHasVAddr(unsigned Opc)
int getMTBUFOpcode(unsigned BaseOpc, unsigned Elements)
bool getMUBUFHasSoffset(unsigned Opc)
const MIMGBaseOpcodeInfo * getMIMGBaseOpcode(unsigned Opc)
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
int getMaskedMIMGOp(unsigned Opc, unsigned NewChannels)
bool getMTBUFHasVAddr(unsigned Opc)
int getMUBUFElements(unsigned Opc)
const GcnBufferFormatInfo * getGcnBufferFormatInfo(uint8_t BitsPerComp, uint8_t NumComponents, uint8_t NumFormat, const MCSubtargetInfo &STI)
bool getMUBUFHasSrsrc(unsigned Opc)
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.
@ Add64
64 bits label addition
@ Add32
32 bits label addition
NodeAddr< DefNode * > Def
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
This is an optimization pass for GlobalISel generic memory operations.
bool operator<(int64_t V1, const APSInt &V2)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr T maskLeadingOnes(unsigned N)
Create a bitmask with the N left-most bits set to 1, and all other bits set to 0.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
char & SILoadStoreOptimizerLegacyID
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
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...
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
DWARFExpression::Operation Op
std::vector< std::pair< LineLocation, FunctionId > > AnchorList
constexpr unsigned BitWidth
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
@ End
Run the machine verifier once, at the end of the pipeline.
AAResults AliasAnalysis
Temporary typedef for legacy code that uses a generic AliasAnalysis pointer or reference.
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
MCRegisterClass TargetRegisterClass
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.