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)
190 struct BaseRegisters {
194 unsigned LoSubReg = 0;
195 unsigned HiSubReg = 0;
197 bool UseV64Pattern =
false;
219 static bool dmasksCanBeCombined(
const CombineInfo &CI,
221 const CombineInfo &Paired);
222 static bool offsetsCanBeCombined(CombineInfo &CI,
const GCNSubtarget &STI,
223 CombineInfo &Paired,
bool Modify =
false);
224 static bool widthsFit(
const GCNSubtarget &STI,
const CombineInfo &CI,
225 const CombineInfo &Paired);
226 unsigned getNewOpcode(
const CombineInfo &CI,
const CombineInfo &Paired);
227 static std::pair<unsigned, unsigned> getSubRegIdxs(
const CombineInfo &CI,
228 const CombineInfo &Paired);
230 getTargetRegisterClass(
const CombineInfo &CI,
231 const CombineInfo &Paired)
const;
234 CombineInfo *checkAndPrepareMerge(CombineInfo &CI, CombineInfo &Paired);
236 void copyToDestRegs(CombineInfo &CI, CombineInfo &Paired,
240 Register copyFromSrcRegs(CombineInfo &CI, CombineInfo &Paired,
244 unsigned read2Opcode(
unsigned EltSize,
bool GDS)
const;
245 unsigned read2ST64Opcode(
unsigned EltSize,
bool GDS)
const;
247 mergeRead2Pair(CombineInfo &CI, CombineInfo &Paired,
250 unsigned write2Opcode(
unsigned EltSize,
bool GDS)
const;
251 unsigned write2ST64Opcode(
unsigned EltSize,
bool GDS)
const;
252 unsigned getWrite2Opcode(
const CombineInfo &CI)
const;
255 mergeWrite2Pair(CombineInfo &CI, CombineInfo &Paired,
258 mergeImagePair(CombineInfo &CI, CombineInfo &Paired,
261 mergeSMemLoadImmPair(CombineInfo &CI, CombineInfo &Paired,
264 mergeBufferLoadPair(CombineInfo &CI, CombineInfo &Paired,
267 mergeBufferStorePair(CombineInfo &CI, CombineInfo &Paired,
270 mergeTBufferLoadPair(CombineInfo &CI, CombineInfo &Paired,
273 mergeTBufferStorePair(CombineInfo &CI, CombineInfo &Paired,
276 mergeFlatLoadPair(CombineInfo &CI, CombineInfo &Paired,
279 mergeFlatStorePair(CombineInfo &CI, CombineInfo &Paired,
283 int32_t NewOffset)
const;
284 void updateAsyncLDSAddress(
MachineInstr &
MI, int32_t OffsetDiff)
const;
289 MemAddress &Addr)
const;
298 std::list<std::list<CombineInfo> > &MergeableInsts)
const;
303 std::list<std::list<CombineInfo>> &MergeableInsts)
const;
306 const CombineInfo &Paired);
308 static InstClassEnum getCommonInstClass(
const CombineInfo &CI,
309 const CombineInfo &Paired);
311 bool optimizeInstsWithSameBaseAddr(std::list<CombineInfo> &MergeList,
312 bool &OptimizeListAgain);
313 bool optimizeBlock(std::list<std::list<CombineInfo> > &MergeableInsts);
328 StringRef getPassName()
const override {
return "SI Load Store Optimizer"; }
343 const unsigned Opc =
MI.getOpcode();
349 if (
TII.isImage(
MI)) {
351 TII.getNamedOperand(
MI, AMDGPU::OpName::dmask)->getImm();
359 case AMDGPU::S_BUFFER_LOAD_DWORD_IMM:
360 case AMDGPU::S_BUFFER_LOAD_DWORD_SGPR_IMM:
361 case AMDGPU::S_LOAD_DWORD_IMM:
362 case AMDGPU::GLOBAL_LOAD_DWORD:
363 case AMDGPU::GLOBAL_LOAD_DWORD_SADDR:
364 case AMDGPU::GLOBAL_STORE_DWORD:
365 case AMDGPU::GLOBAL_STORE_DWORD_SADDR:
366 case AMDGPU::FLAT_LOAD_DWORD:
367 case AMDGPU::FLAT_STORE_DWORD:
368 case AMDGPU::FLAT_LOAD_DWORD_SADDR:
369 case AMDGPU::FLAT_STORE_DWORD_SADDR:
371 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM:
372 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM:
373 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM_ec:
374 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM_ec:
375 case AMDGPU::S_LOAD_DWORDX2_IMM:
376 case AMDGPU::S_LOAD_DWORDX2_IMM_ec:
377 case AMDGPU::GLOBAL_LOAD_DWORDX2:
378 case AMDGPU::GLOBAL_LOAD_DWORDX2_SADDR:
379 case AMDGPU::GLOBAL_STORE_DWORDX2:
380 case AMDGPU::GLOBAL_STORE_DWORDX2_SADDR:
381 case AMDGPU::FLAT_LOAD_DWORDX2:
382 case AMDGPU::FLAT_STORE_DWORDX2:
383 case AMDGPU::FLAT_LOAD_DWORDX2_SADDR:
384 case AMDGPU::FLAT_STORE_DWORDX2_SADDR:
386 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM:
387 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM:
388 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM_ec:
389 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM_ec:
390 case AMDGPU::S_LOAD_DWORDX3_IMM:
391 case AMDGPU::S_LOAD_DWORDX3_IMM_ec:
392 case AMDGPU::GLOBAL_LOAD_DWORDX3:
393 case AMDGPU::GLOBAL_LOAD_DWORDX3_SADDR:
394 case AMDGPU::GLOBAL_STORE_DWORDX3:
395 case AMDGPU::GLOBAL_STORE_DWORDX3_SADDR:
396 case AMDGPU::FLAT_LOAD_DWORDX3:
397 case AMDGPU::FLAT_STORE_DWORDX3:
398 case AMDGPU::FLAT_LOAD_DWORDX3_SADDR:
399 case AMDGPU::FLAT_STORE_DWORDX3_SADDR:
401 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM:
402 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM:
403 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM_ec:
404 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM_ec:
405 case AMDGPU::S_LOAD_DWORDX4_IMM:
406 case AMDGPU::S_LOAD_DWORDX4_IMM_ec:
407 case AMDGPU::GLOBAL_LOAD_DWORDX4:
408 case AMDGPU::GLOBAL_LOAD_DWORDX4_SADDR:
409 case AMDGPU::GLOBAL_STORE_DWORDX4:
410 case AMDGPU::GLOBAL_STORE_DWORDX4_SADDR:
411 case AMDGPU::FLAT_LOAD_DWORDX4:
412 case AMDGPU::FLAT_STORE_DWORDX4:
413 case AMDGPU::FLAT_LOAD_DWORDX4_SADDR:
414 case AMDGPU::FLAT_STORE_DWORDX4_SADDR:
416 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM:
417 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM:
418 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM_ec:
419 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM_ec:
420 case AMDGPU::S_LOAD_DWORDX8_IMM:
421 case AMDGPU::S_LOAD_DWORDX8_IMM_ec:
423 case AMDGPU::DS_READ_B32:
424 case AMDGPU::DS_READ_B32_gfx9:
425 case AMDGPU::DS_WRITE_B32:
426 case AMDGPU::DS_WRITE_B32_gfx9:
428 case AMDGPU::DS_READ_B64:
429 case AMDGPU::DS_READ_B64_gfx9:
430 case AMDGPU::DS_WRITE_B64:
431 case AMDGPU::DS_WRITE_B64_gfx9:
446 case AMDGPU::BUFFER_LOAD_DWORD_BOTHEN:
447 case AMDGPU::BUFFER_LOAD_DWORD_BOTHEN_exact:
448 case AMDGPU::BUFFER_LOAD_DWORD_IDXEN:
449 case AMDGPU::BUFFER_LOAD_DWORD_IDXEN_exact:
450 case AMDGPU::BUFFER_LOAD_DWORD_OFFEN:
451 case AMDGPU::BUFFER_LOAD_DWORD_OFFEN_exact:
452 case AMDGPU::BUFFER_LOAD_DWORD_OFFSET:
453 case AMDGPU::BUFFER_LOAD_DWORD_OFFSET_exact:
454 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_BOTHEN:
455 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_BOTHEN_exact:
456 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_IDXEN:
457 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_IDXEN_exact:
458 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_OFFEN:
459 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_OFFEN_exact:
460 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_OFFSET:
461 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_OFFSET_exact:
463 case AMDGPU::BUFFER_STORE_DWORD_BOTHEN:
464 case AMDGPU::BUFFER_STORE_DWORD_BOTHEN_exact:
465 case AMDGPU::BUFFER_STORE_DWORD_IDXEN:
466 case AMDGPU::BUFFER_STORE_DWORD_IDXEN_exact:
467 case AMDGPU::BUFFER_STORE_DWORD_OFFEN:
468 case AMDGPU::BUFFER_STORE_DWORD_OFFEN_exact:
469 case AMDGPU::BUFFER_STORE_DWORD_OFFSET:
470 case AMDGPU::BUFFER_STORE_DWORD_OFFSET_exact:
471 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_BOTHEN:
472 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_BOTHEN_exact:
473 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_IDXEN:
474 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_IDXEN_exact:
475 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_OFFEN:
476 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_OFFEN_exact:
477 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_OFFSET:
478 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_OFFSET_exact:
491 if (
TII.get(
Opc).mayStore() || !
TII.get(
Opc).mayLoad() ||
500 case AMDGPU::TBUFFER_LOAD_FORMAT_X_BOTHEN:
501 case AMDGPU::TBUFFER_LOAD_FORMAT_X_BOTHEN_exact:
502 case AMDGPU::TBUFFER_LOAD_FORMAT_X_IDXEN:
503 case AMDGPU::TBUFFER_LOAD_FORMAT_X_IDXEN_exact:
504 case AMDGPU::TBUFFER_LOAD_FORMAT_X_OFFEN:
505 case AMDGPU::TBUFFER_LOAD_FORMAT_X_OFFEN_exact:
506 case AMDGPU::TBUFFER_LOAD_FORMAT_X_OFFSET:
507 case AMDGPU::TBUFFER_LOAD_FORMAT_X_OFFSET_exact:
508 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_BOTHEN:
509 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_BOTHEN_exact:
510 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_IDXEN:
511 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_IDXEN_exact:
512 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_OFFEN:
513 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_OFFEN_exact:
514 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_OFFSET:
515 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_OFFSET_exact:
517 case AMDGPU::TBUFFER_STORE_FORMAT_X_OFFEN:
518 case AMDGPU::TBUFFER_STORE_FORMAT_X_OFFEN_exact:
519 case AMDGPU::TBUFFER_STORE_FORMAT_X_OFFSET:
520 case AMDGPU::TBUFFER_STORE_FORMAT_X_OFFSET_exact:
521 case AMDGPU::TBUFFER_STORE_FORMAT_X_VBUFFER_OFFEN:
522 case AMDGPU::TBUFFER_STORE_FORMAT_X_VBUFFER_OFFEN_exact:
523 case AMDGPU::TBUFFER_STORE_FORMAT_X_VBUFFER_OFFSET:
524 case AMDGPU::TBUFFER_STORE_FORMAT_X_VBUFFER_OFFSET_exact:
525 return TBUFFER_STORE;
529 case AMDGPU::S_BUFFER_LOAD_DWORD_IMM:
530 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM:
531 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM:
532 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM:
533 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM:
534 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM_ec:
535 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM_ec:
536 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM_ec:
537 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM_ec:
538 return S_BUFFER_LOAD_IMM;
539 case AMDGPU::S_BUFFER_LOAD_DWORD_SGPR_IMM:
540 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM:
541 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM:
542 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM:
543 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM:
544 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM_ec:
545 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM_ec:
546 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM_ec:
547 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM_ec:
548 return S_BUFFER_LOAD_SGPR_IMM;
549 case AMDGPU::S_LOAD_DWORD_IMM:
550 case AMDGPU::S_LOAD_DWORDX2_IMM:
551 case AMDGPU::S_LOAD_DWORDX3_IMM:
552 case AMDGPU::S_LOAD_DWORDX4_IMM:
553 case AMDGPU::S_LOAD_DWORDX8_IMM:
554 case AMDGPU::S_LOAD_DWORDX2_IMM_ec:
555 case AMDGPU::S_LOAD_DWORDX3_IMM_ec:
556 case AMDGPU::S_LOAD_DWORDX4_IMM_ec:
557 case AMDGPU::S_LOAD_DWORDX8_IMM_ec:
559 case AMDGPU::DS_READ_B32:
560 case AMDGPU::DS_READ_B32_gfx9:
561 case AMDGPU::DS_READ_B64:
562 case AMDGPU::DS_READ_B64_gfx9:
564 case AMDGPU::DS_WRITE_B32:
565 case AMDGPU::DS_WRITE_B32_gfx9:
566 case AMDGPU::DS_WRITE_B64:
567 case AMDGPU::DS_WRITE_B64_gfx9:
569 case AMDGPU::GLOBAL_LOAD_DWORD:
570 case AMDGPU::GLOBAL_LOAD_DWORDX2:
571 case AMDGPU::GLOBAL_LOAD_DWORDX3:
572 case AMDGPU::GLOBAL_LOAD_DWORDX4:
573 case AMDGPU::FLAT_LOAD_DWORD:
574 case AMDGPU::FLAT_LOAD_DWORDX2:
575 case AMDGPU::FLAT_LOAD_DWORDX3:
576 case AMDGPU::FLAT_LOAD_DWORDX4:
578 case AMDGPU::GLOBAL_LOAD_DWORD_SADDR:
579 case AMDGPU::GLOBAL_LOAD_DWORDX2_SADDR:
580 case AMDGPU::GLOBAL_LOAD_DWORDX3_SADDR:
581 case AMDGPU::GLOBAL_LOAD_DWORDX4_SADDR:
582 return GLOBAL_LOAD_SADDR;
583 case AMDGPU::GLOBAL_STORE_DWORD:
584 case AMDGPU::GLOBAL_STORE_DWORDX2:
585 case AMDGPU::GLOBAL_STORE_DWORDX3:
586 case AMDGPU::GLOBAL_STORE_DWORDX4:
587 case AMDGPU::FLAT_STORE_DWORD:
588 case AMDGPU::FLAT_STORE_DWORDX2:
589 case AMDGPU::FLAT_STORE_DWORDX3:
590 case AMDGPU::FLAT_STORE_DWORDX4:
592 case AMDGPU::GLOBAL_STORE_DWORD_SADDR:
593 case AMDGPU::GLOBAL_STORE_DWORDX2_SADDR:
594 case AMDGPU::GLOBAL_STORE_DWORDX3_SADDR:
595 case AMDGPU::GLOBAL_STORE_DWORDX4_SADDR:
596 return GLOBAL_STORE_SADDR;
597 case AMDGPU::FLAT_LOAD_DWORD_SADDR:
598 case AMDGPU::FLAT_LOAD_DWORDX2_SADDR:
599 case AMDGPU::FLAT_LOAD_DWORDX3_SADDR:
600 case AMDGPU::FLAT_LOAD_DWORDX4_SADDR:
601 return FLAT_LOAD_SADDR;
602 case AMDGPU::FLAT_STORE_DWORD_SADDR:
603 case AMDGPU::FLAT_STORE_DWORDX2_SADDR:
604 case AMDGPU::FLAT_STORE_DWORDX3_SADDR:
605 case AMDGPU::FLAT_STORE_DWORDX4_SADDR:
606 return FLAT_STORE_SADDR;
621 return Info->BaseOpcode;
626 case AMDGPU::DS_READ_B32:
627 case AMDGPU::DS_READ_B32_gfx9:
628 case AMDGPU::DS_READ_B64:
629 case AMDGPU::DS_READ_B64_gfx9:
630 case AMDGPU::DS_WRITE_B32:
631 case AMDGPU::DS_WRITE_B32_gfx9:
632 case AMDGPU::DS_WRITE_B64:
633 case AMDGPU::DS_WRITE_B64_gfx9:
635 case AMDGPU::S_BUFFER_LOAD_DWORD_IMM:
636 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM:
637 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM:
638 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM:
639 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM:
640 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM_ec:
641 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM_ec:
642 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM_ec:
643 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM_ec:
644 return AMDGPU::S_BUFFER_LOAD_DWORD_IMM;
645 case AMDGPU::S_BUFFER_LOAD_DWORD_SGPR_IMM:
646 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM:
647 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM:
648 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM:
649 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM:
650 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM_ec:
651 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM_ec:
652 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM_ec:
653 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM_ec:
654 return AMDGPU::S_BUFFER_LOAD_DWORD_SGPR_IMM;
655 case AMDGPU::S_LOAD_DWORD_IMM:
656 case AMDGPU::S_LOAD_DWORDX2_IMM:
657 case AMDGPU::S_LOAD_DWORDX3_IMM:
658 case AMDGPU::S_LOAD_DWORDX4_IMM:
659 case AMDGPU::S_LOAD_DWORDX8_IMM:
660 case AMDGPU::S_LOAD_DWORDX2_IMM_ec:
661 case AMDGPU::S_LOAD_DWORDX3_IMM_ec:
662 case AMDGPU::S_LOAD_DWORDX4_IMM_ec:
663 case AMDGPU::S_LOAD_DWORDX8_IMM_ec:
664 return AMDGPU::S_LOAD_DWORD_IMM;
665 case AMDGPU::GLOBAL_LOAD_DWORD:
666 case AMDGPU::GLOBAL_LOAD_DWORDX2:
667 case AMDGPU::GLOBAL_LOAD_DWORDX3:
668 case AMDGPU::GLOBAL_LOAD_DWORDX4:
669 case AMDGPU::FLAT_LOAD_DWORD:
670 case AMDGPU::FLAT_LOAD_DWORDX2:
671 case AMDGPU::FLAT_LOAD_DWORDX3:
672 case AMDGPU::FLAT_LOAD_DWORDX4:
673 return AMDGPU::FLAT_LOAD_DWORD;
674 case AMDGPU::GLOBAL_LOAD_DWORD_SADDR:
675 case AMDGPU::GLOBAL_LOAD_DWORDX2_SADDR:
676 case AMDGPU::GLOBAL_LOAD_DWORDX3_SADDR:
677 case AMDGPU::GLOBAL_LOAD_DWORDX4_SADDR:
678 return AMDGPU::GLOBAL_LOAD_DWORD_SADDR;
679 case AMDGPU::GLOBAL_STORE_DWORD:
680 case AMDGPU::GLOBAL_STORE_DWORDX2:
681 case AMDGPU::GLOBAL_STORE_DWORDX3:
682 case AMDGPU::GLOBAL_STORE_DWORDX4:
683 case AMDGPU::FLAT_STORE_DWORD:
684 case AMDGPU::FLAT_STORE_DWORDX2:
685 case AMDGPU::FLAT_STORE_DWORDX3:
686 case AMDGPU::FLAT_STORE_DWORDX4:
687 return AMDGPU::FLAT_STORE_DWORD;
688 case AMDGPU::GLOBAL_STORE_DWORD_SADDR:
689 case AMDGPU::GLOBAL_STORE_DWORDX2_SADDR:
690 case AMDGPU::GLOBAL_STORE_DWORDX3_SADDR:
691 case AMDGPU::GLOBAL_STORE_DWORDX4_SADDR:
692 return AMDGPU::GLOBAL_STORE_DWORD_SADDR;
693 case AMDGPU::FLAT_LOAD_DWORD_SADDR:
694 case AMDGPU::FLAT_LOAD_DWORDX2_SADDR:
695 case AMDGPU::FLAT_LOAD_DWORDX3_SADDR:
696 case AMDGPU::FLAT_LOAD_DWORDX4_SADDR:
697 return AMDGPU::FLAT_LOAD_DWORD_SADDR;
698 case AMDGPU::FLAT_STORE_DWORD_SADDR:
699 case AMDGPU::FLAT_STORE_DWORDX2_SADDR:
700 case AMDGPU::FLAT_STORE_DWORDX3_SADDR:
701 case AMDGPU::FLAT_STORE_DWORDX4_SADDR:
702 return AMDGPU::FLAT_STORE_DWORD_SADDR;
713SILoadStoreOptimizer::getCommonInstClass(
const CombineInfo &CI,
714 const CombineInfo &Paired) {
715 assert(CI.InstClass == Paired.InstClass);
717 if ((CI.InstClass == FLAT_LOAD || CI.InstClass == FLAT_STORE) &&
719 return (CI.InstClass == FLAT_STORE) ? GLOBAL_STORE : GLOBAL_LOAD;
733 Result.SOffset =
true;
739 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
740 if (VAddr0Idx >= 0) {
741 AMDGPU::OpName RsrcName =
742 TII.isMIMG(
Opc) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
743 int RsrcIdx = AMDGPU::getNamedOperandIdx(
Opc, RsrcName);
744 Result.NumVAddrs = RsrcIdx - VAddr0Idx;
761 Result.SOffset =
true;
769 case AMDGPU::S_BUFFER_LOAD_DWORD_SGPR_IMM:
770 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM:
771 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM:
772 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM:
773 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM:
774 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM_ec:
775 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM_ec:
776 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM_ec:
777 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM_ec:
778 Result.SOffset =
true;
780 case AMDGPU::S_BUFFER_LOAD_DWORD_IMM:
781 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM:
782 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM:
783 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM:
784 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM:
785 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM_ec:
786 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM_ec:
787 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM_ec:
788 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM_ec:
789 case AMDGPU::S_LOAD_DWORD_IMM:
790 case AMDGPU::S_LOAD_DWORDX2_IMM:
791 case AMDGPU::S_LOAD_DWORDX3_IMM:
792 case AMDGPU::S_LOAD_DWORDX4_IMM:
793 case AMDGPU::S_LOAD_DWORDX8_IMM:
794 case AMDGPU::S_LOAD_DWORDX2_IMM_ec:
795 case AMDGPU::S_LOAD_DWORDX3_IMM_ec:
796 case AMDGPU::S_LOAD_DWORDX4_IMM_ec:
797 case AMDGPU::S_LOAD_DWORDX8_IMM_ec:
800 case AMDGPU::DS_READ_B32:
801 case AMDGPU::DS_READ_B64:
802 case AMDGPU::DS_READ_B32_gfx9:
803 case AMDGPU::DS_READ_B64_gfx9:
804 case AMDGPU::DS_WRITE_B32:
805 case AMDGPU::DS_WRITE_B64:
806 case AMDGPU::DS_WRITE_B32_gfx9:
807 case AMDGPU::DS_WRITE_B64_gfx9:
810 case AMDGPU::GLOBAL_LOAD_DWORD_SADDR:
811 case AMDGPU::GLOBAL_LOAD_DWORDX2_SADDR:
812 case AMDGPU::GLOBAL_LOAD_DWORDX3_SADDR:
813 case AMDGPU::GLOBAL_LOAD_DWORDX4_SADDR:
814 case AMDGPU::GLOBAL_STORE_DWORD_SADDR:
815 case AMDGPU::GLOBAL_STORE_DWORDX2_SADDR:
816 case AMDGPU::GLOBAL_STORE_DWORDX3_SADDR:
817 case AMDGPU::GLOBAL_STORE_DWORDX4_SADDR:
818 case AMDGPU::FLAT_LOAD_DWORD_SADDR:
819 case AMDGPU::FLAT_LOAD_DWORDX2_SADDR:
820 case AMDGPU::FLAT_LOAD_DWORDX3_SADDR:
821 case AMDGPU::FLAT_LOAD_DWORDX4_SADDR:
822 case AMDGPU::FLAT_STORE_DWORD_SADDR:
823 case AMDGPU::FLAT_STORE_DWORDX2_SADDR:
824 case AMDGPU::FLAT_STORE_DWORDX3_SADDR:
825 case AMDGPU::FLAT_STORE_DWORDX4_SADDR:
828 case AMDGPU::GLOBAL_LOAD_DWORD:
829 case AMDGPU::GLOBAL_LOAD_DWORDX2:
830 case AMDGPU::GLOBAL_LOAD_DWORDX3:
831 case AMDGPU::GLOBAL_LOAD_DWORDX4:
832 case AMDGPU::GLOBAL_STORE_DWORD:
833 case AMDGPU::GLOBAL_STORE_DWORDX2:
834 case AMDGPU::GLOBAL_STORE_DWORDX3:
835 case AMDGPU::GLOBAL_STORE_DWORDX4:
836 case AMDGPU::FLAT_LOAD_DWORD:
837 case AMDGPU::FLAT_LOAD_DWORDX2:
838 case AMDGPU::FLAT_LOAD_DWORDX3:
839 case AMDGPU::FLAT_LOAD_DWORDX4:
840 case AMDGPU::FLAT_STORE_DWORD:
841 case AMDGPU::FLAT_STORE_DWORDX2:
842 case AMDGPU::FLAT_STORE_DWORDX3:
843 case AMDGPU::FLAT_STORE_DWORDX4:
850 const SILoadStoreOptimizer &LSO) {
852 unsigned Opc =
MI->getOpcode();
853 InstClass = getInstClass(
Opc, *LSO.TII);
855 if (InstClass == UNKNOWN)
858 DataRC = LSO.getDataRegClass(*
MI);
863 (
Opc == AMDGPU::DS_READ_B64 ||
Opc == AMDGPU::DS_READ_B64_gfx9) ? 8
868 (
Opc == AMDGPU::DS_WRITE_B64 ||
Opc == AMDGPU::DS_WRITE_B64_gfx9) ? 8
871 case S_BUFFER_LOAD_IMM:
872 case S_BUFFER_LOAD_SGPR_IMM:
881 if (InstClass == MIMG) {
886 int OffsetIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::offset);
887 Offset =
I->getOperand(OffsetIdx).getImm();
890 if (InstClass == TBUFFER_LOAD || InstClass == TBUFFER_STORE) {
894 EltSize = Info->BitsPerComp / 8;
897 Width = getOpcodeWidth(*
I, *LSO.TII);
899 if ((InstClass == DS_READ) || (InstClass == DS_WRITE)) {
902 }
else if (InstClass != MIMG) {
906 AddressRegs Regs = getRegs(
Opc, *LSO.TII);
910 for (
unsigned J = 0; J < Regs.NumVAddrs; J++)
911 AddrIdx[NumAddresses++] =
912 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0) + J;
914 AddrIdx[NumAddresses++] =
915 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::addr);
917 AddrIdx[NumAddresses++] =
918 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::sbase);
920 AddrIdx[NumAddresses++] = AMDGPU::getNamedOperandIdx(
921 Opc, isVIMAGEorVSAMPLE ? AMDGPU::OpName::rsrc : AMDGPU::OpName::srsrc);
923 AddrIdx[NumAddresses++] =
924 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::soffset);
926 AddrIdx[NumAddresses++] =
927 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::saddr);
929 AddrIdx[NumAddresses++] =
930 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr);
932 AddrIdx[NumAddresses++] = AMDGPU::getNamedOperandIdx(
933 Opc, isVIMAGEorVSAMPLE ? AMDGPU::OpName::samp : AMDGPU::OpName::ssamp);
934 assert(NumAddresses <= MaxAddressRegs);
936 for (
unsigned J = 0; J < NumAddresses; J++)
937 AddrReg[J] = &
I->getOperand(AddrIdx[J]);
943 "SI Load Store Optimizer",
false,
false)
948char SILoadStoreOptimizerLegacy::ID = 0;
955 for (
const auto &
Op :
MI.operands()) {
959 RegDefs.insert(Op.getReg());
961 RegUses.insert(Op.getReg());
965bool SILoadStoreOptimizer::canSwapInstructions(
966 const DenseSet<Register> &ARegDefs,
const DenseSet<Register> &ARegUses,
967 const MachineInstr &
A,
const MachineInstr &
B)
const {
968 if (
A.mayLoadOrStore() &&
B.mayLoadOrStore() &&
969 (
A.mayStore() ||
B.mayStore()) &&
A.mayAlias(AA,
B,
true))
971 for (
const auto &BOp :
B.operands()) {
974 if ((BOp.isDef() || BOp.readsReg()) && ARegDefs.
contains(BOp.getReg()))
976 if (BOp.isDef() && ARegUses.
contains(BOp.getReg()))
985SILoadStoreOptimizer::combineKnownAdjacentMMOs(
const CombineInfo &CI,
986 const CombineInfo &Paired) {
987 const MachineMemOperand *MMOa = *CI.I->memoperands_begin();
988 const MachineMemOperand *MMOb = *Paired.I->memoperands_begin();
1006bool SILoadStoreOptimizer::dmasksCanBeCombined(
const CombineInfo &CI,
1007 const SIInstrInfo &
TII,
1008 const CombineInfo &Paired) {
1009 assert(CI.InstClass == MIMG);
1012 const auto *TFEOp =
TII.getNamedOperand(*CI.I, AMDGPU::OpName::tfe);
1013 const auto *LWEOp =
TII.getNamedOperand(*CI.I, AMDGPU::OpName::lwe);
1015 if ((TFEOp && TFEOp->getImm()) || (LWEOp && LWEOp->getImm()))
1019 AMDGPU::OpName OperandsToMatch[] = {
1020 AMDGPU::OpName::cpol, AMDGPU::OpName::d16, AMDGPU::OpName::unorm,
1021 AMDGPU::OpName::da, AMDGPU::OpName::r128, AMDGPU::OpName::a16,
1022 AMDGPU::OpName::dim};
1024 for (AMDGPU::OpName
op : OperandsToMatch) {
1025 int Idx = AMDGPU::getNamedOperandIdx(CI.I->getOpcode(),
op);
1026 if (AMDGPU::getNamedOperandIdx(Paired.I->getOpcode(),
op) != Idx)
1029 CI.I->getOperand(Idx).getImm() != Paired.I->getOperand(Idx).getImm())
1034 unsigned MaxMask = std::max(CI.DMask, Paired.DMask);
1035 unsigned MinMask = std::min(CI.DMask, Paired.DMask);
1041 if ((1u << AllowedBitsForMin) <= MinMask)
1048 unsigned ComponentCount,
1050 if (ComponentCount > 4)
1069 return NewFormatInfo->
Format;
1082bool SILoadStoreOptimizer::offsetsCanBeCombined(CombineInfo &CI,
1083 const GCNSubtarget &STI,
1084 CombineInfo &Paired,
1086 assert(CI.InstClass != MIMG);
1090 if (CI.Offset == Paired.Offset)
1093 if (CI.GDS != Paired.GDS)
1097 if ((CI.Offset % CI.EltSize != 0) || (Paired.Offset % CI.EltSize != 0))
1100 if (CI.InstClass == TBUFFER_LOAD || CI.InstClass == TBUFFER_STORE) {
1102 const llvm::AMDGPU::GcnBufferFormatInfo *Info0 =
1104 const llvm::AMDGPU::GcnBufferFormatInfo *Info1 =
1116 unsigned NumCombinedComponents = CI.Width + Paired.Width;
1117 if (NumCombinedComponents == 3 && CI.EltSize <= 2)
1118 NumCombinedComponents = 4;
1126 unsigned ElemIndex0 = CI.Offset / CI.EltSize;
1127 unsigned ElemIndex1 = Paired.Offset / Paired.EltSize;
1128 if (ElemIndex0 + CI.Width != ElemIndex1 &&
1129 ElemIndex1 + Paired.Width != ElemIndex0)
1135 unsigned MergedBytes = CI.EltSize * NumCombinedComponents;
1136 unsigned RequiredAlign = std::min(MergedBytes, 4u);
1137 unsigned MinOff = std::min(CI.Offset, Paired.Offset);
1138 if (MinOff % RequiredAlign != 0)
1144 uint32_t EltOffset0 = CI.Offset / CI.EltSize;
1145 uint32_t EltOffset1 = Paired.Offset / CI.EltSize;
1150 if ((CI.InstClass != DS_READ) && (CI.InstClass != DS_WRITE)) {
1151 if (EltOffset0 + CI.Width != EltOffset1 &&
1152 EltOffset1 + Paired.Width != EltOffset0)
1158 if (CI.InstClass == S_LOAD_IMM || CI.InstClass == S_BUFFER_LOAD_IMM ||
1159 CI.InstClass == S_BUFFER_LOAD_SGPR_IMM) {
1165 if (CI.Width != Paired.Width &&
1166 (CI.Width < Paired.Width) == (CI.Offset < Paired.Offset))
1174 if ((EltOffset0 % 64 == 0) && (EltOffset1 % 64) == 0 &&
1177 CI.Offset = EltOffset0 / 64;
1178 Paired.Offset = EltOffset1 / 64;
1187 CI.Offset = EltOffset0;
1188 Paired.Offset = EltOffset1;
1194 uint32_t Min = std::min(EltOffset0, EltOffset1);
1195 uint32_t
Max = std::max(EltOffset0, EltOffset1);
1198 if (((Max - Min) & ~Mask) == 0) {
1207 CI.BaseOff = BaseOff * CI.EltSize;
1208 CI.Offset = (EltOffset0 - BaseOff) / 64;
1209 Paired.Offset = (EltOffset1 - BaseOff) / 64;
1221 CI.BaseOff = BaseOff * CI.EltSize;
1222 CI.Offset = EltOffset0 - BaseOff;
1223 Paired.Offset = EltOffset1 - BaseOff;
1231bool SILoadStoreOptimizer::widthsFit(
const GCNSubtarget &STM,
1232 const CombineInfo &CI,
1233 const CombineInfo &Paired) {
1234 const unsigned Width = (CI.Width + Paired.Width);
1235 switch (CI.InstClass) {
1238 case S_BUFFER_LOAD_IMM:
1239 case S_BUFFER_LOAD_SGPR_IMM:
1249 return STM.hasScalarDwordx3Loads();
1255SILoadStoreOptimizer::getDataRegClass(
const MachineInstr &
MI)
const {
1256 if (
const auto *Dst =
TII->getNamedOperand(
MI, AMDGPU::OpName::vdst)) {
1257 return TRI->getRegClassForReg(*MRI, Dst->getReg());
1259 if (
const auto *Src =
TII->getNamedOperand(
MI, AMDGPU::OpName::vdata)) {
1260 return TRI->getRegClassForReg(*MRI, Src->getReg());
1262 if (
const auto *Src =
TII->getNamedOperand(
MI, AMDGPU::OpName::data0)) {
1263 return TRI->getRegClassForReg(*MRI, Src->getReg());
1265 if (
const auto *Dst =
TII->getNamedOperand(
MI, AMDGPU::OpName::sdst)) {
1266 return TRI->getRegClassForReg(*MRI, Dst->getReg());
1268 if (
const auto *Src =
TII->getNamedOperand(
MI, AMDGPU::OpName::sdata)) {
1269 return TRI->getRegClassForReg(*MRI, Src->getReg());
1276SILoadStoreOptimizer::CombineInfo *
1277SILoadStoreOptimizer::checkAndPrepareMerge(CombineInfo &CI,
1278 CombineInfo &Paired) {
1281 if (CI.InstClass == UNKNOWN || Paired.InstClass == UNKNOWN)
1283 assert(CI.InstClass == Paired.InstClass);
1285 if (getInstSubclass(CI.I->getOpcode(), *
TII) !=
1286 getInstSubclass(Paired.I->getOpcode(), *
TII))
1291 if (CI.InstClass == MIMG) {
1292 if (!dmasksCanBeCombined(CI, *
TII, Paired))
1295 if (!widthsFit(*STM, CI, Paired) || !offsetsCanBeCombined(CI, *STM, Paired))
1299 DenseSet<Register> RegDefs;
1300 DenseSet<Register> RegUses;
1302 if (CI.I->mayLoad()) {
1306 if (!canSwapInstructions(RegDefs, RegUses, *Paired.I, *
MBBI))
1314 if (!canSwapInstructions(RegDefs, RegUses, *CI.I, *
MBBI))
1324 if (CI.InstClass == DS_READ || CI.InstClass == DS_WRITE) {
1325 if (STM->hasNeedsAligned2addrDS() &&
1326 (CI.I->memoperands_empty() ||
1327 (*CI.I->memoperands_begin())->getAlign().value() < CI.Width * 4))
1329 offsetsCanBeCombined(CI, *STM, Paired,
true);
1332 if (CI.InstClass == DS_WRITE) {
1340 const MachineOperand *Data0 =
1341 TII->getNamedOperand(*CI.I, AMDGPU::OpName::data0);
1342 const MachineOperand *Data1 =
1343 TII->getNamedOperand(*Paired.I, AMDGPU::OpName::data0);
1345 const MCInstrDesc &Write2Opc =
TII->get(getWrite2Opcode(CI));
1346 int Data0Idx = AMDGPU::getNamedOperandIdx(Write2Opc.
getOpcode(),
1347 AMDGPU::OpName::data0);
1348 int Data1Idx = AMDGPU::getNamedOperandIdx(Write2Opc.
getOpcode(),
1349 AMDGPU::OpName::data1);
1355 if (
unsigned SubReg = Data0->
getSubReg()) {
1360 if (
unsigned SubReg = Data1->
getSubReg()) {
1378void SILoadStoreOptimizer::copyToDestRegs(
1379 CombineInfo &CI, CombineInfo &Paired,
1381 AMDGPU::OpName OpName,
Register DestReg)
const {
1382 MachineBasicBlock *
MBB = CI.I->getParent();
1384 auto [SubRegIdx0, SubRegIdx1] = getSubRegIdxs(CI, Paired);
1387 const MCInstrDesc &CopyDesc =
TII->get(TargetOpcode::COPY);
1388 auto *Dest0 =
TII->getNamedOperand(*CI.I, OpName);
1389 auto *Dest1 =
TII->getNamedOperand(*Paired.I, OpName);
1394 Dest0->setIsEarlyClobber(
false);
1395 Dest1->setIsEarlyClobber(
false);
1399 .
addReg(DestReg, {}, SubRegIdx0);
1402 .
addReg(DestReg, {}, SubRegIdx1);
1408SILoadStoreOptimizer::copyFromSrcRegs(CombineInfo &CI, CombineInfo &Paired,
1411 AMDGPU::OpName OpName)
const {
1412 MachineBasicBlock *
MBB = CI.I->getParent();
1414 auto [SubRegIdx0, SubRegIdx1] = getSubRegIdxs(CI, Paired);
1420 const auto *
Src0 =
TII->getNamedOperand(*CI.I, OpName);
1421 const auto *
Src1 =
TII->getNamedOperand(*Paired.I, OpName);
1423 BuildMI(*
MBB, InsertBefore,
DL,
TII->get(AMDGPU::REG_SEQUENCE), SrcReg)
1432unsigned SILoadStoreOptimizer::read2Opcode(
unsigned EltSize,
bool GDS)
const {
1434 return (EltSize == 4) ? AMDGPU::DS_READ2_B32 : AMDGPU::DS_READ2_B64;
1435 return (EltSize == 4) ? AMDGPU::DS_READ2_B32_gfx9 : AMDGPU::DS_READ2_B64_gfx9;
1438unsigned SILoadStoreOptimizer::read2ST64Opcode(
unsigned EltSize,
1441 return (EltSize == 4) ? AMDGPU::DS_READ2ST64_B32 : AMDGPU::DS_READ2ST64_B64;
1443 return (EltSize == 4) ? AMDGPU::DS_READ2ST64_B32_gfx9
1444 : AMDGPU::DS_READ2ST64_B64_gfx9;
1448SILoadStoreOptimizer::mergeRead2Pair(CombineInfo &CI, CombineInfo &Paired,
1450 MachineBasicBlock *
MBB = CI.I->getParent();
1454 const auto *AddrReg =
TII->getNamedOperand(*CI.I, AMDGPU::OpName::addr);
1456 unsigned NewOffset0 = std::min(CI.Offset, Paired.Offset);
1457 unsigned NewOffset1 = std::max(CI.Offset, Paired.Offset);
1458 unsigned Opc = CI.UseST64 ? read2ST64Opcode(CI.EltSize, CI.GDS)
1459 : read2Opcode(CI.EltSize, CI.GDS);
1462 (NewOffset0 != NewOffset1) &&
"Computed offset doesn't fit");
1464 const MCInstrDesc &Read2Desc =
TII->get(
Opc);
1473 unsigned BaseSubReg = AddrReg->getSubReg();
1481 TII->getAddNoCarry(*
MBB, InsertBefore,
DL, BaseReg)
1483 .addReg(AddrReg->getReg(), {}, BaseSubReg)
1488 MachineInstrBuilder Read2 =
1490 .
addReg(BaseReg, {}, BaseSubReg)
1496 copyToDestRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdst, DestReg);
1498 CI.I->eraseFromParent();
1499 Paired.I->eraseFromParent();
1505unsigned SILoadStoreOptimizer::write2Opcode(
unsigned EltSize,
bool GDS)
const {
1507 return (EltSize == 4) ? AMDGPU::DS_WRITE2_B32 : AMDGPU::DS_WRITE2_B64;
1508 return (EltSize == 4) ? AMDGPU::DS_WRITE2_B32_gfx9
1509 : AMDGPU::DS_WRITE2_B64_gfx9;
1512unsigned SILoadStoreOptimizer::write2ST64Opcode(
unsigned EltSize,
1515 return (EltSize == 4) ? AMDGPU::DS_WRITE2ST64_B32
1516 : AMDGPU::DS_WRITE2ST64_B64;
1518 return (EltSize == 4) ? AMDGPU::DS_WRITE2ST64_B32_gfx9
1519 : AMDGPU::DS_WRITE2ST64_B64_gfx9;
1522unsigned SILoadStoreOptimizer::getWrite2Opcode(
const CombineInfo &CI)
const {
1523 return CI.UseST64 ? write2ST64Opcode(CI.EltSize, CI.GDS)
1524 : write2Opcode(CI.EltSize, CI.GDS);
1528 CombineInfo &CI, CombineInfo &Paired,
1530 MachineBasicBlock *
MBB = CI.I->getParent();
1534 const MachineOperand *AddrReg =
1535 TII->getNamedOperand(*CI.I, AMDGPU::OpName::addr);
1536 const MachineOperand *Data0 =
1537 TII->getNamedOperand(*CI.I, AMDGPU::OpName::data0);
1538 const MachineOperand *Data1 =
1539 TII->getNamedOperand(*Paired.I, AMDGPU::OpName::data0);
1541 unsigned NewOffset0 = CI.Offset;
1542 unsigned NewOffset1 = Paired.Offset;
1543 unsigned Opc = getWrite2Opcode(CI);
1545 if (NewOffset0 > NewOffset1) {
1552 (NewOffset0 != NewOffset1) &&
"Computed offset doesn't fit");
1554 const MCInstrDesc &Write2Desc =
TII->get(
Opc);
1559 unsigned BaseSubReg = AddrReg->
getSubReg();
1567 TII->getAddNoCarry(*
MBB, InsertBefore,
DL, BaseReg)
1569 .addReg(AddrReg->
getReg(), {}, BaseSubReg)
1574 MachineInstrBuilder Write2 =
BuildMI(*
MBB, InsertBefore,
DL, Write2Desc)
1575 .
addReg(BaseReg, {}, BaseSubReg)
1581 .cloneMergedMemRefs({&*CI.I, &*Paired.I});
1583 CI.I->eraseFromParent();
1584 Paired.I->eraseFromParent();
1586 LLVM_DEBUG(
dbgs() <<
"Inserted write2 inst: " << *Write2 <<
'\n');
1591SILoadStoreOptimizer::mergeImagePair(CombineInfo &CI, CombineInfo &Paired,
1593 MachineBasicBlock *
MBB = CI.I->getParent();
1597 const unsigned Opcode = getNewOpcode(CI, Paired);
1602 unsigned MergedDMask = CI.DMask | Paired.DMask;
1604 AMDGPU::getNamedOperandIdx(CI.I->getOpcode(), AMDGPU::OpName::dmask);
1606 auto MIB =
BuildMI(*
MBB, InsertBefore,
DL,
TII->get(Opcode), DestReg);
1607 for (
unsigned I = 1,
E = (*CI.I).getNumOperands();
I !=
E; ++
I) {
1609 MIB.addImm(MergedDMask);
1611 MIB.add((*CI.I).getOperand(
I));
1617 assert(CI.I->hasOneMemOperand() && Paired.I->hasOneMemOperand());
1619 MachineInstr *
New = MIB.addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1621 copyToDestRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdata, DestReg);
1623 CI.I->eraseFromParent();
1624 Paired.I->eraseFromParent();
1629 CombineInfo &CI, CombineInfo &Paired,
1631 MachineBasicBlock *
MBB = CI.I->getParent();
1635 const unsigned Opcode = getNewOpcode(CI, Paired);
1640 unsigned MergedOffset = std::min(CI.Offset, Paired.Offset);
1645 assert(CI.I->hasOneMemOperand() && Paired.I->hasOneMemOperand());
1647 MachineInstrBuilder
New =
1649 .
add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::sbase));
1650 if (CI.InstClass == S_BUFFER_LOAD_SGPR_IMM)
1651 New.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::soffset));
1652 New.addImm(MergedOffset);
1653 New.addImm(CI.CPol).addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1655 copyToDestRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::sdst, DestReg);
1657 CI.I->eraseFromParent();
1658 Paired.I->eraseFromParent();
1663 CombineInfo &CI, CombineInfo &Paired,
1665 MachineBasicBlock *
MBB = CI.I->getParent();
1670 const unsigned Opcode = getNewOpcode(CI, Paired);
1676 unsigned MergedOffset = std::min(CI.Offset, Paired.Offset);
1678 auto MIB =
BuildMI(*
MBB, InsertBefore,
DL,
TII->get(Opcode), DestReg);
1680 AddressRegs Regs = getRegs(Opcode, *
TII);
1683 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr));
1688 assert(CI.I->hasOneMemOperand() && Paired.I->hasOneMemOperand());
1691 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::srsrc))
1692 .add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::soffset))
1693 .addImm(MergedOffset)
1696 .addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1698 copyToDestRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdata, DestReg);
1700 CI.I->eraseFromParent();
1701 Paired.I->eraseFromParent();
1706 CombineInfo &CI, CombineInfo &Paired,
1708 MachineBasicBlock *
MBB = CI.I->getParent();
1713 const unsigned Opcode = getNewOpcode(CI, Paired);
1719 unsigned MergedOffset = std::min(CI.Offset, Paired.Offset);
1721 auto MIB =
BuildMI(*
MBB, InsertBefore,
DL,
TII->get(Opcode), DestReg);
1723 AddressRegs Regs = getRegs(Opcode, *
TII);
1726 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr));
1731 unsigned NumCombinedComponents = CI.Width + Paired.Width;
1732 if (NumCombinedComponents == 3 && CI.EltSize <= 2)
1733 NumCombinedComponents = 4;
1734 unsigned JoinedFormat =
1740 assert(CI.I->hasOneMemOperand() && Paired.I->hasOneMemOperand());
1743 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::srsrc))
1744 .add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::soffset))
1745 .addImm(MergedOffset)
1746 .addImm(JoinedFormat)
1749 .addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1751 copyToDestRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdata, DestReg);
1753 CI.I->eraseFromParent();
1754 Paired.I->eraseFromParent();
1759 CombineInfo &CI, CombineInfo &Paired,
1761 MachineBasicBlock *
MBB = CI.I->getParent();
1765 const unsigned Opcode = getNewOpcode(CI, Paired);
1768 copyFromSrcRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdata);
1772 AddressRegs Regs = getRegs(Opcode, *
TII);
1775 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr));
1780 unsigned NumCombinedComponents = CI.Width + Paired.Width;
1781 if (NumCombinedComponents == 3 && CI.EltSize <= 2)
1782 NumCombinedComponents = 4;
1783 unsigned JoinedFormat =
1789 assert(CI.I->hasOneMemOperand() && Paired.I->hasOneMemOperand());
1792 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::srsrc))
1793 .add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::soffset))
1794 .addImm(std::min(CI.Offset, Paired.Offset))
1795 .addImm(JoinedFormat)
1798 .addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1800 CI.I->eraseFromParent();
1801 Paired.I->eraseFromParent();
1806 CombineInfo &CI, CombineInfo &Paired,
1808 MachineBasicBlock *
MBB = CI.I->getParent();
1813 const unsigned Opcode = getNewOpcode(CI, Paired);
1818 auto MIB =
BuildMI(*
MBB, InsertBefore,
DL,
TII->get(Opcode), DestReg);
1820 if (
auto *SAddr =
TII->getNamedOperand(*CI.I, AMDGPU::OpName::saddr))
1824 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr))
1825 .addImm(std::min(CI.Offset, Paired.Offset))
1827 .addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1829 copyToDestRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdst, DestReg);
1831 CI.I->eraseFromParent();
1832 Paired.I->eraseFromParent();
1837 CombineInfo &CI, CombineInfo &Paired,
1839 MachineBasicBlock *
MBB = CI.I->getParent();
1844 const unsigned Opcode = getNewOpcode(CI, Paired);
1847 copyFromSrcRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdata);
1850 .
add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr))
1853 if (
auto *SAddr =
TII->getNamedOperand(*CI.I, AMDGPU::OpName::saddr))
1857 MIB.addImm(std::min(CI.Offset, Paired.Offset))
1859 .addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1861 CI.I->eraseFromParent();
1862 Paired.I->eraseFromParent();
1871 (MMOs.
size() != 1 || MMOs[0]->
getAlign().value() < Width * 4);
1874unsigned SILoadStoreOptimizer::getNewOpcode(
const CombineInfo &CI,
1875 const CombineInfo &Paired) {
1876 const unsigned Width = CI.Width + Paired.Width;
1877 const CombineInfo &Leading = Paired < CI ? Paired : CI;
1880 const bool NeedsConstrainedOpc =
1883 switch (getCommonInstClass(CI, Paired)) {
1885 assert(CI.InstClass == BUFFER_LOAD || CI.InstClass == BUFFER_STORE);
1896 case S_BUFFER_LOAD_IMM: {
1901 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM_ec
1902 : AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM;
1904 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM_ec
1905 : AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM;
1907 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM_ec
1908 : AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM;
1910 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM_ec
1911 : AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM;
1914 case S_BUFFER_LOAD_SGPR_IMM: {
1919 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM_ec
1920 : AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM;
1922 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM_ec
1923 : AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM;
1925 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM_ec
1926 : AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM;
1928 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM_ec
1929 : AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM;
1937 return NeedsConstrainedOpc ? AMDGPU::S_LOAD_DWORDX2_IMM_ec
1938 : AMDGPU::S_LOAD_DWORDX2_IMM;
1940 return NeedsConstrainedOpc ? AMDGPU::S_LOAD_DWORDX3_IMM_ec
1941 : AMDGPU::S_LOAD_DWORDX3_IMM;
1943 return NeedsConstrainedOpc ? AMDGPU::S_LOAD_DWORDX4_IMM_ec
1944 : AMDGPU::S_LOAD_DWORDX4_IMM;
1946 return NeedsConstrainedOpc ? AMDGPU::S_LOAD_DWORDX8_IMM_ec
1947 : AMDGPU::S_LOAD_DWORDX8_IMM;
1955 return AMDGPU::GLOBAL_LOAD_DWORDX2;
1957 return AMDGPU::GLOBAL_LOAD_DWORDX3;
1959 return AMDGPU::GLOBAL_LOAD_DWORDX4;
1961 case GLOBAL_LOAD_SADDR:
1966 return AMDGPU::GLOBAL_LOAD_DWORDX2_SADDR;
1968 return AMDGPU::GLOBAL_LOAD_DWORDX3_SADDR;
1970 return AMDGPU::GLOBAL_LOAD_DWORDX4_SADDR;
1977 return AMDGPU::GLOBAL_STORE_DWORDX2;
1979 return AMDGPU::GLOBAL_STORE_DWORDX3;
1981 return AMDGPU::GLOBAL_STORE_DWORDX4;
1983 case GLOBAL_STORE_SADDR:
1988 return AMDGPU::GLOBAL_STORE_DWORDX2_SADDR;
1990 return AMDGPU::GLOBAL_STORE_DWORDX3_SADDR;
1992 return AMDGPU::GLOBAL_STORE_DWORDX4_SADDR;
1999 return AMDGPU::FLAT_LOAD_DWORDX2;
2001 return AMDGPU::FLAT_LOAD_DWORDX3;
2003 return AMDGPU::FLAT_LOAD_DWORDX4;
2010 return AMDGPU::FLAT_STORE_DWORDX2;
2012 return AMDGPU::FLAT_STORE_DWORDX3;
2014 return AMDGPU::FLAT_STORE_DWORDX4;
2016 case FLAT_LOAD_SADDR:
2021 return AMDGPU::FLAT_LOAD_DWORDX2_SADDR;
2023 return AMDGPU::FLAT_LOAD_DWORDX3_SADDR;
2025 return AMDGPU::FLAT_LOAD_DWORDX4_SADDR;
2027 case FLAT_STORE_SADDR:
2032 return AMDGPU::FLAT_STORE_DWORDX2_SADDR;
2034 return AMDGPU::FLAT_STORE_DWORDX3_SADDR;
2036 return AMDGPU::FLAT_STORE_DWORDX4_SADDR;
2045std::pair<unsigned, unsigned>
2046SILoadStoreOptimizer::getSubRegIdxs(
const CombineInfo &CI,
2047 const CombineInfo &Paired) {
2048 assert((CI.InstClass != MIMG ||
2050 CI.Width + Paired.Width)) &&
2056 static const unsigned Idxs[5][4] = {
2057 {AMDGPU::sub0, AMDGPU::sub0_sub1, AMDGPU::sub0_sub1_sub2, AMDGPU::sub0_sub1_sub2_sub3},
2058 {AMDGPU::sub1, AMDGPU::sub1_sub2, AMDGPU::sub1_sub2_sub3, AMDGPU::sub1_sub2_sub3_sub4},
2059 {AMDGPU::sub2, AMDGPU::sub2_sub3, AMDGPU::sub2_sub3_sub4, AMDGPU::sub2_sub3_sub4_sub5},
2060 {AMDGPU::sub3, AMDGPU::sub3_sub4, AMDGPU::sub3_sub4_sub5, AMDGPU::sub3_sub4_sub5_sub6},
2061 {AMDGPU::sub4, AMDGPU::sub4_sub5, AMDGPU::sub4_sub5_sub6, AMDGPU::sub4_sub5_sub6_sub7},
2064 assert(CI.Width >= 1 && CI.Width <= 4);
2065 assert(Paired.Width >= 1 && Paired.Width <= 4);
2068 Idx1 = Idxs[0][Paired.Width - 1];
2069 Idx0 = Idxs[Paired.Width][CI.Width - 1];
2071 Idx0 = Idxs[0][CI.Width - 1];
2072 Idx1 = Idxs[CI.Width][Paired.Width - 1];
2075 return {Idx0, Idx1};
2079SILoadStoreOptimizer::getTargetRegisterClass(
const CombineInfo &CI,
2080 const CombineInfo &Paired)
const {
2081 if (CI.InstClass == S_BUFFER_LOAD_IMM ||
2082 CI.InstClass == S_BUFFER_LOAD_SGPR_IMM || CI.InstClass == S_LOAD_IMM) {
2083 switch (CI.Width + Paired.Width) {
2087 return &AMDGPU::SReg_64_XEXECRegClass;
2089 return &AMDGPU::SGPR_96RegClass;
2091 return &AMDGPU::SGPR_128RegClass;
2093 return &AMDGPU::SGPR_256RegClass;
2095 return &AMDGPU::SGPR_512RegClass;
2101 unsigned BitWidth = 32 * (CI.Width + Paired.Width);
2102 return TRI->isAGPRClass(getDataRegClass(*CI.I))
2108 CombineInfo &CI, CombineInfo &Paired,
2110 MachineBasicBlock *
MBB = CI.I->getParent();
2114 const unsigned Opcode = getNewOpcode(CI, Paired);
2117 copyFromSrcRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdata);
2121 AddressRegs Regs = getRegs(Opcode, *
TII);
2124 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr));
2130 assert(CI.I->hasOneMemOperand() && Paired.I->hasOneMemOperand());
2133 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::srsrc))
2134 .add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::soffset))
2135 .addImm(std::min(CI.Offset, Paired.Offset))
2138 .addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
2140 CI.I->eraseFromParent();
2141 Paired.I->eraseFromParent();
2146SILoadStoreOptimizer::createRegOrImm(int32_t Val, MachineInstr &
MI)
const {
2147 APInt
V(32, Val,
true);
2148 if (
TII->isInlineConstant(V))
2153 BuildMI(*
MI.getParent(),
MI.getIterator(),
MI.getDebugLoc(),
2154 TII->get(AMDGPU::S_MOV_B32),
Reg)
2162Register SILoadStoreOptimizer::computeBase(MachineInstr &
MI,
2163 const MemAddress &Addr)
const {
2171 if (Addr.Base.UseV64Pattern) {
2173 TII->getRegClass(
TII->get(AMDGPU::V_ADD_U64_e64), 0));
2177 MachineInstr *MovOffset =
2181 MachineInstr *
Add64 =
2195 assert((
TRI->getRegSizeInBits(Addr.Base.LoReg, *MRI) == 32 ||
2196 Addr.Base.LoSubReg) &&
2197 "Expected 32-bit Base-Register-Low!!");
2199 assert((
TRI->getRegSizeInBits(Addr.Base.HiReg, *MRI) == 32 ||
2200 Addr.Base.HiSubReg) &&
2201 "Expected 32-bit Base-Register-Hi!!");
2203 MachineOperand OffsetLo = createRegOrImm(
static_cast<int32_t
>(Addr.Offset),
MI);
2204 MachineOperand OffsetHi =
2205 createRegOrImm(
static_cast<int32_t
>(Addr.Offset >> 32),
MI);
2207 const auto *CarryRC =
TRI->getWaveMaskRegClass();
2213 MachineInstr *LoHalf =
2215 .
addReg(CarryReg, RegState::Define)
2216 .
addReg(Addr.Base.LoReg, {}, Addr.Base.LoSubReg)
2220 MachineInstr *HiHalf =
2222 .
addReg(DeadCarryReg, RegState::Define | RegState::Dead)
2223 .
addReg(Addr.Base.HiReg, {}, Addr.Base.HiSubReg)
2229 MachineInstr *FullBase =
2240 dbgs() <<
" " << *HiHalf <<
"\n";
2241 dbgs() <<
" " << *FullBase <<
"\n\n";);
2247void SILoadStoreOptimizer::updateBaseAndOffset(MachineInstr &
MI,
2249 int32_t NewOffset)
const {
2250 auto *
Base =
TII->getNamedOperand(
MI, AMDGPU::OpName::vaddr);
2251 Base->setReg(NewBase);
2252 Base->setIsKill(
false);
2253 TII->getNamedOperand(
MI, AMDGPU::OpName::offset)->setImm(NewOffset);
2259bool SILoadStoreOptimizer::processBaseWithConstOffset64(
2260 MachineInstr *AddDef,
const MachineOperand &
Base, MemAddress &Addr)
const {
2264 MachineOperand *
Src0 =
TII->getNamedOperand(*AddDef, AMDGPU::OpName::src0);
2265 MachineOperand *
Src1 =
TII->getNamedOperand(*AddDef, AMDGPU::OpName::src1);
2267 const MachineOperand *BaseOp =
nullptr;
2269 auto Offset =
TII->getImmOrMaterializedImm(*MRI, *Src1);
2280 Addr.Base.LoReg = BaseOp->
getReg();
2281 Addr.Base.UseV64Pattern =
true;
2299void SILoadStoreOptimizer::processBaseWithConstOffset(
const MachineOperand &
Base,
2300 MemAddress &Addr)
const {
2309 if (
Def->getOpcode() == AMDGPU::V_ADD_U64_e64) {
2310 if (processBaseWithConstOffset64(Def,
Base, Addr))
2315 if (
Def->getOpcode() != AMDGPU::REG_SEQUENCE ||
Def->getNumOperands() != 5)
2318 MachineOperand BaseLo =
Def->getOperand(1);
2319 MachineOperand BaseHi =
Def->getOperand(3);
2326 if (!BaseLoDef || BaseLoDef->
getOpcode() != AMDGPU::V_ADD_CO_U32_e64 ||
2327 !BaseHiDef || BaseHiDef->
getOpcode() != AMDGPU::V_ADDC_U32_e64)
2330 MachineOperand *
Src0 =
TII->getNamedOperand(*BaseLoDef, AMDGPU::OpName::src0);
2331 MachineOperand *
Src1 =
TII->getNamedOperand(*BaseLoDef, AMDGPU::OpName::src1);
2333 auto Offset0P =
TII->getImmOrMaterializedImm(*MRI, *Src0);
2337 if (!(Offset0P =
TII->getImmOrMaterializedImm(*MRI, *Src1)))
2342 if (!BaseLo.
isReg())
2345 Src0 =
TII->getNamedOperand(*BaseHiDef, AMDGPU::OpName::src0);
2346 Src1 =
TII->getNamedOperand(*BaseHiDef, AMDGPU::OpName::src1);
2351 if (!
Src1->isImm() ||
Src0->isImm())
2357 if (!BaseHi.
isReg())
2360 Addr.Base.LoReg = BaseLo.
getReg();
2361 Addr.Base.HiReg = BaseHi.
getReg();
2362 Addr.Base.LoSubReg = BaseLo.
getSubReg();
2363 Addr.Base.HiSubReg = BaseHi.
getSubReg();
2364 Addr.Offset = (*Offset0P & 0x00000000ffffffff) | (Offset1 << 32);
2371void SILoadStoreOptimizer::updateAsyncLDSAddress(MachineInstr &
MI,
2372 int32_t OffsetDiff)
const {
2373 if (!
TII->usesASYNC_CNT(
MI) || OffsetDiff == 0)
2376 MachineOperand *LDSAddr =
TII->getNamedOperand(
MI, AMDGPU::OpName::vdst);
2378 LDSAddr =
TII->getNamedOperand(
MI, AMDGPU::OpName::vdata);
2393bool SILoadStoreOptimizer::promoteConstantOffsetToImm(
2395 MemInfoMap &Visited,
2396 SmallPtrSet<MachineInstr *, 4> &
AnchorList)
const {
2409 ? AMDGPU::FlatAddrSpace::FlatGlobal
2410 : AMDGPU::FlatAddrSpace::FLAT;
2411 bool AllowNegativeOffset =
2412 TII->allowNegativeFlatOffset(FlatVariant) && !
TII->usesASYNC_CNT(
MI);
2416 bool IsOffsetU16 =
TII->usesASYNC_CNT(
MI);
2423 if (
TII->getNamedOperand(
MI, AMDGPU::OpName::offset)->getImm()) {
2429 MachineOperand &
Base = *
TII->getNamedOperand(
MI, AMDGPU::OpName::vaddr);
2430 auto [It,
Inserted] = Visited.try_emplace(&
MI);
2433 processBaseWithConstOffset(
Base, MAddr);
2438 if (MAddr.Offset == 0) {
2439 LLVM_DEBUG(
dbgs() <<
" Failed to extract constant-offset or there are no"
2440 " constant offsets that can be promoted.\n";);
2446 <<
"} Offset: " << MAddr.Offset <<
"\n\n";);
2473 MachineInstr *AnchorInst =
nullptr;
2474 MemAddress AnchorAddr;
2475 uint32_t MaxDist = std::numeric_limits<uint32_t>::min();
2477 bool MIIsAnchor =
false;
2486 MachineInstr &MINext = *
MBBI;
2490 TII->getNamedOperand(MINext, AMDGPU::OpName::offset)->getImm())
2493 const MachineOperand &BaseNext =
2494 *
TII->getNamedOperand(MINext, AMDGPU::OpName::vaddr);
2495 MemAddress MAddrNext;
2496 auto [It,
Inserted] = Visited.try_emplace(&MINext);
2498 processBaseWithConstOffset(BaseNext, MAddrNext);
2499 It->second = MAddrNext;
2501 MAddrNext = It->second;
2503 if (MAddrNext.Base.LoReg != MAddr.Base.LoReg ||
2504 MAddrNext.Base.HiReg != MAddr.Base.HiReg ||
2505 MAddrNext.Base.LoSubReg != MAddr.Base.LoSubReg ||
2506 MAddrNext.Base.HiSubReg != MAddr.Base.HiSubReg)
2509 InstsWCommonBase.
emplace_back(&MINext, MAddrNext.Offset);
2511 if (AllowNegativeOffset) {
2512 int64_t Dist = MAddr.Offset - MAddrNext.Offset;
2513 TargetLoweringBase::AddrMode AM;
2517 (uint32_t)std::abs(Dist) > MaxDist) {
2518 MaxDist = std::abs(Dist);
2520 AnchorAddr = MAddrNext;
2521 AnchorInst = &MINext;
2529 if (!AllowNegativeOffset && !InstsWCommonBase.
empty()) {
2530 for (
auto &[Inst,
Offset] : InstsWCommonBase) {
2531 int64_t Dist = MAddr.Offset -
Offset;
2532 TargetLoweringBase::AddrMode AM;
2537 (!AnchorInst ||
Offset < AnchorAddr.Offset)) {
2538 AnchorAddr = Visited[Inst];
2547 LLVM_DEBUG(
dbgs() <<
" Anchor-Inst(with max-distance from Offset): ";
2548 AnchorInst->
dump());
2550 << AnchorAddr.Offset <<
"\n\n");
2555 int32_t OffsetDiff = MAddr.Offset - AnchorAddr.Offset;
2556 updateBaseAndOffset(
MI,
Base, OffsetDiff);
2557 updateAsyncLDSAddress(
MI, OffsetDiff);
2560 for (
auto [OtherMI, OtherOffset] : InstsWCommonBase) {
2561 TargetLoweringBase::AddrMode AM;
2563 AM.
BaseOffs = OtherOffset - AnchorAddr.Offset;
2566 (AllowNegativeOffset || AM.
BaseOffs >= 0) &&
2570 int32_t OtherOffsetDiff = OtherOffset - AnchorAddr.Offset;
2571 updateBaseAndOffset(*OtherMI,
Base, OtherOffsetDiff);
2572 updateAsyncLDSAddress(*OtherMI, OtherOffsetDiff);
2581 LLVM_DEBUG(
dbgs() <<
" MI is anchor (smallest offset); promoting "
2582 "candidates relative to MI's base.\n");
2585 bool AnyPromoted =
false;
2587 for (
auto [OtherMI, OtherOffset] : InstsWCommonBase) {
2588 int64_t Dist = OtherOffset - MAddr.Offset;
2589 TargetLoweringBase::AddrMode AM;
2596 updateBaseAndOffset(*OtherMI,
Base, Dist);
2597 updateAsyncLDSAddress(*OtherMI, Dist);
2604 TII->getNamedOperand(
MI, AMDGPU::OpName::vaddr)->setIsKill(
false);
2613void SILoadStoreOptimizer::addInstToMergeableList(
const CombineInfo &CI,
2614 std::list<std::list<CombineInfo> > &MergeableInsts)
const {
2615 for (std::list<CombineInfo> &AddrList : MergeableInsts) {
2616 if (AddrList.front().InstClass == CI.InstClass &&
2617 AddrList.front().hasSameBaseAddress(CI)) {
2618 AddrList.emplace_back(CI);
2624 MergeableInsts.emplace_back(1, CI);
2627std::pair<MachineBasicBlock::iterator, bool>
2628SILoadStoreOptimizer::collectMergeableInsts(
2630 MemInfoMap &Visited, SmallPtrSet<MachineInstr *, 4> &
AnchorList,
2631 std::list<std::list<CombineInfo>> &MergeableInsts)
const {
2637 for (; BlockI !=
End; ++BlockI) {
2638 MachineInstr &
MI = *BlockI;
2642 if (promoteConstantOffsetToImm(
MI, Visited,
AnchorList))
2647 if (
MI.hasOrderedMemoryRef() ||
MI.hasUnmodeledSideEffects()) {
2655 const InstClassEnum InstClass = getInstClass(
MI.getOpcode(), *
TII);
2656 if (InstClass == UNKNOWN)
2661 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::swz);
2662 if (Swizzled != -1 &&
MI.getOperand(Swizzled).getImm())
2665 if (InstClass == TBUFFER_LOAD || InstClass == TBUFFER_STORE) {
2668 dbgs() <<
"Skip tbuffer combine: relaxed OOB mode not enabled\n");
2672 const MachineOperand *Fmt =
2673 TII->getNamedOperand(
MI, AMDGPU::OpName::format);
2678 }
else if (InstClass == MIMG) {
2681 const auto *TFEOp =
TII->getNamedOperand(
MI, AMDGPU::OpName::tfe);
2682 if (TFEOp && TFEOp->getImm())
2685 const auto *LWEOp =
TII->getNamedOperand(
MI, AMDGPU::OpName::lwe);
2686 if (LWEOp && LWEOp->getImm())
2691 CI.setMI(
MI, *
this);
2694 if (!CI.hasMergeableAddress(*MRI))
2709 for (std::list<std::list<CombineInfo>>::iterator
I = MergeableInsts.begin(),
2710 E = MergeableInsts.end();
I !=
E;) {
2712 std::list<CombineInfo> &MergeList = *
I;
2713 if (MergeList.size() <= 1) {
2717 I = MergeableInsts.erase(
I);
2725 [] (
const CombineInfo &
A,
const CombineInfo &
B) {
2726 return A.Offset <
B.Offset;
2737bool SILoadStoreOptimizer::optimizeBlock(
2738 std::list<std::list<CombineInfo> > &MergeableInsts) {
2741 for (std::list<std::list<CombineInfo>>::iterator
I = MergeableInsts.begin(),
2742 E = MergeableInsts.end();
I !=
E;) {
2743 std::list<CombineInfo> &MergeList = *
I;
2745 bool OptimizeListAgain =
false;
2746 if (!optimizeInstsWithSameBaseAddr(MergeList, OptimizeListAgain)) {
2750 I = MergeableInsts.erase(
I);
2758 if (!OptimizeListAgain) {
2759 I = MergeableInsts.erase(
I);
2762 OptimizeAgain =
true;
2768SILoadStoreOptimizer::optimizeInstsWithSameBaseAddr(
2769 std::list<CombineInfo> &MergeList,
2770 bool &OptimizeListAgain) {
2771 if (MergeList.empty())
2776 for (
auto I = MergeList.begin(),
Next = std::next(
I);
Next != MergeList.end();
2777 Next = std::next(
I)) {
2782 if ((*First).Order > (*Second).Order)
2784 CombineInfo &CI = *
First;
2785 CombineInfo &Paired = *Second;
2787 CombineInfo *Where = checkAndPrepareMerge(CI, Paired);
2795 LLVM_DEBUG(
dbgs() <<
"Merging: " << *CI.I <<
" with: " << *Paired.I);
2798 switch (CI.InstClass) {
2803 NewMI = mergeRead2Pair(CI, Paired, Where->I);
2806 NewMI = mergeWrite2Pair(CI, Paired, Where->I);
2808 case S_BUFFER_LOAD_IMM:
2809 case S_BUFFER_LOAD_SGPR_IMM:
2811 NewMI = mergeSMemLoadImmPair(CI, Paired, Where->I);
2812 OptimizeListAgain |= CI.Width + Paired.Width < 8;
2815 NewMI = mergeBufferLoadPair(CI, Paired, Where->I);
2816 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2819 NewMI = mergeBufferStorePair(CI, Paired, Where->I);
2820 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2823 NewMI = mergeImagePair(CI, Paired, Where->I);
2824 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2827 NewMI = mergeTBufferLoadPair(CI, Paired, Where->I);
2828 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2831 NewMI = mergeTBufferStorePair(CI, Paired, Where->I);
2832 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2835 case FLAT_LOAD_SADDR:
2837 case GLOBAL_LOAD_SADDR:
2838 NewMI = mergeFlatLoadPair(CI, Paired, Where->I);
2839 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2842 case FLAT_STORE_SADDR:
2844 case GLOBAL_STORE_SADDR:
2845 NewMI = mergeFlatStorePair(CI, Paired, Where->I);
2846 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2849 CI.setMI(NewMI, *
this);
2850 CI.Order = Where->Order;
2854 MergeList.erase(Second);
2860bool SILoadStoreOptimizerLegacy::runOnMachineFunction(
MachineFunction &MF) {
2863 return SILoadStoreOptimizer(
2864 &getAnalysis<AAResultsWrapperPass>().getAAResults())
2888 for (MachineBasicBlock &
MBB : MF) {
2892 bool CollectModified;
2893 std::list<std::list<CombineInfo>> MergeableInsts;
2897 std::tie(SectionEnd, CollectModified) =
2903 OptimizeAgain =
false;
2905 }
while (OptimizeAgain);
2927 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)
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()
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 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,...
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 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)
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.
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).
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
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.