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;
123 int AddrIdx[MaxAddressRegs];
125 unsigned NumAddresses;
128 bool hasSameBaseAddress(
const CombineInfo &CI) {
129 if (NumAddresses != CI.NumAddresses)
133 for (
unsigned i = 0; i < NumAddresses; i++) {
136 if (AddrReg[i]->isImm() || AddrRegNext.
isImm()) {
137 if (AddrReg[i]->isImm() != AddrRegNext.
isImm() ||
155 for (
unsigned i = 0; i < NumAddresses; ++i) {
164 if (!AddrOp->
isReg())
170 AddrOp->
getReg() != AMDGPU::SGPR_NULL)
189 struct BaseRegisters {
193 unsigned LoSubReg = 0;
194 unsigned HiSubReg = 0;
196 bool UseV64Pattern =
false;
218 static bool dmasksCanBeCombined(
const CombineInfo &CI,
220 const CombineInfo &Paired);
221 static bool offsetsCanBeCombined(CombineInfo &CI,
const GCNSubtarget &STI,
222 CombineInfo &Paired,
bool Modify =
false);
223 static bool widthsFit(
const GCNSubtarget &STI,
const CombineInfo &CI,
224 const CombineInfo &Paired);
225 unsigned getNewOpcode(
const CombineInfo &CI,
const CombineInfo &Paired);
226 static std::pair<unsigned, unsigned> getSubRegIdxs(
const CombineInfo &CI,
227 const CombineInfo &Paired);
229 getTargetRegisterClass(
const CombineInfo &CI,
230 const CombineInfo &Paired)
const;
233 CombineInfo *checkAndPrepareMerge(CombineInfo &CI, CombineInfo &Paired);
235 void copyToDestRegs(CombineInfo &CI, CombineInfo &Paired,
239 Register copyFromSrcRegs(CombineInfo &CI, CombineInfo &Paired,
243 unsigned read2Opcode(
unsigned EltSize)
const;
244 unsigned read2ST64Opcode(
unsigned EltSize)
const;
246 mergeRead2Pair(CombineInfo &CI, CombineInfo &Paired,
249 unsigned write2Opcode(
unsigned EltSize)
const;
250 unsigned write2ST64Opcode(
unsigned EltSize)
const;
251 unsigned getWrite2Opcode(
const CombineInfo &CI)
const;
254 mergeWrite2Pair(CombineInfo &CI, CombineInfo &Paired,
257 mergeImagePair(CombineInfo &CI, CombineInfo &Paired,
260 mergeSMemLoadImmPair(CombineInfo &CI, CombineInfo &Paired,
263 mergeBufferLoadPair(CombineInfo &CI, CombineInfo &Paired,
266 mergeBufferStorePair(CombineInfo &CI, CombineInfo &Paired,
269 mergeTBufferLoadPair(CombineInfo &CI, CombineInfo &Paired,
272 mergeTBufferStorePair(CombineInfo &CI, CombineInfo &Paired,
275 mergeFlatLoadPair(CombineInfo &CI, CombineInfo &Paired,
278 mergeFlatStorePair(CombineInfo &CI, CombineInfo &Paired,
282 int32_t NewOffset)
const;
283 void updateAsyncLDSAddress(
MachineInstr &
MI, int32_t OffsetDiff)
const;
288 MemAddress &Addr)
const;
297 std::list<std::list<CombineInfo> > &MergeableInsts)
const;
302 std::list<std::list<CombineInfo>> &MergeableInsts)
const;
305 const CombineInfo &Paired);
307 static InstClassEnum getCommonInstClass(
const CombineInfo &CI,
308 const CombineInfo &Paired);
310 bool optimizeInstsWithSameBaseAddr(std::list<CombineInfo> &MergeList,
311 bool &OptimizeListAgain);
312 bool optimizeBlock(std::list<std::list<CombineInfo> > &MergeableInsts);
327 StringRef getPassName()
const override {
return "SI Load Store Optimizer"; }
342 const unsigned Opc =
MI.getOpcode();
348 if (
TII.isImage(
MI)) {
350 TII.getNamedOperand(
MI, AMDGPU::OpName::dmask)->getImm();
358 case AMDGPU::S_BUFFER_LOAD_DWORD_IMM:
359 case AMDGPU::S_BUFFER_LOAD_DWORD_SGPR_IMM:
360 case AMDGPU::S_LOAD_DWORD_IMM:
361 case AMDGPU::GLOBAL_LOAD_DWORD:
362 case AMDGPU::GLOBAL_LOAD_DWORD_SADDR:
363 case AMDGPU::GLOBAL_STORE_DWORD:
364 case AMDGPU::GLOBAL_STORE_DWORD_SADDR:
365 case AMDGPU::FLAT_LOAD_DWORD:
366 case AMDGPU::FLAT_STORE_DWORD:
367 case AMDGPU::FLAT_LOAD_DWORD_SADDR:
368 case AMDGPU::FLAT_STORE_DWORD_SADDR:
370 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM:
371 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM:
372 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM_ec:
373 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM_ec:
374 case AMDGPU::S_LOAD_DWORDX2_IMM:
375 case AMDGPU::S_LOAD_DWORDX2_IMM_ec:
376 case AMDGPU::GLOBAL_LOAD_DWORDX2:
377 case AMDGPU::GLOBAL_LOAD_DWORDX2_SADDR:
378 case AMDGPU::GLOBAL_STORE_DWORDX2:
379 case AMDGPU::GLOBAL_STORE_DWORDX2_SADDR:
380 case AMDGPU::FLAT_LOAD_DWORDX2:
381 case AMDGPU::FLAT_STORE_DWORDX2:
382 case AMDGPU::FLAT_LOAD_DWORDX2_SADDR:
383 case AMDGPU::FLAT_STORE_DWORDX2_SADDR:
385 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM:
386 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM:
387 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM_ec:
388 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM_ec:
389 case AMDGPU::S_LOAD_DWORDX3_IMM:
390 case AMDGPU::S_LOAD_DWORDX3_IMM_ec:
391 case AMDGPU::GLOBAL_LOAD_DWORDX3:
392 case AMDGPU::GLOBAL_LOAD_DWORDX3_SADDR:
393 case AMDGPU::GLOBAL_STORE_DWORDX3:
394 case AMDGPU::GLOBAL_STORE_DWORDX3_SADDR:
395 case AMDGPU::FLAT_LOAD_DWORDX3:
396 case AMDGPU::FLAT_STORE_DWORDX3:
397 case AMDGPU::FLAT_LOAD_DWORDX3_SADDR:
398 case AMDGPU::FLAT_STORE_DWORDX3_SADDR:
400 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM:
401 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM:
402 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM_ec:
403 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM_ec:
404 case AMDGPU::S_LOAD_DWORDX4_IMM:
405 case AMDGPU::S_LOAD_DWORDX4_IMM_ec:
406 case AMDGPU::GLOBAL_LOAD_DWORDX4:
407 case AMDGPU::GLOBAL_LOAD_DWORDX4_SADDR:
408 case AMDGPU::GLOBAL_STORE_DWORDX4:
409 case AMDGPU::GLOBAL_STORE_DWORDX4_SADDR:
410 case AMDGPU::FLAT_LOAD_DWORDX4:
411 case AMDGPU::FLAT_STORE_DWORDX4:
412 case AMDGPU::FLAT_LOAD_DWORDX4_SADDR:
413 case AMDGPU::FLAT_STORE_DWORDX4_SADDR:
415 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM:
416 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM:
417 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM_ec:
418 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM_ec:
419 case AMDGPU::S_LOAD_DWORDX8_IMM:
420 case AMDGPU::S_LOAD_DWORDX8_IMM_ec:
422 case AMDGPU::DS_READ_B32:
423 case AMDGPU::DS_READ_B32_gfx9:
424 case AMDGPU::DS_WRITE_B32:
425 case AMDGPU::DS_WRITE_B32_gfx9:
427 case AMDGPU::DS_READ_B64:
428 case AMDGPU::DS_READ_B64_gfx9:
429 case AMDGPU::DS_WRITE_B64:
430 case AMDGPU::DS_WRITE_B64_gfx9:
445 case AMDGPU::BUFFER_LOAD_DWORD_BOTHEN:
446 case AMDGPU::BUFFER_LOAD_DWORD_BOTHEN_exact:
447 case AMDGPU::BUFFER_LOAD_DWORD_IDXEN:
448 case AMDGPU::BUFFER_LOAD_DWORD_IDXEN_exact:
449 case AMDGPU::BUFFER_LOAD_DWORD_OFFEN:
450 case AMDGPU::BUFFER_LOAD_DWORD_OFFEN_exact:
451 case AMDGPU::BUFFER_LOAD_DWORD_OFFSET:
452 case AMDGPU::BUFFER_LOAD_DWORD_OFFSET_exact:
453 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_BOTHEN:
454 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_BOTHEN_exact:
455 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_IDXEN:
456 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_IDXEN_exact:
457 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_OFFEN:
458 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_OFFEN_exact:
459 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_OFFSET:
460 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_OFFSET_exact:
462 case AMDGPU::BUFFER_STORE_DWORD_BOTHEN:
463 case AMDGPU::BUFFER_STORE_DWORD_BOTHEN_exact:
464 case AMDGPU::BUFFER_STORE_DWORD_IDXEN:
465 case AMDGPU::BUFFER_STORE_DWORD_IDXEN_exact:
466 case AMDGPU::BUFFER_STORE_DWORD_OFFEN:
467 case AMDGPU::BUFFER_STORE_DWORD_OFFEN_exact:
468 case AMDGPU::BUFFER_STORE_DWORD_OFFSET:
469 case AMDGPU::BUFFER_STORE_DWORD_OFFSET_exact:
470 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_BOTHEN:
471 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_BOTHEN_exact:
472 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_IDXEN:
473 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_IDXEN_exact:
474 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_OFFEN:
475 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_OFFEN_exact:
476 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_OFFSET:
477 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_OFFSET_exact:
490 if (
TII.get(
Opc).mayStore() || !
TII.get(
Opc).mayLoad() ||
499 case AMDGPU::TBUFFER_LOAD_FORMAT_X_BOTHEN:
500 case AMDGPU::TBUFFER_LOAD_FORMAT_X_BOTHEN_exact:
501 case AMDGPU::TBUFFER_LOAD_FORMAT_X_IDXEN:
502 case AMDGPU::TBUFFER_LOAD_FORMAT_X_IDXEN_exact:
503 case AMDGPU::TBUFFER_LOAD_FORMAT_X_OFFEN:
504 case AMDGPU::TBUFFER_LOAD_FORMAT_X_OFFEN_exact:
505 case AMDGPU::TBUFFER_LOAD_FORMAT_X_OFFSET:
506 case AMDGPU::TBUFFER_LOAD_FORMAT_X_OFFSET_exact:
507 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_BOTHEN:
508 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_BOTHEN_exact:
509 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_IDXEN:
510 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_IDXEN_exact:
511 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_OFFEN:
512 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_OFFEN_exact:
513 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_OFFSET:
514 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_OFFSET_exact:
516 case AMDGPU::TBUFFER_STORE_FORMAT_X_OFFEN:
517 case AMDGPU::TBUFFER_STORE_FORMAT_X_OFFEN_exact:
518 case AMDGPU::TBUFFER_STORE_FORMAT_X_OFFSET:
519 case AMDGPU::TBUFFER_STORE_FORMAT_X_OFFSET_exact:
520 case AMDGPU::TBUFFER_STORE_FORMAT_X_VBUFFER_OFFEN:
521 case AMDGPU::TBUFFER_STORE_FORMAT_X_VBUFFER_OFFEN_exact:
522 case AMDGPU::TBUFFER_STORE_FORMAT_X_VBUFFER_OFFSET:
523 case AMDGPU::TBUFFER_STORE_FORMAT_X_VBUFFER_OFFSET_exact:
524 return TBUFFER_STORE;
528 case AMDGPU::S_BUFFER_LOAD_DWORD_IMM:
529 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM:
530 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM:
531 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM:
532 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM:
533 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM_ec:
534 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM_ec:
535 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM_ec:
536 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM_ec:
537 return S_BUFFER_LOAD_IMM;
538 case AMDGPU::S_BUFFER_LOAD_DWORD_SGPR_IMM:
539 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM:
540 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM:
541 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM:
542 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM:
543 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM_ec:
544 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM_ec:
545 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM_ec:
546 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM_ec:
547 return S_BUFFER_LOAD_SGPR_IMM;
548 case AMDGPU::S_LOAD_DWORD_IMM:
549 case AMDGPU::S_LOAD_DWORDX2_IMM:
550 case AMDGPU::S_LOAD_DWORDX3_IMM:
551 case AMDGPU::S_LOAD_DWORDX4_IMM:
552 case AMDGPU::S_LOAD_DWORDX8_IMM:
553 case AMDGPU::S_LOAD_DWORDX2_IMM_ec:
554 case AMDGPU::S_LOAD_DWORDX3_IMM_ec:
555 case AMDGPU::S_LOAD_DWORDX4_IMM_ec:
556 case AMDGPU::S_LOAD_DWORDX8_IMM_ec:
558 case AMDGPU::DS_READ_B32:
559 case AMDGPU::DS_READ_B32_gfx9:
560 case AMDGPU::DS_READ_B64:
561 case AMDGPU::DS_READ_B64_gfx9:
563 case AMDGPU::DS_WRITE_B32:
564 case AMDGPU::DS_WRITE_B32_gfx9:
565 case AMDGPU::DS_WRITE_B64:
566 case AMDGPU::DS_WRITE_B64_gfx9:
568 case AMDGPU::GLOBAL_LOAD_DWORD:
569 case AMDGPU::GLOBAL_LOAD_DWORDX2:
570 case AMDGPU::GLOBAL_LOAD_DWORDX3:
571 case AMDGPU::GLOBAL_LOAD_DWORDX4:
572 case AMDGPU::FLAT_LOAD_DWORD:
573 case AMDGPU::FLAT_LOAD_DWORDX2:
574 case AMDGPU::FLAT_LOAD_DWORDX3:
575 case AMDGPU::FLAT_LOAD_DWORDX4:
577 case AMDGPU::GLOBAL_LOAD_DWORD_SADDR:
578 case AMDGPU::GLOBAL_LOAD_DWORDX2_SADDR:
579 case AMDGPU::GLOBAL_LOAD_DWORDX3_SADDR:
580 case AMDGPU::GLOBAL_LOAD_DWORDX4_SADDR:
581 return GLOBAL_LOAD_SADDR;
582 case AMDGPU::GLOBAL_STORE_DWORD:
583 case AMDGPU::GLOBAL_STORE_DWORDX2:
584 case AMDGPU::GLOBAL_STORE_DWORDX3:
585 case AMDGPU::GLOBAL_STORE_DWORDX4:
586 case AMDGPU::FLAT_STORE_DWORD:
587 case AMDGPU::FLAT_STORE_DWORDX2:
588 case AMDGPU::FLAT_STORE_DWORDX3:
589 case AMDGPU::FLAT_STORE_DWORDX4:
591 case AMDGPU::GLOBAL_STORE_DWORD_SADDR:
592 case AMDGPU::GLOBAL_STORE_DWORDX2_SADDR:
593 case AMDGPU::GLOBAL_STORE_DWORDX3_SADDR:
594 case AMDGPU::GLOBAL_STORE_DWORDX4_SADDR:
595 return GLOBAL_STORE_SADDR;
596 case AMDGPU::FLAT_LOAD_DWORD_SADDR:
597 case AMDGPU::FLAT_LOAD_DWORDX2_SADDR:
598 case AMDGPU::FLAT_LOAD_DWORDX3_SADDR:
599 case AMDGPU::FLAT_LOAD_DWORDX4_SADDR:
600 return FLAT_LOAD_SADDR;
601 case AMDGPU::FLAT_STORE_DWORD_SADDR:
602 case AMDGPU::FLAT_STORE_DWORDX2_SADDR:
603 case AMDGPU::FLAT_STORE_DWORDX3_SADDR:
604 case AMDGPU::FLAT_STORE_DWORDX4_SADDR:
605 return FLAT_STORE_SADDR;
620 return Info->BaseOpcode;
625 case AMDGPU::DS_READ_B32:
626 case AMDGPU::DS_READ_B32_gfx9:
627 case AMDGPU::DS_READ_B64:
628 case AMDGPU::DS_READ_B64_gfx9:
629 case AMDGPU::DS_WRITE_B32:
630 case AMDGPU::DS_WRITE_B32_gfx9:
631 case AMDGPU::DS_WRITE_B64:
632 case AMDGPU::DS_WRITE_B64_gfx9:
634 case AMDGPU::S_BUFFER_LOAD_DWORD_IMM:
635 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM:
636 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM:
637 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM:
638 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM:
639 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM_ec:
640 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM_ec:
641 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM_ec:
642 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM_ec:
643 return AMDGPU::S_BUFFER_LOAD_DWORD_IMM;
644 case AMDGPU::S_BUFFER_LOAD_DWORD_SGPR_IMM:
645 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM:
646 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM:
647 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM:
648 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM:
649 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM_ec:
650 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM_ec:
651 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM_ec:
652 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM_ec:
653 return AMDGPU::S_BUFFER_LOAD_DWORD_SGPR_IMM;
654 case AMDGPU::S_LOAD_DWORD_IMM:
655 case AMDGPU::S_LOAD_DWORDX2_IMM:
656 case AMDGPU::S_LOAD_DWORDX3_IMM:
657 case AMDGPU::S_LOAD_DWORDX4_IMM:
658 case AMDGPU::S_LOAD_DWORDX8_IMM:
659 case AMDGPU::S_LOAD_DWORDX2_IMM_ec:
660 case AMDGPU::S_LOAD_DWORDX3_IMM_ec:
661 case AMDGPU::S_LOAD_DWORDX4_IMM_ec:
662 case AMDGPU::S_LOAD_DWORDX8_IMM_ec:
663 return AMDGPU::S_LOAD_DWORD_IMM;
664 case AMDGPU::GLOBAL_LOAD_DWORD:
665 case AMDGPU::GLOBAL_LOAD_DWORDX2:
666 case AMDGPU::GLOBAL_LOAD_DWORDX3:
667 case AMDGPU::GLOBAL_LOAD_DWORDX4:
668 case AMDGPU::FLAT_LOAD_DWORD:
669 case AMDGPU::FLAT_LOAD_DWORDX2:
670 case AMDGPU::FLAT_LOAD_DWORDX3:
671 case AMDGPU::FLAT_LOAD_DWORDX4:
672 return AMDGPU::FLAT_LOAD_DWORD;
673 case AMDGPU::GLOBAL_LOAD_DWORD_SADDR:
674 case AMDGPU::GLOBAL_LOAD_DWORDX2_SADDR:
675 case AMDGPU::GLOBAL_LOAD_DWORDX3_SADDR:
676 case AMDGPU::GLOBAL_LOAD_DWORDX4_SADDR:
677 return AMDGPU::GLOBAL_LOAD_DWORD_SADDR;
678 case AMDGPU::GLOBAL_STORE_DWORD:
679 case AMDGPU::GLOBAL_STORE_DWORDX2:
680 case AMDGPU::GLOBAL_STORE_DWORDX3:
681 case AMDGPU::GLOBAL_STORE_DWORDX4:
682 case AMDGPU::FLAT_STORE_DWORD:
683 case AMDGPU::FLAT_STORE_DWORDX2:
684 case AMDGPU::FLAT_STORE_DWORDX3:
685 case AMDGPU::FLAT_STORE_DWORDX4:
686 return AMDGPU::FLAT_STORE_DWORD;
687 case AMDGPU::GLOBAL_STORE_DWORD_SADDR:
688 case AMDGPU::GLOBAL_STORE_DWORDX2_SADDR:
689 case AMDGPU::GLOBAL_STORE_DWORDX3_SADDR:
690 case AMDGPU::GLOBAL_STORE_DWORDX4_SADDR:
691 return AMDGPU::GLOBAL_STORE_DWORD_SADDR;
692 case AMDGPU::FLAT_LOAD_DWORD_SADDR:
693 case AMDGPU::FLAT_LOAD_DWORDX2_SADDR:
694 case AMDGPU::FLAT_LOAD_DWORDX3_SADDR:
695 case AMDGPU::FLAT_LOAD_DWORDX4_SADDR:
696 return AMDGPU::FLAT_LOAD_DWORD_SADDR;
697 case AMDGPU::FLAT_STORE_DWORD_SADDR:
698 case AMDGPU::FLAT_STORE_DWORDX2_SADDR:
699 case AMDGPU::FLAT_STORE_DWORDX3_SADDR:
700 case AMDGPU::FLAT_STORE_DWORDX4_SADDR:
701 return AMDGPU::FLAT_STORE_DWORD_SADDR;
712SILoadStoreOptimizer::getCommonInstClass(
const CombineInfo &CI,
713 const CombineInfo &Paired) {
714 assert(CI.InstClass == Paired.InstClass);
716 if ((CI.InstClass == FLAT_LOAD || CI.InstClass == FLAT_STORE) &&
718 return (CI.InstClass == FLAT_STORE) ? GLOBAL_STORE : GLOBAL_LOAD;
732 Result.SOffset =
true;
738 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
739 if (VAddr0Idx >= 0) {
740 AMDGPU::OpName RsrcName =
741 TII.isMIMG(
Opc) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
742 int RsrcIdx = AMDGPU::getNamedOperandIdx(
Opc, RsrcName);
743 Result.NumVAddrs = RsrcIdx - VAddr0Idx;
760 Result.SOffset =
true;
768 case AMDGPU::S_BUFFER_LOAD_DWORD_SGPR_IMM:
769 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM:
770 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM:
771 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM:
772 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM:
773 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM_ec:
774 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM_ec:
775 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM_ec:
776 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM_ec:
777 Result.SOffset =
true;
779 case AMDGPU::S_BUFFER_LOAD_DWORD_IMM:
780 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM:
781 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM:
782 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM:
783 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM:
784 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM_ec:
785 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM_ec:
786 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM_ec:
787 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM_ec:
788 case AMDGPU::S_LOAD_DWORD_IMM:
789 case AMDGPU::S_LOAD_DWORDX2_IMM:
790 case AMDGPU::S_LOAD_DWORDX3_IMM:
791 case AMDGPU::S_LOAD_DWORDX4_IMM:
792 case AMDGPU::S_LOAD_DWORDX8_IMM:
793 case AMDGPU::S_LOAD_DWORDX2_IMM_ec:
794 case AMDGPU::S_LOAD_DWORDX3_IMM_ec:
795 case AMDGPU::S_LOAD_DWORDX4_IMM_ec:
796 case AMDGPU::S_LOAD_DWORDX8_IMM_ec:
799 case AMDGPU::DS_READ_B32:
800 case AMDGPU::DS_READ_B64:
801 case AMDGPU::DS_READ_B32_gfx9:
802 case AMDGPU::DS_READ_B64_gfx9:
803 case AMDGPU::DS_WRITE_B32:
804 case AMDGPU::DS_WRITE_B64:
805 case AMDGPU::DS_WRITE_B32_gfx9:
806 case AMDGPU::DS_WRITE_B64_gfx9:
809 case AMDGPU::GLOBAL_LOAD_DWORD_SADDR:
810 case AMDGPU::GLOBAL_LOAD_DWORDX2_SADDR:
811 case AMDGPU::GLOBAL_LOAD_DWORDX3_SADDR:
812 case AMDGPU::GLOBAL_LOAD_DWORDX4_SADDR:
813 case AMDGPU::GLOBAL_STORE_DWORD_SADDR:
814 case AMDGPU::GLOBAL_STORE_DWORDX2_SADDR:
815 case AMDGPU::GLOBAL_STORE_DWORDX3_SADDR:
816 case AMDGPU::GLOBAL_STORE_DWORDX4_SADDR:
817 case AMDGPU::FLAT_LOAD_DWORD_SADDR:
818 case AMDGPU::FLAT_LOAD_DWORDX2_SADDR:
819 case AMDGPU::FLAT_LOAD_DWORDX3_SADDR:
820 case AMDGPU::FLAT_LOAD_DWORDX4_SADDR:
821 case AMDGPU::FLAT_STORE_DWORD_SADDR:
822 case AMDGPU::FLAT_STORE_DWORDX2_SADDR:
823 case AMDGPU::FLAT_STORE_DWORDX3_SADDR:
824 case AMDGPU::FLAT_STORE_DWORDX4_SADDR:
827 case AMDGPU::GLOBAL_LOAD_DWORD:
828 case AMDGPU::GLOBAL_LOAD_DWORDX2:
829 case AMDGPU::GLOBAL_LOAD_DWORDX3:
830 case AMDGPU::GLOBAL_LOAD_DWORDX4:
831 case AMDGPU::GLOBAL_STORE_DWORD:
832 case AMDGPU::GLOBAL_STORE_DWORDX2:
833 case AMDGPU::GLOBAL_STORE_DWORDX3:
834 case AMDGPU::GLOBAL_STORE_DWORDX4:
835 case AMDGPU::FLAT_LOAD_DWORD:
836 case AMDGPU::FLAT_LOAD_DWORDX2:
837 case AMDGPU::FLAT_LOAD_DWORDX3:
838 case AMDGPU::FLAT_LOAD_DWORDX4:
839 case AMDGPU::FLAT_STORE_DWORD:
840 case AMDGPU::FLAT_STORE_DWORDX2:
841 case AMDGPU::FLAT_STORE_DWORDX3:
842 case AMDGPU::FLAT_STORE_DWORDX4:
849 const SILoadStoreOptimizer &LSO) {
851 unsigned Opc =
MI->getOpcode();
852 InstClass = getInstClass(
Opc, *LSO.TII);
854 if (InstClass == UNKNOWN)
857 DataRC = LSO.getDataRegClass(*
MI);
862 (
Opc == AMDGPU::DS_READ_B64 ||
Opc == AMDGPU::DS_READ_B64_gfx9) ? 8
867 (
Opc == AMDGPU::DS_WRITE_B64 ||
Opc == AMDGPU::DS_WRITE_B64_gfx9) ? 8
870 case S_BUFFER_LOAD_IMM:
871 case S_BUFFER_LOAD_SGPR_IMM:
880 if (InstClass == MIMG) {
885 int OffsetIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::offset);
886 Offset =
I->getOperand(OffsetIdx).getImm();
889 if (InstClass == TBUFFER_LOAD || InstClass == TBUFFER_STORE) {
893 EltSize = Info->BitsPerComp / 8;
896 Width = getOpcodeWidth(*
I, *LSO.TII);
898 if ((InstClass == DS_READ) || (InstClass == DS_WRITE)) {
900 }
else if (InstClass != MIMG) {
904 AddressRegs Regs = getRegs(
Opc, *LSO.TII);
908 for (
unsigned J = 0; J < Regs.NumVAddrs; J++)
909 AddrIdx[NumAddresses++] =
910 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0) + J;
912 AddrIdx[NumAddresses++] =
913 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::addr);
915 AddrIdx[NumAddresses++] =
916 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::sbase);
918 AddrIdx[NumAddresses++] = AMDGPU::getNamedOperandIdx(
919 Opc, isVIMAGEorVSAMPLE ? AMDGPU::OpName::rsrc : AMDGPU::OpName::srsrc);
921 AddrIdx[NumAddresses++] =
922 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::soffset);
924 AddrIdx[NumAddresses++] =
925 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::saddr);
927 AddrIdx[NumAddresses++] =
928 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr);
930 AddrIdx[NumAddresses++] = AMDGPU::getNamedOperandIdx(
931 Opc, isVIMAGEorVSAMPLE ? AMDGPU::OpName::samp : AMDGPU::OpName::ssamp);
932 assert(NumAddresses <= MaxAddressRegs);
934 for (
unsigned J = 0; J < NumAddresses; J++)
935 AddrReg[J] = &
I->getOperand(AddrIdx[J]);
941 "SI Load Store Optimizer",
false,
false)
946char SILoadStoreOptimizerLegacy::ID = 0;
951 return new SILoadStoreOptimizerLegacy();
957 for (
const auto &
Op :
MI.operands()) {
967bool SILoadStoreOptimizer::canSwapInstructions(
968 const DenseSet<Register> &ARegDefs,
const DenseSet<Register> &ARegUses,
969 const MachineInstr &
A,
const MachineInstr &
B)
const {
970 if (
A.mayLoadOrStore() &&
B.mayLoadOrStore() &&
971 (
A.mayStore() ||
B.mayStore()) &&
A.mayAlias(AA,
B,
true))
973 for (
const auto &BOp :
B.operands()) {
976 if ((BOp.isDef() || BOp.readsReg()) && ARegDefs.
contains(BOp.getReg()))
978 if (BOp.isDef() && ARegUses.
contains(BOp.getReg()))
987SILoadStoreOptimizer::combineKnownAdjacentMMOs(
const CombineInfo &CI,
988 const CombineInfo &Paired) {
989 const MachineMemOperand *MMOa = *CI.I->memoperands_begin();
990 const MachineMemOperand *MMOb = *Paired.I->memoperands_begin();
1008bool SILoadStoreOptimizer::dmasksCanBeCombined(
const CombineInfo &CI,
1009 const SIInstrInfo &
TII,
1010 const CombineInfo &Paired) {
1011 assert(CI.InstClass == MIMG);
1014 const auto *TFEOp =
TII.getNamedOperand(*CI.I, AMDGPU::OpName::tfe);
1015 const auto *LWEOp =
TII.getNamedOperand(*CI.I, AMDGPU::OpName::lwe);
1017 if ((TFEOp && TFEOp->getImm()) || (LWEOp && LWEOp->getImm()))
1021 AMDGPU::OpName OperandsToMatch[] = {
1022 AMDGPU::OpName::cpol, AMDGPU::OpName::d16, AMDGPU::OpName::unorm,
1023 AMDGPU::OpName::da, AMDGPU::OpName::r128, AMDGPU::OpName::a16,
1024 AMDGPU::OpName::dim};
1026 for (AMDGPU::OpName
op : OperandsToMatch) {
1027 int Idx = AMDGPU::getNamedOperandIdx(CI.I->getOpcode(),
op);
1028 if (AMDGPU::getNamedOperandIdx(Paired.I->getOpcode(),
op) != Idx)
1031 CI.I->getOperand(Idx).getImm() != Paired.I->getOperand(Idx).getImm())
1036 unsigned MaxMask = std::max(CI.DMask, Paired.DMask);
1037 unsigned MinMask = std::min(CI.DMask, Paired.DMask);
1043 if ((1u << AllowedBitsForMin) <= MinMask)
1050 unsigned ComponentCount,
1052 if (ComponentCount > 4)
1071 return NewFormatInfo->
Format;
1084bool SILoadStoreOptimizer::offsetsCanBeCombined(CombineInfo &CI,
1085 const GCNSubtarget &STI,
1086 CombineInfo &Paired,
1088 assert(CI.InstClass != MIMG);
1092 if (CI.Offset == Paired.Offset)
1096 if ((CI.Offset % CI.EltSize != 0) || (Paired.Offset % CI.EltSize != 0))
1099 if (CI.InstClass == TBUFFER_LOAD || CI.InstClass == TBUFFER_STORE) {
1101 const llvm::AMDGPU::GcnBufferFormatInfo *Info0 =
1103 const llvm::AMDGPU::GcnBufferFormatInfo *Info1 =
1115 unsigned NumCombinedComponents = CI.Width + Paired.Width;
1116 if (NumCombinedComponents == 3 && CI.EltSize <= 2)
1117 NumCombinedComponents = 4;
1125 unsigned ElemIndex0 = CI.Offset / CI.EltSize;
1126 unsigned ElemIndex1 = Paired.Offset / Paired.EltSize;
1127 if (ElemIndex0 + CI.Width != ElemIndex1 &&
1128 ElemIndex1 + Paired.Width != ElemIndex0)
1134 unsigned MergedBytes = CI.EltSize * NumCombinedComponents;
1135 unsigned RequiredAlign = std::min(MergedBytes, 4u);
1136 unsigned MinOff = std::min(CI.Offset, Paired.Offset);
1137 if (MinOff % RequiredAlign != 0)
1143 uint32_t EltOffset0 = CI.Offset / CI.EltSize;
1144 uint32_t EltOffset1 = Paired.Offset / CI.EltSize;
1149 if ((CI.InstClass != DS_READ) && (CI.InstClass != DS_WRITE)) {
1150 if (EltOffset0 + CI.Width != EltOffset1 &&
1151 EltOffset1 + Paired.Width != EltOffset0)
1157 if (CI.InstClass == S_LOAD_IMM || CI.InstClass == S_BUFFER_LOAD_IMM ||
1158 CI.InstClass == S_BUFFER_LOAD_SGPR_IMM) {
1164 if (CI.Width != Paired.Width &&
1165 (CI.Width < Paired.Width) == (CI.Offset < Paired.Offset))
1173 if ((EltOffset0 % 64 == 0) && (EltOffset1 % 64) == 0 &&
1176 CI.Offset = EltOffset0 / 64;
1177 Paired.Offset = EltOffset1 / 64;
1186 CI.Offset = EltOffset0;
1187 Paired.Offset = EltOffset1;
1193 uint32_t Min = std::min(EltOffset0, EltOffset1);
1194 uint32_t
Max = std::max(EltOffset0, EltOffset1);
1197 if (((Max - Min) & ~Mask) == 0) {
1206 CI.BaseOff = BaseOff * CI.EltSize;
1207 CI.Offset = (EltOffset0 - BaseOff) / 64;
1208 Paired.Offset = (EltOffset1 - BaseOff) / 64;
1220 CI.BaseOff = BaseOff * CI.EltSize;
1221 CI.Offset = EltOffset0 - BaseOff;
1222 Paired.Offset = EltOffset1 - BaseOff;
1230bool SILoadStoreOptimizer::widthsFit(
const GCNSubtarget &STM,
1231 const CombineInfo &CI,
1232 const CombineInfo &Paired) {
1233 const unsigned Width = (CI.Width + Paired.Width);
1234 switch (CI.InstClass) {
1237 case S_BUFFER_LOAD_IMM:
1238 case S_BUFFER_LOAD_SGPR_IMM:
1248 return STM.hasScalarDwordx3Loads();
1254SILoadStoreOptimizer::getDataRegClass(
const MachineInstr &
MI)
const {
1255 if (
const auto *Dst =
TII->getNamedOperand(
MI, AMDGPU::OpName::vdst)) {
1256 return TRI->getRegClassForReg(*MRI, Dst->getReg());
1258 if (
const auto *Src =
TII->getNamedOperand(
MI, AMDGPU::OpName::vdata)) {
1259 return TRI->getRegClassForReg(*MRI, Src->getReg());
1261 if (
const auto *Src =
TII->getNamedOperand(
MI, AMDGPU::OpName::data0)) {
1262 return TRI->getRegClassForReg(*MRI, Src->getReg());
1264 if (
const auto *Dst =
TII->getNamedOperand(
MI, AMDGPU::OpName::sdst)) {
1265 return TRI->getRegClassForReg(*MRI, Dst->getReg());
1267 if (
const auto *Src =
TII->getNamedOperand(
MI, AMDGPU::OpName::sdata)) {
1268 return TRI->getRegClassForReg(*MRI, Src->getReg());
1275SILoadStoreOptimizer::CombineInfo *
1276SILoadStoreOptimizer::checkAndPrepareMerge(CombineInfo &CI,
1277 CombineInfo &Paired) {
1280 if (CI.InstClass == UNKNOWN || Paired.InstClass == UNKNOWN)
1282 assert(CI.InstClass == Paired.InstClass);
1284 if (getInstSubclass(CI.I->getOpcode(), *
TII) !=
1285 getInstSubclass(Paired.I->getOpcode(), *
TII))
1290 if (CI.InstClass == MIMG) {
1291 if (!dmasksCanBeCombined(CI, *
TII, Paired))
1294 if (!widthsFit(*STM, CI, Paired) || !offsetsCanBeCombined(CI, *STM, Paired))
1298 DenseSet<Register> RegDefs;
1299 DenseSet<Register> RegUses;
1301 if (CI.I->mayLoad()) {
1305 if (!canSwapInstructions(RegDefs, RegUses, *Paired.I, *
MBBI))
1313 if (!canSwapInstructions(RegDefs, RegUses, *CI.I, *
MBBI))
1323 if (CI.InstClass == DS_READ || CI.InstClass == DS_WRITE) {
1324 if (STM->hasNeedsAligned2addrDS() &&
1325 (CI.I->memoperands_empty() ||
1326 (*CI.I->memoperands_begin())->getAlign().value() < CI.Width * 4))
1328 offsetsCanBeCombined(CI, *STM, Paired,
true);
1331 if (CI.InstClass == DS_WRITE) {
1339 const MachineOperand *Data0 =
1340 TII->getNamedOperand(*CI.I, AMDGPU::OpName::data0);
1341 const MachineOperand *Data1 =
1342 TII->getNamedOperand(*Paired.I, AMDGPU::OpName::data0);
1344 const MCInstrDesc &Write2Opc =
TII->get(getWrite2Opcode(CI));
1345 int Data0Idx = AMDGPU::getNamedOperandIdx(Write2Opc.
getOpcode(),
1346 AMDGPU::OpName::data0);
1347 int Data1Idx = AMDGPU::getNamedOperandIdx(Write2Opc.
getOpcode(),
1348 AMDGPU::OpName::data1);
1354 if (
unsigned SubReg = Data0->
getSubReg()) {
1359 if (
unsigned SubReg = Data1->
getSubReg()) {
1377void SILoadStoreOptimizer::copyToDestRegs(
1378 CombineInfo &CI, CombineInfo &Paired,
1380 AMDGPU::OpName OpName,
Register DestReg)
const {
1381 MachineBasicBlock *
MBB = CI.I->getParent();
1383 auto [SubRegIdx0, SubRegIdx1] = getSubRegIdxs(CI, Paired);
1386 const MCInstrDesc &CopyDesc =
TII->get(TargetOpcode::COPY);
1387 auto *Dest0 =
TII->getNamedOperand(*CI.I, OpName);
1388 auto *Dest1 =
TII->getNamedOperand(*Paired.I, OpName);
1393 Dest0->setIsEarlyClobber(
false);
1394 Dest1->setIsEarlyClobber(
false);
1398 .
addReg(DestReg, {}, SubRegIdx0);
1401 .
addReg(DestReg, RegState::Kill, SubRegIdx1);
1407SILoadStoreOptimizer::copyFromSrcRegs(CombineInfo &CI, CombineInfo &Paired,
1410 AMDGPU::OpName OpName)
const {
1411 MachineBasicBlock *
MBB = CI.I->getParent();
1413 auto [SubRegIdx0, SubRegIdx1] = getSubRegIdxs(CI, Paired);
1419 const auto *Src0 =
TII->getNamedOperand(*CI.I, OpName);
1420 const auto *Src1 =
TII->getNamedOperand(*Paired.I, OpName);
1422 BuildMI(*
MBB, InsertBefore,
DL,
TII->get(AMDGPU::REG_SEQUENCE), SrcReg)
1431unsigned SILoadStoreOptimizer::read2Opcode(
unsigned EltSize)
const {
1433 return (EltSize == 4) ? AMDGPU::DS_READ2_B32 : AMDGPU::DS_READ2_B64;
1434 return (EltSize == 4) ? AMDGPU::DS_READ2_B32_gfx9 : AMDGPU::DS_READ2_B64_gfx9;
1437unsigned SILoadStoreOptimizer::read2ST64Opcode(
unsigned EltSize)
const {
1439 return (EltSize == 4) ? AMDGPU::DS_READ2ST64_B32 : AMDGPU::DS_READ2ST64_B64;
1441 return (EltSize == 4) ? AMDGPU::DS_READ2ST64_B32_gfx9
1442 : AMDGPU::DS_READ2ST64_B64_gfx9;
1446SILoadStoreOptimizer::mergeRead2Pair(CombineInfo &CI, CombineInfo &Paired,
1448 MachineBasicBlock *
MBB = CI.I->getParent();
1452 const auto *AddrReg =
TII->getNamedOperand(*CI.I, AMDGPU::OpName::addr);
1454 unsigned NewOffset0 = std::min(CI.Offset, Paired.Offset);
1455 unsigned NewOffset1 = std::max(CI.Offset, Paired.Offset);
1457 CI.UseST64 ? read2ST64Opcode(CI.EltSize) : read2Opcode(CI.EltSize);
1460 (NewOffset0 != NewOffset1) &&
"Computed offset doesn't fit");
1462 const MCInstrDesc &Read2Desc =
TII->get(
Opc);
1471 unsigned BaseSubReg = AddrReg->getSubReg();
1479 BaseRegFlags = RegState::Kill;
1481 TII->getAddNoCarry(*
MBB, InsertBefore,
DL, BaseReg)
1483 .addReg(AddrReg->getReg(), {}, BaseSubReg)
1488 MachineInstrBuilder Read2 =
1490 .
addReg(BaseReg, BaseRegFlags, BaseSubReg)
1496 copyToDestRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdst, DestReg);
1498 CI.I->eraseFromParent();
1499 Paired.I->eraseFromParent();
1505unsigned SILoadStoreOptimizer::write2Opcode(
unsigned EltSize)
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)
const {
1514 return (EltSize == 4) ? AMDGPU::DS_WRITE2ST64_B32
1515 : AMDGPU::DS_WRITE2ST64_B64;
1517 return (EltSize == 4) ? AMDGPU::DS_WRITE2ST64_B32_gfx9
1518 : AMDGPU::DS_WRITE2ST64_B64_gfx9;
1521unsigned SILoadStoreOptimizer::getWrite2Opcode(
const CombineInfo &CI)
const {
1522 return CI.UseST64 ? write2ST64Opcode(CI.EltSize) : write2Opcode(CI.EltSize);
1526 CombineInfo &CI, CombineInfo &Paired,
1528 MachineBasicBlock *
MBB = CI.I->getParent();
1532 const MachineOperand *AddrReg =
1533 TII->getNamedOperand(*CI.I, AMDGPU::OpName::addr);
1534 const MachineOperand *Data0 =
1535 TII->getNamedOperand(*CI.I, AMDGPU::OpName::data0);
1536 const MachineOperand *Data1 =
1537 TII->getNamedOperand(*Paired.I, AMDGPU::OpName::data0);
1539 unsigned NewOffset0 = CI.Offset;
1540 unsigned NewOffset1 = Paired.Offset;
1541 unsigned Opc = getWrite2Opcode(CI);
1543 if (NewOffset0 > NewOffset1) {
1550 (NewOffset0 != NewOffset1) &&
"Computed offset doesn't fit");
1552 const MCInstrDesc &Write2Desc =
TII->get(
Opc);
1557 unsigned BaseSubReg = AddrReg->
getSubReg();
1565 BaseRegFlags = RegState::Kill;
1567 TII->getAddNoCarry(*
MBB, InsertBefore,
DL, BaseReg)
1569 .addReg(AddrReg->
getReg(), {}, BaseSubReg)
1574 MachineInstrBuilder Write2 =
1576 .
addReg(BaseReg, BaseRegFlags, BaseSubReg)
1584 CI.I->eraseFromParent();
1585 Paired.I->eraseFromParent();
1587 LLVM_DEBUG(
dbgs() <<
"Inserted write2 inst: " << *Write2 <<
'\n');
1592SILoadStoreOptimizer::mergeImagePair(CombineInfo &CI, CombineInfo &Paired,
1594 MachineBasicBlock *
MBB = CI.I->getParent();
1598 const unsigned Opcode = getNewOpcode(CI, Paired);
1603 unsigned MergedDMask = CI.DMask | Paired.DMask;
1605 AMDGPU::getNamedOperandIdx(CI.I->getOpcode(), AMDGPU::OpName::dmask);
1607 auto MIB =
BuildMI(*
MBB, InsertBefore,
DL,
TII->get(Opcode), DestReg);
1608 for (
unsigned I = 1,
E = (*CI.I).getNumOperands();
I !=
E; ++
I) {
1610 MIB.addImm(MergedDMask);
1612 MIB.add((*CI.I).getOperand(
I));
1618 assert(CI.I->hasOneMemOperand() && Paired.I->hasOneMemOperand());
1620 MachineInstr *
New = MIB.addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1622 copyToDestRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdata, DestReg);
1624 CI.I->eraseFromParent();
1625 Paired.I->eraseFromParent();
1630 CombineInfo &CI, CombineInfo &Paired,
1632 MachineBasicBlock *
MBB = CI.I->getParent();
1636 const unsigned Opcode = getNewOpcode(CI, Paired);
1641 unsigned MergedOffset = std::min(CI.Offset, Paired.Offset);
1646 assert(CI.I->hasOneMemOperand() && Paired.I->hasOneMemOperand());
1648 MachineInstrBuilder
New =
1650 .
add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::sbase));
1651 if (CI.InstClass == S_BUFFER_LOAD_SGPR_IMM)
1652 New.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::soffset));
1653 New.addImm(MergedOffset);
1654 New.addImm(CI.CPol).addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1656 copyToDestRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::sdst, DestReg);
1658 CI.I->eraseFromParent();
1659 Paired.I->eraseFromParent();
1664 CombineInfo &CI, CombineInfo &Paired,
1666 MachineBasicBlock *
MBB = CI.I->getParent();
1671 const unsigned Opcode = getNewOpcode(CI, Paired);
1677 unsigned MergedOffset = std::min(CI.Offset, Paired.Offset);
1679 auto MIB =
BuildMI(*
MBB, InsertBefore,
DL,
TII->get(Opcode), DestReg);
1681 AddressRegs Regs = getRegs(Opcode, *
TII);
1684 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr));
1689 assert(CI.I->hasOneMemOperand() && Paired.I->hasOneMemOperand());
1692 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::srsrc))
1693 .add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::soffset))
1694 .addImm(MergedOffset)
1697 .addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1699 copyToDestRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdata, DestReg);
1701 CI.I->eraseFromParent();
1702 Paired.I->eraseFromParent();
1707 CombineInfo &CI, CombineInfo &Paired,
1709 MachineBasicBlock *
MBB = CI.I->getParent();
1714 const unsigned Opcode = getNewOpcode(CI, Paired);
1720 unsigned MergedOffset = std::min(CI.Offset, Paired.Offset);
1722 auto MIB =
BuildMI(*
MBB, InsertBefore,
DL,
TII->get(Opcode), DestReg);
1724 AddressRegs Regs = getRegs(Opcode, *
TII);
1727 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr));
1732 unsigned NumCombinedComponents = CI.Width + Paired.Width;
1733 if (NumCombinedComponents == 3 && CI.EltSize <= 2)
1734 NumCombinedComponents = 4;
1735 unsigned JoinedFormat =
1741 assert(CI.I->hasOneMemOperand() && Paired.I->hasOneMemOperand());
1744 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::srsrc))
1745 .add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::soffset))
1746 .addImm(MergedOffset)
1747 .addImm(JoinedFormat)
1750 .addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1752 copyToDestRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdata, DestReg);
1754 CI.I->eraseFromParent();
1755 Paired.I->eraseFromParent();
1760 CombineInfo &CI, CombineInfo &Paired,
1762 MachineBasicBlock *
MBB = CI.I->getParent();
1766 const unsigned Opcode = getNewOpcode(CI, Paired);
1769 copyFromSrcRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdata);
1772 .
addReg(SrcReg, RegState::Kill);
1774 AddressRegs Regs = getRegs(Opcode, *
TII);
1777 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr));
1782 unsigned NumCombinedComponents = CI.Width + Paired.Width;
1783 if (NumCombinedComponents == 3 && CI.EltSize <= 2)
1784 NumCombinedComponents = 4;
1785 unsigned JoinedFormat =
1791 assert(CI.I->hasOneMemOperand() && Paired.I->hasOneMemOperand());
1794 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::srsrc))
1795 .add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::soffset))
1796 .addImm(std::min(CI.Offset, Paired.Offset))
1797 .addImm(JoinedFormat)
1800 .addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1802 CI.I->eraseFromParent();
1803 Paired.I->eraseFromParent();
1808 CombineInfo &CI, CombineInfo &Paired,
1810 MachineBasicBlock *
MBB = CI.I->getParent();
1815 const unsigned Opcode = getNewOpcode(CI, Paired);
1820 auto MIB =
BuildMI(*
MBB, InsertBefore,
DL,
TII->get(Opcode), DestReg);
1822 if (
auto *SAddr =
TII->getNamedOperand(*CI.I, AMDGPU::OpName::saddr))
1826 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr))
1827 .addImm(std::min(CI.Offset, Paired.Offset))
1829 .addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1831 copyToDestRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdst, DestReg);
1833 CI.I->eraseFromParent();
1834 Paired.I->eraseFromParent();
1839 CombineInfo &CI, CombineInfo &Paired,
1841 MachineBasicBlock *
MBB = CI.I->getParent();
1846 const unsigned Opcode = getNewOpcode(CI, Paired);
1849 copyFromSrcRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdata);
1852 .
add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr))
1853 .
addReg(SrcReg, RegState::Kill);
1855 if (
auto *SAddr =
TII->getNamedOperand(*CI.I, AMDGPU::OpName::saddr))
1859 MIB.addImm(std::min(CI.Offset, Paired.Offset))
1861 .addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1863 CI.I->eraseFromParent();
1864 Paired.I->eraseFromParent();
1873 (MMOs.
size() != 1 || MMOs[0]->
getAlign().value() < Width * 4);
1876unsigned SILoadStoreOptimizer::getNewOpcode(
const CombineInfo &CI,
1877 const CombineInfo &Paired) {
1878 const unsigned Width = CI.Width + Paired.Width;
1879 const CombineInfo &Leading = Paired < CI ? Paired : CI;
1882 const bool NeedsConstrainedOpc =
1885 switch (getCommonInstClass(CI, Paired)) {
1887 assert(CI.InstClass == BUFFER_LOAD || CI.InstClass == BUFFER_STORE);
1898 case S_BUFFER_LOAD_IMM: {
1903 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM_ec
1904 : AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM;
1906 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM_ec
1907 : AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM;
1909 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM_ec
1910 : AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM;
1912 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM_ec
1913 : AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM;
1916 case S_BUFFER_LOAD_SGPR_IMM: {
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;
1939 return NeedsConstrainedOpc ? AMDGPU::S_LOAD_DWORDX2_IMM_ec
1940 : AMDGPU::S_LOAD_DWORDX2_IMM;
1942 return NeedsConstrainedOpc ? AMDGPU::S_LOAD_DWORDX3_IMM_ec
1943 : AMDGPU::S_LOAD_DWORDX3_IMM;
1945 return NeedsConstrainedOpc ? AMDGPU::S_LOAD_DWORDX4_IMM_ec
1946 : AMDGPU::S_LOAD_DWORDX4_IMM;
1948 return NeedsConstrainedOpc ? AMDGPU::S_LOAD_DWORDX8_IMM_ec
1949 : AMDGPU::S_LOAD_DWORDX8_IMM;
1957 return AMDGPU::GLOBAL_LOAD_DWORDX2;
1959 return AMDGPU::GLOBAL_LOAD_DWORDX3;
1961 return AMDGPU::GLOBAL_LOAD_DWORDX4;
1963 case GLOBAL_LOAD_SADDR:
1968 return AMDGPU::GLOBAL_LOAD_DWORDX2_SADDR;
1970 return AMDGPU::GLOBAL_LOAD_DWORDX3_SADDR;
1972 return AMDGPU::GLOBAL_LOAD_DWORDX4_SADDR;
1979 return AMDGPU::GLOBAL_STORE_DWORDX2;
1981 return AMDGPU::GLOBAL_STORE_DWORDX3;
1983 return AMDGPU::GLOBAL_STORE_DWORDX4;
1985 case GLOBAL_STORE_SADDR:
1990 return AMDGPU::GLOBAL_STORE_DWORDX2_SADDR;
1992 return AMDGPU::GLOBAL_STORE_DWORDX3_SADDR;
1994 return AMDGPU::GLOBAL_STORE_DWORDX4_SADDR;
2001 return AMDGPU::FLAT_LOAD_DWORDX2;
2003 return AMDGPU::FLAT_LOAD_DWORDX3;
2005 return AMDGPU::FLAT_LOAD_DWORDX4;
2012 return AMDGPU::FLAT_STORE_DWORDX2;
2014 return AMDGPU::FLAT_STORE_DWORDX3;
2016 return AMDGPU::FLAT_STORE_DWORDX4;
2018 case FLAT_LOAD_SADDR:
2023 return AMDGPU::FLAT_LOAD_DWORDX2_SADDR;
2025 return AMDGPU::FLAT_LOAD_DWORDX3_SADDR;
2027 return AMDGPU::FLAT_LOAD_DWORDX4_SADDR;
2029 case FLAT_STORE_SADDR:
2034 return AMDGPU::FLAT_STORE_DWORDX2_SADDR;
2036 return AMDGPU::FLAT_STORE_DWORDX3_SADDR;
2038 return AMDGPU::FLAT_STORE_DWORDX4_SADDR;
2047std::pair<unsigned, unsigned>
2048SILoadStoreOptimizer::getSubRegIdxs(
const CombineInfo &CI,
2049 const CombineInfo &Paired) {
2050 assert((CI.InstClass != MIMG ||
2052 CI.Width + Paired.Width)) &&
2058 static const unsigned Idxs[5][4] = {
2059 {AMDGPU::sub0, AMDGPU::sub0_sub1, AMDGPU::sub0_sub1_sub2, AMDGPU::sub0_sub1_sub2_sub3},
2060 {AMDGPU::sub1, AMDGPU::sub1_sub2, AMDGPU::sub1_sub2_sub3, AMDGPU::sub1_sub2_sub3_sub4},
2061 {AMDGPU::sub2, AMDGPU::sub2_sub3, AMDGPU::sub2_sub3_sub4, AMDGPU::sub2_sub3_sub4_sub5},
2062 {AMDGPU::sub3, AMDGPU::sub3_sub4, AMDGPU::sub3_sub4_sub5, AMDGPU::sub3_sub4_sub5_sub6},
2063 {AMDGPU::sub4, AMDGPU::sub4_sub5, AMDGPU::sub4_sub5_sub6, AMDGPU::sub4_sub5_sub6_sub7},
2066 assert(CI.Width >= 1 && CI.Width <= 4);
2067 assert(Paired.Width >= 1 && Paired.Width <= 4);
2070 Idx1 = Idxs[0][Paired.Width - 1];
2071 Idx0 = Idxs[Paired.Width][CI.Width - 1];
2073 Idx0 = Idxs[0][CI.Width - 1];
2074 Idx1 = Idxs[CI.Width][Paired.Width - 1];
2077 return {Idx0, Idx1};
2081SILoadStoreOptimizer::getTargetRegisterClass(
const CombineInfo &CI,
2082 const CombineInfo &Paired)
const {
2083 if (CI.InstClass == S_BUFFER_LOAD_IMM ||
2084 CI.InstClass == S_BUFFER_LOAD_SGPR_IMM || CI.InstClass == S_LOAD_IMM) {
2085 switch (CI.Width + Paired.Width) {
2089 return &AMDGPU::SReg_64_XEXECRegClass;
2091 return &AMDGPU::SGPR_96RegClass;
2093 return &AMDGPU::SGPR_128RegClass;
2095 return &AMDGPU::SGPR_256RegClass;
2097 return &AMDGPU::SGPR_512RegClass;
2103 unsigned BitWidth = 32 * (CI.Width + Paired.Width);
2104 return TRI->isAGPRClass(getDataRegClass(*CI.I))
2110 CombineInfo &CI, CombineInfo &Paired,
2112 MachineBasicBlock *
MBB = CI.I->getParent();
2116 const unsigned Opcode = getNewOpcode(CI, Paired);
2119 copyFromSrcRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdata);
2122 .
addReg(SrcReg, RegState::Kill);
2124 AddressRegs Regs = getRegs(Opcode, *
TII);
2127 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr));
2133 assert(CI.I->hasOneMemOperand() && Paired.I->hasOneMemOperand());
2136 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::srsrc))
2137 .add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::soffset))
2138 .addImm(std::min(CI.Offset, Paired.Offset))
2141 .addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
2143 CI.I->eraseFromParent();
2144 Paired.I->eraseFromParent();
2149SILoadStoreOptimizer::createRegOrImm(int32_t Val, MachineInstr &
MI)
const {
2150 APInt
V(32, Val,
true);
2151 if (
TII->isInlineConstant(V))
2156 BuildMI(*
MI.getParent(),
MI.getIterator(),
MI.getDebugLoc(),
2157 TII->get(AMDGPU::S_MOV_B32),
Reg)
2165Register SILoadStoreOptimizer::computeBase(MachineInstr &
MI,
2166 const MemAddress &Addr)
const {
2174 if (Addr.Base.UseV64Pattern) {
2176 TII->getRegClass(
TII->get(AMDGPU::V_ADD_U64_e64), 0));
2180 MachineInstr *MovOffset =
2184 MachineInstr *
Add64 =
2187 .
addReg(OffsetReg, RegState::Kill)
2198 assert((
TRI->getRegSizeInBits(Addr.Base.LoReg, *MRI) == 32 ||
2199 Addr.Base.LoSubReg) &&
2200 "Expected 32-bit Base-Register-Low!!");
2202 assert((
TRI->getRegSizeInBits(Addr.Base.HiReg, *MRI) == 32 ||
2203 Addr.Base.HiSubReg) &&
2204 "Expected 32-bit Base-Register-Hi!!");
2206 MachineOperand OffsetLo = createRegOrImm(
static_cast<int32_t
>(Addr.Offset),
MI);
2207 MachineOperand OffsetHi =
2208 createRegOrImm(
static_cast<int32_t
>(Addr.Offset >> 32),
MI);
2210 const auto *CarryRC =
TRI->getWaveMaskRegClass();
2216 MachineInstr *LoHalf =
2218 .
addReg(CarryReg, RegState::Define)
2219 .
addReg(Addr.Base.LoReg, {}, Addr.Base.LoSubReg)
2223 MachineInstr *HiHalf =
2225 .
addReg(DeadCarryReg, RegState::Define | RegState::Dead)
2226 .
addReg(Addr.Base.HiReg, {}, Addr.Base.HiSubReg)
2228 .
addReg(CarryReg, RegState::Kill)
2232 MachineInstr *FullBase =
2243 dbgs() <<
" " << *HiHalf <<
"\n";
2244 dbgs() <<
" " << *FullBase <<
"\n\n";);
2250void SILoadStoreOptimizer::updateBaseAndOffset(MachineInstr &
MI,
2252 int32_t NewOffset)
const {
2253 auto *
Base =
TII->getNamedOperand(
MI, AMDGPU::OpName::vaddr);
2254 Base->setReg(NewBase);
2255 Base->setIsKill(
false);
2256 TII->getNamedOperand(
MI, AMDGPU::OpName::offset)->setImm(NewOffset);
2262bool SILoadStoreOptimizer::processBaseWithConstOffset64(
2263 MachineInstr *AddDef,
const MachineOperand &
Base, MemAddress &Addr)
const {
2267 MachineOperand *Src0 =
TII->getNamedOperand(*AddDef, AMDGPU::OpName::src0);
2268 MachineOperand *Src1 =
TII->getNamedOperand(*AddDef, AMDGPU::OpName::src1);
2270 const MachineOperand *BaseOp =
nullptr;
2272 auto Offset =
TII->getImmOrMaterializedImm(*MRI, *Src1);
2283 Addr.Base.LoReg = BaseOp->
getReg();
2284 Addr.Base.UseV64Pattern =
true;
2302void SILoadStoreOptimizer::processBaseWithConstOffset(
const MachineOperand &
Base,
2303 MemAddress &Addr)
const {
2312 if (
Def->getOpcode() == AMDGPU::V_ADD_U64_e64) {
2313 if (processBaseWithConstOffset64(Def,
Base, Addr))
2318 if (
Def->getOpcode() != AMDGPU::REG_SEQUENCE ||
Def->getNumOperands() != 5)
2321 MachineOperand BaseLo =
Def->getOperand(1);
2322 MachineOperand BaseHi =
Def->getOperand(3);
2329 if (!BaseLoDef || BaseLoDef->
getOpcode() != AMDGPU::V_ADD_CO_U32_e64 ||
2330 !BaseHiDef || BaseHiDef->
getOpcode() != AMDGPU::V_ADDC_U32_e64)
2333 MachineOperand *Src0 =
TII->getNamedOperand(*BaseLoDef, AMDGPU::OpName::src0);
2334 MachineOperand *Src1 =
TII->getNamedOperand(*BaseLoDef, AMDGPU::OpName::src1);
2336 auto Offset0P =
TII->getImmOrMaterializedImm(*MRI, *Src0);
2340 if (!(Offset0P =
TII->getImmOrMaterializedImm(*MRI, *Src1)))
2345 if (!BaseLo.
isReg())
2348 Src0 =
TII->getNamedOperand(*BaseHiDef, AMDGPU::OpName::src0);
2349 Src1 =
TII->getNamedOperand(*BaseHiDef, AMDGPU::OpName::src1);
2360 if (!BaseHi.
isReg())
2363 Addr.Base.LoReg = BaseLo.
getReg();
2364 Addr.Base.HiReg = BaseHi.
getReg();
2365 Addr.Base.LoSubReg = BaseLo.
getSubReg();
2366 Addr.Base.HiSubReg = BaseHi.
getSubReg();
2367 Addr.Offset = (*Offset0P & 0x00000000ffffffff) | (Offset1 << 32);
2374void SILoadStoreOptimizer::updateAsyncLDSAddress(MachineInstr &
MI,
2375 int32_t OffsetDiff)
const {
2376 if (!
TII->usesASYNC_CNT(
MI) || OffsetDiff == 0)
2379 MachineOperand *LDSAddr =
TII->getNamedOperand(
MI, AMDGPU::OpName::vdst);
2381 LDSAddr =
TII->getNamedOperand(
MI, AMDGPU::OpName::vdata);
2396bool SILoadStoreOptimizer::promoteConstantOffsetToImm(
2398 MemInfoMap &Visited,
2399 SmallPtrSet<MachineInstr *, 4> &
AnchorList)
const {
2412 ? AMDGPU::FlatAddrSpace::FlatGlobal
2413 : AMDGPU::FlatAddrSpace::FLAT;
2414 bool AllowNegativeOffset =
2415 TII->allowNegativeFlatOffset(FlatVariant) && !
TII->usesASYNC_CNT(
MI);
2419 bool IsOffsetU16 =
TII->usesASYNC_CNT(
MI);
2426 if (
TII->getNamedOperand(
MI, AMDGPU::OpName::offset)->getImm()) {
2432 MachineOperand &
Base = *
TII->getNamedOperand(
MI, AMDGPU::OpName::vaddr);
2433 auto [It,
Inserted] = Visited.try_emplace(&
MI);
2436 processBaseWithConstOffset(
Base, MAddr);
2441 if (MAddr.Offset == 0) {
2442 LLVM_DEBUG(
dbgs() <<
" Failed to extract constant-offset or there are no"
2443 " constant offsets that can be promoted.\n";);
2449 <<
"} Offset: " << MAddr.Offset <<
"\n\n";);
2476 MachineInstr *AnchorInst =
nullptr;
2477 MemAddress AnchorAddr;
2478 uint32_t MaxDist = std::numeric_limits<uint32_t>::min();
2480 bool MIIsAnchor =
false;
2489 MachineInstr &MINext = *
MBBI;
2493 TII->getNamedOperand(MINext, AMDGPU::OpName::offset)->getImm())
2496 const MachineOperand &BaseNext =
2497 *
TII->getNamedOperand(MINext, AMDGPU::OpName::vaddr);
2498 MemAddress MAddrNext;
2499 auto [It,
Inserted] = Visited.try_emplace(&MINext);
2501 processBaseWithConstOffset(BaseNext, MAddrNext);
2502 It->second = MAddrNext;
2504 MAddrNext = It->second;
2506 if (MAddrNext.Base.LoReg != MAddr.Base.LoReg ||
2507 MAddrNext.Base.HiReg != MAddr.Base.HiReg ||
2508 MAddrNext.Base.LoSubReg != MAddr.Base.LoSubReg ||
2509 MAddrNext.Base.HiSubReg != MAddr.Base.HiSubReg)
2512 InstsWCommonBase.
emplace_back(&MINext, MAddrNext.Offset);
2514 if (AllowNegativeOffset) {
2515 int64_t Dist = MAddr.Offset - MAddrNext.Offset;
2516 TargetLoweringBase::AddrMode AM;
2520 (uint32_t)std::abs(Dist) > MaxDist) {
2521 MaxDist = std::abs(Dist);
2523 AnchorAddr = MAddrNext;
2524 AnchorInst = &MINext;
2532 if (!AllowNegativeOffset && !InstsWCommonBase.
empty()) {
2533 for (
auto &[Inst,
Offset] : InstsWCommonBase) {
2534 int64_t Dist = MAddr.Offset -
Offset;
2535 TargetLoweringBase::AddrMode AM;
2540 (!AnchorInst ||
Offset < AnchorAddr.Offset)) {
2541 AnchorAddr = Visited[Inst];
2550 LLVM_DEBUG(
dbgs() <<
" Anchor-Inst(with max-distance from Offset): ";
2551 AnchorInst->
dump());
2553 << AnchorAddr.Offset <<
"\n\n");
2558 int32_t OffsetDiff = MAddr.Offset - AnchorAddr.Offset;
2559 updateBaseAndOffset(
MI,
Base, OffsetDiff);
2560 updateAsyncLDSAddress(
MI, OffsetDiff);
2563 for (
auto [OtherMI, OtherOffset] : InstsWCommonBase) {
2564 TargetLoweringBase::AddrMode AM;
2566 AM.
BaseOffs = OtherOffset - AnchorAddr.Offset;
2569 (AllowNegativeOffset || AM.
BaseOffs >= 0) &&
2573 int32_t OtherOffsetDiff = OtherOffset - AnchorAddr.Offset;
2574 updateBaseAndOffset(*OtherMI,
Base, OtherOffsetDiff);
2575 updateAsyncLDSAddress(*OtherMI, OtherOffsetDiff);
2584 LLVM_DEBUG(
dbgs() <<
" MI is anchor (smallest offset); promoting "
2585 "candidates relative to MI's base.\n");
2588 bool AnyPromoted =
false;
2590 for (
auto [OtherMI, OtherOffset] : InstsWCommonBase) {
2591 int64_t Dist = OtherOffset - MAddr.Offset;
2592 TargetLoweringBase::AddrMode AM;
2599 updateBaseAndOffset(*OtherMI,
Base, Dist);
2600 updateAsyncLDSAddress(*OtherMI, Dist);
2607 TII->getNamedOperand(
MI, AMDGPU::OpName::vaddr)->setIsKill(
false);
2616void SILoadStoreOptimizer::addInstToMergeableList(
const CombineInfo &CI,
2617 std::list<std::list<CombineInfo> > &MergeableInsts)
const {
2618 for (std::list<CombineInfo> &AddrList : MergeableInsts) {
2619 if (AddrList.front().InstClass == CI.InstClass &&
2620 AddrList.front().hasSameBaseAddress(CI)) {
2621 AddrList.emplace_back(CI);
2627 MergeableInsts.emplace_back(1, CI);
2630std::pair<MachineBasicBlock::iterator, bool>
2631SILoadStoreOptimizer::collectMergeableInsts(
2633 MemInfoMap &Visited, SmallPtrSet<MachineInstr *, 4> &
AnchorList,
2634 std::list<std::list<CombineInfo>> &MergeableInsts)
const {
2640 for (; BlockI != End; ++BlockI) {
2641 MachineInstr &
MI = *BlockI;
2645 if (promoteConstantOffsetToImm(
MI, Visited,
AnchorList))
2650 if (
MI.hasOrderedMemoryRef() ||
MI.hasUnmodeledSideEffects()) {
2658 const InstClassEnum InstClass = getInstClass(
MI.getOpcode(), *
TII);
2659 if (InstClass == UNKNOWN)
2664 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::swz);
2665 if (Swizzled != -1 &&
MI.getOperand(Swizzled).getImm())
2668 if (InstClass == TBUFFER_LOAD || InstClass == TBUFFER_STORE) {
2671 dbgs() <<
"Skip tbuffer combine: relaxed OOB mode not enabled\n");
2675 const MachineOperand *Fmt =
2676 TII->getNamedOperand(
MI, AMDGPU::OpName::format);
2681 }
else if (InstClass == MIMG) {
2684 const auto *TFEOp =
TII->getNamedOperand(
MI, AMDGPU::OpName::tfe);
2685 if (TFEOp && TFEOp->getImm())
2688 const auto *LWEOp =
TII->getNamedOperand(
MI, AMDGPU::OpName::lwe);
2689 if (LWEOp && LWEOp->getImm())
2694 CI.setMI(
MI, *
this);
2697 if (!CI.hasMergeableAddress(*MRI))
2712 for (std::list<std::list<CombineInfo>>::iterator
I = MergeableInsts.begin(),
2713 E = MergeableInsts.end();
I !=
E;) {
2715 std::list<CombineInfo> &MergeList = *
I;
2716 if (MergeList.size() <= 1) {
2720 I = MergeableInsts.erase(
I);
2728 [] (
const CombineInfo &
A,
const CombineInfo &
B) {
2729 return A.Offset <
B.Offset;
2740bool SILoadStoreOptimizer::optimizeBlock(
2741 std::list<std::list<CombineInfo> > &MergeableInsts) {
2744 for (std::list<std::list<CombineInfo>>::iterator
I = MergeableInsts.begin(),
2745 E = MergeableInsts.end();
I !=
E;) {
2746 std::list<CombineInfo> &MergeList = *
I;
2748 bool OptimizeListAgain =
false;
2749 if (!optimizeInstsWithSameBaseAddr(MergeList, OptimizeListAgain)) {
2753 I = MergeableInsts.erase(
I);
2761 if (!OptimizeListAgain) {
2762 I = MergeableInsts.erase(
I);
2765 OptimizeAgain =
true;
2771SILoadStoreOptimizer::optimizeInstsWithSameBaseAddr(
2772 std::list<CombineInfo> &MergeList,
2773 bool &OptimizeListAgain) {
2774 if (MergeList.empty())
2779 for (
auto I = MergeList.begin(),
Next = std::next(
I);
Next != MergeList.end();
2780 Next = std::next(
I)) {
2785 if ((*First).Order > (*Second).Order)
2787 CombineInfo &CI = *
First;
2788 CombineInfo &Paired = *Second;
2790 CombineInfo *Where = checkAndPrepareMerge(CI, Paired);
2798 LLVM_DEBUG(
dbgs() <<
"Merging: " << *CI.I <<
" with: " << *Paired.I);
2801 switch (CI.InstClass) {
2806 NewMI = mergeRead2Pair(CI, Paired, Where->I);
2809 NewMI = mergeWrite2Pair(CI, Paired, Where->I);
2811 case S_BUFFER_LOAD_IMM:
2812 case S_BUFFER_LOAD_SGPR_IMM:
2814 NewMI = mergeSMemLoadImmPair(CI, Paired, Where->I);
2815 OptimizeListAgain |= CI.Width + Paired.Width < 8;
2818 NewMI = mergeBufferLoadPair(CI, Paired, Where->I);
2819 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2822 NewMI = mergeBufferStorePair(CI, Paired, Where->I);
2823 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2826 NewMI = mergeImagePair(CI, Paired, Where->I);
2827 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2830 NewMI = mergeTBufferLoadPair(CI, Paired, Where->I);
2831 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2834 NewMI = mergeTBufferStorePair(CI, Paired, Where->I);
2835 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2838 case FLAT_LOAD_SADDR:
2840 case GLOBAL_LOAD_SADDR:
2841 NewMI = mergeFlatLoadPair(CI, Paired, Where->I);
2842 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2845 case FLAT_STORE_SADDR:
2847 case GLOBAL_STORE_SADDR:
2848 NewMI = mergeFlatStorePair(CI, Paired, Where->I);
2849 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2852 CI.setMI(NewMI, *
this);
2853 CI.Order = Where->Order;
2857 MergeList.erase(Second);
2863bool SILoadStoreOptimizerLegacy::runOnMachineFunction(
MachineFunction &MF) {
2866 return SILoadStoreOptimizer(
2867 &getAnalysis<AAResultsWrapperPass>().getAAResults())
2891 for (MachineBasicBlock &
MBB : MF) {
2895 bool CollectModified;
2896 std::list<std::list<CombineInfo>> MergeableInsts;
2900 std::tie(SectionEnd, CollectModified) =
2906 OptimizeAgain =
false;
2908 }
while (OptimizeAgain);
2930 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.
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 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.
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.
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(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.
@ 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.