72#define DEBUG_TYPE "si-load-store-opt"
80 S_BUFFER_LOAD_SGPR_IMM,
99 unsigned char NumVAddrs = 0;
102 bool SOffset =
false;
110const unsigned MaxAddressRegs = 12 + 1 + 1;
112class SILoadStoreOptimizer {
121 InstClassEnum InstClass;
125 int AddrIdx[MaxAddressRegs];
127 unsigned NumAddresses;
130 bool hasSameBaseAddress(
const CombineInfo &CI) {
131 if (NumAddresses != CI.NumAddresses)
135 for (
unsigned i = 0; i < NumAddresses; i++) {
138 if (AddrReg[i]->isImm() || AddrRegNext.
isImm()) {
139 if (AddrReg[i]->isImm() != AddrRegNext.
isImm() ||
157 for (
unsigned i = 0; i < NumAddresses; ++i) {
166 if (!AddrOp->
isReg())
172 AddrOp->
getReg() != AMDGPU::SGPR_NULL)
191 struct BaseRegisters {
195 unsigned LoSubReg = 0;
196 unsigned HiSubReg = 0;
198 bool UseV64Pattern =
false;
220 static bool dmasksCanBeCombined(
const CombineInfo &CI,
222 const CombineInfo &Paired);
223 static bool offsetsCanBeCombined(CombineInfo &CI,
const GCNSubtarget &STI,
224 CombineInfo &Paired,
bool Modify =
false);
225 static bool widthsFit(
const GCNSubtarget &STI,
const CombineInfo &CI,
226 const CombineInfo &Paired);
227 unsigned getNewOpcode(
const CombineInfo &CI,
const CombineInfo &Paired);
228 static std::pair<unsigned, unsigned> getSubRegIdxs(
const CombineInfo &CI,
229 const CombineInfo &Paired);
231 getTargetRegisterClass(
const CombineInfo &CI,
232 const CombineInfo &Paired)
const;
235 CombineInfo *checkAndPrepareMerge(CombineInfo &CI, CombineInfo &Paired);
237 void copyToDestRegs(CombineInfo &CI, CombineInfo &Paired,
241 Register copyFromSrcRegs(CombineInfo &CI, CombineInfo &Paired,
245 unsigned read2Opcode(
unsigned EltSize)
const;
246 unsigned read2ST64Opcode(
unsigned EltSize)
const;
248 mergeRead2Pair(CombineInfo &CI, CombineInfo &Paired,
251 unsigned write2Opcode(
unsigned EltSize)
const;
252 unsigned write2ST64Opcode(
unsigned EltSize)
const;
253 unsigned getWrite2Opcode(
const CombineInfo &CI)
const;
256 mergeWrite2Pair(CombineInfo &CI, CombineInfo &Paired,
259 mergeImagePair(CombineInfo &CI, CombineInfo &Paired,
262 mergeSMemLoadImmPair(CombineInfo &CI, CombineInfo &Paired,
265 mergeBufferLoadPair(CombineInfo &CI, CombineInfo &Paired,
268 mergeBufferStorePair(CombineInfo &CI, CombineInfo &Paired,
271 mergeTBufferLoadPair(CombineInfo &CI, CombineInfo &Paired,
274 mergeTBufferStorePair(CombineInfo &CI, CombineInfo &Paired,
277 mergeFlatLoadPair(CombineInfo &CI, CombineInfo &Paired,
280 mergeFlatStorePair(CombineInfo &CI, CombineInfo &Paired,
284 int32_t NewOffset)
const;
285 void updateAsyncLDSAddress(
MachineInstr &
MI, int32_t OffsetDiff)
const;
290 MemAddress &Addr)
const;
299 std::list<std::list<CombineInfo> > &MergeableInsts)
const;
304 std::list<std::list<CombineInfo>> &MergeableInsts)
const;
307 const CombineInfo &Paired);
309 static InstClassEnum getCommonInstClass(
const CombineInfo &CI,
310 const CombineInfo &Paired);
312 bool optimizeInstsWithSameBaseAddr(std::list<CombineInfo> &MergeList,
313 bool &OptimizeListAgain);
314 bool optimizeBlock(std::list<std::list<CombineInfo> > &MergeableInsts);
329 StringRef getPassName()
const override {
return "SI Load Store Optimizer"; }
345 const unsigned Opc =
MI.getOpcode();
351 if (
TII.isImage(
MI)) {
353 TII.getNamedOperand(
MI, AMDGPU::OpName::dmask)->getImm();
361 case AMDGPU::S_BUFFER_LOAD_DWORD_IMM:
362 case AMDGPU::S_BUFFER_LOAD_DWORD_SGPR_IMM:
363 case AMDGPU::S_LOAD_DWORD_IMM:
364 case AMDGPU::GLOBAL_LOAD_DWORD:
365 case AMDGPU::GLOBAL_LOAD_DWORD_SADDR:
366 case AMDGPU::GLOBAL_STORE_DWORD:
367 case AMDGPU::GLOBAL_STORE_DWORD_SADDR:
368 case AMDGPU::FLAT_LOAD_DWORD:
369 case AMDGPU::FLAT_STORE_DWORD:
370 case AMDGPU::FLAT_LOAD_DWORD_SADDR:
371 case AMDGPU::FLAT_STORE_DWORD_SADDR:
373 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM:
374 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM:
375 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM_ec:
376 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM_ec:
377 case AMDGPU::S_LOAD_DWORDX2_IMM:
378 case AMDGPU::S_LOAD_DWORDX2_IMM_ec:
379 case AMDGPU::GLOBAL_LOAD_DWORDX2:
380 case AMDGPU::GLOBAL_LOAD_DWORDX2_SADDR:
381 case AMDGPU::GLOBAL_STORE_DWORDX2:
382 case AMDGPU::GLOBAL_STORE_DWORDX2_SADDR:
383 case AMDGPU::FLAT_LOAD_DWORDX2:
384 case AMDGPU::FLAT_STORE_DWORDX2:
385 case AMDGPU::FLAT_LOAD_DWORDX2_SADDR:
386 case AMDGPU::FLAT_STORE_DWORDX2_SADDR:
388 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM:
389 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM:
390 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM_ec:
391 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM_ec:
392 case AMDGPU::S_LOAD_DWORDX3_IMM:
393 case AMDGPU::S_LOAD_DWORDX3_IMM_ec:
394 case AMDGPU::GLOBAL_LOAD_DWORDX3:
395 case AMDGPU::GLOBAL_LOAD_DWORDX3_SADDR:
396 case AMDGPU::GLOBAL_STORE_DWORDX3:
397 case AMDGPU::GLOBAL_STORE_DWORDX3_SADDR:
398 case AMDGPU::FLAT_LOAD_DWORDX3:
399 case AMDGPU::FLAT_STORE_DWORDX3:
400 case AMDGPU::FLAT_LOAD_DWORDX3_SADDR:
401 case AMDGPU::FLAT_STORE_DWORDX3_SADDR:
403 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM:
404 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM:
405 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM_ec:
406 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM_ec:
407 case AMDGPU::S_LOAD_DWORDX4_IMM:
408 case AMDGPU::S_LOAD_DWORDX4_IMM_ec:
409 case AMDGPU::GLOBAL_LOAD_DWORDX4:
410 case AMDGPU::GLOBAL_LOAD_DWORDX4_SADDR:
411 case AMDGPU::GLOBAL_STORE_DWORDX4:
412 case AMDGPU::GLOBAL_STORE_DWORDX4_SADDR:
413 case AMDGPU::FLAT_LOAD_DWORDX4:
414 case AMDGPU::FLAT_STORE_DWORDX4:
415 case AMDGPU::FLAT_LOAD_DWORDX4_SADDR:
416 case AMDGPU::FLAT_STORE_DWORDX4_SADDR:
418 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM:
419 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM:
420 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM_ec:
421 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM_ec:
422 case AMDGPU::S_LOAD_DWORDX8_IMM:
423 case AMDGPU::S_LOAD_DWORDX8_IMM_ec:
425 case AMDGPU::DS_READ_B32:
426 case AMDGPU::DS_READ_B32_gfx9:
427 case AMDGPU::DS_WRITE_B32:
428 case AMDGPU::DS_WRITE_B32_gfx9:
430 case AMDGPU::DS_READ_B64:
431 case AMDGPU::DS_READ_B64_gfx9:
432 case AMDGPU::DS_WRITE_B64:
433 case AMDGPU::DS_WRITE_B64_gfx9:
448 case AMDGPU::BUFFER_LOAD_DWORD_BOTHEN:
449 case AMDGPU::BUFFER_LOAD_DWORD_BOTHEN_exact:
450 case AMDGPU::BUFFER_LOAD_DWORD_IDXEN:
451 case AMDGPU::BUFFER_LOAD_DWORD_IDXEN_exact:
452 case AMDGPU::BUFFER_LOAD_DWORD_OFFEN:
453 case AMDGPU::BUFFER_LOAD_DWORD_OFFEN_exact:
454 case AMDGPU::BUFFER_LOAD_DWORD_OFFSET:
455 case AMDGPU::BUFFER_LOAD_DWORD_OFFSET_exact:
456 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_BOTHEN:
457 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_BOTHEN_exact:
458 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_IDXEN:
459 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_IDXEN_exact:
460 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_OFFEN:
461 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_OFFEN_exact:
462 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_OFFSET:
463 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_OFFSET_exact:
465 case AMDGPU::BUFFER_STORE_DWORD_BOTHEN:
466 case AMDGPU::BUFFER_STORE_DWORD_BOTHEN_exact:
467 case AMDGPU::BUFFER_STORE_DWORD_IDXEN:
468 case AMDGPU::BUFFER_STORE_DWORD_IDXEN_exact:
469 case AMDGPU::BUFFER_STORE_DWORD_OFFEN:
470 case AMDGPU::BUFFER_STORE_DWORD_OFFEN_exact:
471 case AMDGPU::BUFFER_STORE_DWORD_OFFSET:
472 case AMDGPU::BUFFER_STORE_DWORD_OFFSET_exact:
473 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_BOTHEN:
474 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_BOTHEN_exact:
475 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_IDXEN:
476 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_IDXEN_exact:
477 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_OFFEN:
478 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_OFFEN_exact:
479 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_OFFSET:
480 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_OFFSET_exact:
493 if (
TII.get(
Opc).mayStore() || !
TII.get(
Opc).mayLoad() ||
502 case AMDGPU::TBUFFER_LOAD_FORMAT_X_BOTHEN:
503 case AMDGPU::TBUFFER_LOAD_FORMAT_X_BOTHEN_exact:
504 case AMDGPU::TBUFFER_LOAD_FORMAT_X_IDXEN:
505 case AMDGPU::TBUFFER_LOAD_FORMAT_X_IDXEN_exact:
506 case AMDGPU::TBUFFER_LOAD_FORMAT_X_OFFEN:
507 case AMDGPU::TBUFFER_LOAD_FORMAT_X_OFFEN_exact:
508 case AMDGPU::TBUFFER_LOAD_FORMAT_X_OFFSET:
509 case AMDGPU::TBUFFER_LOAD_FORMAT_X_OFFSET_exact:
510 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_BOTHEN:
511 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_BOTHEN_exact:
512 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_IDXEN:
513 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_IDXEN_exact:
514 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_OFFEN:
515 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_OFFEN_exact:
516 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_OFFSET:
517 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_OFFSET_exact:
519 case AMDGPU::TBUFFER_STORE_FORMAT_X_OFFEN:
520 case AMDGPU::TBUFFER_STORE_FORMAT_X_OFFEN_exact:
521 case AMDGPU::TBUFFER_STORE_FORMAT_X_OFFSET:
522 case AMDGPU::TBUFFER_STORE_FORMAT_X_OFFSET_exact:
523 case AMDGPU::TBUFFER_STORE_FORMAT_X_VBUFFER_OFFEN:
524 case AMDGPU::TBUFFER_STORE_FORMAT_X_VBUFFER_OFFEN_exact:
525 case AMDGPU::TBUFFER_STORE_FORMAT_X_VBUFFER_OFFSET:
526 case AMDGPU::TBUFFER_STORE_FORMAT_X_VBUFFER_OFFSET_exact:
527 return TBUFFER_STORE;
531 case AMDGPU::S_BUFFER_LOAD_DWORD_IMM:
532 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM:
533 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM:
534 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM:
535 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM:
536 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM_ec:
537 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM_ec:
538 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM_ec:
539 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM_ec:
540 return S_BUFFER_LOAD_IMM;
541 case AMDGPU::S_BUFFER_LOAD_DWORD_SGPR_IMM:
542 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM:
543 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM:
544 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM:
545 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM:
546 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM_ec:
547 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM_ec:
548 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM_ec:
549 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM_ec:
550 return S_BUFFER_LOAD_SGPR_IMM;
551 case AMDGPU::S_LOAD_DWORD_IMM:
552 case AMDGPU::S_LOAD_DWORDX2_IMM:
553 case AMDGPU::S_LOAD_DWORDX3_IMM:
554 case AMDGPU::S_LOAD_DWORDX4_IMM:
555 case AMDGPU::S_LOAD_DWORDX8_IMM:
556 case AMDGPU::S_LOAD_DWORDX2_IMM_ec:
557 case AMDGPU::S_LOAD_DWORDX3_IMM_ec:
558 case AMDGPU::S_LOAD_DWORDX4_IMM_ec:
559 case AMDGPU::S_LOAD_DWORDX8_IMM_ec:
561 case AMDGPU::DS_READ_B32:
562 case AMDGPU::DS_READ_B32_gfx9:
563 case AMDGPU::DS_READ_B64:
564 case AMDGPU::DS_READ_B64_gfx9:
566 case AMDGPU::DS_WRITE_B32:
567 case AMDGPU::DS_WRITE_B32_gfx9:
568 case AMDGPU::DS_WRITE_B64:
569 case AMDGPU::DS_WRITE_B64_gfx9:
571 case AMDGPU::GLOBAL_LOAD_DWORD:
572 case AMDGPU::GLOBAL_LOAD_DWORDX2:
573 case AMDGPU::GLOBAL_LOAD_DWORDX3:
574 case AMDGPU::GLOBAL_LOAD_DWORDX4:
575 case AMDGPU::FLAT_LOAD_DWORD:
576 case AMDGPU::FLAT_LOAD_DWORDX2:
577 case AMDGPU::FLAT_LOAD_DWORDX3:
578 case AMDGPU::FLAT_LOAD_DWORDX4:
580 case AMDGPU::GLOBAL_LOAD_DWORD_SADDR:
581 case AMDGPU::GLOBAL_LOAD_DWORDX2_SADDR:
582 case AMDGPU::GLOBAL_LOAD_DWORDX3_SADDR:
583 case AMDGPU::GLOBAL_LOAD_DWORDX4_SADDR:
584 return GLOBAL_LOAD_SADDR;
585 case AMDGPU::GLOBAL_STORE_DWORD:
586 case AMDGPU::GLOBAL_STORE_DWORDX2:
587 case AMDGPU::GLOBAL_STORE_DWORDX3:
588 case AMDGPU::GLOBAL_STORE_DWORDX4:
589 case AMDGPU::FLAT_STORE_DWORD:
590 case AMDGPU::FLAT_STORE_DWORDX2:
591 case AMDGPU::FLAT_STORE_DWORDX3:
592 case AMDGPU::FLAT_STORE_DWORDX4:
594 case AMDGPU::GLOBAL_STORE_DWORD_SADDR:
595 case AMDGPU::GLOBAL_STORE_DWORDX2_SADDR:
596 case AMDGPU::GLOBAL_STORE_DWORDX3_SADDR:
597 case AMDGPU::GLOBAL_STORE_DWORDX4_SADDR:
598 return GLOBAL_STORE_SADDR;
599 case AMDGPU::FLAT_LOAD_DWORD_SADDR:
600 case AMDGPU::FLAT_LOAD_DWORDX2_SADDR:
601 case AMDGPU::FLAT_LOAD_DWORDX3_SADDR:
602 case AMDGPU::FLAT_LOAD_DWORDX4_SADDR:
603 return FLAT_LOAD_SADDR;
604 case AMDGPU::FLAT_STORE_DWORD_SADDR:
605 case AMDGPU::FLAT_STORE_DWORDX2_SADDR:
606 case AMDGPU::FLAT_STORE_DWORDX3_SADDR:
607 case AMDGPU::FLAT_STORE_DWORDX4_SADDR:
608 return FLAT_STORE_SADDR;
623 return Info->BaseOpcode;
628 case AMDGPU::DS_READ_B32:
629 case AMDGPU::DS_READ_B32_gfx9:
630 case AMDGPU::DS_READ_B64:
631 case AMDGPU::DS_READ_B64_gfx9:
632 case AMDGPU::DS_WRITE_B32:
633 case AMDGPU::DS_WRITE_B32_gfx9:
634 case AMDGPU::DS_WRITE_B64:
635 case AMDGPU::DS_WRITE_B64_gfx9:
637 case AMDGPU::S_BUFFER_LOAD_DWORD_IMM:
638 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM:
639 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM:
640 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM:
641 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM:
642 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM_ec:
643 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM_ec:
644 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM_ec:
645 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM_ec:
646 return AMDGPU::S_BUFFER_LOAD_DWORD_IMM;
647 case AMDGPU::S_BUFFER_LOAD_DWORD_SGPR_IMM:
648 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM:
649 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM:
650 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM:
651 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM:
652 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM_ec:
653 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM_ec:
654 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM_ec:
655 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM_ec:
656 return AMDGPU::S_BUFFER_LOAD_DWORD_SGPR_IMM;
657 case AMDGPU::S_LOAD_DWORD_IMM:
658 case AMDGPU::S_LOAD_DWORDX2_IMM:
659 case AMDGPU::S_LOAD_DWORDX3_IMM:
660 case AMDGPU::S_LOAD_DWORDX4_IMM:
661 case AMDGPU::S_LOAD_DWORDX8_IMM:
662 case AMDGPU::S_LOAD_DWORDX2_IMM_ec:
663 case AMDGPU::S_LOAD_DWORDX3_IMM_ec:
664 case AMDGPU::S_LOAD_DWORDX4_IMM_ec:
665 case AMDGPU::S_LOAD_DWORDX8_IMM_ec:
666 return AMDGPU::S_LOAD_DWORD_IMM;
667 case AMDGPU::GLOBAL_LOAD_DWORD:
668 case AMDGPU::GLOBAL_LOAD_DWORDX2:
669 case AMDGPU::GLOBAL_LOAD_DWORDX3:
670 case AMDGPU::GLOBAL_LOAD_DWORDX4:
671 case AMDGPU::FLAT_LOAD_DWORD:
672 case AMDGPU::FLAT_LOAD_DWORDX2:
673 case AMDGPU::FLAT_LOAD_DWORDX3:
674 case AMDGPU::FLAT_LOAD_DWORDX4:
675 return AMDGPU::FLAT_LOAD_DWORD;
676 case AMDGPU::GLOBAL_LOAD_DWORD_SADDR:
677 case AMDGPU::GLOBAL_LOAD_DWORDX2_SADDR:
678 case AMDGPU::GLOBAL_LOAD_DWORDX3_SADDR:
679 case AMDGPU::GLOBAL_LOAD_DWORDX4_SADDR:
680 return AMDGPU::GLOBAL_LOAD_DWORD_SADDR;
681 case AMDGPU::GLOBAL_STORE_DWORD:
682 case AMDGPU::GLOBAL_STORE_DWORDX2:
683 case AMDGPU::GLOBAL_STORE_DWORDX3:
684 case AMDGPU::GLOBAL_STORE_DWORDX4:
685 case AMDGPU::FLAT_STORE_DWORD:
686 case AMDGPU::FLAT_STORE_DWORDX2:
687 case AMDGPU::FLAT_STORE_DWORDX3:
688 case AMDGPU::FLAT_STORE_DWORDX4:
689 return AMDGPU::FLAT_STORE_DWORD;
690 case AMDGPU::GLOBAL_STORE_DWORD_SADDR:
691 case AMDGPU::GLOBAL_STORE_DWORDX2_SADDR:
692 case AMDGPU::GLOBAL_STORE_DWORDX3_SADDR:
693 case AMDGPU::GLOBAL_STORE_DWORDX4_SADDR:
694 return AMDGPU::GLOBAL_STORE_DWORD_SADDR;
695 case AMDGPU::FLAT_LOAD_DWORD_SADDR:
696 case AMDGPU::FLAT_LOAD_DWORDX2_SADDR:
697 case AMDGPU::FLAT_LOAD_DWORDX3_SADDR:
698 case AMDGPU::FLAT_LOAD_DWORDX4_SADDR:
699 return AMDGPU::FLAT_LOAD_DWORD_SADDR;
700 case AMDGPU::FLAT_STORE_DWORD_SADDR:
701 case AMDGPU::FLAT_STORE_DWORDX2_SADDR:
702 case AMDGPU::FLAT_STORE_DWORDX3_SADDR:
703 case AMDGPU::FLAT_STORE_DWORDX4_SADDR:
704 return AMDGPU::FLAT_STORE_DWORD_SADDR;
715SILoadStoreOptimizer::getCommonInstClass(
const CombineInfo &CI,
716 const CombineInfo &Paired) {
717 assert(CI.InstClass == Paired.InstClass);
719 if ((CI.InstClass == FLAT_LOAD || CI.InstClass == FLAT_STORE) &&
721 return (CI.InstClass == FLAT_STORE) ? GLOBAL_STORE : GLOBAL_LOAD;
735 Result.SOffset =
true;
741 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
742 if (VAddr0Idx >= 0) {
743 AMDGPU::OpName RsrcName =
744 TII.isMIMG(
Opc) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
745 int RsrcIdx = AMDGPU::getNamedOperandIdx(
Opc, RsrcName);
746 Result.NumVAddrs = RsrcIdx - VAddr0Idx;
763 Result.SOffset =
true;
771 case AMDGPU::S_BUFFER_LOAD_DWORD_SGPR_IMM:
772 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM:
773 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM:
774 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM:
775 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM:
776 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM_ec:
777 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM_ec:
778 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM_ec:
779 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM_ec:
780 Result.SOffset =
true;
782 case AMDGPU::S_BUFFER_LOAD_DWORD_IMM:
783 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM:
784 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM:
785 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM:
786 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM:
787 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM_ec:
788 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM_ec:
789 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM_ec:
790 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM_ec:
791 case AMDGPU::S_LOAD_DWORD_IMM:
792 case AMDGPU::S_LOAD_DWORDX2_IMM:
793 case AMDGPU::S_LOAD_DWORDX3_IMM:
794 case AMDGPU::S_LOAD_DWORDX4_IMM:
795 case AMDGPU::S_LOAD_DWORDX8_IMM:
796 case AMDGPU::S_LOAD_DWORDX2_IMM_ec:
797 case AMDGPU::S_LOAD_DWORDX3_IMM_ec:
798 case AMDGPU::S_LOAD_DWORDX4_IMM_ec:
799 case AMDGPU::S_LOAD_DWORDX8_IMM_ec:
802 case AMDGPU::DS_READ_B32:
803 case AMDGPU::DS_READ_B64:
804 case AMDGPU::DS_READ_B32_gfx9:
805 case AMDGPU::DS_READ_B64_gfx9:
806 case AMDGPU::DS_WRITE_B32:
807 case AMDGPU::DS_WRITE_B64:
808 case AMDGPU::DS_WRITE_B32_gfx9:
809 case AMDGPU::DS_WRITE_B64_gfx9:
812 case AMDGPU::GLOBAL_LOAD_DWORD_SADDR:
813 case AMDGPU::GLOBAL_LOAD_DWORDX2_SADDR:
814 case AMDGPU::GLOBAL_LOAD_DWORDX3_SADDR:
815 case AMDGPU::GLOBAL_LOAD_DWORDX4_SADDR:
816 case AMDGPU::GLOBAL_STORE_DWORD_SADDR:
817 case AMDGPU::GLOBAL_STORE_DWORDX2_SADDR:
818 case AMDGPU::GLOBAL_STORE_DWORDX3_SADDR:
819 case AMDGPU::GLOBAL_STORE_DWORDX4_SADDR:
820 case AMDGPU::FLAT_LOAD_DWORD_SADDR:
821 case AMDGPU::FLAT_LOAD_DWORDX2_SADDR:
822 case AMDGPU::FLAT_LOAD_DWORDX3_SADDR:
823 case AMDGPU::FLAT_LOAD_DWORDX4_SADDR:
824 case AMDGPU::FLAT_STORE_DWORD_SADDR:
825 case AMDGPU::FLAT_STORE_DWORDX2_SADDR:
826 case AMDGPU::FLAT_STORE_DWORDX3_SADDR:
827 case AMDGPU::FLAT_STORE_DWORDX4_SADDR:
830 case AMDGPU::GLOBAL_LOAD_DWORD:
831 case AMDGPU::GLOBAL_LOAD_DWORDX2:
832 case AMDGPU::GLOBAL_LOAD_DWORDX3:
833 case AMDGPU::GLOBAL_LOAD_DWORDX4:
834 case AMDGPU::GLOBAL_STORE_DWORD:
835 case AMDGPU::GLOBAL_STORE_DWORDX2:
836 case AMDGPU::GLOBAL_STORE_DWORDX3:
837 case AMDGPU::GLOBAL_STORE_DWORDX4:
838 case AMDGPU::FLAT_LOAD_DWORD:
839 case AMDGPU::FLAT_LOAD_DWORDX2:
840 case AMDGPU::FLAT_LOAD_DWORDX3:
841 case AMDGPU::FLAT_LOAD_DWORDX4:
842 case AMDGPU::FLAT_STORE_DWORD:
843 case AMDGPU::FLAT_STORE_DWORDX2:
844 case AMDGPU::FLAT_STORE_DWORDX3:
845 case AMDGPU::FLAT_STORE_DWORDX4:
852 const SILoadStoreOptimizer &LSO) {
854 unsigned Opc =
MI->getOpcode();
855 InstClass = getInstClass(
Opc, *LSO.TII);
857 if (InstClass == UNKNOWN)
860 DataRC = LSO.getDataRegClass(*
MI);
865 (
Opc == AMDGPU::DS_READ_B64 ||
Opc == AMDGPU::DS_READ_B64_gfx9) ? 8
870 (
Opc == AMDGPU::DS_WRITE_B64 ||
Opc == AMDGPU::DS_WRITE_B64_gfx9) ? 8
873 case S_BUFFER_LOAD_IMM:
874 case S_BUFFER_LOAD_SGPR_IMM:
883 if (InstClass == MIMG) {
888 int OffsetIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::offset);
889 Offset =
I->getOperand(OffsetIdx).getImm();
892 if (InstClass == TBUFFER_LOAD || InstClass == TBUFFER_STORE) {
896 EltSize = Info->BitsPerComp / 8;
899 Width = getOpcodeWidth(*
I, *LSO.TII);
901 if ((InstClass == DS_READ) || (InstClass == DS_WRITE)) {
903 }
else if (InstClass != MIMG) {
907 AddressRegs Regs = getRegs(
Opc, *LSO.TII);
911 for (
unsigned J = 0; J < Regs.NumVAddrs; J++)
912 AddrIdx[NumAddresses++] =
913 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0) + J;
915 AddrIdx[NumAddresses++] =
916 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::addr);
918 AddrIdx[NumAddresses++] =
919 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::sbase);
921 AddrIdx[NumAddresses++] = AMDGPU::getNamedOperandIdx(
922 Opc, isVIMAGEorVSAMPLE ? AMDGPU::OpName::rsrc : AMDGPU::OpName::srsrc);
924 AddrIdx[NumAddresses++] =
925 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::soffset);
927 AddrIdx[NumAddresses++] =
928 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::saddr);
930 AddrIdx[NumAddresses++] =
931 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr);
933 AddrIdx[NumAddresses++] = AMDGPU::getNamedOperandIdx(
934 Opc, isVIMAGEorVSAMPLE ? AMDGPU::OpName::samp : AMDGPU::OpName::ssamp);
935 assert(NumAddresses <= MaxAddressRegs);
937 for (
unsigned J = 0; J < NumAddresses; J++)
938 AddrReg[J] = &
I->getOperand(AddrIdx[J]);
944 "SI Load Store Optimizer",
false,
false)
949char SILoadStoreOptimizerLegacy::
ID = 0;
954 return new SILoadStoreOptimizerLegacy();
960 for (
const auto &
Op :
MI.operands()) {
970bool SILoadStoreOptimizer::canSwapInstructions(
971 const DenseSet<Register> &ARegDefs,
const DenseSet<Register> &ARegUses,
972 const MachineInstr &
A,
const MachineInstr &
B)
const {
973 if (
A.mayLoadOrStore() &&
B.mayLoadOrStore() &&
974 (
A.mayStore() ||
B.mayStore()) &&
A.mayAlias(AA,
B,
true))
976 for (
const auto &BOp :
B.operands()) {
979 if ((BOp.isDef() || BOp.readsReg()) && ARegDefs.
contains(BOp.getReg()))
981 if (BOp.isDef() && ARegUses.
contains(BOp.getReg()))
990SILoadStoreOptimizer::combineKnownAdjacentMMOs(
const CombineInfo &CI,
991 const CombineInfo &Paired) {
992 const MachineMemOperand *MMOa = *CI.I->memoperands_begin();
993 const MachineMemOperand *MMOb = *Paired.I->memoperands_begin();
1007 MachineFunction *MF = CI.I->getMF();
1011bool SILoadStoreOptimizer::dmasksCanBeCombined(
const CombineInfo &CI,
1012 const SIInstrInfo &
TII,
1013 const CombineInfo &Paired) {
1014 assert(CI.InstClass == MIMG);
1017 const auto *TFEOp =
TII.getNamedOperand(*CI.I, AMDGPU::OpName::tfe);
1018 const auto *LWEOp =
TII.getNamedOperand(*CI.I, AMDGPU::OpName::lwe);
1020 if ((TFEOp && TFEOp->getImm()) || (LWEOp && LWEOp->getImm()))
1024 AMDGPU::OpName OperandsToMatch[] = {
1025 AMDGPU::OpName::cpol, AMDGPU::OpName::d16, AMDGPU::OpName::unorm,
1026 AMDGPU::OpName::da, AMDGPU::OpName::r128, AMDGPU::OpName::a16};
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)
1098 if ((CI.Offset % CI.EltSize != 0) || (Paired.Offset % CI.EltSize != 0))
1101 if (CI.InstClass == TBUFFER_LOAD || CI.InstClass == TBUFFER_STORE) {
1103 const llvm::AMDGPU::GcnBufferFormatInfo *Info0 =
1105 const llvm::AMDGPU::GcnBufferFormatInfo *Info1 =
1117 unsigned NumCombinedComponents = CI.Width + Paired.Width;
1118 if (NumCombinedComponents == 3 && CI.EltSize <= 2)
1119 NumCombinedComponents = 4;
1127 unsigned ElemIndex0 = CI.Offset / CI.EltSize;
1128 unsigned ElemIndex1 = Paired.Offset / Paired.EltSize;
1129 if (ElemIndex0 + CI.Width != ElemIndex1 &&
1130 ElemIndex1 + Paired.Width != ElemIndex0)
1136 unsigned MergedBytes = CI.EltSize * NumCombinedComponents;
1137 unsigned RequiredAlign = std::min(MergedBytes, 4u);
1138 unsigned MinOff = std::min(CI.Offset, Paired.Offset);
1139 if (MinOff % RequiredAlign != 0)
1145 uint32_t EltOffset0 = CI.Offset / CI.EltSize;
1146 uint32_t EltOffset1 = Paired.Offset / CI.EltSize;
1151 if ((CI.InstClass != DS_READ) && (CI.InstClass != DS_WRITE)) {
1152 if (EltOffset0 + CI.Width != EltOffset1 &&
1153 EltOffset1 + Paired.Width != EltOffset0)
1159 if (CI.InstClass == S_LOAD_IMM || CI.InstClass == S_BUFFER_LOAD_IMM ||
1160 CI.InstClass == S_BUFFER_LOAD_SGPR_IMM) {
1166 if (CI.Width != Paired.Width &&
1167 (CI.Width < Paired.Width) == (CI.Offset < Paired.Offset))
1175 if ((EltOffset0 % 64 == 0) && (EltOffset1 % 64) == 0 &&
1178 CI.Offset = EltOffset0 / 64;
1179 Paired.Offset = EltOffset1 / 64;
1188 CI.Offset = EltOffset0;
1189 Paired.Offset = EltOffset1;
1195 uint32_t Min = std::min(EltOffset0, EltOffset1);
1196 uint32_t
Max = std::max(EltOffset0, EltOffset1);
1199 if (((Max - Min) & ~Mask) == 0) {
1208 CI.BaseOff = BaseOff * CI.EltSize;
1209 CI.Offset = (EltOffset0 - BaseOff) / 64;
1210 Paired.Offset = (EltOffset1 - BaseOff) / 64;
1222 CI.BaseOff = BaseOff * CI.EltSize;
1223 CI.Offset = EltOffset0 - BaseOff;
1224 Paired.Offset = EltOffset1 - BaseOff;
1232bool SILoadStoreOptimizer::widthsFit(
const GCNSubtarget &STM,
1233 const CombineInfo &CI,
1234 const CombineInfo &Paired) {
1235 const unsigned Width = (CI.Width + Paired.Width);
1236 switch (CI.InstClass) {
1239 case S_BUFFER_LOAD_IMM:
1240 case S_BUFFER_LOAD_SGPR_IMM:
1250 return STM.hasScalarDwordx3Loads();
1256SILoadStoreOptimizer::getDataRegClass(
const MachineInstr &
MI)
const {
1257 if (
const auto *Dst =
TII->getNamedOperand(
MI, AMDGPU::OpName::vdst)) {
1258 return TRI->getRegClassForReg(*MRI, Dst->getReg());
1260 if (
const auto *Src =
TII->getNamedOperand(
MI, AMDGPU::OpName::vdata)) {
1261 return TRI->getRegClassForReg(*MRI, Src->getReg());
1263 if (
const auto *Src =
TII->getNamedOperand(
MI, AMDGPU::OpName::data0)) {
1264 return TRI->getRegClassForReg(*MRI, Src->getReg());
1266 if (
const auto *Dst =
TII->getNamedOperand(
MI, AMDGPU::OpName::sdst)) {
1267 return TRI->getRegClassForReg(*MRI, Dst->getReg());
1269 if (
const auto *Src =
TII->getNamedOperand(
MI, AMDGPU::OpName::sdata)) {
1270 return TRI->getRegClassForReg(*MRI, Src->getReg());
1277SILoadStoreOptimizer::CombineInfo *
1278SILoadStoreOptimizer::checkAndPrepareMerge(CombineInfo &CI,
1279 CombineInfo &Paired) {
1282 if (CI.InstClass == UNKNOWN || Paired.InstClass == UNKNOWN)
1284 assert(CI.InstClass == Paired.InstClass);
1286 if (getInstSubclass(CI.I->getOpcode(), *
TII) !=
1287 getInstSubclass(Paired.I->getOpcode(), *
TII))
1292 if (CI.InstClass == MIMG) {
1293 if (!dmasksCanBeCombined(CI, *
TII, Paired))
1296 if (!widthsFit(*STM, CI, Paired) || !offsetsCanBeCombined(CI, *STM, Paired))
1300 DenseSet<Register> RegDefs;
1301 DenseSet<Register> RegUses;
1303 if (CI.I->mayLoad()) {
1307 if (!canSwapInstructions(RegDefs, RegUses, *Paired.I, *
MBBI))
1315 if (!canSwapInstructions(RegDefs, RegUses, *CI.I, *
MBBI))
1325 if (CI.InstClass == DS_READ || CI.InstClass == DS_WRITE)
1326 offsetsCanBeCombined(CI, *STM, Paired,
true);
1328 if (CI.InstClass == DS_WRITE) {
1336 const MachineOperand *Data0 =
1337 TII->getNamedOperand(*CI.I, AMDGPU::OpName::data0);
1338 const MachineOperand *Data1 =
1339 TII->getNamedOperand(*Paired.I, AMDGPU::OpName::data0);
1341 const MCInstrDesc &Write2Opc =
TII->get(getWrite2Opcode(CI));
1342 int Data0Idx = AMDGPU::getNamedOperandIdx(Write2Opc.
getOpcode(),
1343 AMDGPU::OpName::data0);
1344 int Data1Idx = AMDGPU::getNamedOperandIdx(Write2Opc.
getOpcode(),
1345 AMDGPU::OpName::data1);
1351 if (
unsigned SubReg = Data0->
getSubReg()) {
1356 if (
unsigned SubReg = Data1->
getSubReg()) {
1374void SILoadStoreOptimizer::copyToDestRegs(
1375 CombineInfo &CI, CombineInfo &Paired,
1377 AMDGPU::OpName OpName,
Register DestReg)
const {
1378 MachineBasicBlock *
MBB = CI.I->getParent();
1380 auto [SubRegIdx0, SubRegIdx1] = getSubRegIdxs(CI, Paired);
1383 const MCInstrDesc &CopyDesc =
TII->get(TargetOpcode::COPY);
1384 auto *Dest0 =
TII->getNamedOperand(*CI.I, OpName);
1385 auto *Dest1 =
TII->getNamedOperand(*Paired.I, OpName);
1390 Dest0->setIsEarlyClobber(
false);
1391 Dest1->setIsEarlyClobber(
false);
1395 .
addReg(DestReg, {}, SubRegIdx0);
1398 .
addReg(DestReg, RegState::Kill, SubRegIdx1);
1404SILoadStoreOptimizer::copyFromSrcRegs(CombineInfo &CI, CombineInfo &Paired,
1407 AMDGPU::OpName OpName)
const {
1408 MachineBasicBlock *
MBB = CI.I->getParent();
1410 auto [SubRegIdx0, SubRegIdx1] = getSubRegIdxs(CI, Paired);
1416 const auto *Src0 =
TII->getNamedOperand(*CI.I, OpName);
1417 const auto *Src1 =
TII->getNamedOperand(*Paired.I, OpName);
1419 BuildMI(*
MBB, InsertBefore,
DL,
TII->get(AMDGPU::REG_SEQUENCE), SrcReg)
1428unsigned SILoadStoreOptimizer::read2Opcode(
unsigned EltSize)
const {
1430 return (EltSize == 4) ? AMDGPU::DS_READ2_B32 : AMDGPU::DS_READ2_B64;
1431 return (EltSize == 4) ? AMDGPU::DS_READ2_B32_gfx9 : AMDGPU::DS_READ2_B64_gfx9;
1434unsigned SILoadStoreOptimizer::read2ST64Opcode(
unsigned EltSize)
const {
1436 return (EltSize == 4) ? AMDGPU::DS_READ2ST64_B32 : AMDGPU::DS_READ2ST64_B64;
1438 return (EltSize == 4) ? AMDGPU::DS_READ2ST64_B32_gfx9
1439 : AMDGPU::DS_READ2ST64_B64_gfx9;
1443SILoadStoreOptimizer::mergeRead2Pair(CombineInfo &CI, CombineInfo &Paired,
1445 MachineBasicBlock *
MBB = CI.I->getParent();
1449 const auto *AddrReg =
TII->getNamedOperand(*CI.I, AMDGPU::OpName::addr);
1451 unsigned NewOffset0 = std::min(CI.Offset, Paired.Offset);
1452 unsigned NewOffset1 = std::max(CI.Offset, Paired.Offset);
1454 CI.UseST64 ? read2ST64Opcode(CI.EltSize) : read2Opcode(CI.EltSize);
1457 (NewOffset0 != NewOffset1) &&
"Computed offset doesn't fit");
1459 const MCInstrDesc &Read2Desc =
TII->get(
Opc);
1468 unsigned BaseSubReg = AddrReg->getSubReg();
1476 BaseRegFlags = RegState::Kill;
1478 TII->getAddNoCarry(*
MBB, InsertBefore,
DL, BaseReg)
1480 .addReg(AddrReg->getReg(), {}, BaseSubReg)
1485 MachineInstrBuilder Read2 =
1487 .
addReg(BaseReg, BaseRegFlags, BaseSubReg)
1493 copyToDestRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdst, DestReg);
1495 CI.I->eraseFromParent();
1496 Paired.I->eraseFromParent();
1502unsigned SILoadStoreOptimizer::write2Opcode(
unsigned EltSize)
const {
1504 return (EltSize == 4) ? AMDGPU::DS_WRITE2_B32 : AMDGPU::DS_WRITE2_B64;
1505 return (EltSize == 4) ? AMDGPU::DS_WRITE2_B32_gfx9
1506 : AMDGPU::DS_WRITE2_B64_gfx9;
1509unsigned SILoadStoreOptimizer::write2ST64Opcode(
unsigned EltSize)
const {
1511 return (EltSize == 4) ? AMDGPU::DS_WRITE2ST64_B32
1512 : AMDGPU::DS_WRITE2ST64_B64;
1514 return (EltSize == 4) ? AMDGPU::DS_WRITE2ST64_B32_gfx9
1515 : AMDGPU::DS_WRITE2ST64_B64_gfx9;
1518unsigned SILoadStoreOptimizer::getWrite2Opcode(
const CombineInfo &CI)
const {
1519 return CI.UseST64 ? write2ST64Opcode(CI.EltSize) : write2Opcode(CI.EltSize);
1523 CombineInfo &CI, CombineInfo &Paired,
1525 MachineBasicBlock *
MBB = CI.I->getParent();
1529 const MachineOperand *AddrReg =
1530 TII->getNamedOperand(*CI.I, AMDGPU::OpName::addr);
1531 const MachineOperand *Data0 =
1532 TII->getNamedOperand(*CI.I, AMDGPU::OpName::data0);
1533 const MachineOperand *Data1 =
1534 TII->getNamedOperand(*Paired.I, AMDGPU::OpName::data0);
1536 unsigned NewOffset0 = CI.Offset;
1537 unsigned NewOffset1 = Paired.Offset;
1538 unsigned Opc = getWrite2Opcode(CI);
1540 if (NewOffset0 > NewOffset1) {
1547 (NewOffset0 != NewOffset1) &&
"Computed offset doesn't fit");
1549 const MCInstrDesc &Write2Desc =
TII->get(
Opc);
1554 unsigned BaseSubReg = AddrReg->
getSubReg();
1562 BaseRegFlags = RegState::Kill;
1564 TII->getAddNoCarry(*
MBB, InsertBefore,
DL, BaseReg)
1566 .addReg(AddrReg->
getReg(), {}, BaseSubReg)
1571 MachineInstrBuilder Write2 =
1573 .
addReg(BaseReg, BaseRegFlags, BaseSubReg)
1581 CI.I->eraseFromParent();
1582 Paired.I->eraseFromParent();
1584 LLVM_DEBUG(
dbgs() <<
"Inserted write2 inst: " << *Write2 <<
'\n');
1589SILoadStoreOptimizer::mergeImagePair(CombineInfo &CI, CombineInfo &Paired,
1591 MachineBasicBlock *
MBB = CI.I->getParent();
1595 const unsigned Opcode = getNewOpcode(CI, Paired);
1600 unsigned MergedDMask = CI.DMask | Paired.DMask;
1602 AMDGPU::getNamedOperandIdx(CI.I->getOpcode(), AMDGPU::OpName::dmask);
1604 auto MIB =
BuildMI(*
MBB, InsertBefore,
DL,
TII->get(Opcode), DestReg);
1605 for (
unsigned I = 1,
E = (*CI.I).getNumOperands();
I !=
E; ++
I) {
1607 MIB.addImm(MergedDMask);
1609 MIB.add((*CI.I).getOperand(
I));
1615 assert(CI.I->hasOneMemOperand() && Paired.I->hasOneMemOperand());
1617 MachineInstr *
New = MIB.addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1619 copyToDestRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdata, DestReg);
1621 CI.I->eraseFromParent();
1622 Paired.I->eraseFromParent();
1627 CombineInfo &CI, CombineInfo &Paired,
1629 MachineBasicBlock *
MBB = CI.I->getParent();
1633 const unsigned Opcode = getNewOpcode(CI, Paired);
1638 unsigned MergedOffset = std::min(CI.Offset, Paired.Offset);
1643 assert(CI.I->hasOneMemOperand() && Paired.I->hasOneMemOperand());
1645 MachineInstrBuilder
New =
1647 .
add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::sbase));
1648 if (CI.InstClass == S_BUFFER_LOAD_SGPR_IMM)
1649 New.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::soffset));
1650 New.addImm(MergedOffset);
1651 New.addImm(CI.CPol).addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1653 copyToDestRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::sdst, DestReg);
1655 CI.I->eraseFromParent();
1656 Paired.I->eraseFromParent();
1661 CombineInfo &CI, CombineInfo &Paired,
1663 MachineBasicBlock *
MBB = CI.I->getParent();
1668 const unsigned Opcode = getNewOpcode(CI, Paired);
1674 unsigned MergedOffset = std::min(CI.Offset, Paired.Offset);
1676 auto MIB =
BuildMI(*
MBB, InsertBefore,
DL,
TII->get(Opcode), DestReg);
1678 AddressRegs Regs = getRegs(Opcode, *
TII);
1681 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr));
1686 assert(CI.I->hasOneMemOperand() && Paired.I->hasOneMemOperand());
1689 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::srsrc))
1690 .add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::soffset))
1691 .addImm(MergedOffset)
1694 .addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1696 copyToDestRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdata, DestReg);
1698 CI.I->eraseFromParent();
1699 Paired.I->eraseFromParent();
1704 CombineInfo &CI, CombineInfo &Paired,
1706 MachineBasicBlock *
MBB = CI.I->getParent();
1711 const unsigned Opcode = getNewOpcode(CI, Paired);
1717 unsigned MergedOffset = std::min(CI.Offset, Paired.Offset);
1719 auto MIB =
BuildMI(*
MBB, InsertBefore,
DL,
TII->get(Opcode), DestReg);
1721 AddressRegs Regs = getRegs(Opcode, *
TII);
1724 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr));
1729 unsigned NumCombinedComponents = CI.Width + Paired.Width;
1730 if (NumCombinedComponents == 3 && CI.EltSize <= 2)
1731 NumCombinedComponents = 4;
1732 unsigned JoinedFormat =
1738 assert(CI.I->hasOneMemOperand() && Paired.I->hasOneMemOperand());
1741 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::srsrc))
1742 .add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::soffset))
1743 .addImm(MergedOffset)
1744 .addImm(JoinedFormat)
1747 .addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1749 copyToDestRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdata, DestReg);
1751 CI.I->eraseFromParent();
1752 Paired.I->eraseFromParent();
1757 CombineInfo &CI, CombineInfo &Paired,
1759 MachineBasicBlock *
MBB = CI.I->getParent();
1763 const unsigned Opcode = getNewOpcode(CI, Paired);
1766 copyFromSrcRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdata);
1769 .
addReg(SrcReg, RegState::Kill);
1771 AddressRegs Regs = getRegs(Opcode, *
TII);
1774 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr));
1779 unsigned NumCombinedComponents = CI.Width + Paired.Width;
1780 if (NumCombinedComponents == 3 && CI.EltSize <= 2)
1781 NumCombinedComponents = 4;
1782 unsigned JoinedFormat =
1788 assert(CI.I->hasOneMemOperand() && Paired.I->hasOneMemOperand());
1791 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::srsrc))
1792 .add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::soffset))
1793 .addImm(std::min(CI.Offset, Paired.Offset))
1794 .addImm(JoinedFormat)
1797 .addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1799 CI.I->eraseFromParent();
1800 Paired.I->eraseFromParent();
1805 CombineInfo &CI, CombineInfo &Paired,
1807 MachineBasicBlock *
MBB = CI.I->getParent();
1812 const unsigned Opcode = getNewOpcode(CI, Paired);
1817 auto MIB =
BuildMI(*
MBB, InsertBefore,
DL,
TII->get(Opcode), DestReg);
1819 if (
auto *SAddr =
TII->getNamedOperand(*CI.I, AMDGPU::OpName::saddr))
1823 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr))
1824 .addImm(std::min(CI.Offset, Paired.Offset))
1826 .addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1828 copyToDestRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdst, DestReg);
1830 CI.I->eraseFromParent();
1831 Paired.I->eraseFromParent();
1836 CombineInfo &CI, CombineInfo &Paired,
1838 MachineBasicBlock *
MBB = CI.I->getParent();
1843 const unsigned Opcode = getNewOpcode(CI, Paired);
1846 copyFromSrcRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdata);
1849 .
add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr))
1850 .
addReg(SrcReg, RegState::Kill);
1852 if (
auto *SAddr =
TII->getNamedOperand(*CI.I, AMDGPU::OpName::saddr))
1856 MIB.addImm(std::min(CI.Offset, Paired.Offset))
1858 .addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1860 CI.I->eraseFromParent();
1861 Paired.I->eraseFromParent();
1870 (MMOs.
size() != 1 || MMOs[0]->
getAlign().value() < Width * 4);
1873unsigned SILoadStoreOptimizer::getNewOpcode(
const CombineInfo &CI,
1874 const CombineInfo &Paired) {
1875 const unsigned Width = CI.Width + Paired.Width;
1877 switch (getCommonInstClass(CI, Paired)) {
1879 assert(CI.InstClass == BUFFER_LOAD || CI.InstClass == BUFFER_STORE);
1890 case S_BUFFER_LOAD_IMM: {
1893 bool NeedsConstrainedOpc =
1899 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM_ec
1900 : AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM;
1902 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM_ec
1903 : AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM;
1905 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM_ec
1906 : AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM;
1908 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM_ec
1909 : AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM;
1912 case S_BUFFER_LOAD_SGPR_IMM: {
1915 bool NeedsConstrainedOpc =
1921 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM_ec
1922 : AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM;
1924 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM_ec
1925 : AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM;
1927 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM_ec
1928 : AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM;
1930 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM_ec
1931 : AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM;
1937 bool NeedsConstrainedOpc =
1943 return NeedsConstrainedOpc ? AMDGPU::S_LOAD_DWORDX2_IMM_ec
1944 : AMDGPU::S_LOAD_DWORDX2_IMM;
1946 return NeedsConstrainedOpc ? AMDGPU::S_LOAD_DWORDX3_IMM_ec
1947 : AMDGPU::S_LOAD_DWORDX3_IMM;
1949 return NeedsConstrainedOpc ? AMDGPU::S_LOAD_DWORDX4_IMM_ec
1950 : AMDGPU::S_LOAD_DWORDX4_IMM;
1952 return NeedsConstrainedOpc ? AMDGPU::S_LOAD_DWORDX8_IMM_ec
1953 : AMDGPU::S_LOAD_DWORDX8_IMM;
1961 return AMDGPU::GLOBAL_LOAD_DWORDX2;
1963 return AMDGPU::GLOBAL_LOAD_DWORDX3;
1965 return AMDGPU::GLOBAL_LOAD_DWORDX4;
1967 case GLOBAL_LOAD_SADDR:
1972 return AMDGPU::GLOBAL_LOAD_DWORDX2_SADDR;
1974 return AMDGPU::GLOBAL_LOAD_DWORDX3_SADDR;
1976 return AMDGPU::GLOBAL_LOAD_DWORDX4_SADDR;
1983 return AMDGPU::GLOBAL_STORE_DWORDX2;
1985 return AMDGPU::GLOBAL_STORE_DWORDX3;
1987 return AMDGPU::GLOBAL_STORE_DWORDX4;
1989 case GLOBAL_STORE_SADDR:
1994 return AMDGPU::GLOBAL_STORE_DWORDX2_SADDR;
1996 return AMDGPU::GLOBAL_STORE_DWORDX3_SADDR;
1998 return AMDGPU::GLOBAL_STORE_DWORDX4_SADDR;
2005 return AMDGPU::FLAT_LOAD_DWORDX2;
2007 return AMDGPU::FLAT_LOAD_DWORDX3;
2009 return AMDGPU::FLAT_LOAD_DWORDX4;
2016 return AMDGPU::FLAT_STORE_DWORDX2;
2018 return AMDGPU::FLAT_STORE_DWORDX3;
2020 return AMDGPU::FLAT_STORE_DWORDX4;
2022 case FLAT_LOAD_SADDR:
2027 return AMDGPU::FLAT_LOAD_DWORDX2_SADDR;
2029 return AMDGPU::FLAT_LOAD_DWORDX3_SADDR;
2031 return AMDGPU::FLAT_LOAD_DWORDX4_SADDR;
2033 case FLAT_STORE_SADDR:
2038 return AMDGPU::FLAT_STORE_DWORDX2_SADDR;
2040 return AMDGPU::FLAT_STORE_DWORDX3_SADDR;
2042 return AMDGPU::FLAT_STORE_DWORDX4_SADDR;
2051std::pair<unsigned, unsigned>
2052SILoadStoreOptimizer::getSubRegIdxs(
const CombineInfo &CI,
2053 const CombineInfo &Paired) {
2054 assert((CI.InstClass != MIMG ||
2056 CI.Width + Paired.Width)) &&
2062 static const unsigned Idxs[5][4] = {
2063 {AMDGPU::sub0, AMDGPU::sub0_sub1, AMDGPU::sub0_sub1_sub2, AMDGPU::sub0_sub1_sub2_sub3},
2064 {AMDGPU::sub1, AMDGPU::sub1_sub2, AMDGPU::sub1_sub2_sub3, AMDGPU::sub1_sub2_sub3_sub4},
2065 {AMDGPU::sub2, AMDGPU::sub2_sub3, AMDGPU::sub2_sub3_sub4, AMDGPU::sub2_sub3_sub4_sub5},
2066 {AMDGPU::sub3, AMDGPU::sub3_sub4, AMDGPU::sub3_sub4_sub5, AMDGPU::sub3_sub4_sub5_sub6},
2067 {AMDGPU::sub4, AMDGPU::sub4_sub5, AMDGPU::sub4_sub5_sub6, AMDGPU::sub4_sub5_sub6_sub7},
2070 assert(CI.Width >= 1 && CI.Width <= 4);
2071 assert(Paired.Width >= 1 && Paired.Width <= 4);
2074 Idx1 = Idxs[0][Paired.Width - 1];
2075 Idx0 = Idxs[Paired.Width][CI.Width - 1];
2077 Idx0 = Idxs[0][CI.Width - 1];
2078 Idx1 = Idxs[CI.Width][Paired.Width - 1];
2081 return {Idx0, Idx1};
2085SILoadStoreOptimizer::getTargetRegisterClass(
const CombineInfo &CI,
2086 const CombineInfo &Paired)
const {
2087 if (CI.InstClass == S_BUFFER_LOAD_IMM ||
2088 CI.InstClass == S_BUFFER_LOAD_SGPR_IMM || CI.InstClass == S_LOAD_IMM) {
2089 switch (CI.Width + Paired.Width) {
2093 return &AMDGPU::SReg_64_XEXECRegClass;
2095 return &AMDGPU::SGPR_96RegClass;
2097 return &AMDGPU::SGPR_128RegClass;
2099 return &AMDGPU::SGPR_256RegClass;
2101 return &AMDGPU::SGPR_512RegClass;
2107 unsigned BitWidth = 32 * (CI.Width + Paired.Width);
2108 return TRI->isAGPRClass(getDataRegClass(*CI.I))
2114 CombineInfo &CI, CombineInfo &Paired,
2116 MachineBasicBlock *
MBB = CI.I->getParent();
2120 const unsigned Opcode = getNewOpcode(CI, Paired);
2123 copyFromSrcRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdata);
2126 .
addReg(SrcReg, RegState::Kill);
2128 AddressRegs Regs = getRegs(Opcode, *
TII);
2131 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr));
2137 assert(CI.I->hasOneMemOperand() && Paired.I->hasOneMemOperand());
2140 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::srsrc))
2141 .add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::soffset))
2142 .addImm(std::min(CI.Offset, Paired.Offset))
2145 .addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
2147 CI.I->eraseFromParent();
2148 Paired.I->eraseFromParent();
2153SILoadStoreOptimizer::createRegOrImm(int32_t Val, MachineInstr &
MI)
const {
2154 APInt
V(32, Val,
true);
2155 if (
TII->isInlineConstant(V))
2160 BuildMI(*
MI.getParent(),
MI.getIterator(),
MI.getDebugLoc(),
2161 TII->get(AMDGPU::S_MOV_B32),
Reg)
2169Register SILoadStoreOptimizer::computeBase(MachineInstr &
MI,
2170 const MemAddress &Addr)
const {
2171 MachineBasicBlock *
MBB =
MI.getParent();
2178 if (Addr.Base.UseV64Pattern) {
2180 TII->getRegClass(
TII->get(AMDGPU::V_ADD_U64_e64), 0));
2184 MachineInstr *MovOffset =
2188 MachineInstr *
Add64 =
2191 .
addReg(OffsetReg, RegState::Kill)
2202 assert((
TRI->getRegSizeInBits(Addr.Base.LoReg, *MRI) == 32 ||
2203 Addr.Base.LoSubReg) &&
2204 "Expected 32-bit Base-Register-Low!!");
2206 assert((
TRI->getRegSizeInBits(Addr.Base.HiReg, *MRI) == 32 ||
2207 Addr.Base.HiSubReg) &&
2208 "Expected 32-bit Base-Register-Hi!!");
2210 MachineOperand OffsetLo = createRegOrImm(
static_cast<int32_t
>(Addr.Offset),
MI);
2211 MachineOperand OffsetHi =
2212 createRegOrImm(
static_cast<int32_t
>(Addr.Offset >> 32),
MI);
2214 const auto *CarryRC =
TRI->getWaveMaskRegClass();
2220 MachineInstr *LoHalf =
2222 .
addReg(CarryReg, RegState::Define)
2223 .
addReg(Addr.Base.LoReg, {}, Addr.Base.LoSubReg)
2227 MachineInstr *HiHalf =
2229 .
addReg(DeadCarryReg, RegState::Define | RegState::Dead)
2230 .
addReg(Addr.Base.HiReg, {}, Addr.Base.HiSubReg)
2232 .
addReg(CarryReg, RegState::Kill)
2236 MachineInstr *FullBase =
2247 dbgs() <<
" " << *HiHalf <<
"\n";
2248 dbgs() <<
" " << *FullBase <<
"\n\n";);
2254void SILoadStoreOptimizer::updateBaseAndOffset(MachineInstr &
MI,
2256 int32_t NewOffset)
const {
2257 auto *
Base =
TII->getNamedOperand(
MI, AMDGPU::OpName::vaddr);
2258 Base->setReg(NewBase);
2259 Base->setIsKill(
false);
2260 TII->getNamedOperand(
MI, AMDGPU::OpName::offset)->setImm(NewOffset);
2266bool SILoadStoreOptimizer::processBaseWithConstOffset64(
2267 MachineInstr *AddDef,
const MachineOperand &
Base, MemAddress &Addr)
const {
2271 MachineOperand *Src0 =
TII->getNamedOperand(*AddDef, AMDGPU::OpName::src0);
2272 MachineOperand *Src1 =
TII->getNamedOperand(*AddDef, AMDGPU::OpName::src1);
2274 const MachineOperand *BaseOp =
nullptr;
2276 auto Offset =
TII->getImmOrMaterializedImm(*Src1);
2287 Addr.Base.LoReg = BaseOp->
getReg();
2288 Addr.Base.UseV64Pattern =
true;
2306void SILoadStoreOptimizer::processBaseWithConstOffset(
const MachineOperand &
Base,
2307 MemAddress &Addr)
const {
2316 if (
Def->getOpcode() == AMDGPU::V_ADD_U64_e64) {
2317 if (processBaseWithConstOffset64(Def,
Base, Addr))
2322 if (
Def->getOpcode() != AMDGPU::REG_SEQUENCE ||
Def->getNumOperands() != 5)
2325 MachineOperand BaseLo =
Def->getOperand(1);
2326 MachineOperand BaseHi =
Def->getOperand(3);
2333 if (!BaseLoDef || BaseLoDef->
getOpcode() != AMDGPU::V_ADD_CO_U32_e64 ||
2334 !BaseHiDef || BaseHiDef->
getOpcode() != AMDGPU::V_ADDC_U32_e64)
2337 MachineOperand *Src0 =
TII->getNamedOperand(*BaseLoDef, AMDGPU::OpName::src0);
2338 MachineOperand *Src1 =
TII->getNamedOperand(*BaseLoDef, AMDGPU::OpName::src1);
2340 auto Offset0P =
TII->getImmOrMaterializedImm(*Src0);
2344 if (!(Offset0P =
TII->getImmOrMaterializedImm(*Src1)))
2349 if (!BaseLo.
isReg())
2352 Src0 =
TII->getNamedOperand(*BaseHiDef, AMDGPU::OpName::src0);
2353 Src1 =
TII->getNamedOperand(*BaseHiDef, AMDGPU::OpName::src1);
2361 uint64_t Offset1 = Src1->
getImm();
2364 if (!BaseHi.
isReg())
2367 Addr.Base.LoReg = BaseLo.
getReg();
2368 Addr.Base.HiReg = BaseHi.
getReg();
2369 Addr.Base.LoSubReg = BaseLo.
getSubReg();
2370 Addr.Base.HiSubReg = BaseHi.
getSubReg();
2371 Addr.Offset = (*Offset0P & 0x00000000ffffffff) | (Offset1 << 32);
2378void SILoadStoreOptimizer::updateAsyncLDSAddress(MachineInstr &
MI,
2379 int32_t OffsetDiff)
const {
2380 if (!
TII->usesASYNC_CNT(
MI) || OffsetDiff == 0)
2383 MachineOperand *LDSAddr =
TII->getNamedOperand(
MI, AMDGPU::OpName::vdst);
2385 LDSAddr =
TII->getNamedOperand(
MI, AMDGPU::OpName::vdata);
2390 MachineBasicBlock &
MBB = *
MI.getParent();
2400bool SILoadStoreOptimizer::promoteConstantOffsetToImm(
2402 MemInfoMap &Visited,
2403 SmallPtrSet<MachineInstr *, 4> &
AnchorList)
const {
2416 ? AMDGPU::FlatAddrSpace::FlatGlobal
2417 : AMDGPU::FlatAddrSpace::FLAT;
2418 bool AllowNegativeOffset =
2419 TII->allowNegativeFlatOffset(FlatVariant) && !
TII->usesASYNC_CNT(
MI);
2423 bool IsOffsetU16 =
TII->usesASYNC_CNT(
MI);
2430 if (
TII->getNamedOperand(
MI, AMDGPU::OpName::offset)->getImm()) {
2436 MachineOperand &
Base = *
TII->getNamedOperand(
MI, AMDGPU::OpName::vaddr);
2437 auto [It,
Inserted] = Visited.try_emplace(&
MI);
2440 processBaseWithConstOffset(
Base, MAddr);
2445 if (MAddr.Offset == 0) {
2446 LLVM_DEBUG(
dbgs() <<
" Failed to extract constant-offset or there are no"
2447 " constant offsets that can be promoted.\n";);
2453 <<
"} Offset: " << MAddr.Offset <<
"\n\n";);
2480 MachineInstr *AnchorInst =
nullptr;
2481 MemAddress AnchorAddr;
2482 uint32_t MaxDist = std::numeric_limits<uint32_t>::min();
2484 bool MIIsAnchor =
false;
2486 MachineBasicBlock *
MBB =
MI.getParent();
2493 MachineInstr &MINext = *
MBBI;
2497 TII->getNamedOperand(MINext, AMDGPU::OpName::offset)->getImm())
2500 const MachineOperand &BaseNext =
2501 *
TII->getNamedOperand(MINext, AMDGPU::OpName::vaddr);
2502 MemAddress MAddrNext;
2503 auto [It,
Inserted] = Visited.try_emplace(&MINext);
2505 processBaseWithConstOffset(BaseNext, MAddrNext);
2506 It->second = MAddrNext;
2508 MAddrNext = It->second;
2510 if (MAddrNext.Base.LoReg != MAddr.Base.LoReg ||
2511 MAddrNext.Base.HiReg != MAddr.Base.HiReg ||
2512 MAddrNext.Base.LoSubReg != MAddr.Base.LoSubReg ||
2513 MAddrNext.Base.HiSubReg != MAddr.Base.HiSubReg)
2516 InstsWCommonBase.
emplace_back(&MINext, MAddrNext.Offset);
2518 if (AllowNegativeOffset) {
2519 int64_t Dist = MAddr.Offset - MAddrNext.Offset;
2520 TargetLoweringBase::AddrMode AM;
2524 (uint32_t)std::abs(Dist) > MaxDist) {
2525 MaxDist = std::abs(Dist);
2527 AnchorAddr = MAddrNext;
2528 AnchorInst = &MINext;
2536 if (!AllowNegativeOffset && !InstsWCommonBase.
empty()) {
2537 for (
auto &[Inst,
Offset] : InstsWCommonBase) {
2538 int64_t Dist = MAddr.Offset -
Offset;
2539 TargetLoweringBase::AddrMode AM;
2544 (!AnchorInst ||
Offset < AnchorAddr.Offset)) {
2545 AnchorAddr = Visited[Inst];
2554 LLVM_DEBUG(
dbgs() <<
" Anchor-Inst(with max-distance from Offset): ";
2555 AnchorInst->
dump());
2557 << AnchorAddr.Offset <<
"\n\n");
2562 int32_t OffsetDiff = MAddr.Offset - AnchorAddr.Offset;
2563 updateBaseAndOffset(
MI,
Base, OffsetDiff);
2564 updateAsyncLDSAddress(
MI, OffsetDiff);
2567 for (
auto [OtherMI, OtherOffset] : InstsWCommonBase) {
2568 TargetLoweringBase::AddrMode AM;
2570 AM.
BaseOffs = OtherOffset - AnchorAddr.Offset;
2573 (AllowNegativeOffset || AM.
BaseOffs >= 0) &&
2577 int32_t OtherOffsetDiff = OtherOffset - AnchorAddr.Offset;
2578 updateBaseAndOffset(*OtherMI,
Base, OtherOffsetDiff);
2579 updateAsyncLDSAddress(*OtherMI, OtherOffsetDiff);
2588 LLVM_DEBUG(
dbgs() <<
" MI is anchor (smallest offset); promoting "
2589 "candidates relative to MI's base.\n");
2592 bool AnyPromoted =
false;
2594 for (
auto [OtherMI, OtherOffset] : InstsWCommonBase) {
2595 int64_t Dist = OtherOffset - MAddr.Offset;
2596 TargetLoweringBase::AddrMode AM;
2603 updateBaseAndOffset(*OtherMI,
Base, Dist);
2604 updateAsyncLDSAddress(*OtherMI, Dist);
2611 TII->getNamedOperand(
MI, AMDGPU::OpName::vaddr)->setIsKill(
false);
2620void SILoadStoreOptimizer::addInstToMergeableList(
const CombineInfo &CI,
2621 std::list<std::list<CombineInfo> > &MergeableInsts)
const {
2622 for (std::list<CombineInfo> &AddrList : MergeableInsts) {
2623 if (AddrList.front().InstClass == CI.InstClass &&
2624 AddrList.front().hasSameBaseAddress(CI)) {
2625 AddrList.emplace_back(CI);
2631 MergeableInsts.emplace_back(1, CI);
2634std::pair<MachineBasicBlock::iterator, bool>
2635SILoadStoreOptimizer::collectMergeableInsts(
2637 MemInfoMap &Visited, SmallPtrSet<MachineInstr *, 4> &
AnchorList,
2638 std::list<std::list<CombineInfo>> &MergeableInsts)
const {
2644 for (; BlockI != End; ++BlockI) {
2645 MachineInstr &
MI = *BlockI;
2649 if (promoteConstantOffsetToImm(
MI, Visited,
AnchorList))
2654 if (
MI.hasOrderedMemoryRef() ||
MI.hasUnmodeledSideEffects()) {
2662 const InstClassEnum InstClass = getInstClass(
MI.getOpcode(), *
TII);
2663 if (InstClass == UNKNOWN)
2668 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::swz);
2669 if (Swizzled != -1 &&
MI.getOperand(Swizzled).getImm())
2672 if (InstClass == TBUFFER_LOAD || InstClass == TBUFFER_STORE) {
2673 const MachineOperand *Fmt =
2674 TII->getNamedOperand(
MI, AMDGPU::OpName::format);
2682 CI.setMI(
MI, *
this);
2685 if (!CI.hasMergeableAddress(*MRI))
2700 for (std::list<std::list<CombineInfo>>::iterator
I = MergeableInsts.begin(),
2701 E = MergeableInsts.end();
I !=
E;) {
2703 std::list<CombineInfo> &MergeList = *
I;
2704 if (MergeList.size() <= 1) {
2708 I = MergeableInsts.erase(
I);
2716 [] (
const CombineInfo &
A,
const CombineInfo &
B) {
2717 return A.Offset <
B.Offset;
2728bool SILoadStoreOptimizer::optimizeBlock(
2729 std::list<std::list<CombineInfo> > &MergeableInsts) {
2732 for (std::list<std::list<CombineInfo>>::iterator
I = MergeableInsts.begin(),
2733 E = MergeableInsts.end();
I !=
E;) {
2734 std::list<CombineInfo> &MergeList = *
I;
2736 bool OptimizeListAgain =
false;
2737 if (!optimizeInstsWithSameBaseAddr(MergeList, OptimizeListAgain)) {
2741 I = MergeableInsts.erase(
I);
2749 if (!OptimizeListAgain) {
2750 I = MergeableInsts.erase(
I);
2753 OptimizeAgain =
true;
2759SILoadStoreOptimizer::optimizeInstsWithSameBaseAddr(
2760 std::list<CombineInfo> &MergeList,
2761 bool &OptimizeListAgain) {
2762 if (MergeList.empty())
2767 for (
auto I = MergeList.begin(),
Next = std::next(
I);
Next != MergeList.end();
2768 Next = std::next(
I)) {
2773 if ((*First).Order > (*Second).Order)
2775 CombineInfo &CI = *
First;
2776 CombineInfo &Paired = *Second;
2778 CombineInfo *Where = checkAndPrepareMerge(CI, Paired);
2786 LLVM_DEBUG(
dbgs() <<
"Merging: " << *CI.I <<
" with: " << *Paired.I);
2789 switch (CI.InstClass) {
2794 NewMI = mergeRead2Pair(CI, Paired, Where->I);
2797 NewMI = mergeWrite2Pair(CI, Paired, Where->I);
2799 case S_BUFFER_LOAD_IMM:
2800 case S_BUFFER_LOAD_SGPR_IMM:
2802 NewMI = mergeSMemLoadImmPair(CI, Paired, Where->I);
2803 OptimizeListAgain |= CI.Width + Paired.Width < 8;
2806 NewMI = mergeBufferLoadPair(CI, Paired, Where->I);
2807 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2810 NewMI = mergeBufferStorePair(CI, Paired, Where->I);
2811 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2814 NewMI = mergeImagePair(CI, Paired, Where->I);
2815 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2818 NewMI = mergeTBufferLoadPair(CI, Paired, Where->I);
2819 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2822 NewMI = mergeTBufferStorePair(CI, Paired, Where->I);
2823 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2826 case FLAT_LOAD_SADDR:
2828 case GLOBAL_LOAD_SADDR:
2829 NewMI = mergeFlatLoadPair(CI, Paired, Where->I);
2830 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2833 case FLAT_STORE_SADDR:
2835 case GLOBAL_STORE_SADDR:
2836 NewMI = mergeFlatStorePair(CI, Paired, Where->I);
2837 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2840 CI.setMI(NewMI, *
this);
2841 CI.Order = Where->Order;
2845 MergeList.erase(Second);
2851bool SILoadStoreOptimizerLegacy::runOnMachineFunction(MachineFunction &MF) {
2854 return SILoadStoreOptimizer(
2855 &getAnalysis<AAResultsWrapperPass>().getAAResults())
2859bool SILoadStoreOptimizer::run(MachineFunction &MF) {
2879 for (MachineBasicBlock &
MBB : MF) {
2883 bool CollectModified;
2884 std::list<std::list<CombineInfo>> MergeableInsts;
2888 std::tie(SectionEnd, CollectModified) =
2894 OptimizeAgain =
false;
2896 }
while (OptimizeAgain);
2918 bool Changed = SILoadStoreOptimizer(&
AA).run(MF);
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)
Provides AMDGPU specific target descriptions.
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)
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)
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()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
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.
FunctionPass class - This class is used to implement most global optimizations.
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 ldsRequiresM0Init() const
Return if most LDS instructions have an m0 use that require m0 to be initialized.
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.
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.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
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,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
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 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)
bool isLegalFlatAddressingMode(const AddrMode &AM, unsigned AddrSpace) const
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.
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
#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).
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(uint64_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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ Add64
64 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.
RegState
Flags to represent properties of register accesses.
constexpr T maskLeadingOnes(unsigned N)
Create a bitmask with the N left-most bits set to 1, and all other bits set to 0.
FunctionPass * createSILoadStoreOptimizerLegacyPass()
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.
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.