LLVM: lib/CodeGen/MachineCopyPropagation.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

75#include

76#include

77

78using namespace llvm;

79

80#define DEBUG_TYPE "machine-cp"

81

82STATISTIC(NumDeletes, "Number of dead copies deleted");

83STATISTIC(NumCopyForwards, "Number of copy uses forwarded");

84STATISTIC(NumCopyBackwardPropagated, "Number of copy defs backward propagated");

85STATISTIC(SpillageChainsLength, "Length of spillage chains");

86STATISTIC(NumSpillageChains, "Number of spillage chains");

88 "Controls which register COPYs are forwarded");

89

94

95namespace {

96

97static std::optional isCopyInstr(const MachineInstr &MI,

99 bool UseCopyInstr) {

100 if (UseCopyInstr)

101 return TII.isCopyInstr(MI);

102

103 if (MI.isCopy())

104 return std::optional(

106

107 return std::nullopt;

108}

109

110class CopyTracker {

111 struct CopyInfo {

112 MachineInstr *MI = nullptr;

113 MachineInstr *LastSeenUseInCopy = nullptr;

114 SmallPtrSet<MachineInstr *, 4> SrcUsers;

116 bool Avail = false;

117 };

118

119 DenseMap<MCRegUnit, CopyInfo> Copies;

120

121

122

123

124 DenseMap<const uint32_t *, BitVector> RegMaskToPreservedRegUnits;

125

126public:

127

128 BitVector &getPreservedRegUnits(const MachineOperand &RegMaskOp,

129 const TargetRegisterInfo &TRI) {

130 const uint32_t *RegMask = RegMaskOp.getRegMask();

131 auto [It, Inserted] = RegMaskToPreservedRegUnits.try_emplace(RegMask);

132 if (!Inserted) {

133 return It->second;

134 } else {

135 BitVector &PreservedRegUnits = It->second;

136

137 PreservedRegUnits.resize(TRI.getNumRegUnits());

138 for (unsigned SafeReg = 0, E = TRI.getNumRegs(); SafeReg < E; ++SafeReg)

140 for (MCRegUnit SafeUnit : TRI.regunits(SafeReg))

141 PreservedRegUnits.set(static_cast<unsigned>(SafeUnit));

142

143 return PreservedRegUnits;

144 }

145 }

146

147

148

150 const TargetRegisterInfo &TRI) {

151 for (MCRegister Reg : Regs) {

152

153 for (MCRegUnit Unit : TRI.regunits(Reg)) {

154 auto CI = Copies.find(Unit);

155 if (CI != Copies.end())

156 CI->second.Avail = false;

157 }

158 }

159 }

160

161

162 void invalidateRegister(MCRegister Reg, const TargetRegisterInfo &TRI,

163 const TargetInstrInfo &TII, bool UseCopyInstr) {

164

165

166

167

168 SmallSet<MCRegUnit, 8> RegUnitsToInvalidate;

169 auto InvalidateCopy = [&](MachineInstr *MI) {

170 std::optional CopyOperands =

171 isCopyInstr(*MI, TII, UseCopyInstr);

172 assert(CopyOperands && "Expect copy");

173

174 auto Dest = TRI.regunits(CopyOperands->Destination->getReg().asMCReg());

175 auto Src = TRI.regunits(CopyOperands->Source->getReg().asMCReg());

178 };

179

180 for (MCRegUnit Unit : TRI.regunits(Reg)) {

181 auto I = Copies.find(Unit);

182 if (I != Copies.end()) {

183 if (MachineInstr *MI = I->second.MI)

184 InvalidateCopy(MI);

185 if (MachineInstr *MI = I->second.LastSeenUseInCopy)

186 InvalidateCopy(MI);

187 }

188 }

189 for (MCRegUnit Unit : RegUnitsToInvalidate)

190 Copies.erase(Unit);

191 }

192

193

194 void clobberRegUnit(MCRegUnit Unit, const TargetRegisterInfo &TRI,

195 const TargetInstrInfo &TII, bool UseCopyInstr) {

196 auto I = Copies.find(Unit);

197 if (I != Copies.end()) {

198

199

200 markRegsUnavailable(I->second.DefRegs, TRI);

201

202

203 if (MachineInstr *MI = I->second.MI) {

204 std::optional CopyOperands =

205 isCopyInstr(*MI, TII, UseCopyInstr);

206

207 MCRegister Def = CopyOperands->Destination->getReg().asMCReg();

208 MCRegister Src = CopyOperands->Source->getReg().asMCReg();

209

210 markRegsUnavailable(Def, TRI);

211

212

213

214

215

216

217

218

219

220

221

222

223

224 for (MCRegUnit SrcUnit : TRI.regunits(Src)) {

225 auto SrcCopy = Copies.find(SrcUnit);

226 if (SrcCopy != Copies.end() && SrcCopy->second.LastSeenUseInCopy) {

227

228

229 for (auto itr = SrcCopy->second.DefRegs.begin();

230 itr != SrcCopy->second.DefRegs.end(); itr++) {

231 if (*itr == Def) {

232 SrcCopy->second.DefRegs.erase(itr);

233

234

235

236

237

238 if (SrcCopy->second.DefRegs.empty() && !SrcCopy->second.MI) {

239 Copies.erase(SrcCopy);

240 }

241 break;

242 }

243 }

244 }

245 }

246 }

247

248 Copies.erase(I);

249 }

250 }

251

252

253 void clobberRegister(MCRegister Reg, const TargetRegisterInfo &TRI,

254 const TargetInstrInfo &TII, bool UseCopyInstr) {

255 for (MCRegUnit Unit : TRI.regunits(Reg)) {

256 clobberRegUnit(Unit, TRI, TII, UseCopyInstr);

257 }

258 }

259

260

261

262

263 bool trackSrcUsers(MCRegister Reg, MachineInstr &MI,

264 const TargetRegisterInfo &TRI, const TargetInstrInfo &TII,

265 bool UseCopyInstr) {

266 MCRegUnit RU = *TRI.regunits(Reg).begin();

267 MachineInstr *AvailCopy = findCopyDefViaUnit(RU, TRI);

268 if (!AvailCopy)

269 return false;

270

271 std::optional CopyOperands =

272 isCopyInstr(*AvailCopy, TII, UseCopyInstr);

273 Register Src = CopyOperands->Source->getReg();

274

275

276 if (Src != Reg)

277 return false;

278

279 auto I = Copies.find(RU);

280 if (I == Copies.end())

281 return false;

282

283 I->second.SrcUsers.insert(&MI);

284 return true;

285 }

286

287

288 SmallPtrSet<MachineInstr *, 4> getSrcUsers(MCRegister Reg,

289 const TargetRegisterInfo &TRI) {

290 MCRegUnit RU = *TRI.regunits(Reg).begin();

291 auto I = Copies.find(RU);

292 if (I == Copies.end())

293 return {};

294 return I->second.SrcUsers;

295 }

296

297

298 void trackCopy(MachineInstr *MI, const TargetRegisterInfo &TRI,

299 const TargetInstrInfo &TII, bool UseCopyInstr) {

300 std::optional CopyOperands =

301 isCopyInstr(*MI, TII, UseCopyInstr);

302 assert(CopyOperands && "Tracking non-copy?");

303

304 MCRegister Src = CopyOperands->Source->getReg().asMCReg();

305 MCRegister Def = CopyOperands->Destination->getReg().asMCReg();

306

307

308 for (MCRegUnit Unit : TRI.regunits(Def))

309 Copies[Unit] = {MI, nullptr, {}, {}, true};

310

311

312

313 for (MCRegUnit Unit : TRI.regunits(Src)) {

316 Copy.DefRegs.push_back(Def);

317 Copy.LastSeenUseInCopy = MI;

318 }

319 }

320

321 bool hasAnyCopies() {

322 return !Copies.empty();

323 }

324

325 MachineInstr *findCopyForUnit(MCRegUnit RegUnit,

326 const TargetRegisterInfo &TRI,

327 bool MustBeAvailable = false) {

328 auto CI = Copies.find(RegUnit);

329 if (CI == Copies.end())

330 return nullptr;

331 if (MustBeAvailable && !CI->second.Avail)

332 return nullptr;

333 return CI->second.MI;

334 }

335

336 MachineInstr *findCopyDefViaUnit(MCRegUnit RegUnit,

337 const TargetRegisterInfo &TRI) {

338 auto CI = Copies.find(RegUnit);

339 if (CI == Copies.end())

340 return nullptr;

341 if (CI->second.DefRegs.size() != 1)

342 return nullptr;

343 MCRegUnit RU = *TRI.regunits(CI->second.DefRegs[0]).begin();

344 return findCopyForUnit(RU, TRI, true);

345 }

346

347 MachineInstr *findAvailBackwardCopy(MachineInstr &I, MCRegister Reg,

348 const TargetRegisterInfo &TRI,

349 const TargetInstrInfo &TII,

350 bool UseCopyInstr) {

351 MCRegUnit RU = *TRI.regunits(Reg).begin();

352 MachineInstr *AvailCopy = findCopyDefViaUnit(RU, TRI);

353

354 if (!AvailCopy)

355 return nullptr;

356

357 std::optional CopyOperands =

358 isCopyInstr(*AvailCopy, TII, UseCopyInstr);

359 Register AvailSrc = CopyOperands->Source->getReg();

360 Register AvailDef = CopyOperands->Destination->getReg();

361 if (TRI.isSubRegisterEq(AvailSrc, Reg))

362 return nullptr;

363

364 for (const MachineInstr &MI :

366 for (const MachineOperand &MO : MI.operands())

367 if (MO.isRegMask())

368

369 if (MO.clobbersPhysReg(AvailSrc) || MO.clobbersPhysReg(AvailDef))

370 return nullptr;

371

372 return AvailCopy;

373 }

374

375 MachineInstr *findAvailCopy(MachineInstr &DestCopy, MCRegister Reg,

376 const TargetRegisterInfo &TRI,

377 const TargetInstrInfo &TII, bool UseCopyInstr) {

378

379

380 MCRegUnit RU = *TRI.regunits(Reg).begin();

381 MachineInstr *AvailCopy =

382 findCopyForUnit(RU, TRI, true);

383

384 if (!AvailCopy)

385 return nullptr;

386

387 std::optional CopyOperands =

388 isCopyInstr(*AvailCopy, TII, UseCopyInstr);

389 Register AvailSrc = CopyOperands->Source->getReg();

390 Register AvailDef = CopyOperands->Destination->getReg();

391 if (TRI.isSubRegisterEq(AvailDef, Reg))

392 return nullptr;

393

394

395

396 for (const MachineInstr &MI :

398 for (const MachineOperand &MO : MI.operands())

399 if (MO.isRegMask())

400 if (MO.clobbersPhysReg(AvailSrc) || MO.clobbersPhysReg(AvailDef))

401 return nullptr;

402

403 return AvailCopy;

404 }

405

406

407 MachineInstr *findLastSeenDefInCopy(const MachineInstr &Current,

408 MCRegister Reg,

409 const TargetRegisterInfo &TRI,

410 const TargetInstrInfo &TII,

411 bool UseCopyInstr) {

412 MCRegUnit RU = *TRI.regunits(Reg).begin();

413 auto CI = Copies.find(RU);

414 if (CI == Copies.end() || !CI->second.Avail)

415 return nullptr;

416

417 MachineInstr *DefCopy = CI->second.MI;

418 std::optional CopyOperands =

419 isCopyInstr(*DefCopy, TII, UseCopyInstr);

420 Register Def = CopyOperands->Destination->getReg();

421 if (TRI.isSubRegisterEq(Def, Reg))

422 return nullptr;

423

424 for (const MachineInstr &MI :

425 make_range(static_cast<const MachineInstr *>(DefCopy)->getIterator(),

427 for (const MachineOperand &MO : MI.operands())

428 if (MO.isRegMask())

429 if (MO.clobbersPhysReg(Def)) {

432 return nullptr;

433 }

434

435 return DefCopy;

436 }

437

438

439 MachineInstr *findLastSeenUseInCopy(MCRegister Reg,

440 const TargetRegisterInfo &TRI) {

441 MCRegUnit RU = *TRI.regunits(Reg).begin();

442 auto CI = Copies.find(RU);

443 if (CI == Copies.end())

444 return nullptr;

445 return CI->second.LastSeenUseInCopy;

446 }

447

448 void clear() {

449 Copies.clear();

450 }

451};

452

453class MachineCopyPropagation {

454 const TargetRegisterInfo *TRI = nullptr;

455 const TargetInstrInfo *TII = nullptr;

456 const MachineRegisterInfo *MRI = nullptr;

457

458

459 bool UseCopyInstr;

460

461public:

462 MachineCopyPropagation(bool CopyInstr = false)

464

465 bool run(MachineFunction &MF);

466

467private:

468 typedef enum { DebugUse = false, RegularUse = true } DebugType;

469

470 void ReadRegister(MCRegister Reg, MachineInstr &Reader, DebugType DT);

471 void readSuccessorLiveIns(const MachineBasicBlock &MBB);

472 void ForwardCopyPropagateBlock(MachineBasicBlock &MBB);

473 void BackwardCopyPropagateBlock(MachineBasicBlock &MBB);

474 void EliminateSpillageCopies(MachineBasicBlock &MBB);

475 bool eraseIfRedundant(MachineInstr &Copy, MCRegister Src, MCRegister Def);

476 void forwardUses(MachineInstr &MI);

477 void propagateDefs(MachineInstr &MI);

478 bool isForwardableRegClassCopy(const MachineInstr &Copy,

479 const MachineInstr &UseI, unsigned UseIdx);

480 bool isBackwardPropagatableRegClassCopy(const MachineInstr &Copy,

481 const MachineInstr &UseI,

482 unsigned UseIdx);

483 bool hasImplicitOverlap(const MachineInstr &MI, const MachineOperand &Use);

484 bool hasOverlappingMultipleDef(const MachineInstr &MI,

485 const MachineOperand &MODef, Register Def);

486 bool canUpdateSrcUsers(const MachineInstr &Copy,

487 const MachineOperand &CopySrc);

488

489

490 SmallSetVector<MachineInstr *, 8> MaybeDeadCopies;

491

492

493 DenseMap<MachineInstr *, SmallPtrSet<MachineInstr *, 2>> CopyDbgUsers;

494

495 CopyTracker Tracker;

496

497 bool Changed = false;

498};

499

501 bool UseCopyInstr;

502

503public:

504 static char ID;

505

506 MachineCopyPropagationLegacy(bool UseCopyInstr = false)

507 : MachineFunctionPass(ID), UseCopyInstr(UseCopyInstr) {}

508

509 void getAnalysisUsage(AnalysisUsage &AU) const override {

512 }

513

514 bool runOnMachineFunction(MachineFunction &MF) override;

515

516 MachineFunctionProperties getRequiredProperties() const override {

517 return MachineFunctionProperties().setNoVRegs();

518 }

519};

520

521}

522

523char MachineCopyPropagationLegacy::ID = 0;

524

526

528 "Machine Copy Propagation Pass", false, false)

529

531 DebugType DT) {

532

533

534

535 for (MCRegUnit Unit : TRI->regunits(Reg)) {

536 if (MachineInstr *Copy = Tracker.findCopyForUnit(Unit, *TRI)) {

537 if (DT == RegularUse) {

538 LLVM_DEBUG(dbgs() << "MCP: Copy is used - not dead: "; Copy->dump());

539 MaybeDeadCopies.remove(Copy);

540 } else {

541 CopyDbgUsers[Copy].insert(&Reader);

542 }

543 }

544 }

545}

546

547void MachineCopyPropagation::readSuccessorLiveIns(

549 if (MaybeDeadCopies.empty())

550 return;

551

552

553 for (const MachineBasicBlock *Succ : MBB.successors()) {

554 for (const auto &LI : Succ->liveins()) {

555 for (MCRegUnitMaskIterator U(LI.PhysReg, TRI); U.isValid(); ++U) {

557 if ((Mask & LI.LaneMask).any()) {

558 if (MachineInstr *Copy = Tracker.findCopyForUnit(Unit, *TRI))

559 MaybeDeadCopies.remove(Copy);

560 }

561 }

562 }

563 }

564}

565

566

567

568

569

570

571

575

576 std::optional CopyOperands =

577 isCopyInstr(PreviousCopy, *TII, UseCopyInstr);

578 MCRegister PreviousSrc = CopyOperands->Source->getReg().asMCReg();

579 MCRegister PreviousDef = CopyOperands->Destination->getReg().asMCReg();

580 if (Src == PreviousSrc && Def == PreviousDef)

581 return true;

582 if (TRI->isSubRegister(PreviousSrc, Src))

583 return false;

584 unsigned SubIdx = TRI->getSubRegIndex(PreviousSrc, Src);

585 return SubIdx == TRI->getSubRegIndex(PreviousDef, Def);

586}

587

588

589

590

591bool MachineCopyPropagation::eraseIfRedundant(MachineInstr &Copy,

592 MCRegister Src, MCRegister Def) {

593

594

595 if (MRI->isReserved(Src) || MRI->isReserved(Def))

596 return false;

597

598

599 MachineInstr *PrevCopy =

600 Tracker.findAvailCopy(Copy, Def, *TRI, *TII, UseCopyInstr);

601 if (!PrevCopy)

602 return false;

603

604 auto PrevCopyOperands = isCopyInstr(*PrevCopy, *TII, UseCopyInstr);

605

606 if (PrevCopyOperands->Destination->isDead())

607 return false;

608 if (isNopCopy(*PrevCopy, Src, Def, TRI, TII, UseCopyInstr))

609 return false;

610

612

613

614

615 std::optional CopyOperands =

616 isCopyInstr(Copy, *TII, UseCopyInstr);

617 assert(CopyOperands);

618

619 Register CopyDef = CopyOperands->Destination->getReg();

620 assert(CopyDef == Src || CopyDef == Def);

621 for (MachineInstr &MI :

623 MI.clearRegisterKills(CopyDef, TRI);

624

625

626 if (!CopyOperands->Source->isUndef()) {

627 PrevCopy->getOperand(PrevCopyOperands->Source->getOperandNo())

629 }

630

631 Copy.eraseFromParent();

633 ++NumDeletes;

634 return true;

635}

636

637bool MachineCopyPropagation::isBackwardPropagatableRegClassCopy(

638 const MachineInstr &Copy, const MachineInstr &UseI, unsigned UseIdx) {

639 std::optional CopyOperands =

640 isCopyInstr(Copy, *TII, UseCopyInstr);

641 Register Def = CopyOperands->Destination->getReg();

642

643 if (const TargetRegisterClass *URC =

645 return URC->contains(Def);

646

647

648

649 return false;

650}

651

652

653

654

655bool MachineCopyPropagation::isForwardableRegClassCopy(const MachineInstr &Copy,

656 const MachineInstr &UseI,

657 unsigned UseIdx) {

658 std::optional CopyOperands =

659 isCopyInstr(Copy, *TII, UseCopyInstr);

660 Register CopySrcReg = CopyOperands->Source->getReg();

661

662

663

664 if (const TargetRegisterClass *URC =

666 return URC->contains(CopySrcReg);

667

668 auto UseICopyOperands = isCopyInstr(UseI, *TII, UseCopyInstr);

669 if (!UseICopyOperands)

670 return false;

671

672

673

674

675

676

677

678

679

680

681

682

683

684

685

686

687

688

689

690

691

692 Register UseDstReg = UseICopyOperands->Destination->getReg();

693 bool Found = false;

694 bool IsCrossClass = false;

695 for (const TargetRegisterClass *RC : TRI->regclasses()) {

696 if (RC->contains(CopySrcReg) && RC->contains(UseDstReg)) {

697 Found = true;

698 if (TRI->getCrossCopyRegClass(RC) != RC) {

699 IsCrossClass = true;

700 break;

701 }

702 }

703 }

704 if (!Found)

705 return false;

706 if (!IsCrossClass)

707 return true;

708

709

710 Register CopyDstReg = CopyOperands->Destination->getReg();

711 for (const TargetRegisterClass *RC : TRI->regclasses()) {

712 if (RC->contains(CopySrcReg) && RC->contains(CopyDstReg) &&

713 TRI->getCrossCopyRegClass(RC) != RC)

714 return true;

715 }

716 return false;

717}

718

719

720

721

722

723

724

725

726

727bool MachineCopyPropagation::hasImplicitOverlap(const MachineInstr &MI,

728 const MachineOperand &Use) {

729 for (const MachineOperand &MIUse : MI.uses())

730 if (&MIUse != &Use && MIUse.isReg() && MIUse.isImplicit() &&

731 MIUse.isUse() && TRI->regsOverlap(Use.getReg(), MIUse.getReg()))

732 return true;

733

734 return false;

735}

736

737

738

739

740

741bool MachineCopyPropagation::hasOverlappingMultipleDef(

742 const MachineInstr &MI, const MachineOperand &MODef, Register Def) {

743 for (const MachineOperand &MIDef : MI.all_defs()) {

744 if ((&MIDef != &MODef) && MIDef.isReg() &&

745 TRI->regsOverlap(Def, MIDef.getReg()))

746 return true;

747 }

748

749 return false;

750}

751

752

753

754bool MachineCopyPropagation::canUpdateSrcUsers(const MachineInstr &Copy,

755 const MachineOperand &CopySrc) {

756 assert(CopySrc.isReg() && "Expected a register operand");

757 for (auto *SrcUser : Tracker.getSrcUsers(CopySrc.getReg(), *TRI)) {

758 if (hasImplicitOverlap(*SrcUser, CopySrc))

759 return false;

760

761 for (MachineOperand &MO : SrcUser->uses()) {

762 if (!MO.isReg() || !MO.isUse() || MO.getReg() != CopySrc.getReg())

763 continue;

764 if (MO.isTied() || !MO.isRenamable() ||

765 !isBackwardPropagatableRegClassCopy(Copy, *SrcUser,

766 MO.getOperandNo()))

767 return false;

768 }

769 }

770 return true;

771}

772

773

774

775void MachineCopyPropagation::forwardUses(MachineInstr &MI) {

776 if (!Tracker.hasAnyCopies())

777 return;

778

779

780

781

782 for (unsigned OpIdx = 0, OpEnd = MI.getNumOperands(); OpIdx < OpEnd;

784 MachineOperand &MOUse = MI.getOperand(OpIdx);

785

786

787

788

789

792 continue;

793

795 continue;

796

797

798

799

801 continue;

802

804 *TRI, *TII, UseCopyInstr);

805 if (!Copy)

806 continue;

807

808 std::optional CopyOperands =

809 isCopyInstr(*Copy, *TII, UseCopyInstr);

810 Register CopyDstReg = CopyOperands->Destination->getReg();

811 const MachineOperand &CopySrc = *CopyOperands->Source;

813

814 Register ForwardedReg = CopySrcReg;

815

816

817 if (MOUse.getReg() != CopyDstReg) {

818 unsigned SubRegIdx = TRI->getSubRegIndex(CopyDstReg, MOUse.getReg());

820 "MI source is not a sub-register of Copy destination");

821 ForwardedReg = TRI->getSubReg(CopySrcReg, SubRegIdx);

822 if (!ForwardedReg) {

823 LLVM_DEBUG(dbgs() << "MCP: Copy source does not have sub-register "

824 << TRI->getSubRegIndexName(SubRegIdx) << '\n');

825 continue;

826 }

827 }

828

829

830 if (MRI->isReserved(CopySrcReg) && MRI->isConstantPhysReg(CopySrcReg))

831 continue;

832

833 if (!isForwardableRegClassCopy(*Copy, MI, OpIdx))

834 continue;

835

836 if (hasImplicitOverlap(MI, MOUse))

837 continue;

838

839

840

841

842 if (isCopyInstr(MI, *TII, UseCopyInstr) &&

843 MI.modifiesRegister(CopySrcReg, TRI) &&

844 MI.definesRegister(CopySrcReg, nullptr)) {

845 LLVM_DEBUG(dbgs() << "MCP: Copy source overlap with dest in " << MI);

846 continue;

847 }

848

850 LLVM_DEBUG(dbgs() << "MCP: Skipping forwarding due to debug counter:\n "

851 << MI);

852 continue;

853 }

854

856 << "\n with " << printReg(ForwardedReg, TRI)

857 << "\n in " << MI << " from " << *Copy);

858

859 MOUse.setReg(ForwardedReg);

860

864

865 LLVM_DEBUG(dbgs() << "MCP: After replacement: " << MI << "\n");

866

867

868 for (MachineInstr &KMI :

869 make_range(Copy->getIterator(), std::next(MI.getIterator())))

870 KMI.clearRegisterKills(CopySrcReg, TRI);

871

872 ++NumCopyForwards;

874 }

875}

876

877void MachineCopyPropagation::ForwardCopyPropagateBlock(MachineBasicBlock &MBB) {

879 << "\n");

880

882

883 std::optional CopyOperands =

884 isCopyInstr(MI, *TII, UseCopyInstr);

885 if (CopyOperands) {

886 Register RegSrc = CopyOperands->Source->getReg();

887 Register RegDef = CopyOperands->Destination->getReg();

888 if (TRI->regsOverlap(RegDef, RegSrc)) {

890 "MachineCopyPropagation should be run after register allocation!");

891

893 MCRegister Src = RegSrc.asMCReg();

894

895

896

897

898

899

900

901

902

903

904

905

906

907

908

909

910 if (eraseIfRedundant(MI, Def, Src) || eraseIfRedundant(MI, Src, Def))

911 continue;

912 }

913 }

914

915

916 for (const MachineOperand &MO : MI.operands())

917 if (MO.isReg() && MO.isEarlyClobber()) {

918 MCRegister Reg = MO.getReg().asMCReg();

919

920

921

922 if (MO.isTied())

923 ReadRegister(Reg, MI, RegularUse);

924 Tracker.clobberRegister(Reg, *TRI, *TII, UseCopyInstr);

925 }

926

927 forwardUses(MI);

928

929

930

933 LLVM_DEBUG(dbgs() << "MCP: After simplifyInstruction: " << MI);

934 }

935

936 CopyOperands = isCopyInstr(MI, *TII, UseCopyInstr);

937 if (CopyOperands) {

938 Register RegSrc = CopyOperands->Source->getReg();

939 Register RegDef = CopyOperands->Destination->getReg();

940

941 if (TRI->regsOverlap(RegDef, RegSrc)) {

942

944 if (MRI->isReserved(Def))

945 MaybeDeadCopies.insert(&MI);

946 }

947 }

948

950 const MachineOperand *RegMask = nullptr;

951 for (const MachineOperand &MO : MI.operands()) {

952 if (MO.isRegMask())

953 RegMask = &MO;

954 if (!MO.isReg())

955 continue;

957 if (Reg)

958 continue;

959

961 "MachineCopyPropagation should be run after register allocation!");

962

963 if (MO.isDef() && !MO.isEarlyClobber()) {

964

965 if (MRI->isConstantPhysReg(Reg)) {

967 continue;

968 }

969 } else if (MO.readsReg())

970 ReadRegister(Reg.asMCReg(), MI, MO.isDebug() ? DebugUse : RegularUse);

971 }

972

973

974

975

976 if (RegMask) {

977 BitVector &PreservedRegUnits =

978 Tracker.getPreservedRegUnits(*RegMask, *TRI);

979

980

981 for (SmallSetVector<MachineInstr *, 8>::iterator DI =

982 MaybeDeadCopies.begin();

983 DI != MaybeDeadCopies.end();) {

984 MachineInstr *MaybeDead = *DI;

985 std::optional CopyOperands =

986 isCopyInstr(*MaybeDead, *TII, UseCopyInstr);

987 MCRegister Reg = CopyOperands->Destination->getReg().asMCReg();

989

991 ++DI;

992 continue;

993 }

994

995

996

997 bool MIRefedinCopyInfo = false;

998 for (MCRegUnit RegUnit : TRI->regunits(Reg)) {

999 if (!PreservedRegUnits.test(static_cast<unsigned>(RegUnit)))

1000 Tracker.clobberRegUnit(RegUnit, *TRI, *TII, UseCopyInstr);

1001 else {

1002 if (MaybeDead == Tracker.findCopyForUnit(RegUnit, *TRI)) {

1003 MIRefedinCopyInfo = true;

1004 }

1005 }

1006 }

1007

1008

1009

1010 DI = MaybeDeadCopies.erase(DI);

1011

1012

1013 if (MIRefedinCopyInfo)

1014 continue;

1015

1016 LLVM_DEBUG(dbgs() << "MCP: Removing copy due to regmask clobbering: "

1017 << *MaybeDead);

1018

1021 ++NumDeletes;

1022 }

1023 }

1024

1025

1026 for (MCRegister Reg : Defs)

1027 Tracker.clobberRegister(Reg, *TRI, *TII, UseCopyInstr);

1028

1029 if (CopyOperands) {

1030 Register RegSrc = CopyOperands->Source->getReg();

1031 Register RegDef = CopyOperands->Destination->getReg();

1032 if (TRI->regsOverlap(RegDef, RegSrc)) {

1033 Tracker.trackCopy(&MI, *TRI, *TII, UseCopyInstr);

1034 }

1035 }

1036 }

1037

1038 bool TracksLiveness = MRI->tracksLiveness();

1039

1040

1041

1042 if (TracksLiveness)

1043 readSuccessorLiveIns(MBB);

1044

1045

1046

1047

1049 for (MachineInstr *MaybeDead : MaybeDeadCopies) {

1050 LLVM_DEBUG(dbgs() << "MCP: Removing copy due to no live-out succ: ";

1051 MaybeDead->dump());

1052

1053 std::optional CopyOperands =

1054 isCopyInstr(*MaybeDead, *TII, UseCopyInstr);

1055 assert(CopyOperands);

1056

1057 Register SrcReg = CopyOperands->Source->getReg();

1058 Register DestReg = CopyOperands->Destination->getReg();

1059 assert(MRI->isReserved(DestReg));

1060

1061

1062 const auto &DbgUsers = CopyDbgUsers[MaybeDead];

1064 DbgUsers.end());

1066 MaybeDeadDbgUsers);

1067

1070 ++NumDeletes;

1071 }

1072 }

1073

1074 MaybeDeadCopies.clear();

1075 CopyDbgUsers.clear();

1076 Tracker.clear();

1077}

1078

1083

1084 if (!Def || !Src)

1085 return false;

1086

1087 if (MRI.isReserved(Def) || MRI.isReserved(Src))

1088 return false;

1089

1091}

1092

1093void MachineCopyPropagation::propagateDefs(MachineInstr &MI) {

1094 if (!Tracker.hasAnyCopies())

1095 return;

1096

1097 for (unsigned OpIdx = 0, OpEnd = MI.getNumOperands(); OpIdx != OpEnd;

1099 MachineOperand &MODef = MI.getOperand(OpIdx);

1100

1101 if (!MODef.isReg() || MODef.isUse())

1102 continue;

1103

1104

1106 continue;

1107

1108 if (!MODef.getReg())

1109 continue;

1110

1111

1113 continue;

1114

1115 MachineInstr *Copy = Tracker.findAvailBackwardCopy(

1117 if (!Copy)

1118 continue;

1119

1120 std::optional CopyOperands =

1121 isCopyInstr(*Copy, *TII, UseCopyInstr);

1122 Register Def = CopyOperands->Destination->getReg();

1123 Register Src = CopyOperands->Source->getReg();

1124

1125 if (MODef.getReg() != Src)

1126 continue;

1127

1128 if (!isBackwardPropagatableRegClassCopy(*Copy, MI, OpIdx))

1129 continue;

1130

1131 if (hasImplicitOverlap(MI, MODef))

1132 continue;

1133

1134 if (hasOverlappingMultipleDef(MI, MODef, Def))

1135 continue;

1136

1137 if (!canUpdateSrcUsers(*Copy, *CopyOperands->Source))

1138 continue;

1139

1141 << "\n with " << printReg(Def, TRI) << "\n in "

1142 << MI << " from " << *Copy);

1143

1145 MODef.setIsRenamable(CopyOperands->Destination->isRenamable());

1146

1147 for (auto *SrcUser : Tracker.getSrcUsers(Src, *TRI)) {

1148 for (MachineOperand &MO : SrcUser->uses()) {

1149 if (!MO.isReg() || !MO.isUse() || MO.getReg() != Src)

1150 continue;

1151 MO.setReg(Def);

1152 MO.setIsRenamable(CopyOperands->Destination->isRenamable());

1153 }

1154 }

1155

1156 LLVM_DEBUG(dbgs() << "MCP: After replacement: " << MI << "\n");

1157 MaybeDeadCopies.insert(Copy);

1159 ++NumCopyBackwardPropagated;

1160 }

1161}

1162

1163void MachineCopyPropagation::BackwardCopyPropagateBlock(

1164 MachineBasicBlock &MBB) {

1166 << "\n");

1167

1169

1170 std::optional CopyOperands =

1171 isCopyInstr(MI, *TII, UseCopyInstr);

1172 if (CopyOperands && MI.getNumImplicitOperands() == 0) {

1173 Register DefReg = CopyOperands->Destination->getReg();

1174 Register SrcReg = CopyOperands->Source->getReg();

1175

1176 if (TRI->regsOverlap(DefReg, SrcReg)) {

1177

1178

1180 Tracker.invalidateRegister(SrcReg.asMCReg(), *TRI, *TII,

1181 UseCopyInstr);

1182 Tracker.invalidateRegister(DefReg.asMCReg(), *TRI, *TII,

1183 UseCopyInstr);

1184 Tracker.trackCopy(&MI, *TRI, *TII, UseCopyInstr);

1185 continue;

1186 }

1187 }

1188 }

1189

1190

1191 for (const MachineOperand &MO : MI.operands())

1192 if (MO.isReg() && MO.isEarlyClobber()) {

1193 MCRegister Reg = MO.getReg().asMCReg();

1194 if (Reg)

1195 continue;

1196 Tracker.invalidateRegister(Reg, *TRI, *TII, UseCopyInstr);

1197 }

1198

1199 propagateDefs(MI);

1200 for (const MachineOperand &MO : MI.operands()) {

1201 if (!MO.isReg())

1202 continue;

1203

1204 if (!MO.getReg())

1205 continue;

1206

1207 if (MO.isDef())

1208 Tracker.invalidateRegister(MO.getReg().asMCReg(), *TRI, *TII,

1209 UseCopyInstr);

1210

1211 if (MO.readsReg()) {

1212 if (MO.isDebug()) {

1213

1214

1215

1216 for (MCRegUnit Unit : TRI->regunits(MO.getReg().asMCReg())) {

1217 if (auto *Copy = Tracker.findCopyDefViaUnit(Unit, *TRI)) {

1218 CopyDbgUsers[Copy].insert(&MI);

1219 }

1220 }

1221 } else if (!Tracker.trackSrcUsers(MO.getReg().asMCReg(), MI, *TRI, *TII,

1222 UseCopyInstr)) {

1223

1224 Tracker.invalidateRegister(MO.getReg().asMCReg(), *TRI, *TII,

1225 UseCopyInstr);

1226 }

1227 }

1228 }

1229 }

1230

1231 for (auto *Copy : MaybeDeadCopies) {

1232 std::optional CopyOperands =

1233 isCopyInstr(*Copy, *TII, UseCopyInstr);

1234 Register Src = CopyOperands->Source->getReg();

1235 Register Def = CopyOperands->Destination->getReg();

1236 const auto &DbgUsers = CopyDbgUsers[Copy];

1238 DbgUsers.end());

1239

1240 MRI->updateDbgUsersToReg(Src.asMCReg(), Def.asMCReg(), MaybeDeadDbgUsers);

1241 Copy->eraseFromParent();

1242 ++NumDeletes;

1243 }

1244

1245 MaybeDeadCopies.clear();

1246 CopyDbgUsers.clear();

1247 Tracker.clear();

1248}

1249

1254 auto &SC = SpillChain[Leader];

1255 auto &RC = ReloadChain[Leader];

1256 for (auto I = SC.rbegin(), E = SC.rend(); I != E; ++I)

1257 (*I)->dump();

1259 MI->dump();

1260}

1261

1262

1263

1264

1265

1266

1267

1268

1269

1270

1271

1272

1273

1274

1275

1276

1277

1278

1279

1280

1281

1282

1283

1284

1285

1286

1287

1288

1289

1290

1291

1292

1293

1294

1295

1296

1297

1298

1299

1300void MachineCopyPropagation::EliminateSpillageCopies(MachineBasicBlock &MBB) {

1301

1302

1303 DenseMap<MachineInstr *, MachineInstr *> ChainLeader;

1304

1305

1306

1307

1308 DenseMap<MachineInstr *, SmallVector<MachineInstr *>> SpillChain, ReloadChain;

1309

1310

1311 DenseSet<const MachineInstr *> CopySourceInvalid;

1312

1313 auto TryFoldSpillageCopies =

1314 [&, this](const SmallVectorImpl<MachineInstr *> &SC,

1315 const SmallVectorImpl<MachineInstr *> &RC) {

1316 assert(SC.size() == RC.size() && "Spill-reload should be paired");

1317

1318

1319

1320

1321

1322

1323

1324

1325

1326

1327 if (SC.size() <= 2)

1328 return;

1329

1330

1331 for (const MachineInstr *Spill : drop_begin(SC))

1332 if (CopySourceInvalid.count(Spill))

1333 return;

1334

1335 for (const MachineInstr *Reload : drop_end(RC))

1336 if (CopySourceInvalid.count(Reload))

1337 return;

1338

1340 for (const TargetRegisterClass *RC : TRI->regclasses()) {

1341 if (RC->contains(Def) && RC->contains(Src))

1342 return true;

1343 }

1344 return false;

1345 };

1346

1347 auto UpdateReg = [](MachineInstr *MI, const MachineOperand *Old,

1348 const MachineOperand *New) {

1349 for (MachineOperand &MO : MI->operands()) {

1350 if (&MO == Old)

1351 MO.setReg(New->getReg());

1352 }

1353 };

1354

1355 std::optional InnerMostSpillCopy =

1356 isCopyInstr(*SC[0], *TII, UseCopyInstr);

1357 std::optional OuterMostSpillCopy =

1358 isCopyInstr(*SC.back(), *TII, UseCopyInstr);

1359 std::optional InnerMostReloadCopy =

1360 isCopyInstr(*RC[0], *TII, UseCopyInstr);

1361 std::optional OuterMostReloadCopy =

1362 isCopyInstr(*RC.back(), *TII, UseCopyInstr);

1363 if (!CheckCopyConstraint(OuterMostSpillCopy->Source->getReg(),

1364 InnerMostSpillCopy->Source->getReg()) ||

1365 !CheckCopyConstraint(InnerMostReloadCopy->Destination->getReg(),

1366 OuterMostReloadCopy->Destination->getReg()))

1367 return;

1368

1369 SpillageChainsLength += SC.size() + RC.size();

1370 NumSpillageChains += 1;

1371 UpdateReg(SC[0], InnerMostSpillCopy->Destination,

1372 OuterMostSpillCopy->Source);

1373 UpdateReg(RC[0], InnerMostReloadCopy->Source,

1374 OuterMostReloadCopy->Destination);

1375

1376 for (size_t I = 1; I < SC.size() - 1; ++I) {

1377 SC[I]->eraseFromParent();

1378 RC[I]->eraseFromParent();

1379 NumDeletes += 2;

1380 }

1381 };

1382

1383 auto IsFoldableCopy = [this](const MachineInstr &MaybeCopy) {

1384 if (MaybeCopy.getNumImplicitOperands() > 0)

1385 return false;

1386 std::optional CopyOperands =

1387 isCopyInstr(MaybeCopy, *TII, UseCopyInstr);

1388 if (!CopyOperands)

1389 return false;

1390 Register Src = CopyOperands->Source->getReg();

1391 Register Def = CopyOperands->Destination->getReg();

1392 return Src && Def && TRI->regsOverlap(Src, Def) &&

1393 CopyOperands->Source->isRenamable() &&

1394 CopyOperands->Destination->isRenamable();

1395 };

1396

1397 auto IsSpillReloadPair = [&, this](const MachineInstr &Spill,

1398 const MachineInstr &Reload) {

1399 if (!IsFoldableCopy(Spill) || !IsFoldableCopy(Reload))

1400 return false;

1401 std::optional SpillCopy =

1402 isCopyInstr(Spill, *TII, UseCopyInstr);

1403 std::optional ReloadCopy =

1404 isCopyInstr(Reload, *TII, UseCopyInstr);

1405 if (!SpillCopy || !ReloadCopy)

1406 return false;

1407 return SpillCopy->Source->getReg() == ReloadCopy->Destination->getReg() &&

1408 SpillCopy->Destination->getReg() == ReloadCopy->Source->getReg();

1409 };

1410

1411 auto IsChainedCopy = [&, this](const MachineInstr &Prev,

1412 const MachineInstr &Current) {

1413 if (!IsFoldableCopy(Prev) || !IsFoldableCopy(Current))

1414 return false;

1415 std::optional PrevCopy =

1416 isCopyInstr(Prev, *TII, UseCopyInstr);

1417 std::optional CurrentCopy =

1418 isCopyInstr(Current, *TII, UseCopyInstr);

1419 if (!PrevCopy || !CurrentCopy)

1420 return false;

1421 return PrevCopy->Source->getReg() == CurrentCopy->Destination->getReg();

1422 };

1423

1425 std::optional CopyOperands =

1426 isCopyInstr(MI, *TII, UseCopyInstr);

1427

1428

1429 SmallSet<Register, 8> RegsToClobber;

1430 if (!CopyOperands) {

1431 for (const MachineOperand &MO : MI.operands()) {

1432 if (!MO.isReg())

1433 continue;

1435 if (Reg)

1436 continue;

1437 MachineInstr *LastUseCopy =

1438 Tracker.findLastSeenUseInCopy(Reg.asMCReg(), *TRI);

1439 if (LastUseCopy) {

1444 CopySourceInvalid.insert(LastUseCopy);

1445 }

1446

1447

1448

1449

1450

1451

1453 UseCopyInstr))

1454

1456 }

1458 Tracker.clobberRegister(Reg, *TRI, *TII, UseCopyInstr);

1460 << "\n");

1461 }

1462 continue;

1463 }

1464

1465 Register Src = CopyOperands->Source->getReg();

1466 Register Def = CopyOperands->Destination->getReg();

1467

1468 LLVM_DEBUG(dbgs() << "MCP: Searching paired spill for reload: ");

1470 MachineInstr *MaybeSpill =

1471 Tracker.findLastSeenDefInCopy(MI, Src.asMCReg(), *TRI, *TII, UseCopyInstr);

1472 bool MaybeSpillIsChained = ChainLeader.count(MaybeSpill);

1473 if (!MaybeSpillIsChained && MaybeSpill &&

1474 IsSpillReloadPair(*MaybeSpill, MI)) {

1475

1476

1477

1478

1479

1480

1481

1482

1483

1484

1485

1486

1487

1488

1489

1490

1491

1492

1493

1494

1495

1496

1497

1498

1499

1500

1501

1502

1503

1504

1505

1506

1509 MachineInstr *MaybePrevReload =

1510 Tracker.findLastSeenUseInCopy(Def.asMCReg(), *TRI);

1511 auto Leader = ChainLeader.find(MaybePrevReload);

1512 MachineInstr *L = nullptr;

1513 if (Leader == ChainLeader.end() ||

1514 (MaybePrevReload && !IsChainedCopy(*MaybePrevReload, MI))) {

1515 L = &MI;

1517 "SpillChain should not have contained newly found chain");

1518 } else {

1519 assert(MaybePrevReload &&

1520 "Found a valid leader through nullptr should not happend");

1521 L = Leader->second;

1523 "Existing chain's length should be larger than zero");

1524 }

1526 "Newly found paired spill-reload should not belong to any chain "

1527 "at this point");

1528 ChainLeader.insert({MaybeSpill, L});

1530 SpillChain[L].push_back(MaybeSpill);

1531 ReloadChain[L].push_back(&MI);

1532 LLVM_DEBUG(dbgs() << "MCP: Chain " << L << " now is:\n");

1534 } else if (MaybeSpill && !MaybeSpillIsChained) {

1535

1536

1537

1538

1539

1540

1541

1542

1543

1544

1545

1546

1547

1548 LLVM_DEBUG(dbgs() << "MCP: Not paired spill-reload:\n");

1551 Tracker.clobberRegister(Src.asMCReg(), *TRI, *TII, UseCopyInstr);

1553 << "\n");

1554 }

1555 Tracker.trackCopy(&MI, *TRI, *TII, UseCopyInstr);

1556 }

1557

1558 for (auto I = SpillChain.begin(), E = SpillChain.end(); I != E; ++I) {

1559 auto &SC = I->second;

1561 "Reload chain of the same leader should exist");

1562 auto &RC = ReloadChain[I->first];

1563 TryFoldSpillageCopies(SC, RC);

1564 }

1565

1566 MaybeDeadCopies.clear();

1567 CopyDbgUsers.clear();

1568 Tracker.clear();

1569}

1570

1571bool MachineCopyPropagationLegacy::runOnMachineFunction(MachineFunction &MF) {

1573 return false;

1574

1575 return MachineCopyPropagation(UseCopyInstr).run(MF);

1576}

1577

1578PreservedAnalyses

1582 if (!MachineCopyPropagation(UseCopyInstr).run(MF))

1586 return PA;

1587}

1588

1590 bool isSpillageCopyElimEnabled = false;

1593 isSpillageCopyElimEnabled =

1595 break;

1597 isSpillageCopyElimEnabled = true;

1598 break;

1600 isSpillageCopyElimEnabled = false;

1601 break;

1602 }

1603

1605

1609

1611 if (isSpillageCopyElimEnabled)

1612 EliminateSpillageCopies(MBB);

1613 BackwardCopyPropagateBlock(MBB);

1614 ForwardCopyPropagateBlock(MBB);

1615 }

1616

1618}

1619

1620MachineFunctionPass *

1622 return new MachineCopyPropagationLegacy(UseCopyInstr);

1623}

unsigned const MachineRegisterInfo * MRI

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

const TargetInstrInfo & TII

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

This file provides an implementation of debug counters.

#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC)

This file defines the DenseMap class.

static cl::opt< cl::boolOrDefault > EnableSpillageCopyElimination("enable-spill-copy-elim", cl::Hidden)

static bool isBackwardPropagatableCopy(const DestSourcePair &CopyOperands, const MachineRegisterInfo &MRI)

Definition MachineCopyPropagation.cpp:1079

static void printSpillReloadChain(DenseMap< MachineInstr *, SmallVector< MachineInstr * > > &SpillChain, DenseMap< MachineInstr *, SmallVector< MachineInstr * > > &ReloadChain, MachineInstr *Leader)

Definition MachineCopyPropagation.cpp:1250

static bool isNopCopy(const MachineInstr &PreviousCopy, MCRegister Src, MCRegister Def, const TargetRegisterInfo *TRI, const TargetInstrInfo *TII, bool UseCopyInstr)

Return true if PreviousCopy did copy register Src to register Def.

Definition MachineCopyPropagation.cpp:572

static cl::opt< bool > MCPUseCopyInstr("mcp-use-is-copy-instr", cl::init(false), cl::Hidden)

Register const TargetRegisterInfo * TRI

Promote Memory to Register

MachineInstr unsigned OpIdx

#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)

This file implements a set that has insertion order iteration characteristics.

This file defines the SmallSet class.

This file defines the SmallVector class.

This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...

#define STATISTIC(VARNAME, DESC)

LLVM_ABI void setPreservesCFG()

This function should be called by the pass, iff they do not:

bool test(unsigned Idx) const

void resize(unsigned N, bool t=false)

resize - Grow or shrink the bitvector.

Represents analyses that only rely on functions' control flow.

static bool shouldExecute(CounterInfo &Counter)

iterator find(const_arg_type_t< KeyT > Val)

size_type count(const_arg_type_t< KeyT > Val) const

Return 1 if the specified key is in the map, 0 otherwise.

std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)

Wrapper class representing physical registers. Should be passed by value.

An RAII based helper class to modify MachineFunctionProperties when running pass.

iterator_range< succ_iterator > successors()

LLVM_ABI StringRef getName() const

Return the name of the corresponding LLVM basic block, or an empty string.

PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)

Definition MachineCopyPropagation.cpp:1579

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.

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.

Representation of each machine instruction.

LLVM_ABI void eraseFromParent()

Unlink 'this' from the containing basic block and delete it.

LLVM_ABI void dump() const

const MachineOperand & getOperand(unsigned i) const

LLVM_ABI const TargetRegisterClass * getRegClassConstraint(unsigned OpIdx, const TargetInstrInfo *TII, const TargetRegisterInfo *TRI) const

Compute the static register class constraint for operand OpIdx.

LLVM_ABI void setIsRenamable(bool Val=true)

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.

LLVM_ABI bool isRenamable() const

isRenamable - Returns true if this register may be renamed, i.e.

void setIsUndef(bool Val=true)

Register getReg() const

getReg - Returns the register number.

static bool clobbersPhysReg(const uint32_t *RegMask, MCRegister PhysReg)

clobbersPhysReg - Returns true if this RegMask clobbers PhysReg.

const uint32_t * getRegMask() const

getRegMask - Returns a bit mask of registers preserved by this RegMask operand.

MachineRegisterInfo - Keep track of information for virtual and physical registers,...

static PreservedAnalyses all()

Construct a special preserved set that preserves all passes.

Wrapper class representing virtual and physical registers.

MCRegister asMCReg() const

Utility to check-convert this value to a MCRegister.

constexpr bool isVirtual() const

Return true if the specified register number is in the virtual register namespace.

constexpr bool isPhysical() const

Return true if the specified register number is in the physical register namespace.

void insert_range(Range &&R)

std::pair< const_iterator, bool > insert(const T &V)

insert - Insert an element into the set if it isn't already there.

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

TargetInstrInfo - Interface to description of machine instruction set.

virtual bool simplifyInstruction(MachineInstr &MI) const

If possible, converts the instruction to a simplified/canonical form.

TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...

virtual bool enableSpillageCopyElimination() const

Enable spillage copy elimination in MachineCopyPropagation pass.

virtual const TargetInstrInfo * getInstrInfo() const

virtual const TargetRegisterInfo * getRegisterInfo() const =0

Return the target's register information.

std::pair< iterator, bool > insert(const ValueT &V)

size_type count(const_arg_type_t< ValueT > V) const

Return 1 if the specified key is in the set, 0 otherwise.

reverse_self_iterator getReverseIterator()

self_iterator getIterator()

This provides a very simple, boring adaptor for a begin and end iterator into a range type.

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.

initializer< Ty > init(const Ty &Val)

PointerTypeMap run(const Module &M)

Compute the PointerTypeMap for the module M.

NodeAddr< DefNode * > Def

NodeAddr< UseNode * > Use

This is an optimization pass for GlobalISel generic memory operations.

auto drop_begin(T &&RangeOrContainer, size_t N=1)

Return a range covering RangeOrContainer with the first N elements excluded.

auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)

Get the size of a range.

iterator_range< T > make_range(T x, T y)

Convenience function for iterating over sub-ranges.

iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)

Make a range that does early increment to allow mutation of the underlying range without disrupting i...

AnalysisManager< MachineFunction > MachineFunctionAnalysisManager

LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()

Returns the minimum set of Analyses that all machine function passes must preserve.

auto reverse(ContainerTy &&C)

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

class LLVM_GSL_OWNER SmallVector

Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...

auto drop_end(T &&RangeOrContainer, size_t N=1)

Return a range covering RangeOrContainer with the last N elements excluded.

ArrayRef(const T &OneElt) -> ArrayRef< T >

bool is_contained(R &&Range, const E &Element)

Returns true if Element is found in Range.

LLVM_ABI MachineFunctionPass * createMachineCopyPropagationPass(bool UseCopyInstr)

Definition MachineCopyPropagation.cpp:1621

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.

LLVM_ABI char & MachineCopyPropagationID

MachineCopyPropagation - This pass performs copy propagation on machine instructions.

Definition MachineCopyPropagation.cpp:525

const MachineOperand * Source

const MachineOperand * Destination