70#define DEBUG_TYPE "si-load-store-opt"
78 S_BUFFER_LOAD_SGPR_IMM,
97 unsigned char NumVAddrs = 0;
100 bool SOffset =
false;
108const unsigned MaxAddressRegs = 12 + 1 + 1;
110class SILoadStoreOptimizer {
119 InstClassEnum InstClass;
124 int AddrIdx[MaxAddressRegs];
126 unsigned NumAddresses;
129 bool hasSameBaseAddress(
const CombineInfo &CI) {
130 if (NumAddresses != CI.NumAddresses)
134 for (
unsigned i = 0; i < NumAddresses; i++) {
137 if (AddrReg[i]->isImm() || AddrRegNext.
isImm()) {
138 if (AddrReg[i]->isImm() != AddrRegNext.
isImm() ||
156 for (
unsigned i = 0; i < NumAddresses; ++i) {
165 if (!AddrOp->
isReg())
171 AddrOp->
getReg() != AMDGPU::SGPR_NULL)
176 if (
MRI.hasOneNonDBGUse(AddrOp->
getReg()))
190 struct BaseRegisters {
194 unsigned LoSubReg = 0;
195 unsigned HiSubReg = 0;
197 bool UseV64Pattern =
false;
199 bool UseScratchVGPRPattern =
false;
221 static bool dmasksCanBeCombined(
const CombineInfo &CI,
223 const CombineInfo &Paired);
224 static bool offsetsCanBeCombined(CombineInfo &CI,
const GCNSubtarget &STI,
225 CombineInfo &Paired,
bool Modify =
false);
226 static bool widthsFit(
const GCNSubtarget &STI,
const CombineInfo &CI,
227 const CombineInfo &Paired);
228 unsigned getNewOpcode(
const CombineInfo &CI,
const CombineInfo &Paired);
229 static std::pair<unsigned, unsigned> getSubRegIdxs(
const CombineInfo &CI,
230 const CombineInfo &Paired);
232 getTargetRegisterClass(
const CombineInfo &CI,
233 const CombineInfo &Paired)
const;
236 CombineInfo *checkAndPrepareMerge(CombineInfo &CI, CombineInfo &Paired);
238 void copyToDestRegs(CombineInfo &CI, CombineInfo &Paired,
242 Register copyFromSrcRegs(CombineInfo &CI, CombineInfo &Paired,
246 unsigned read2Opcode(
unsigned EltSize,
bool GDS)
const;
247 unsigned read2ST64Opcode(
unsigned EltSize,
bool GDS)
const;
249 mergeRead2Pair(CombineInfo &CI, CombineInfo &Paired,
252 unsigned write2Opcode(
unsigned EltSize,
bool GDS)
const;
253 unsigned write2ST64Opcode(
unsigned EltSize,
bool GDS)
const;
254 unsigned getWrite2Opcode(
const CombineInfo &CI)
const;
257 mergeWrite2Pair(CombineInfo &CI, CombineInfo &Paired,
260 mergeImagePair(CombineInfo &CI, CombineInfo &Paired,
263 mergeSMemLoadImmPair(CombineInfo &CI, CombineInfo &Paired,
266 mergeBufferLoadPair(CombineInfo &CI, CombineInfo &Paired,
269 mergeBufferStorePair(CombineInfo &CI, CombineInfo &Paired,
272 mergeTBufferLoadPair(CombineInfo &CI, CombineInfo &Paired,
275 mergeTBufferStorePair(CombineInfo &CI, CombineInfo &Paired,
278 mergeFlatLoadPair(CombineInfo &CI, CombineInfo &Paired,
281 mergeFlatStorePair(CombineInfo &CI, CombineInfo &Paired,
285 int32_t NewOffset)
const;
286 void updateAsyncLDSAddress(
MachineInstr &
MI, int32_t OffsetDiff)
const;
291 MemAddress &Addr)
const;
293 MemAddress &Addr)
const;
302 std::list<std::list<CombineInfo> > &MergeableInsts)
const;
307 std::list<std::list<CombineInfo>> &MergeableInsts)
const;
310 const CombineInfo &Paired);
312 static InstClassEnum getCommonInstClass(
const CombineInfo &CI,
313 const CombineInfo &Paired);
315 bool optimizeInstsWithSameBaseAddr(std::list<CombineInfo> &MergeList,
316 bool &OptimizeListAgain);
317 bool optimizeBlock(std::list<std::list<CombineInfo> > &MergeableInsts);
332 StringRef getPassName()
const override {
return "SI Load Store Optimizer"; }
347 const unsigned Opc =
MI.getOpcode();
353 if (
TII.isImage(
MI)) {
355 TII.getNamedOperand(
MI, AMDGPU::OpName::dmask)->getImm();
363 case AMDGPU::S_BUFFER_LOAD_DWORD_IMM:
364 case AMDGPU::S_BUFFER_LOAD_DWORD_SGPR_IMM:
365 case AMDGPU::S_LOAD_DWORD_IMM:
366 case AMDGPU::GLOBAL_LOAD_DWORD:
367 case AMDGPU::GLOBAL_LOAD_DWORD_SADDR:
368 case AMDGPU::GLOBAL_STORE_DWORD:
369 case AMDGPU::GLOBAL_STORE_DWORD_SADDR:
370 case AMDGPU::FLAT_LOAD_DWORD:
371 case AMDGPU::FLAT_STORE_DWORD:
372 case AMDGPU::FLAT_LOAD_DWORD_SADDR:
373 case AMDGPU::FLAT_STORE_DWORD_SADDR:
375 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM:
376 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM:
377 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM_ec:
378 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM_ec:
379 case AMDGPU::S_LOAD_DWORDX2_IMM:
380 case AMDGPU::S_LOAD_DWORDX2_IMM_ec:
381 case AMDGPU::GLOBAL_LOAD_DWORDX2:
382 case AMDGPU::GLOBAL_LOAD_DWORDX2_SADDR:
383 case AMDGPU::GLOBAL_STORE_DWORDX2:
384 case AMDGPU::GLOBAL_STORE_DWORDX2_SADDR:
385 case AMDGPU::FLAT_LOAD_DWORDX2:
386 case AMDGPU::FLAT_STORE_DWORDX2:
387 case AMDGPU::FLAT_LOAD_DWORDX2_SADDR:
388 case AMDGPU::FLAT_STORE_DWORDX2_SADDR:
390 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM:
391 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM:
392 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM_ec:
393 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM_ec:
394 case AMDGPU::S_LOAD_DWORDX3_IMM:
395 case AMDGPU::S_LOAD_DWORDX3_IMM_ec:
396 case AMDGPU::GLOBAL_LOAD_DWORDX3:
397 case AMDGPU::GLOBAL_LOAD_DWORDX3_SADDR:
398 case AMDGPU::GLOBAL_STORE_DWORDX3:
399 case AMDGPU::GLOBAL_STORE_DWORDX3_SADDR:
400 case AMDGPU::FLAT_LOAD_DWORDX3:
401 case AMDGPU::FLAT_STORE_DWORDX3:
402 case AMDGPU::FLAT_LOAD_DWORDX3_SADDR:
403 case AMDGPU::FLAT_STORE_DWORDX3_SADDR:
405 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM:
406 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM:
407 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM_ec:
408 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM_ec:
409 case AMDGPU::S_LOAD_DWORDX4_IMM:
410 case AMDGPU::S_LOAD_DWORDX4_IMM_ec:
411 case AMDGPU::GLOBAL_LOAD_DWORDX4:
412 case AMDGPU::GLOBAL_LOAD_DWORDX4_SADDR:
413 case AMDGPU::GLOBAL_STORE_DWORDX4:
414 case AMDGPU::GLOBAL_STORE_DWORDX4_SADDR:
415 case AMDGPU::FLAT_LOAD_DWORDX4:
416 case AMDGPU::FLAT_STORE_DWORDX4:
417 case AMDGPU::FLAT_LOAD_DWORDX4_SADDR:
418 case AMDGPU::FLAT_STORE_DWORDX4_SADDR:
420 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM:
421 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM:
422 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM_ec:
423 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM_ec:
424 case AMDGPU::S_LOAD_DWORDX8_IMM:
425 case AMDGPU::S_LOAD_DWORDX8_IMM_ec:
427 case AMDGPU::DS_READ_B32:
428 case AMDGPU::DS_READ_B32_gfx9:
429 case AMDGPU::DS_WRITE_B32:
430 case AMDGPU::DS_WRITE_B32_gfx9:
432 case AMDGPU::DS_READ_B64:
433 case AMDGPU::DS_READ_B64_gfx9:
434 case AMDGPU::DS_WRITE_B64:
435 case AMDGPU::DS_WRITE_B64_gfx9:
450 case AMDGPU::BUFFER_LOAD_DWORD_BOTHEN:
451 case AMDGPU::BUFFER_LOAD_DWORD_BOTHEN_exact:
452 case AMDGPU::BUFFER_LOAD_DWORD_IDXEN:
453 case AMDGPU::BUFFER_LOAD_DWORD_IDXEN_exact:
454 case AMDGPU::BUFFER_LOAD_DWORD_OFFEN:
455 case AMDGPU::BUFFER_LOAD_DWORD_OFFEN_exact:
456 case AMDGPU::BUFFER_LOAD_DWORD_OFFSET:
457 case AMDGPU::BUFFER_LOAD_DWORD_OFFSET_exact:
458 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_BOTHEN:
459 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_BOTHEN_exact:
460 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_IDXEN:
461 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_IDXEN_exact:
462 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_OFFEN:
463 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_OFFEN_exact:
464 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_OFFSET:
465 case AMDGPU::BUFFER_LOAD_DWORD_VBUFFER_OFFSET_exact:
467 case AMDGPU::BUFFER_STORE_DWORD_BOTHEN:
468 case AMDGPU::BUFFER_STORE_DWORD_BOTHEN_exact:
469 case AMDGPU::BUFFER_STORE_DWORD_IDXEN:
470 case AMDGPU::BUFFER_STORE_DWORD_IDXEN_exact:
471 case AMDGPU::BUFFER_STORE_DWORD_OFFEN:
472 case AMDGPU::BUFFER_STORE_DWORD_OFFEN_exact:
473 case AMDGPU::BUFFER_STORE_DWORD_OFFSET:
474 case AMDGPU::BUFFER_STORE_DWORD_OFFSET_exact:
475 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_BOTHEN:
476 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_BOTHEN_exact:
477 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_IDXEN:
478 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_IDXEN_exact:
479 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_OFFEN:
480 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_OFFEN_exact:
481 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_OFFSET:
482 case AMDGPU::BUFFER_STORE_DWORD_VBUFFER_OFFSET_exact:
495 if (
TII.get(
Opc).mayStore() || !
TII.get(
Opc).mayLoad() ||
504 case AMDGPU::TBUFFER_LOAD_FORMAT_X_BOTHEN:
505 case AMDGPU::TBUFFER_LOAD_FORMAT_X_BOTHEN_exact:
506 case AMDGPU::TBUFFER_LOAD_FORMAT_X_IDXEN:
507 case AMDGPU::TBUFFER_LOAD_FORMAT_X_IDXEN_exact:
508 case AMDGPU::TBUFFER_LOAD_FORMAT_X_OFFEN:
509 case AMDGPU::TBUFFER_LOAD_FORMAT_X_OFFEN_exact:
510 case AMDGPU::TBUFFER_LOAD_FORMAT_X_OFFSET:
511 case AMDGPU::TBUFFER_LOAD_FORMAT_X_OFFSET_exact:
512 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_BOTHEN:
513 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_BOTHEN_exact:
514 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_IDXEN:
515 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_IDXEN_exact:
516 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_OFFEN:
517 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_OFFEN_exact:
518 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_OFFSET:
519 case AMDGPU::TBUFFER_LOAD_FORMAT_X_VBUFFER_OFFSET_exact:
521 case AMDGPU::TBUFFER_STORE_FORMAT_X_OFFEN:
522 case AMDGPU::TBUFFER_STORE_FORMAT_X_OFFEN_exact:
523 case AMDGPU::TBUFFER_STORE_FORMAT_X_OFFSET:
524 case AMDGPU::TBUFFER_STORE_FORMAT_X_OFFSET_exact:
525 case AMDGPU::TBUFFER_STORE_FORMAT_X_VBUFFER_OFFEN:
526 case AMDGPU::TBUFFER_STORE_FORMAT_X_VBUFFER_OFFEN_exact:
527 case AMDGPU::TBUFFER_STORE_FORMAT_X_VBUFFER_OFFSET:
528 case AMDGPU::TBUFFER_STORE_FORMAT_X_VBUFFER_OFFSET_exact:
529 return TBUFFER_STORE;
533 case AMDGPU::S_BUFFER_LOAD_DWORD_IMM:
534 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM:
535 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM:
536 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM:
537 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM:
538 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM_ec:
539 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM_ec:
540 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM_ec:
541 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM_ec:
542 return S_BUFFER_LOAD_IMM;
543 case AMDGPU::S_BUFFER_LOAD_DWORD_SGPR_IMM:
544 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM:
545 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM:
546 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM:
547 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM:
548 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM_ec:
549 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM_ec:
550 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM_ec:
551 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM_ec:
552 return S_BUFFER_LOAD_SGPR_IMM;
553 case AMDGPU::S_LOAD_DWORD_IMM:
554 case AMDGPU::S_LOAD_DWORDX2_IMM:
555 case AMDGPU::S_LOAD_DWORDX3_IMM:
556 case AMDGPU::S_LOAD_DWORDX4_IMM:
557 case AMDGPU::S_LOAD_DWORDX8_IMM:
558 case AMDGPU::S_LOAD_DWORDX2_IMM_ec:
559 case AMDGPU::S_LOAD_DWORDX3_IMM_ec:
560 case AMDGPU::S_LOAD_DWORDX4_IMM_ec:
561 case AMDGPU::S_LOAD_DWORDX8_IMM_ec:
563 case AMDGPU::DS_READ_B32:
564 case AMDGPU::DS_READ_B32_gfx9:
565 case AMDGPU::DS_READ_B64:
566 case AMDGPU::DS_READ_B64_gfx9:
568 case AMDGPU::DS_WRITE_B32:
569 case AMDGPU::DS_WRITE_B32_gfx9:
570 case AMDGPU::DS_WRITE_B64:
571 case AMDGPU::DS_WRITE_B64_gfx9:
573 case AMDGPU::GLOBAL_LOAD_DWORD:
574 case AMDGPU::GLOBAL_LOAD_DWORDX2:
575 case AMDGPU::GLOBAL_LOAD_DWORDX3:
576 case AMDGPU::GLOBAL_LOAD_DWORDX4:
577 case AMDGPU::FLAT_LOAD_DWORD:
578 case AMDGPU::FLAT_LOAD_DWORDX2:
579 case AMDGPU::FLAT_LOAD_DWORDX3:
580 case AMDGPU::FLAT_LOAD_DWORDX4:
582 case AMDGPU::GLOBAL_LOAD_DWORD_SADDR:
583 case AMDGPU::GLOBAL_LOAD_DWORDX2_SADDR:
584 case AMDGPU::GLOBAL_LOAD_DWORDX3_SADDR:
585 case AMDGPU::GLOBAL_LOAD_DWORDX4_SADDR:
586 return GLOBAL_LOAD_SADDR;
587 case AMDGPU::GLOBAL_STORE_DWORD:
588 case AMDGPU::GLOBAL_STORE_DWORDX2:
589 case AMDGPU::GLOBAL_STORE_DWORDX3:
590 case AMDGPU::GLOBAL_STORE_DWORDX4:
591 case AMDGPU::FLAT_STORE_DWORD:
592 case AMDGPU::FLAT_STORE_DWORDX2:
593 case AMDGPU::FLAT_STORE_DWORDX3:
594 case AMDGPU::FLAT_STORE_DWORDX4:
596 case AMDGPU::GLOBAL_STORE_DWORD_SADDR:
597 case AMDGPU::GLOBAL_STORE_DWORDX2_SADDR:
598 case AMDGPU::GLOBAL_STORE_DWORDX3_SADDR:
599 case AMDGPU::GLOBAL_STORE_DWORDX4_SADDR:
600 return GLOBAL_STORE_SADDR;
601 case AMDGPU::FLAT_LOAD_DWORD_SADDR:
602 case AMDGPU::FLAT_LOAD_DWORDX2_SADDR:
603 case AMDGPU::FLAT_LOAD_DWORDX3_SADDR:
604 case AMDGPU::FLAT_LOAD_DWORDX4_SADDR:
605 return FLAT_LOAD_SADDR;
606 case AMDGPU::FLAT_STORE_DWORD_SADDR:
607 case AMDGPU::FLAT_STORE_DWORDX2_SADDR:
608 case AMDGPU::FLAT_STORE_DWORDX3_SADDR:
609 case AMDGPU::FLAT_STORE_DWORDX4_SADDR:
610 return FLAT_STORE_SADDR;
625 return Info->BaseOpcode;
630 case AMDGPU::DS_READ_B32:
631 case AMDGPU::DS_READ_B32_gfx9:
632 case AMDGPU::DS_READ_B64:
633 case AMDGPU::DS_READ_B64_gfx9:
634 case AMDGPU::DS_WRITE_B32:
635 case AMDGPU::DS_WRITE_B32_gfx9:
636 case AMDGPU::DS_WRITE_B64:
637 case AMDGPU::DS_WRITE_B64_gfx9:
639 case AMDGPU::S_BUFFER_LOAD_DWORD_IMM:
640 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM:
641 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM:
642 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM:
643 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM:
644 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM_ec:
645 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM_ec:
646 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM_ec:
647 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM_ec:
648 return AMDGPU::S_BUFFER_LOAD_DWORD_IMM;
649 case AMDGPU::S_BUFFER_LOAD_DWORD_SGPR_IMM:
650 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM:
651 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM:
652 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM:
653 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM:
654 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM_ec:
655 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM_ec:
656 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM_ec:
657 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM_ec:
658 return AMDGPU::S_BUFFER_LOAD_DWORD_SGPR_IMM;
659 case AMDGPU::S_LOAD_DWORD_IMM:
660 case AMDGPU::S_LOAD_DWORDX2_IMM:
661 case AMDGPU::S_LOAD_DWORDX3_IMM:
662 case AMDGPU::S_LOAD_DWORDX4_IMM:
663 case AMDGPU::S_LOAD_DWORDX8_IMM:
664 case AMDGPU::S_LOAD_DWORDX2_IMM_ec:
665 case AMDGPU::S_LOAD_DWORDX3_IMM_ec:
666 case AMDGPU::S_LOAD_DWORDX4_IMM_ec:
667 case AMDGPU::S_LOAD_DWORDX8_IMM_ec:
668 return AMDGPU::S_LOAD_DWORD_IMM;
669 case AMDGPU::GLOBAL_LOAD_DWORD:
670 case AMDGPU::GLOBAL_LOAD_DWORDX2:
671 case AMDGPU::GLOBAL_LOAD_DWORDX3:
672 case AMDGPU::GLOBAL_LOAD_DWORDX4:
673 case AMDGPU::FLAT_LOAD_DWORD:
674 case AMDGPU::FLAT_LOAD_DWORDX2:
675 case AMDGPU::FLAT_LOAD_DWORDX3:
676 case AMDGPU::FLAT_LOAD_DWORDX4:
677 return AMDGPU::FLAT_LOAD_DWORD;
678 case AMDGPU::GLOBAL_LOAD_DWORD_SADDR:
679 case AMDGPU::GLOBAL_LOAD_DWORDX2_SADDR:
680 case AMDGPU::GLOBAL_LOAD_DWORDX3_SADDR:
681 case AMDGPU::GLOBAL_LOAD_DWORDX4_SADDR:
682 return AMDGPU::GLOBAL_LOAD_DWORD_SADDR;
683 case AMDGPU::GLOBAL_STORE_DWORD:
684 case AMDGPU::GLOBAL_STORE_DWORDX2:
685 case AMDGPU::GLOBAL_STORE_DWORDX3:
686 case AMDGPU::GLOBAL_STORE_DWORDX4:
687 case AMDGPU::FLAT_STORE_DWORD:
688 case AMDGPU::FLAT_STORE_DWORDX2:
689 case AMDGPU::FLAT_STORE_DWORDX3:
690 case AMDGPU::FLAT_STORE_DWORDX4:
691 return AMDGPU::FLAT_STORE_DWORD;
692 case AMDGPU::GLOBAL_STORE_DWORD_SADDR:
693 case AMDGPU::GLOBAL_STORE_DWORDX2_SADDR:
694 case AMDGPU::GLOBAL_STORE_DWORDX3_SADDR:
695 case AMDGPU::GLOBAL_STORE_DWORDX4_SADDR:
696 return AMDGPU::GLOBAL_STORE_DWORD_SADDR;
697 case AMDGPU::FLAT_LOAD_DWORD_SADDR:
698 case AMDGPU::FLAT_LOAD_DWORDX2_SADDR:
699 case AMDGPU::FLAT_LOAD_DWORDX3_SADDR:
700 case AMDGPU::FLAT_LOAD_DWORDX4_SADDR:
701 return AMDGPU::FLAT_LOAD_DWORD_SADDR;
702 case AMDGPU::FLAT_STORE_DWORD_SADDR:
703 case AMDGPU::FLAT_STORE_DWORDX2_SADDR:
704 case AMDGPU::FLAT_STORE_DWORDX3_SADDR:
705 case AMDGPU::FLAT_STORE_DWORDX4_SADDR:
706 return AMDGPU::FLAT_STORE_DWORD_SADDR;
717SILoadStoreOptimizer::getCommonInstClass(
const CombineInfo &CI,
718 const CombineInfo &Paired) {
719 assert(CI.InstClass == Paired.InstClass);
721 if ((CI.InstClass == FLAT_LOAD || CI.InstClass == FLAT_STORE) &&
723 return (CI.InstClass == FLAT_STORE) ? GLOBAL_STORE : GLOBAL_LOAD;
737 Result.SOffset =
true;
743 int VAddr0Idx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0);
744 if (VAddr0Idx >= 0) {
745 AMDGPU::OpName RsrcName =
746 TII.isMIMG(
Opc) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
747 int RsrcIdx = AMDGPU::getNamedOperandIdx(
Opc, RsrcName);
748 Result.NumVAddrs = RsrcIdx - VAddr0Idx;
765 Result.SOffset =
true;
773 case AMDGPU::S_BUFFER_LOAD_DWORD_SGPR_IMM:
774 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM:
775 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM:
776 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM:
777 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM:
778 case AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM_ec:
779 case AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM_ec:
780 case AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM_ec:
781 case AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM_ec:
782 Result.SOffset =
true;
784 case AMDGPU::S_BUFFER_LOAD_DWORD_IMM:
785 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM:
786 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM:
787 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM:
788 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM:
789 case AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM_ec:
790 case AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM_ec:
791 case AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM_ec:
792 case AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM_ec:
793 case AMDGPU::S_LOAD_DWORD_IMM:
794 case AMDGPU::S_LOAD_DWORDX2_IMM:
795 case AMDGPU::S_LOAD_DWORDX3_IMM:
796 case AMDGPU::S_LOAD_DWORDX4_IMM:
797 case AMDGPU::S_LOAD_DWORDX8_IMM:
798 case AMDGPU::S_LOAD_DWORDX2_IMM_ec:
799 case AMDGPU::S_LOAD_DWORDX3_IMM_ec:
800 case AMDGPU::S_LOAD_DWORDX4_IMM_ec:
801 case AMDGPU::S_LOAD_DWORDX8_IMM_ec:
804 case AMDGPU::DS_READ_B32:
805 case AMDGPU::DS_READ_B64:
806 case AMDGPU::DS_READ_B32_gfx9:
807 case AMDGPU::DS_READ_B64_gfx9:
808 case AMDGPU::DS_WRITE_B32:
809 case AMDGPU::DS_WRITE_B64:
810 case AMDGPU::DS_WRITE_B32_gfx9:
811 case AMDGPU::DS_WRITE_B64_gfx9:
814 case AMDGPU::GLOBAL_LOAD_DWORD_SADDR:
815 case AMDGPU::GLOBAL_LOAD_DWORDX2_SADDR:
816 case AMDGPU::GLOBAL_LOAD_DWORDX3_SADDR:
817 case AMDGPU::GLOBAL_LOAD_DWORDX4_SADDR:
818 case AMDGPU::GLOBAL_STORE_DWORD_SADDR:
819 case AMDGPU::GLOBAL_STORE_DWORDX2_SADDR:
820 case AMDGPU::GLOBAL_STORE_DWORDX3_SADDR:
821 case AMDGPU::GLOBAL_STORE_DWORDX4_SADDR:
822 case AMDGPU::FLAT_LOAD_DWORD_SADDR:
823 case AMDGPU::FLAT_LOAD_DWORDX2_SADDR:
824 case AMDGPU::FLAT_LOAD_DWORDX3_SADDR:
825 case AMDGPU::FLAT_LOAD_DWORDX4_SADDR:
826 case AMDGPU::FLAT_STORE_DWORD_SADDR:
827 case AMDGPU::FLAT_STORE_DWORDX2_SADDR:
828 case AMDGPU::FLAT_STORE_DWORDX3_SADDR:
829 case AMDGPU::FLAT_STORE_DWORDX4_SADDR:
832 case AMDGPU::GLOBAL_LOAD_DWORD:
833 case AMDGPU::GLOBAL_LOAD_DWORDX2:
834 case AMDGPU::GLOBAL_LOAD_DWORDX3:
835 case AMDGPU::GLOBAL_LOAD_DWORDX4:
836 case AMDGPU::GLOBAL_STORE_DWORD:
837 case AMDGPU::GLOBAL_STORE_DWORDX2:
838 case AMDGPU::GLOBAL_STORE_DWORDX3:
839 case AMDGPU::GLOBAL_STORE_DWORDX4:
840 case AMDGPU::FLAT_LOAD_DWORD:
841 case AMDGPU::FLAT_LOAD_DWORDX2:
842 case AMDGPU::FLAT_LOAD_DWORDX3:
843 case AMDGPU::FLAT_LOAD_DWORDX4:
844 case AMDGPU::FLAT_STORE_DWORD:
845 case AMDGPU::FLAT_STORE_DWORDX2:
846 case AMDGPU::FLAT_STORE_DWORDX3:
847 case AMDGPU::FLAT_STORE_DWORDX4:
854 const SILoadStoreOptimizer &LSO) {
856 unsigned Opc =
MI->getOpcode();
857 InstClass = getInstClass(
Opc, *LSO.TII);
859 if (InstClass == UNKNOWN)
862 DataRC = LSO.getDataRegClass(*
MI);
867 (
Opc == AMDGPU::DS_READ_B64 ||
Opc == AMDGPU::DS_READ_B64_gfx9) ? 8
872 (
Opc == AMDGPU::DS_WRITE_B64 ||
Opc == AMDGPU::DS_WRITE_B64_gfx9) ? 8
875 case S_BUFFER_LOAD_IMM:
876 case S_BUFFER_LOAD_SGPR_IMM:
885 if (InstClass == MIMG) {
890 int OffsetIdx = AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::offset);
891 Offset =
I->getOperand(OffsetIdx).getImm();
894 if (InstClass == TBUFFER_LOAD || InstClass == TBUFFER_STORE) {
898 EltSize = Info->BitsPerComp / 8;
901 Width = getOpcodeWidth(*
I, *LSO.TII);
903 if ((InstClass == DS_READ) || (InstClass == DS_WRITE)) {
906 }
else if (InstClass != MIMG) {
910 AddressRegs Regs = getRegs(
Opc, *LSO.TII);
914 for (
unsigned J = 0; J < Regs.NumVAddrs; J++)
915 AddrIdx[NumAddresses++] =
916 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr0) + J;
918 AddrIdx[NumAddresses++] =
919 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::addr);
921 AddrIdx[NumAddresses++] =
922 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::sbase);
924 AddrIdx[NumAddresses++] = AMDGPU::getNamedOperandIdx(
925 Opc, isVIMAGEorVSAMPLE ? AMDGPU::OpName::rsrc : AMDGPU::OpName::srsrc);
927 AddrIdx[NumAddresses++] =
928 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::soffset);
930 AddrIdx[NumAddresses++] =
931 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::saddr);
933 AddrIdx[NumAddresses++] =
934 AMDGPU::getNamedOperandIdx(
Opc, AMDGPU::OpName::vaddr);
936 AddrIdx[NumAddresses++] = AMDGPU::getNamedOperandIdx(
937 Opc, isVIMAGEorVSAMPLE ? AMDGPU::OpName::samp : AMDGPU::OpName::ssamp);
938 assert(NumAddresses <= MaxAddressRegs);
940 for (
unsigned J = 0; J < NumAddresses; J++)
941 AddrReg[J] = &
I->getOperand(AddrIdx[J]);
947 "SI Load Store Optimizer",
false,
false)
952char SILoadStoreOptimizerLegacy::ID = 0;
959 for (
const auto &
Op :
MI.operands()) {
963 RegDefs.insert(Op.getReg());
965 RegUses.insert(Op.getReg());
969bool SILoadStoreOptimizer::canSwapInstructions(
970 const DenseSet<Register> &ARegDefs,
const DenseSet<Register> &ARegUses,
971 const MachineInstr &
A,
const MachineInstr &
B)
const {
972 if (
A.mayLoadOrStore() &&
B.mayLoadOrStore() &&
973 (
A.mayStore() ||
B.mayStore()) &&
A.mayAlias(AA,
B,
true))
975 for (
const auto &BOp :
B.operands()) {
978 if ((BOp.isDef() || BOp.readsReg()) && ARegDefs.
contains(BOp.getReg()))
980 if (BOp.isDef() && ARegUses.
contains(BOp.getReg()))
989SILoadStoreOptimizer::combineKnownAdjacentMMOs(
const CombineInfo &CI,
990 const CombineInfo &Paired) {
991 const MachineMemOperand *MMOa = *CI.I->memoperands_begin();
992 const MachineMemOperand *MMOb = *Paired.I->memoperands_begin();
1010bool SILoadStoreOptimizer::dmasksCanBeCombined(
const CombineInfo &CI,
1011 const SIInstrInfo &
TII,
1012 const CombineInfo &Paired) {
1013 assert(CI.InstClass == MIMG);
1016 const auto *TFEOp =
TII.getNamedOperand(*CI.I, AMDGPU::OpName::tfe);
1017 const auto *LWEOp =
TII.getNamedOperand(*CI.I, AMDGPU::OpName::lwe);
1019 if ((TFEOp && TFEOp->getImm()) || (LWEOp && LWEOp->getImm()))
1023 AMDGPU::OpName OperandsToMatch[] = {
1024 AMDGPU::OpName::cpol, AMDGPU::OpName::d16, AMDGPU::OpName::unorm,
1025 AMDGPU::OpName::da, AMDGPU::OpName::r128, AMDGPU::OpName::a16,
1026 AMDGPU::OpName::dim};
1028 for (AMDGPU::OpName
op : OperandsToMatch) {
1029 int Idx = AMDGPU::getNamedOperandIdx(CI.I->getOpcode(),
op);
1030 if (AMDGPU::getNamedOperandIdx(Paired.I->getOpcode(),
op) != Idx)
1033 CI.I->getOperand(Idx).getImm() != Paired.I->getOperand(Idx).getImm())
1038 unsigned MaxMask = std::max(CI.DMask, Paired.DMask);
1039 unsigned MinMask = std::min(CI.DMask, Paired.DMask);
1045 if ((1u << AllowedBitsForMin) <= MinMask)
1052 unsigned ComponentCount,
1054 if (ComponentCount > 4)
1073 return NewFormatInfo->
Format;
1086bool SILoadStoreOptimizer::offsetsCanBeCombined(CombineInfo &CI,
1087 const GCNSubtarget &STI,
1088 CombineInfo &Paired,
1090 assert(CI.InstClass != MIMG);
1094 if (CI.Offset == Paired.Offset)
1097 if (CI.GDS != Paired.GDS)
1101 if ((CI.Offset % CI.EltSize != 0) || (Paired.Offset % CI.EltSize != 0))
1104 if (CI.InstClass == TBUFFER_LOAD || CI.InstClass == TBUFFER_STORE) {
1106 const llvm::AMDGPU::GcnBufferFormatInfo *Info0 =
1108 const llvm::AMDGPU::GcnBufferFormatInfo *Info1 =
1120 unsigned NumCombinedComponents = CI.Width + Paired.Width;
1121 if (NumCombinedComponents == 3 && CI.EltSize <= 2)
1122 NumCombinedComponents = 4;
1130 unsigned ElemIndex0 = CI.Offset / CI.EltSize;
1131 unsigned ElemIndex1 = Paired.Offset / Paired.EltSize;
1132 if (ElemIndex0 + CI.Width != ElemIndex1 &&
1133 ElemIndex1 + Paired.Width != ElemIndex0)
1139 unsigned MergedBytes = CI.EltSize * NumCombinedComponents;
1140 Align RequiredAlign(std::min(MergedBytes, 4u));
1145 const CombineInfo &Leading = Paired < CI ? Paired : CI;
1148 Align(std::min(CI.EltSize, 4u)));
1149 return KnownAlign >= RequiredAlign;
1152 uint32_t EltOffset0 = CI.Offset / CI.EltSize;
1153 uint32_t EltOffset1 = Paired.Offset / CI.EltSize;
1158 if ((CI.InstClass != DS_READ) && (CI.InstClass != DS_WRITE)) {
1159 if (EltOffset0 + CI.Width != EltOffset1 &&
1160 EltOffset1 + Paired.Width != EltOffset0)
1166 if (CI.InstClass == S_LOAD_IMM || CI.InstClass == S_BUFFER_LOAD_IMM ||
1167 CI.InstClass == S_BUFFER_LOAD_SGPR_IMM) {
1173 if (CI.Width != Paired.Width &&
1174 (CI.Width < Paired.Width) == (CI.Offset < Paired.Offset))
1182 if ((EltOffset0 % 64 == 0) && (EltOffset1 % 64) == 0 &&
1185 CI.Offset = EltOffset0 / 64;
1186 Paired.Offset = EltOffset1 / 64;
1195 CI.Offset = EltOffset0;
1196 Paired.Offset = EltOffset1;
1202 uint32_t Min = std::min(EltOffset0, EltOffset1);
1203 uint32_t
Max = std::max(EltOffset0, EltOffset1);
1206 if (((Max - Min) & ~Mask) == 0) {
1215 CI.BaseOff = BaseOff * CI.EltSize;
1216 CI.Offset = (EltOffset0 - BaseOff) / 64;
1217 Paired.Offset = (EltOffset1 - BaseOff) / 64;
1229 CI.BaseOff = BaseOff * CI.EltSize;
1230 CI.Offset = EltOffset0 - BaseOff;
1231 Paired.Offset = EltOffset1 - BaseOff;
1239bool SILoadStoreOptimizer::widthsFit(
const GCNSubtarget &STM,
1240 const CombineInfo &CI,
1241 const CombineInfo &Paired) {
1242 const unsigned Width = (CI.Width + Paired.Width);
1243 switch (CI.InstClass) {
1246 case S_BUFFER_LOAD_IMM:
1247 case S_BUFFER_LOAD_SGPR_IMM:
1257 return STM.hasScalarDwordx3Loads();
1263SILoadStoreOptimizer::getDataRegClass(
const MachineInstr &
MI)
const {
1264 if (
const auto *Dst =
TII->getNamedOperand(
MI, AMDGPU::OpName::vdst)) {
1265 return TRI->getRegClassForReg(*
MRI, Dst->getReg());
1267 if (
const auto *Src =
TII->getNamedOperand(
MI, AMDGPU::OpName::vdata)) {
1268 return TRI->getRegClassForReg(*
MRI, Src->getReg());
1270 if (
const auto *Src =
TII->getNamedOperand(
MI, AMDGPU::OpName::data0)) {
1271 return TRI->getRegClassForReg(*
MRI, Src->getReg());
1273 if (
const auto *Dst =
TII->getNamedOperand(
MI, AMDGPU::OpName::sdst)) {
1274 return TRI->getRegClassForReg(*
MRI, Dst->getReg());
1276 if (
const auto *Src =
TII->getNamedOperand(
MI, AMDGPU::OpName::sdata)) {
1277 return TRI->getRegClassForReg(*
MRI, Src->getReg());
1284SILoadStoreOptimizer::CombineInfo *
1285SILoadStoreOptimizer::checkAndPrepareMerge(CombineInfo &CI,
1286 CombineInfo &Paired) {
1289 if (CI.InstClass == UNKNOWN || Paired.InstClass == UNKNOWN)
1291 assert(CI.InstClass == Paired.InstClass);
1293 if (getInstSubclass(CI.I->getOpcode(), *
TII) !=
1294 getInstSubclass(Paired.I->getOpcode(), *
TII))
1299 if (CI.InstClass == MIMG) {
1300 if (!dmasksCanBeCombined(CI, *
TII, Paired))
1303 if (!widthsFit(*STM, CI, Paired) || !offsetsCanBeCombined(CI, *STM, Paired))
1307 DenseSet<Register> RegDefs;
1308 DenseSet<Register> RegUses;
1310 if (CI.I->mayLoad()) {
1314 if (!canSwapInstructions(RegDefs, RegUses, *Paired.I, *
MBBI))
1322 if (!canSwapInstructions(RegDefs, RegUses, *CI.I, *
MBBI))
1332 if (CI.InstClass == DS_READ || CI.InstClass == DS_WRITE) {
1333 if (STM->hasNeedsAligned2addrDS() &&
1334 (CI.I->memoperands_empty() ||
1335 (*CI.I->memoperands_begin())->getAlign().value() < CI.Width * 4))
1337 offsetsCanBeCombined(CI, *STM, Paired,
true);
1340 if (CI.InstClass == DS_WRITE) {
1348 const MachineOperand *Data0 =
1349 TII->getNamedOperand(*CI.I, AMDGPU::OpName::data0);
1350 const MachineOperand *Data1 =
1351 TII->getNamedOperand(*Paired.I, AMDGPU::OpName::data0);
1353 const MCInstrDesc &Write2Opc =
TII->get(getWrite2Opcode(CI));
1354 int Data0Idx = AMDGPU::getNamedOperandIdx(Write2Opc.
getOpcode(),
1355 AMDGPU::OpName::data0);
1356 int Data1Idx = AMDGPU::getNamedOperandIdx(Write2Opc.
getOpcode(),
1357 AMDGPU::OpName::data1);
1363 if (
unsigned SubReg = Data0->
getSubReg()) {
1368 if (
unsigned SubReg = Data1->
getSubReg()) {
1386void SILoadStoreOptimizer::copyToDestRegs(
1387 CombineInfo &CI, CombineInfo &Paired,
1389 AMDGPU::OpName OpName,
Register DestReg)
const {
1390 MachineBasicBlock *
MBB = CI.I->getParent();
1392 auto [SubRegIdx0, SubRegIdx1] = getSubRegIdxs(CI, Paired);
1395 const MCInstrDesc &CopyDesc =
TII->get(TargetOpcode::COPY);
1396 auto *Dest0 =
TII->getNamedOperand(*CI.I, OpName);
1397 auto *Dest1 =
TII->getNamedOperand(*Paired.I, OpName);
1402 Dest0->setIsEarlyClobber(
false);
1403 Dest1->setIsEarlyClobber(
false);
1407 .
addReg(DestReg, {}, SubRegIdx0);
1410 .
addReg(DestReg, {}, SubRegIdx1);
1416SILoadStoreOptimizer::copyFromSrcRegs(CombineInfo &CI, CombineInfo &Paired,
1419 AMDGPU::OpName OpName)
const {
1420 MachineBasicBlock *
MBB = CI.I->getParent();
1422 auto [SubRegIdx0, SubRegIdx1] = getSubRegIdxs(CI, Paired);
1428 const auto *
Src0 =
TII->getNamedOperand(*CI.I, OpName);
1429 const auto *
Src1 =
TII->getNamedOperand(*Paired.I, OpName);
1431 BuildMI(*
MBB, InsertBefore,
DL,
TII->get(AMDGPU::REG_SEQUENCE), SrcReg)
1440unsigned SILoadStoreOptimizer::read2Opcode(
unsigned EltSize,
bool GDS)
const {
1442 return (EltSize == 4) ? AMDGPU::DS_READ2_B32 : AMDGPU::DS_READ2_B64;
1443 return (EltSize == 4) ? AMDGPU::DS_READ2_B32_gfx9 : AMDGPU::DS_READ2_B64_gfx9;
1446unsigned SILoadStoreOptimizer::read2ST64Opcode(
unsigned EltSize,
1449 return (EltSize == 4) ? AMDGPU::DS_READ2ST64_B32 : AMDGPU::DS_READ2ST64_B64;
1451 return (EltSize == 4) ? AMDGPU::DS_READ2ST64_B32_gfx9
1452 : AMDGPU::DS_READ2ST64_B64_gfx9;
1456SILoadStoreOptimizer::mergeRead2Pair(CombineInfo &CI, CombineInfo &Paired,
1458 MachineBasicBlock *
MBB = CI.I->getParent();
1462 const auto *AddrReg =
TII->getNamedOperand(*CI.I, AMDGPU::OpName::addr);
1464 unsigned NewOffset0 = std::min(CI.Offset, Paired.Offset);
1465 unsigned NewOffset1 = std::max(CI.Offset, Paired.Offset);
1466 unsigned Opc = CI.UseST64 ? read2ST64Opcode(CI.EltSize, CI.GDS)
1467 : read2Opcode(CI.EltSize, CI.GDS);
1470 (NewOffset0 != NewOffset1) &&
"Computed offset doesn't fit");
1472 const MCInstrDesc &Read2Desc =
TII->get(
Opc);
1481 unsigned BaseSubReg = AddrReg->getSubReg();
1489 TII->getAddNoCarry(*
MBB, InsertBefore,
DL, BaseReg)
1491 .addReg(AddrReg->getReg(), {}, BaseSubReg)
1496 MachineInstrBuilder Read2 =
1498 .
addReg(BaseReg, {}, BaseSubReg)
1504 copyToDestRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdst, DestReg);
1506 CI.I->eraseFromParent();
1507 Paired.I->eraseFromParent();
1513unsigned SILoadStoreOptimizer::write2Opcode(
unsigned EltSize,
bool GDS)
const {
1515 return (EltSize == 4) ? AMDGPU::DS_WRITE2_B32 : AMDGPU::DS_WRITE2_B64;
1516 return (EltSize == 4) ? AMDGPU::DS_WRITE2_B32_gfx9
1517 : AMDGPU::DS_WRITE2_B64_gfx9;
1520unsigned SILoadStoreOptimizer::write2ST64Opcode(
unsigned EltSize,
1523 return (EltSize == 4) ? AMDGPU::DS_WRITE2ST64_B32
1524 : AMDGPU::DS_WRITE2ST64_B64;
1526 return (EltSize == 4) ? AMDGPU::DS_WRITE2ST64_B32_gfx9
1527 : AMDGPU::DS_WRITE2ST64_B64_gfx9;
1530unsigned SILoadStoreOptimizer::getWrite2Opcode(
const CombineInfo &CI)
const {
1531 return CI.UseST64 ? write2ST64Opcode(CI.EltSize, CI.GDS)
1532 : write2Opcode(CI.EltSize, CI.GDS);
1536 CombineInfo &CI, CombineInfo &Paired,
1538 MachineBasicBlock *
MBB = CI.I->getParent();
1542 const MachineOperand *AddrReg =
1543 TII->getNamedOperand(*CI.I, AMDGPU::OpName::addr);
1544 const MachineOperand *Data0 =
1545 TII->getNamedOperand(*CI.I, AMDGPU::OpName::data0);
1546 const MachineOperand *Data1 =
1547 TII->getNamedOperand(*Paired.I, AMDGPU::OpName::data0);
1549 unsigned NewOffset0 = CI.Offset;
1550 unsigned NewOffset1 = Paired.Offset;
1551 unsigned Opc = getWrite2Opcode(CI);
1553 if (NewOffset0 > NewOffset1) {
1560 (NewOffset0 != NewOffset1) &&
"Computed offset doesn't fit");
1562 const MCInstrDesc &Write2Desc =
TII->get(
Opc);
1567 unsigned BaseSubReg = AddrReg->
getSubReg();
1575 TII->getAddNoCarry(*
MBB, InsertBefore,
DL, BaseReg)
1577 .addReg(AddrReg->
getReg(), {}, BaseSubReg)
1582 MachineInstrBuilder Write2 =
BuildMI(*
MBB, InsertBefore,
DL, Write2Desc)
1583 .
addReg(BaseReg, {}, BaseSubReg)
1589 .cloneMergedMemRefs({&*CI.I, &*Paired.I});
1591 CI.I->eraseFromParent();
1592 Paired.I->eraseFromParent();
1594 LLVM_DEBUG(
dbgs() <<
"Inserted write2 inst: " << *Write2 <<
'\n');
1599SILoadStoreOptimizer::mergeImagePair(CombineInfo &CI, CombineInfo &Paired,
1601 MachineBasicBlock *
MBB = CI.I->getParent();
1605 const unsigned Opcode = getNewOpcode(CI, Paired);
1610 unsigned MergedDMask = CI.DMask | Paired.DMask;
1612 AMDGPU::getNamedOperandIdx(CI.I->getOpcode(), AMDGPU::OpName::dmask);
1614 auto MIB =
BuildMI(*
MBB, InsertBefore,
DL,
TII->get(Opcode), DestReg);
1615 for (
unsigned I = 1,
E = (*CI.I).getNumOperands();
I !=
E; ++
I) {
1617 MIB.addImm(MergedDMask);
1619 MIB.add((*CI.I).getOperand(
I));
1625 assert(CI.I->hasOneMemOperand() && Paired.I->hasOneMemOperand());
1627 MachineInstr *
New = MIB.addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1629 copyToDestRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdata, DestReg);
1631 CI.I->eraseFromParent();
1632 Paired.I->eraseFromParent();
1637 CombineInfo &CI, CombineInfo &Paired,
1639 MachineBasicBlock *
MBB = CI.I->getParent();
1643 const unsigned Opcode = getNewOpcode(CI, Paired);
1648 unsigned MergedOffset = std::min(CI.Offset, Paired.Offset);
1653 assert(CI.I->hasOneMemOperand() && Paired.I->hasOneMemOperand());
1655 MachineInstrBuilder
New =
1657 .
add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::sbase));
1658 if (CI.InstClass == S_BUFFER_LOAD_SGPR_IMM)
1659 New.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::soffset));
1660 New.addImm(MergedOffset);
1661 New.addImm(CI.CPol).addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1663 copyToDestRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::sdst, DestReg);
1665 CI.I->eraseFromParent();
1666 Paired.I->eraseFromParent();
1671 CombineInfo &CI, CombineInfo &Paired,
1673 MachineBasicBlock *
MBB = CI.I->getParent();
1678 const unsigned Opcode = getNewOpcode(CI, Paired);
1684 unsigned MergedOffset = std::min(CI.Offset, Paired.Offset);
1686 auto MIB =
BuildMI(*
MBB, InsertBefore,
DL,
TII->get(Opcode), DestReg);
1688 AddressRegs Regs = getRegs(Opcode, *
TII);
1691 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr));
1696 assert(CI.I->hasOneMemOperand() && Paired.I->hasOneMemOperand());
1699 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::srsrc))
1700 .add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::soffset))
1701 .addImm(MergedOffset)
1704 .addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1706 copyToDestRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdata, DestReg);
1708 CI.I->eraseFromParent();
1709 Paired.I->eraseFromParent();
1714 CombineInfo &CI, CombineInfo &Paired,
1716 MachineBasicBlock *
MBB = CI.I->getParent();
1721 const unsigned Opcode = getNewOpcode(CI, Paired);
1727 unsigned MergedOffset = std::min(CI.Offset, Paired.Offset);
1729 auto MIB =
BuildMI(*
MBB, InsertBefore,
DL,
TII->get(Opcode), DestReg);
1731 AddressRegs Regs = getRegs(Opcode, *
TII);
1734 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr));
1739 unsigned NumCombinedComponents = CI.Width + Paired.Width;
1740 if (NumCombinedComponents == 3 && CI.EltSize <= 2)
1741 NumCombinedComponents = 4;
1742 unsigned JoinedFormat =
1748 assert(CI.I->hasOneMemOperand() && Paired.I->hasOneMemOperand());
1751 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::srsrc))
1752 .add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::soffset))
1753 .addImm(MergedOffset)
1754 .addImm(JoinedFormat)
1757 .addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1759 copyToDestRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdata, DestReg);
1761 CI.I->eraseFromParent();
1762 Paired.I->eraseFromParent();
1767 CombineInfo &CI, CombineInfo &Paired,
1769 MachineBasicBlock *
MBB = CI.I->getParent();
1773 const unsigned Opcode = getNewOpcode(CI, Paired);
1776 copyFromSrcRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdata);
1780 AddressRegs Regs = getRegs(Opcode, *
TII);
1783 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr));
1788 unsigned NumCombinedComponents = CI.Width + Paired.Width;
1789 if (NumCombinedComponents == 3 && CI.EltSize <= 2)
1790 NumCombinedComponents = 4;
1791 unsigned JoinedFormat =
1797 assert(CI.I->hasOneMemOperand() && Paired.I->hasOneMemOperand());
1800 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::srsrc))
1801 .add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::soffset))
1802 .addImm(std::min(CI.Offset, Paired.Offset))
1803 .addImm(JoinedFormat)
1806 .addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1808 CI.I->eraseFromParent();
1809 Paired.I->eraseFromParent();
1814 CombineInfo &CI, CombineInfo &Paired,
1816 MachineBasicBlock *
MBB = CI.I->getParent();
1821 const unsigned Opcode = getNewOpcode(CI, Paired);
1826 auto MIB =
BuildMI(*
MBB, InsertBefore,
DL,
TII->get(Opcode), DestReg);
1828 if (
auto *SAddr =
TII->getNamedOperand(*CI.I, AMDGPU::OpName::saddr))
1832 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr))
1833 .addImm(std::min(CI.Offset, Paired.Offset))
1835 .addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1837 copyToDestRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdst, DestReg);
1839 CI.I->eraseFromParent();
1840 Paired.I->eraseFromParent();
1845 CombineInfo &CI, CombineInfo &Paired,
1847 MachineBasicBlock *
MBB = CI.I->getParent();
1852 const unsigned Opcode = getNewOpcode(CI, Paired);
1855 copyFromSrcRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdata);
1858 .
add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr))
1861 if (
auto *SAddr =
TII->getNamedOperand(*CI.I, AMDGPU::OpName::saddr))
1865 MIB.addImm(std::min(CI.Offset, Paired.Offset))
1867 .addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
1869 CI.I->eraseFromParent();
1870 Paired.I->eraseFromParent();
1879 (MMOs.
size() != 1 || MMOs[0]->
getAlign().value() < Width * 4);
1882unsigned SILoadStoreOptimizer::getNewOpcode(
const CombineInfo &CI,
1883 const CombineInfo &Paired) {
1884 const unsigned Width = CI.Width + Paired.Width;
1885 const CombineInfo &Leading = Paired < CI ? Paired : CI;
1888 const bool NeedsConstrainedOpc =
1891 switch (getCommonInstClass(CI, Paired)) {
1893 assert(CI.InstClass == BUFFER_LOAD || CI.InstClass == BUFFER_STORE);
1904 case S_BUFFER_LOAD_IMM: {
1909 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM_ec
1910 : AMDGPU::S_BUFFER_LOAD_DWORDX2_IMM;
1912 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM_ec
1913 : AMDGPU::S_BUFFER_LOAD_DWORDX3_IMM;
1915 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM_ec
1916 : AMDGPU::S_BUFFER_LOAD_DWORDX4_IMM;
1918 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM_ec
1919 : AMDGPU::S_BUFFER_LOAD_DWORDX8_IMM;
1922 case S_BUFFER_LOAD_SGPR_IMM: {
1927 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM_ec
1928 : AMDGPU::S_BUFFER_LOAD_DWORDX2_SGPR_IMM;
1930 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM_ec
1931 : AMDGPU::S_BUFFER_LOAD_DWORDX3_SGPR_IMM;
1933 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM_ec
1934 : AMDGPU::S_BUFFER_LOAD_DWORDX4_SGPR_IMM;
1936 return NeedsConstrainedOpc ? AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM_ec
1937 : AMDGPU::S_BUFFER_LOAD_DWORDX8_SGPR_IMM;
1945 return NeedsConstrainedOpc ? AMDGPU::S_LOAD_DWORDX2_IMM_ec
1946 : AMDGPU::S_LOAD_DWORDX2_IMM;
1948 return NeedsConstrainedOpc ? AMDGPU::S_LOAD_DWORDX3_IMM_ec
1949 : AMDGPU::S_LOAD_DWORDX3_IMM;
1951 return NeedsConstrainedOpc ? AMDGPU::S_LOAD_DWORDX4_IMM_ec
1952 : AMDGPU::S_LOAD_DWORDX4_IMM;
1954 return NeedsConstrainedOpc ? AMDGPU::S_LOAD_DWORDX8_IMM_ec
1955 : AMDGPU::S_LOAD_DWORDX8_IMM;
1963 return AMDGPU::GLOBAL_LOAD_DWORDX2;
1965 return AMDGPU::GLOBAL_LOAD_DWORDX3;
1967 return AMDGPU::GLOBAL_LOAD_DWORDX4;
1969 case GLOBAL_LOAD_SADDR:
1974 return AMDGPU::GLOBAL_LOAD_DWORDX2_SADDR;
1976 return AMDGPU::GLOBAL_LOAD_DWORDX3_SADDR;
1978 return AMDGPU::GLOBAL_LOAD_DWORDX4_SADDR;
1985 return AMDGPU::GLOBAL_STORE_DWORDX2;
1987 return AMDGPU::GLOBAL_STORE_DWORDX3;
1989 return AMDGPU::GLOBAL_STORE_DWORDX4;
1991 case GLOBAL_STORE_SADDR:
1996 return AMDGPU::GLOBAL_STORE_DWORDX2_SADDR;
1998 return AMDGPU::GLOBAL_STORE_DWORDX3_SADDR;
2000 return AMDGPU::GLOBAL_STORE_DWORDX4_SADDR;
2007 return AMDGPU::FLAT_LOAD_DWORDX2;
2009 return AMDGPU::FLAT_LOAD_DWORDX3;
2011 return AMDGPU::FLAT_LOAD_DWORDX4;
2018 return AMDGPU::FLAT_STORE_DWORDX2;
2020 return AMDGPU::FLAT_STORE_DWORDX3;
2022 return AMDGPU::FLAT_STORE_DWORDX4;
2024 case FLAT_LOAD_SADDR:
2029 return AMDGPU::FLAT_LOAD_DWORDX2_SADDR;
2031 return AMDGPU::FLAT_LOAD_DWORDX3_SADDR;
2033 return AMDGPU::FLAT_LOAD_DWORDX4_SADDR;
2035 case FLAT_STORE_SADDR:
2040 return AMDGPU::FLAT_STORE_DWORDX2_SADDR;
2042 return AMDGPU::FLAT_STORE_DWORDX3_SADDR;
2044 return AMDGPU::FLAT_STORE_DWORDX4_SADDR;
2053std::pair<unsigned, unsigned>
2054SILoadStoreOptimizer::getSubRegIdxs(
const CombineInfo &CI,
2055 const CombineInfo &Paired) {
2056 assert((CI.InstClass != MIMG ||
2058 CI.Width + Paired.Width)) &&
2064 static const unsigned Idxs[5][4] = {
2065 {AMDGPU::sub0, AMDGPU::sub0_sub1, AMDGPU::sub0_sub1_sub2, AMDGPU::sub0_sub1_sub2_sub3},
2066 {AMDGPU::sub1, AMDGPU::sub1_sub2, AMDGPU::sub1_sub2_sub3, AMDGPU::sub1_sub2_sub3_sub4},
2067 {AMDGPU::sub2, AMDGPU::sub2_sub3, AMDGPU::sub2_sub3_sub4, AMDGPU::sub2_sub3_sub4_sub5},
2068 {AMDGPU::sub3, AMDGPU::sub3_sub4, AMDGPU::sub3_sub4_sub5, AMDGPU::sub3_sub4_sub5_sub6},
2069 {AMDGPU::sub4, AMDGPU::sub4_sub5, AMDGPU::sub4_sub5_sub6, AMDGPU::sub4_sub5_sub6_sub7},
2072 assert(CI.Width >= 1 && CI.Width <= 4);
2073 assert(Paired.Width >= 1 && Paired.Width <= 4);
2076 Idx1 = Idxs[0][Paired.Width - 1];
2077 Idx0 = Idxs[Paired.Width][CI.Width - 1];
2079 Idx0 = Idxs[0][CI.Width - 1];
2080 Idx1 = Idxs[CI.Width][Paired.Width - 1];
2083 return {Idx0, Idx1};
2087SILoadStoreOptimizer::getTargetRegisterClass(
const CombineInfo &CI,
2088 const CombineInfo &Paired)
const {
2089 if (CI.InstClass == S_BUFFER_LOAD_IMM ||
2090 CI.InstClass == S_BUFFER_LOAD_SGPR_IMM || CI.InstClass == S_LOAD_IMM) {
2091 switch (CI.Width + Paired.Width) {
2095 return &AMDGPU::SReg_64_XEXECRegClass;
2097 return &AMDGPU::SGPR_96RegClass;
2099 return &AMDGPU::SGPR_128RegClass;
2101 return &AMDGPU::SGPR_256RegClass;
2103 return &AMDGPU::SGPR_512RegClass;
2109 unsigned BitWidth = 32 * (CI.Width + Paired.Width);
2110 return TRI->isAGPRClass(getDataRegClass(*CI.I))
2116 CombineInfo &CI, CombineInfo &Paired,
2118 MachineBasicBlock *
MBB = CI.I->getParent();
2122 const unsigned Opcode = getNewOpcode(CI, Paired);
2125 copyFromSrcRegs(CI, Paired, InsertBefore,
DL, AMDGPU::OpName::vdata);
2129 AddressRegs Regs = getRegs(Opcode, *
TII);
2132 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::vaddr));
2138 assert(CI.I->hasOneMemOperand() && Paired.I->hasOneMemOperand());
2141 MIB.add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::srsrc))
2142 .add(*
TII->getNamedOperand(*CI.I, AMDGPU::OpName::soffset))
2143 .addImm(std::min(CI.Offset, Paired.Offset))
2146 .addMemOperand(combineKnownAdjacentMMOs(CI, Paired));
2148 CI.I->eraseFromParent();
2149 Paired.I->eraseFromParent();
2154SILoadStoreOptimizer::createRegOrImm(int32_t Val, MachineInstr &
MI)
const {
2155 APInt
V(32, Val,
true);
2156 if (
TII->isInlineConstant(
V))
2161 BuildMI(*
MI.getParent(),
MI.getIterator(),
MI.getDebugLoc(),
2162 TII->get(AMDGPU::S_MOV_B32),
Reg)
2170Register SILoadStoreOptimizer::computeBase(MachineInstr &
MI,
2171 const MemAddress &Addr)
const {
2179 if (Addr.Base.UseV64Pattern) {
2181 TII->getRegClass(
TII->get(AMDGPU::V_ADD_U64_e64), 0));
2185 MachineInstr *MovOffset =
2189 MachineInstr *
Add64 =
2203 if (Addr.Base.UseScratchVGPRPattern) {
2205 createRegOrImm(
static_cast<int32_t
>(Addr.Offset),
MI);
2208 MachineInstr *
Add32 =
2210 .
addReg(Addr.Base.LoReg, {}, Addr.Base.LoSubReg)
2220 assert((
TRI->getRegSizeInBits(Addr.Base.LoReg, *
MRI) == 32 ||
2221 Addr.Base.LoSubReg) &&
2222 "Expected 32-bit Base-Register-Low!!");
2224 assert((
TRI->getRegSizeInBits(Addr.Base.HiReg, *
MRI) == 32 ||
2225 Addr.Base.HiSubReg) &&
2226 "Expected 32-bit Base-Register-Hi!!");
2228 MachineOperand OffsetLo = createRegOrImm(
static_cast<int32_t
>(Addr.Offset),
MI);
2229 MachineOperand OffsetHi =
2230 createRegOrImm(
static_cast<int32_t
>(Addr.Offset >> 32),
MI);
2232 const auto *CarryRC =
TRI->getWaveMaskRegClass();
2238 MachineInstr *LoHalf =
2240 .
addReg(CarryReg, RegState::Define)
2241 .
addReg(Addr.Base.LoReg, {}, Addr.Base.LoSubReg)
2245 MachineInstr *HiHalf =
2247 .
addReg(DeadCarryReg, RegState::Define | RegState::Dead)
2248 .
addReg(Addr.Base.HiReg, {}, Addr.Base.HiSubReg)
2254 MachineInstr *FullBase =
2265 dbgs() <<
" " << *HiHalf <<
"\n";
2266 dbgs() <<
" " << *FullBase <<
"\n\n";);
2272void SILoadStoreOptimizer::updateBaseAndOffset(MachineInstr &
MI,
2274 int32_t NewOffset)
const {
2275 auto *
Base =
TII->getNamedOperand(
MI, AMDGPU::OpName::vaddr);
2276 Base->setReg(NewBase);
2277 Base->setIsKill(
false);
2278 TII->getNamedOperand(
MI, AMDGPU::OpName::offset)->setImm(NewOffset);
2284bool SILoadStoreOptimizer::processBaseWithConstOffset64(
2285 MachineInstr *AddDef,
const MachineOperand &
Base, MemAddress &Addr)
const {
2289 MachineOperand *
Src0 =
TII->getNamedOperand(*AddDef, AMDGPU::OpName::src0);
2290 MachineOperand *
Src1 =
TII->getNamedOperand(*AddDef, AMDGPU::OpName::src1);
2292 const MachineOperand *BaseOp =
nullptr;
2294 auto Offset =
TII->getImmOrMaterializedImm(*
MRI, *Src1);
2305 Addr.Base.LoReg = BaseOp->
getReg();
2306 Addr.Base.UseV64Pattern =
true;
2314bool SILoadStoreOptimizer::processBaseWithConstOffset32(
2315 MachineInstr *AddDef, MemAddress &Addr)
const {
2317 if (
TII->getNamedOperand(*AddDef, AMDGPU::OpName::clamp)->getImm())
2320 MachineOperand *
Src0 =
TII->getNamedOperand(*AddDef, AMDGPU::OpName::src0);
2321 MachineOperand *
Src1 =
TII->getNamedOperand(*AddDef, AMDGPU::OpName::src1);
2323 const MachineOperand *BaseOp =
nullptr;
2324 std::optional<int64_t>
Offset;
2326 if ((
Offset =
TII->getImmOrMaterializedImm(*
MRI, *Src1))) {
2328 }
else if ((
Offset =
TII->getImmOrMaterializedImm(*
MRI, *Src0))) {
2339 Addr.Base.LoReg = BaseOp->
getReg();
2340 Addr.Base.LoSubReg = BaseOp->
getSubReg();
2341 Addr.Base.UseScratchVGPRPattern =
true;
2364void SILoadStoreOptimizer::processBaseWithConstOffset(
const MachineOperand &
Base,
2365 MemAddress &Addr)
const {
2374 if (
Def->getOpcode() == AMDGPU::V_ADD_U64_e64) {
2375 if (processBaseWithConstOffset64(Def,
Base, Addr))
2381 if (
Def->getOpcode() == AMDGPU::V_ADD_U32_e64 &&
2383 if (processBaseWithConstOffset32(Def, Addr))
2388 if (
Def->getOpcode() != AMDGPU::REG_SEQUENCE ||
Def->getNumOperands() != 5)
2391 MachineOperand BaseLo =
Def->getOperand(1);
2392 MachineOperand BaseHi =
Def->getOperand(3);
2399 if (!BaseLoDef || BaseLoDef->
getOpcode() != AMDGPU::V_ADD_CO_U32_e64 ||
2400 !BaseHiDef || BaseHiDef->
getOpcode() != AMDGPU::V_ADDC_U32_e64)
2403 MachineOperand *
Src0 =
TII->getNamedOperand(*BaseLoDef, AMDGPU::OpName::src0);
2404 MachineOperand *
Src1 =
TII->getNamedOperand(*BaseLoDef, AMDGPU::OpName::src1);
2406 auto Offset0P =
TII->getImmOrMaterializedImm(*
MRI, *Src0);
2410 if (!(Offset0P =
TII->getImmOrMaterializedImm(*
MRI, *Src1)))
2415 if (!BaseLo.
isReg())
2418 Src0 =
TII->getNamedOperand(*BaseHiDef, AMDGPU::OpName::src0);
2419 Src1 =
TII->getNamedOperand(*BaseHiDef, AMDGPU::OpName::src1);
2424 if (!
Src1->isImm() ||
Src0->isImm())
2430 if (!BaseHi.
isReg())
2433 Addr.Base.LoReg = BaseLo.
getReg();
2434 Addr.Base.HiReg = BaseHi.
getReg();
2435 Addr.Base.LoSubReg = BaseLo.
getSubReg();
2436 Addr.Base.HiSubReg = BaseHi.
getSubReg();
2437 Addr.Offset = (*Offset0P & 0x00000000ffffffff) | (Offset1 << 32);
2444void SILoadStoreOptimizer::updateAsyncLDSAddress(MachineInstr &
MI,
2445 int32_t OffsetDiff)
const {
2446 if (!
TII->usesASYNC_CNT(
MI) || OffsetDiff == 0)
2449 MachineOperand *LDSAddr =
TII->getNamedOperand(
MI, AMDGPU::OpName::vdst);
2451 LDSAddr =
TII->getNamedOperand(
MI, AMDGPU::OpName::vdata);
2466bool SILoadStoreOptimizer::promoteConstantOffsetToImm(
2468 MemInfoMap &Visited,
2469 SmallPtrSet<MachineInstr *, 4> &
AnchorList)
const {
2475 !
TII->getNamedOperand(
MI, AMDGPU::OpName::vaddr))
2480 TII->getNamedOperand(
MI, AMDGPU::OpName::saddr))
2490 : AMDGPU::FlatAddrSpace::FLAT;
2491 bool AllowNegativeOffset =
2492 TII->allowNegativeFlatOffset(FlatVariant) && !
TII->usesASYNC_CNT(
MI);
2496 bool IsOffsetU16 =
TII->usesASYNC_CNT(
MI);
2503 if (
TII->getNamedOperand(
MI, AMDGPU::OpName::offset)->getImm()) {
2509 MachineOperand &
Base = *
TII->getNamedOperand(
MI, AMDGPU::OpName::vaddr);
2510 auto [It,
Inserted] = Visited.try_emplace(&
MI);
2513 processBaseWithConstOffset(
Base, MAddr);
2518 if (MAddr.Offset == 0) {
2519 LLVM_DEBUG(
dbgs() <<
" Failed to extract constant-offset or there are no"
2520 " constant offsets that can be promoted.\n";);
2526 <<
"} Offset: " << MAddr.Offset <<
"\n\n";);
2553 MachineInstr *AnchorInst =
nullptr;
2554 MemAddress AnchorAddr;
2555 uint32_t MaxDist = std::numeric_limits<uint32_t>::min();
2557 bool MIIsAnchor =
false;
2566 MachineInstr &MINext = *
MBBI;
2570 TII->getNamedOperand(MINext, AMDGPU::OpName::offset)->getImm())
2573 const MachineOperand &BaseNext =
2574 *
TII->getNamedOperand(MINext, AMDGPU::OpName::vaddr);
2575 MemAddress MAddrNext;
2576 auto [It,
Inserted] = Visited.try_emplace(&MINext);
2578 processBaseWithConstOffset(BaseNext, MAddrNext);
2579 It->second = MAddrNext;
2581 MAddrNext = It->second;
2583 if (MAddrNext.Base.LoReg != MAddr.Base.LoReg ||
2584 MAddrNext.Base.HiReg != MAddr.Base.HiReg ||
2585 MAddrNext.Base.LoSubReg != MAddr.Base.LoSubReg ||
2586 MAddrNext.Base.HiSubReg != MAddr.Base.HiSubReg)
2589 InstsWCommonBase.
emplace_back(&MINext, MAddrNext.Offset);
2591 if (AllowNegativeOffset) {
2592 int64_t Dist = MAddr.Offset - MAddrNext.Offset;
2593 TargetLoweringBase::AddrMode AM;
2596 if (
TLI->isLegalFlatAddressingMode(AM, AS) &&
2597 (uint32_t)std::abs(Dist) > MaxDist) {
2598 MaxDist = std::abs(Dist);
2600 AnchorAddr = MAddrNext;
2601 AnchorInst = &MINext;
2609 if (!AllowNegativeOffset && !InstsWCommonBase.
empty()) {
2610 for (
auto &[Inst,
Offset] : InstsWCommonBase) {
2611 int64_t Dist = MAddr.Offset -
Offset;
2612 TargetLoweringBase::AddrMode AM;
2615 if (Dist >= 0 &&
TLI->isLegalFlatAddressingMode(AM, AS) &&
2617 (!AnchorInst ||
Offset < AnchorAddr.Offset)) {
2618 AnchorAddr = Visited[Inst];
2627 LLVM_DEBUG(
dbgs() <<
" Anchor-Inst(with max-distance from Offset): ";
2628 AnchorInst->
dump());
2630 << AnchorAddr.Offset <<
"\n\n");
2635 int32_t OffsetDiff = MAddr.Offset - AnchorAddr.Offset;
2636 updateBaseAndOffset(
MI,
Base, OffsetDiff);
2637 updateAsyncLDSAddress(
MI, OffsetDiff);
2640 for (
auto [OtherMI, OtherOffset] : InstsWCommonBase) {
2641 TargetLoweringBase::AddrMode AM;
2643 AM.
BaseOffs = OtherOffset - AnchorAddr.Offset;
2645 if (
TLI->isLegalFlatAddressingMode(AM, AS) &&
2646 (AllowNegativeOffset || AM.
BaseOffs >= 0) &&
2650 int32_t OtherOffsetDiff = OtherOffset - AnchorAddr.Offset;
2651 updateBaseAndOffset(*OtherMI,
Base, OtherOffsetDiff);
2652 updateAsyncLDSAddress(*OtherMI, OtherOffsetDiff);
2661 LLVM_DEBUG(
dbgs() <<
" MI is anchor (smallest offset); promoting "
2662 "candidates relative to MI's base.\n");
2665 bool AnyPromoted =
false;
2667 for (
auto [OtherMI, OtherOffset] : InstsWCommonBase) {
2668 int64_t Dist = OtherOffset - MAddr.Offset;
2669 TargetLoweringBase::AddrMode AM;
2672 if (Dist >= 0 &&
TLI->isLegalFlatAddressingMode(AM, AS) &&
2676 updateBaseAndOffset(*OtherMI,
Base, Dist);
2677 updateAsyncLDSAddress(*OtherMI, Dist);
2684 TII->getNamedOperand(
MI, AMDGPU::OpName::vaddr)->setIsKill(
false);
2693void SILoadStoreOptimizer::addInstToMergeableList(
const CombineInfo &CI,
2694 std::list<std::list<CombineInfo> > &MergeableInsts)
const {
2695 for (std::list<CombineInfo> &AddrList : MergeableInsts) {
2696 if (AddrList.front().InstClass == CI.InstClass &&
2697 AddrList.front().hasSameBaseAddress(CI)) {
2698 AddrList.emplace_back(CI);
2704 MergeableInsts.emplace_back(1, CI);
2707std::pair<MachineBasicBlock::iterator, bool>
2708SILoadStoreOptimizer::collectMergeableInsts(
2710 MemInfoMap &Visited, SmallPtrSet<MachineInstr *, 4> &
AnchorList,
2711 std::list<std::list<CombineInfo>> &MergeableInsts)
const {
2717 for (; BlockI !=
End; ++BlockI) {
2718 MachineInstr &
MI = *BlockI;
2722 if (promoteConstantOffsetToImm(
MI, Visited,
AnchorList))
2727 if (
MI.hasOrderedMemoryRef() ||
MI.hasUnmodeledSideEffects()) {
2735 const InstClassEnum InstClass = getInstClass(
MI.getOpcode(), *
TII);
2736 if (InstClass == UNKNOWN)
2741 AMDGPU::getNamedOperandIdx(
MI.getOpcode(), AMDGPU::OpName::swz);
2742 if (Swizzled != -1 &&
MI.getOperand(Swizzled).getImm())
2745 if (InstClass == TBUFFER_LOAD || InstClass == TBUFFER_STORE) {
2748 dbgs() <<
"Skip tbuffer combine: relaxed OOB mode not enabled\n");
2752 const MachineOperand *Fmt =
2753 TII->getNamedOperand(
MI, AMDGPU::OpName::format);
2758 }
else if (InstClass == MIMG) {
2761 const auto *TFEOp =
TII->getNamedOperand(
MI, AMDGPU::OpName::tfe);
2762 if (TFEOp && TFEOp->getImm())
2765 const auto *LWEOp =
TII->getNamedOperand(
MI, AMDGPU::OpName::lwe);
2766 if (LWEOp && LWEOp->getImm())
2771 CI.setMI(
MI, *
this);
2774 if (!CI.hasMergeableAddress(*
MRI))
2789 for (std::list<std::list<CombineInfo>>::iterator
I = MergeableInsts.begin(),
2790 E = MergeableInsts.end();
I !=
E;) {
2792 std::list<CombineInfo> &MergeList = *
I;
2793 if (MergeList.size() <= 1) {
2797 I = MergeableInsts.erase(
I);
2805 [] (
const CombineInfo &
A,
const CombineInfo &
B) {
2806 return A.Offset <
B.Offset;
2817bool SILoadStoreOptimizer::optimizeBlock(
2818 std::list<std::list<CombineInfo> > &MergeableInsts) {
2821 for (std::list<std::list<CombineInfo>>::iterator
I = MergeableInsts.begin(),
2822 E = MergeableInsts.end();
I !=
E;) {
2823 std::list<CombineInfo> &MergeList = *
I;
2825 bool OptimizeListAgain =
false;
2826 if (!optimizeInstsWithSameBaseAddr(MergeList, OptimizeListAgain)) {
2830 I = MergeableInsts.erase(
I);
2838 if (!OptimizeListAgain) {
2839 I = MergeableInsts.erase(
I);
2842 OptimizeAgain =
true;
2848SILoadStoreOptimizer::optimizeInstsWithSameBaseAddr(
2849 std::list<CombineInfo> &MergeList,
2850 bool &OptimizeListAgain) {
2851 if (MergeList.empty())
2856 for (
auto I = MergeList.begin(),
Next = std::next(
I);
Next != MergeList.end();
2857 Next = std::next(
I)) {
2862 if ((*First).Order > (*Second).Order)
2864 CombineInfo &CI = *
First;
2865 CombineInfo &Paired = *Second;
2867 CombineInfo *Where = checkAndPrepareMerge(CI, Paired);
2875 LLVM_DEBUG(
dbgs() <<
"Merging: " << *CI.I <<
" with: " << *Paired.I);
2878 switch (CI.InstClass) {
2883 NewMI = mergeRead2Pair(CI, Paired, Where->I);
2886 NewMI = mergeWrite2Pair(CI, Paired, Where->I);
2888 case S_BUFFER_LOAD_IMM:
2889 case S_BUFFER_LOAD_SGPR_IMM:
2891 NewMI = mergeSMemLoadImmPair(CI, Paired, Where->I);
2892 OptimizeListAgain |= CI.Width + Paired.Width < 8;
2895 NewMI = mergeBufferLoadPair(CI, Paired, Where->I);
2896 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2899 NewMI = mergeBufferStorePair(CI, Paired, Where->I);
2900 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2903 NewMI = mergeImagePair(CI, Paired, Where->I);
2904 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2907 NewMI = mergeTBufferLoadPair(CI, Paired, Where->I);
2908 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2911 NewMI = mergeTBufferStorePair(CI, Paired, Where->I);
2912 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2915 case FLAT_LOAD_SADDR:
2917 case GLOBAL_LOAD_SADDR:
2918 NewMI = mergeFlatLoadPair(CI, Paired, Where->I);
2919 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2922 case FLAT_STORE_SADDR:
2924 case GLOBAL_STORE_SADDR:
2925 NewMI = mergeFlatStorePair(CI, Paired, Where->I);
2926 OptimizeListAgain |= CI.Width + Paired.Width < 4;
2929 CI.setMI(NewMI, *
this);
2930 CI.Order = Where->Order;
2934 MergeList.erase(Second);
2940bool SILoadStoreOptimizerLegacy::runOnMachineFunction(
MachineFunction &MF) {
2943 return SILoadStoreOptimizer(
2944 &getAnalysis<AAResultsWrapperPass>().getAAResults())
2968 for (MachineBasicBlock &
MBB : MF) {
2972 bool CollectModified;
2973 std::list<std::list<CombineInfo>> MergeableInsts;
2977 std::tie(SectionEnd, CollectModified) =
2983 OptimizeAgain =
false;
2985 }
while (OptimizeAgain);
3007 bool Changed = SILoadStoreOptimizer(&
AA).run(MF);
const TargetLowering & TLI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
INITIALIZE_PASS(AMDGPUImageIntrinsicOptimizer, DEBUG_TYPE, "AMDGPU Image Intrinsic Optimizer", false, false) char AMDGPUImageIntrinsicOptimizer void addInstToMergeableList(IntrinsicInst *II, SmallVector< SmallVector< IntrinsicInst *, 4 > > &MergeableInsts, const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr)
BasicBlock::iterator collectMergeableInsts(BasicBlock::iterator I, BasicBlock::iterator E, SmallVector< SmallVector< IntrinsicInst *, 4 > > &MergeableInsts)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
AMD GCN specific subclass of TargetSubtarget.
const HexagonInstrInfo * TII
static MaybeAlign getAlign(Value *Ptr)
std::pair< Instruction::BinaryOps, Value * > OffsetOp
Find all possible pairs (BinOp, RHS) that BinOp V, RHS can be simplified.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
MachineRegisterInfo & MRI
static uint32_t mostAlignedValueInRange(uint32_t Lo, uint32_t Hi)
static bool needsConstrainedOpcode(const GCNSubtarget &STM, ArrayRef< MachineMemOperand * > MMOs, unsigned Width)
static void addDefsUsesToList(const MachineInstr &MI, DenseSet< Register > &RegDefs, DenseSet< Register > &RegUses)
static unsigned getBufferFormatWithCompCount(unsigned OldFormat, unsigned ComponentCount, const GCNSubtarget &STI)
static bool optimizeBlock(BasicBlock &BB, bool &ModifiedDT, const TargetTransformInfo &TTI, const DataLayout &DL, bool HasBranchDivergence, DomTreeUpdater *DTU)
A manager for alias analyses.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
Represents analyses that only rely on functions' control flow.
static LLVM_ABI DebugLoc getMergedLocation(DebugLoc LocA, DebugLoc LocB)
When two instructions are combined into a single instruction we also need to combine the original loc...
Implements a dense probed hash-table based set.
bool hasOptNone() const
Do not optimize this function (-O0).
bool loadStoreOptEnabled() const
const SIInstrInfo * getInstrInfo() const override
bool hasDwordx3LoadStores() const
const SITargetLowering * getTargetLowering() const override
bool hasRelaxedTBufferOOBMode() const
bool ldsRequiresM0Init() const
Return if most LDS instructions have an m0 use that require m0 to be initialized.
bool hasFlatScratchSVSSwizzleBug() const
bool isXNACKEnabled() const
const HexagonRegisterInfo & getRegisterInfo() const
TypeSize getValue() const
unsigned getOpcode() const
Return the opcode number for this descriptor.
An RAII based helper class to modify MachineFunctionProperties when running pass.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
Properties which a MachineFunction may have at a given point in time.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
const MachineInstrBuilder & cloneMergedMemRefs(ArrayRef< const MachineInstr * > OtherMIs) const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
LLVM_ABI void dump() const
A description of a memory reference used in the backend.
LocationSize getSize() const
Return the size in bytes of the memory reference.
unsigned getAddrSpace() const
const MachinePointerInfo & getPointerInfo() const
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
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...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Wrapper class representing virtual and physical registers.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
static bool isFLATScratch(const MachineInstr &MI)
static bool isVIMAGE(const MachineInstr &MI)
static bool isFLATGlobal(const MachineInstr &MI)
static bool isVSAMPLE(const MachineInstr &MI)
static bool isFLAT(const MachineInstr &MI)
LLVM_READONLY MachineOperand * getNamedOperand(MachineInstr &MI, AMDGPU::OpName OperandName) const
Returns the operand named Op.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
reference emplace_back(ArgTypes &&... Args)
Represent a constant reference to a string, i.e.
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
@ PRIVATE_ADDRESS
Address space for private memory.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
LLVM_READONLY const MIMGInfo * getMIMGInfo(unsigned Opc)
uint64_t convertSMRDOffsetUnits(const MCSubtargetInfo &ST, uint64_t ByteOffset)
Convert ByteOffset to dwords if the subtarget uses dword SMRD immediate offsets.
bool getMTBUFHasSrsrc(unsigned Opc)
int getMTBUFElements(unsigned Opc)
bool getMTBUFHasSoffset(unsigned Opc)
int getMUBUFOpcode(unsigned BaseOpc, unsigned Elements)
int getMUBUFBaseOpcode(unsigned Opc)
LLVM_READONLY bool hasNamedOperand(uint32_t Opcode, OpName NamedIdx)
int getMTBUFBaseOpcode(unsigned Opc)
bool getMUBUFHasVAddr(unsigned Opc)
int getMTBUFOpcode(unsigned BaseOpc, unsigned Elements)
bool getMUBUFHasSoffset(unsigned Opc)
const MIMGBaseOpcodeInfo * getMIMGBaseOpcode(unsigned Opc)
LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)
int getMaskedMIMGOp(unsigned Opc, unsigned NewChannels)
bool getMTBUFHasVAddr(unsigned Opc)
int getMUBUFElements(unsigned Opc)
const GcnBufferFormatInfo * getGcnBufferFormatInfo(uint8_t BitsPerComp, uint8_t NumComponents, uint8_t NumFormat, const MCSubtargetInfo &STI)
bool getMUBUFHasSrsrc(unsigned Opc)
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ Add64
64 bits label addition
@ Add32
32 bits label addition
NodeAddr< DefNode * > Def
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
This is an optimization pass for GlobalISel generic memory operations.
bool operator<(int64_t V1, const APSInt &V2)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr T maskLeadingOnes(unsigned N)
Create a bitmask with the N left-most bits set to 1, and all other bits set to 0.
decltype(auto) getSingleElement(ContainerTy &&C)
Asserts that the given container has a single element and returns that element.
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.