LLVM: lib/CodeGen/PeepholeOptimizer.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

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

95#include

96#include

97#include

98

99using namespace llvm;

102

103#define DEBUG_TYPE "peephole-opt"

104

105

107 cl::desc("Aggressive extension optimization"));

108

111 cl::desc("Disable the peephole optimizer"));

112

113

114

115

118 cl::desc("Disable advanced copy optimization"));

119

121 "disable-non-allocatable-phys-copy-opt", cl::Hidden, cl::init(false),

122 cl::desc("Disable non-allocatable physical register copy optimization"));

123

124

125

128 cl::desc("Limit the length of PHI chains to lookup"));

129

130

131

134 cl::desc("Maximum length of recurrence chain when evaluating the benefit "

135 "of commuting operands"));

136

137STATISTIC(NumReuse, "Number of extension results reused");

138STATISTIC(NumCmps, "Number of compares eliminated");

139STATISTIC(NumImmFold, "Number of move immediate folded");

140STATISTIC(NumLoadFold, "Number of loads folded");

141STATISTIC(NumSelects, "Number of selects optimized");

142STATISTIC(NumUncoalescableCopies, "Number of uncoalescable copies optimized");

143STATISTIC(NumRewrittenCopies, "Number of copies rewritten");

144STATISTIC(NumNAPhysCopies, "Number of non-allocatable physical copies removed");

145

146namespace {

147

148class ValueTrackerResult;

149class RecurrenceInstr;

150

151

152class Rewriter {

153protected:

155 int CurrentSrcIdx = 0;

156public:

158 virtual ~Rewriter() = default;

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185 virtual bool getNextRewritableSource(RegSubRegPair &Src,

187

188

189

190 virtual bool RewriteCurrentSource(Register NewReg, unsigned NewSubReg) = 0;

191};

192

193

194class CopyRewriter : public Rewriter {

195public:

196 CopyRewriter(MachineInstr &MI) : Rewriter(MI) {

197 assert(MI.isCopy() && "Expected copy instruction");

198 }

199 ~CopyRewriter() override = default;

200

203 if (++CurrentSrcIdx > 1)

204 return false;

205

206

207 const MachineOperand &MOSrc = CopyLike.getOperand(CurrentSrcIdx);

209

210 const MachineOperand &MODef = CopyLike.getOperand(0);

212 return true;

213 }

214

215 bool RewriteCurrentSource(Register NewReg, unsigned NewSubReg) override {

216 MachineOperand &MOSrc = CopyLike.getOperand(CurrentSrcIdx);

217 MOSrc.setReg(NewReg);

219 return true;

220 }

221};

222

223

224

225class UncoalescableRewriter : public Rewriter {

226 int NumDefs;

227

228public:

229 UncoalescableRewriter(MachineInstr &MI) : Rewriter(MI) {

230 NumDefs = MI.getDesc().getNumDefs();

231 }

232

233

234

235

236

239

240 if (CurrentSrcIdx == NumDefs)

241 return false;

242

243 while (CopyLike.getOperand(CurrentSrcIdx).isDead()) {

244 ++CurrentSrcIdx;

245 if (CurrentSrcIdx == NumDefs)

246 return false;

247 }

248

249

251 const MachineOperand &MODef = CopyLike.getOperand(CurrentSrcIdx);

253

254 CurrentSrcIdx++;

255 return true;

256 }

257

258 bool RewriteCurrentSource(Register NewReg, unsigned NewSubReg) override {

259 return false;

260 }

261};

262

263

264class InsertSubregRewriter : public Rewriter {

265public:

266 InsertSubregRewriter(MachineInstr &MI) : Rewriter(MI) {

267 assert(MI.isInsertSubreg() && "Invalid instruction");

268 }

269

270

271

272

273

274

275

276

277

278

279

280

283

284 if (CurrentSrcIdx == 2)

285 return false;

286

287 CurrentSrcIdx = 2;

288 const MachineOperand &MOInsertedReg = CopyLike.getOperand(2);

290 const MachineOperand &MODef = CopyLike.getOperand(0);

291

292

293

295

296 return false;

298 (unsigned)CopyLike.getOperand(3).getImm());

299 return true;

300 }

301

302 bool RewriteCurrentSource(Register NewReg, unsigned NewSubReg) override {

303 if (CurrentSrcIdx != 2)

304 return false;

305

306 MachineOperand &MO = CopyLike.getOperand(CurrentSrcIdx);

309 return true;

310 }

311};

312

313

314class ExtractSubregRewriter : public Rewriter {

315 const TargetInstrInfo &TII;

316

317public:

318 ExtractSubregRewriter(MachineInstr &MI, const TargetInstrInfo &TII)

320 assert(MI.isExtractSubreg() && "Invalid instruction");

321 }

322

323

324

325

326

327

330

331 if (CurrentSrcIdx == 1)

332 return false;

333

334 CurrentSrcIdx = 1;

335 const MachineOperand &MOExtractedReg = CopyLike.getOperand(1);

336

338 return false;

339

340 Src =

342

343

344 const MachineOperand &MODef = CopyLike.getOperand(0);

346 return true;

347 }

348

349 bool RewriteCurrentSource(Register NewReg, unsigned NewSubReg) override {

350

351 if (CurrentSrcIdx != 1)

352 return false;

353

354 CopyLike.getOperand(CurrentSrcIdx).setReg(NewReg);

355

356

357

358 if (!NewSubReg) {

359

360

361

362 CurrentSrcIdx = -1;

363

364

365 CopyLike.removeOperand(2);

366

367 CopyLike.setDesc(TII.get(TargetOpcode::COPY));

368 return true;

369 }

370 CopyLike.getOperand(CurrentSrcIdx + 1).setImm(NewSubReg);

371 return true;

372 }

373};

374

375

376class RegSequenceRewriter : public Rewriter {

377public:

378 RegSequenceRewriter(MachineInstr &MI) : Rewriter(MI) {

379 assert(MI.isRegSequence() && "Invalid instruction");

380 CurrentSrcIdx = -1;

381 }

382

383

384

385

386

387

388

389

390

391

392

393

394

395

396

397

398

401

402 CurrentSrcIdx += 2;

403 if (static_cast<unsigned>(CurrentSrcIdx) >= CopyLike.getNumOperands())

404 return false;

405

406 const MachineOperand &MOInsertedReg = CopyLike.getOperand(CurrentSrcIdx);

407 Src.Reg = MOInsertedReg.getReg();

408 Src.SubReg = MOInsertedReg.getSubReg();

409

410

411

412 Dst.SubReg = CopyLike.getOperand(CurrentSrcIdx + 1).getImm();

413

414 const MachineOperand &MODef = CopyLike.getOperand(0);

415 Dst.Reg = MODef.getReg();

416 assert(MODef.getSubReg() == 0 && "cannot have subregister def in SSA");

417 return true;

418 }

419

420 bool RewriteCurrentSource(Register NewReg, unsigned NewSubReg) override {

421 MachineOperand &MO = CopyLike.getOperand(CurrentSrcIdx);

424 return true;

425 }

426};

427

429 const TargetInstrInfo *TII = nullptr;

430 const TargetRegisterInfo *TRI = nullptr;

431 MachineRegisterInfo *MRI = nullptr;

432 MachineDominatorTree *DT = nullptr;

433 MachineLoopInfo *MLI = nullptr;

434

435public:

436 PeepholeOptimizer(MachineDominatorTree *DT, MachineLoopInfo *MLI)

437 : DT(DT), MLI(MLI) {}

438

439 bool run(MachineFunction &MF);

440

441 using RewriteMapTy = SmallDenseMap<RegSubRegPair, ValueTrackerResult>;

442

443

444 using RecurrenceCycle = SmallVector<RecurrenceInstr, 4>;

445

446private:

447 bool optimizeCmpInstr(MachineInstr &MI);

448 bool optimizeExtInstr(MachineInstr &MI, MachineBasicBlock &MBB,

449 SmallPtrSetImpl<MachineInstr *> &LocalMIs);

450 bool optimizeSelect(MachineInstr &MI,

451 SmallPtrSetImpl<MachineInstr *> &LocalMIs);

452 bool optimizeCondBranch(MachineInstr &MI);

453

454 bool optimizeCoalescableCopyImpl(Rewriter &&CpyRewriter);

455 bool optimizeCoalescableCopy(MachineInstr &MI);

456 bool optimizeUncoalescableCopy(MachineInstr &MI,

457 SmallPtrSetImpl<MachineInstr *> &LocalMIs);

458 bool optimizeRecurrence(MachineInstr &PHI);

459 bool findNextSource(const TargetRegisterClass *DefRC, unsigned DefSubReg,

460 RegSubRegPair RegSubReg, RewriteMapTy &RewriteMap);

461 bool isMoveImmediate(MachineInstr &MI, SmallSet<Register, 4> &ImmDefRegs,

462 DenseMap<Register, MachineInstr *> &ImmDefMIs);

463 bool foldImmediate(MachineInstr &MI, SmallSet<Register, 4> &ImmDefRegs,

464 DenseMap<Register, MachineInstr *> &ImmDefMIs,

466

467

468

469

470

472 const SmallSet<Register, 2> &TargetReg,

473 RecurrenceCycle &RC);

474

475

476

477

478

479

480 bool foldRedundantCopy(MachineInstr &MI);

481

482

484

485

486

487

488

489

490 bool

491 foldRedundantNAPhysCopy(MachineInstr &MI,

492 DenseMap<Register, MachineInstr *> &NAPhysToVirtMIs);

493

494 bool isLoadFoldable(MachineInstr &MI,

495 SmallSet<Register, 16> &FoldAsLoadDefCandidates);

496

497

498

499 static bool isCoalescableCopy(const MachineInstr &MI) {

500

501

502 return MI.isCopy() ||

504 MI.isExtractSubreg()));

505 }

506

507

508

509 static bool isUncoalescableCopy(const MachineInstr &MI) {

511 MI.isInsertSubregLike() ||

512 MI.isExtractSubregLike()));

513 }

514

515 MachineInstr &rewriteSource(MachineInstr &CopyLike, RegSubRegPair Def,

516 RewriteMapTy &RewriteMap);

517

518

519

520 DenseMap<RegSubRegPair, MachineInstr *> CopySrcMIs;

521

522

523 void MF_HandleInsertion(MachineInstr &MI) override {}

524

525 bool getCopySrc(MachineInstr &MI, RegSubRegPair &SrcPair) {

526 if (MI.isCopy())

527 return false;

528

529 Register SrcReg = MI.getOperand(1).getReg();

530 unsigned SrcSubReg = MI.getOperand(1).getSubReg();

531 if (!SrcReg.isVirtual() && !MRI->isConstantPhysReg(SrcReg))

532 return false;

533

535 return true;

536 }

537

538

539

540 void deleteChangedCopy(MachineInstr &MI) {

542 if (!getCopySrc(MI, SrcPair))

543 return;

544

545 auto It = CopySrcMIs.find(SrcPair);

546 if (It != CopySrcMIs.end() && It->second == &MI)

547 CopySrcMIs.erase(It);

548 }

549

550 void MF_HandleRemoval(MachineInstr &MI) override { deleteChangedCopy(MI); }

551

552 void MF_HandleChangeDesc(MachineInstr &MI, const MCInstrDesc &TID) override {

553 deleteChangedCopy(MI);

554 }

555};

556

558public:

559 static char ID;

560

561 PeepholeOptimizerLegacy() : MachineFunctionPass(ID) {

563 }

564

565 bool runOnMachineFunction(MachineFunction &MF) override;

566

567 void getAnalysisUsage(AnalysisUsage &AU) const override {

570 AU.addRequired();

571 AU.addPreserved();

573 AU.addRequired();

574 AU.addPreserved();

575 }

576 }

577

578 MachineFunctionProperties getRequiredProperties() const override {

579 return MachineFunctionProperties().setIsSSA();

580 }

581};

582

583

584

585

586

587

588

589class RecurrenceInstr {

590public:

591 using IndexPair = std::pair<unsigned, unsigned>;

592

593 RecurrenceInstr(MachineInstr *MI) : MI(MI) {}

594 RecurrenceInstr(MachineInstr *MI, unsigned Idx1, unsigned Idx2)

595 : MI(MI), CommutePair(std::make_pair(Idx1, Idx2)) {}

596

597 MachineInstr *getMI() const { return MI; }

598 std::optional getCommutePair() const { return CommutePair; }

599

600private:

601 MachineInstr *MI;

602 std::optional CommutePair;

603};

604

605

606

607

608class ValueTrackerResult {

609private:

610

612

613

614 const MachineInstr *Inst = nullptr;

615

616public:

617 ValueTrackerResult() = default;

618

620

621 bool isValid() const { return getNumSources() > 0; }

622

623 void setInst(const MachineInstr *I) { Inst = I; }

624 const MachineInstr *getInst() const { return Inst; }

625

626 void clear() {

627 RegSrcs.clear();

628 Inst = nullptr;

629 }

630

631 void addSource(Register SrcReg, unsigned SrcSubReg) {

632 RegSrcs.push_back(RegSubRegPair(SrcReg, SrcSubReg));

633 }

634

635 void setSource(int Idx, Register SrcReg, unsigned SrcSubReg) {

636 assert(Idx < getNumSources() && "Reg pair source out of index");

638 }

639

640 int getNumSources() const { return RegSrcs.size(); }

641

642 RegSubRegPair getSrc(int Idx) const { return RegSrcs[Idx]; }

643

644 Register getSrcReg(int Idx) const {

645 assert(Idx < getNumSources() && "Reg source out of index");

646 return RegSrcs[Idx].Reg;

647 }

648

649 unsigned getSrcSubReg(int Idx) const {

650 assert(Idx < getNumSources() && "SubReg source out of index");

651 return RegSrcs[Idx].SubReg;

652 }

653

655 if (Other.getInst() != getInst())

656 return false;

657

658 if (Other.getNumSources() != getNumSources())

659 return false;

660

661 for (int i = 0, e = Other.getNumSources(); i != e; ++i)

662 if (Other.getSrcReg(i) != getSrcReg(i) ||

663 Other.getSrcSubReg(i) != getSrcSubReg(i))

664 return false;

665 return true;

666 }

667};

668

669

670

671

672

673

674

675

676

677

678

679

680

681

682

683

684

685class ValueTracker {

686private:

687

688 const MachineInstr *Def = nullptr;

689

690

691 unsigned DefIdx = 0;

692

693

694 unsigned DefSubReg;

695

696

698

699

700 const MachineRegisterInfo &MRI;

701

702

703 const TargetInstrInfo *TII;

704

705

706 ValueTrackerResult getNextSourceImpl();

707

708

709 ValueTrackerResult getNextSourceFromCopy();

710

711

712 ValueTrackerResult getNextSourceFromBitcast();

713

714

715 ValueTrackerResult getNextSourceFromRegSequence();

716

717

718 ValueTrackerResult getNextSourceFromInsertSubreg();

719

720

721 ValueTrackerResult getNextSourceFromExtractSubreg();

722

723

724 ValueTrackerResult getNextSourceFromSubregToReg();

725

726

727 ValueTrackerResult getNextSourceFromPHI();

728

729public:

730

731

732

733

734

735

736

737

738

739 ValueTracker(Register Reg, unsigned DefSubReg, const MachineRegisterInfo &MRI,

740 const TargetInstrInfo *TII = nullptr)

741 : DefSubReg(DefSubReg), Reg(Reg), MRI(MRI), TII(TII) {

742 if (!Reg.isPhysical()) {

743 Def = MRI.getVRegDef(Reg);

744 DefIdx = MRI.def_begin(Reg).getOperandNo();

745 }

746 }

747

748

749

750

751

752

753 ValueTrackerResult getNextSource();

754};

755

756}

757

758char PeepholeOptimizerLegacy::ID = 0;

759

761

763 "Peephole Optimizations", false, false)

768

769

770

771

772

773

774

775

776

777bool PeepholeOptimizer::optimizeExtInstr(

781 unsigned SubIdx;

782 if (TII->isCoalescableExtInstr(MI, SrcReg, DstReg, SubIdx))

783 return false;

784

786 return false;

787

788 if (MRI->hasOneNonDBGUse(SrcReg))

789

790 return false;

791

792

793

795 DstRC = TRI->getSubClassWithSubReg(DstRC, SubIdx);

796 if (!DstRC)

797 return false;

798

799

800

801

802

803

804 bool UseSrcSubIdx =

805 TRI->getSubClassWithSubReg(MRI->getRegClass(SrcReg), SubIdx) != nullptr;

806

807

808

811 ReachedBBs.insert(UI.getParent());

812

813

815

816

818

819 bool ExtendLife = true;

821 MachineInstr *UseMI = UseMO.getParent();

822 if (UseMI == &MI)

823 continue;

824

825 if (UseMI->isPHI()) {

826 ExtendLife = false;

827 continue;

828 }

829

830

831 if (UseSrcSubIdx && UseMO.getSubReg() != SubIdx)

832 continue;

833

834

835

836

837

838

839

840

841

842

843

844

845

846

847

848

849

850

851 if (UseMI->getOpcode() == TargetOpcode::SUBREG_TO_REG)

852 continue;

853

855 if (UseMBB == &MBB) {

856

857 if (!LocalMIs.count(UseMI))

858 Uses.push_back(&UseMO);

859 } else if (ReachedBBs.count(UseMBB)) {

860

861

862 Uses.push_back(&UseMO);

864

865

866 ExtendedUses.push_back(&UseMO);

867 } else {

868

869

870 ExtendLife = false;

871 break;

872 }

873 }

874

875 if (ExtendLife && !ExtendedUses.empty())

876

877 Uses.append(ExtendedUses.begin(), ExtendedUses.end());

878

879

882 SmallPtrSet<MachineBasicBlock *, 4> PHIBBs;

883

884

885

886

887 for (MachineInstr &UI : MRI->use_nodbg_instructions(DstReg))

888 if (UI.isPHI())

889 PHIBBs.insert(UI.getParent());

890

891 const TargetRegisterClass *RC = MRI->getRegClass(SrcReg);

892 for (MachineOperand *UseMO : Uses) {

893 MachineInstr *UseMI = UseMO->getParent();

894 MachineBasicBlock *UseMBB = UseMI->getParent();

895 if (PHIBBs.count(UseMBB))

896 continue;

897

898

899 if (!Changed) {

900 MRI->clearKillFlags(DstReg);

901 MRI->constrainRegClass(DstReg, DstRC);

902 }

903

904

905

906

907

908

909

910

911

912

913

914

915

916

917

918 if (UseSrcSubIdx)

919 RC = MRI->getRegClass(UseMI->getOperand(0).getReg());

920

921 Register NewVR = MRI->createVirtualRegister(RC);

922 BuildMI(*UseMBB, UseMI, UseMI->getDebugLoc(),

923 TII->get(TargetOpcode::COPY), NewVR)

924 .addReg(DstReg, 0, SubIdx);

925 if (UseSrcSubIdx)

926 UseMO->setSubReg(0);

927

928 UseMO->setReg(NewVR);

929 ++NumReuse;

930 Changed = true;

931 }

932 }

933

935}

936

937

938

939

940

941bool PeepholeOptimizer::optimizeCmpInstr(MachineInstr &MI) {

942

943

945 int64_t CmpMask, CmpValue;

948 return false;

949

950

951 LLVM_DEBUG(dbgs() << "Attempting to optimize compare: " << MI);

953 LLVM_DEBUG(dbgs() << " -> Successfully optimized compare!\n");

954 ++NumCmps;

955 return true;

956 }

957

958 return false;

959}

960

961

962bool PeepholeOptimizer::optimizeSelect(

963 MachineInstr &MI, SmallPtrSetImpl<MachineInstr *> &LocalMIs) {

964 unsigned TrueOp = 0;

965 unsigned FalseOp = 0;

966 bool Optimizable = false;

969 return false;

970 if (!Optimizable)

971 return false;

973 return false;

975 MI.eraseFromParent();

976 ++NumSelects;

977 return true;

978}

979

980

981bool PeepholeOptimizer::optimizeCondBranch(MachineInstr &MI) {

983}

984

985

986

987

988

989

990

991

992

993

994

995

996

997

998bool PeepholeOptimizer::findNextSource(const TargetRegisterClass *DefRC,

999 unsigned DefSubReg,

1001 RewriteMapTy &RewriteMap) {

1002

1003

1004

1005

1009

1010 unsigned PHICount = 0;

1011 do {

1013

1015 return false;

1016

1017 ValueTracker ValTracker(CurSrcPair.Reg, CurSrcPair.SubReg, *MRI, TII);

1018

1019

1020

1021 while (true) {

1022 ValueTrackerResult Res = ValTracker.getNextSource();

1023

1024 if (!Res.isValid())

1025 return false;

1026

1027

1028 auto [InsertPt, WasInserted] = RewriteMap.try_emplace(CurSrcPair, Res);

1029

1030 if (!WasInserted) {

1031 const ValueTrackerResult &CurSrcRes = InsertPt->second;

1032

1033 assert(CurSrcRes == Res && "ValueTrackerResult found must match");

1034

1035

1036 if (CurSrcRes.getNumSources() > 1) {

1038 << "findNextSource: found PHI cycle, aborting...\n");

1039 return false;

1040 }

1041 break;

1042 }

1043

1044

1045

1046 unsigned NumSrcs = Res.getNumSources();

1047 if (NumSrcs > 1) {

1048 PHICount++;

1050 LLVM_DEBUG(dbgs() << "findNextSource: PHI limit reached\n");

1051 return false;

1052 }

1053

1054 for (unsigned i = 0; i < NumSrcs; ++i)

1055 SrcToLook.push_back(Res.getSrc(i));

1056 break;

1057 }

1058

1059 CurSrcPair = Res.getSrc(0);

1060

1061

1062

1063

1065 return false;

1066

1067

1068 const TargetRegisterClass *SrcRC = MRI->getRegClass(CurSrcPair.Reg);

1069 if (TRI->shouldRewriteCopySrc(DefRC, DefSubReg, SrcRC,

1071 continue;

1072

1073

1074

1075 if (PHICount > 0 && CurSrcPair.SubReg != 0)

1076 continue;

1077

1078

1079 break;

1080 }

1081 } while (!SrcToLook.empty());

1082

1083

1084 return CurSrcPair.Reg != Reg;

1085}

1086

1087

1088

1089

1090

1091

1096 assert(!SrcRegs.empty() && "No sources to create a PHI instruction?");

1097

1099

1100

1101 assert(SrcRegs[0].SubReg == 0 && "should not have subreg operand");

1102 Register NewVR = MRI.createVirtualRegister(NewRC);

1105 TII.get(TargetOpcode::PHI), NewVR);

1106

1107 unsigned MBBOpIdx = 2;

1109 MIB.addReg(RegPair.Reg, 0, RegPair.SubReg);

1111

1112

1113

1114 MRI.clearKillFlags(RegPair.Reg);

1115 MBBOpIdx += 2;

1116 }

1117

1118 return *MIB;

1119}

1120

1121

1122

1123

1124

1125

1126

1130 const PeepholeOptimizer::RewriteMapTy &RewriteMap,

1131 bool HandleMultipleSources = true) {

1133 while (true) {

1134 ValueTrackerResult Res = RewriteMap.lookup(LookupSrc);

1135

1136 if (!Res.isValid())

1137 return LookupSrc;

1138

1139

1140 unsigned NumSrcs = Res.getNumSources();

1141 if (NumSrcs == 1) {

1142 LookupSrc.Reg = Res.getSrcReg(0);

1143 LookupSrc.SubReg = Res.getSrcSubReg(0);

1144 continue;

1145 }

1146

1147

1148 if (!HandleMultipleSources)

1149 break;

1150

1151

1152

1154 for (unsigned i = 0; i < NumSrcs; ++i) {

1155 RegSubRegPair PHISrc(Res.getSrcReg(i), Res.getSrcSubReg(i));

1158 }

1159

1160

1168 }

1169

1171}

1172

1173bool PeepholeOptimizer::optimizeCoalescableCopyImpl(Rewriter &&CpyRewriter) {

1175

1176

1179 while (CpyRewriter.getNextRewritableSource(TrackPair, Dst)) {

1180 if (Dst.Reg.isPhysical()) {

1181

1182

1183

1184

1185 continue;

1186 }

1187

1188 const TargetRegisterClass *DefRC = MRI->getRegClass(Dst.Reg);

1189

1190

1191 RewriteMapTy RewriteMap;

1192

1193

1194 if (!findNextSource(DefRC, Dst.SubReg, TrackPair, RewriteMap))

1195 continue;

1196

1197

1198

1200 false);

1202 "should not rewrite source to original value");

1203 if (!NewSrc.Reg)

1204 continue;

1205

1206 if (NewSrc.SubReg) {

1207

1208

1209

1210 const TargetRegisterClass *RC = MRI->getRegClass(NewSrc.Reg);

1211 const TargetRegisterClass *WithSubRC =

1212 TRI->getSubClassWithSubReg(RC, NewSrc.SubReg);

1213 if (MRI->constrainRegClass(NewSrc.Reg, WithSubRC))

1214 continue;

1216 }

1217

1218

1219 if (CpyRewriter.RewriteCurrentSource(NewSrc.Reg, NewSrc.SubReg)) {

1220

1221 MRI->clearKillFlags(NewSrc.Reg);

1223 }

1224 }

1225

1226

1227

1228

1229

1230

1231 NumRewrittenCopies += Changed;

1233}

1234

1235

1236

1237

1238

1239

1240

1241

1242

1243

1244

1245

1246bool PeepholeOptimizer::optimizeCoalescableCopy(MachineInstr &MI) {

1247 assert(isCoalescableCopy(MI) && "Invalid argument");

1248 assert(MI.getDesc().getNumDefs() == 1 &&

1249 "Coalescer can understand multiple defs?!");

1250 const MachineOperand &MODef = MI.getOperand(0);

1251

1253 return false;

1254

1255 switch (MI.getOpcode()) {

1256 case TargetOpcode::COPY:

1257 return optimizeCoalescableCopyImpl(CopyRewriter(MI));

1258 case TargetOpcode::INSERT_SUBREG:

1259 return optimizeCoalescableCopyImpl(InsertSubregRewriter(MI));

1260 case TargetOpcode::EXTRACT_SUBREG:

1261 return optimizeCoalescableCopyImpl(ExtractSubregRewriter(MI, *TII));

1262 case TargetOpcode::REG_SEQUENCE:

1263 return optimizeCoalescableCopyImpl(RegSequenceRewriter(MI));

1264 default:

1265

1266 if (MI.isBitcast() || MI.isRegSequenceLike() || MI.isInsertSubregLike() ||

1267 MI.isExtractSubregLike())

1268 return optimizeCoalescableCopyImpl(UncoalescableRewriter(MI));

1269 return false;

1270 }

1271}

1272

1273

1274

1275

1276

1277

1278MachineInstr &PeepholeOptimizer::rewriteSource(MachineInstr &CopyLike,

1280 RewriteMapTy &RewriteMap) {

1281 assert(Def.Reg.isPhysical() && "We do not rewrite physical registers");

1282

1283

1285

1286

1287 const TargetRegisterClass *DefRC = MRI->getRegClass(Def.Reg);

1288 Register NewVReg = MRI->createVirtualRegister(DefRC);

1289

1290 if (NewSrc.SubReg) {

1291 const TargetRegisterClass *NewSrcRC = MRI->getRegClass(NewSrc.Reg);

1292 const TargetRegisterClass *WithSubRC =

1293 TRI->getSubClassWithSubReg(NewSrcRC, NewSrc.SubReg);

1294

1295

1296

1297

1298 if (MRI->constrainRegClass(NewSrc.Reg, WithSubRC))

1299 llvm_unreachable("replacement register cannot support subregister");

1300 }

1301

1302 MachineInstr *NewCopy =

1304 TII->get(TargetOpcode::COPY), NewVReg)

1306

1307 if (Def.SubReg) {

1310 }

1311

1315 MRI->replaceRegWith(Def.Reg, NewVReg);

1316 MRI->clearKillFlags(NewVReg);

1317

1318

1319

1320 MRI->clearKillFlags(NewSrc.Reg);

1321

1322 return *NewCopy;

1323}

1324

1325

1326

1327

1328

1329

1330

1331

1332

1333

1334

1335

1336bool PeepholeOptimizer::optimizeUncoalescableCopy(

1337 MachineInstr &MI, SmallPtrSetImpl<MachineInstr *> &LocalMIs) {

1338 assert(isUncoalescableCopy(MI) && "Invalid argument");

1339 UncoalescableRewriter CpyRewriter(MI);

1340

1341

1342

1343

1344 RewriteMapTy RewriteMap;

1348 while (CpyRewriter.getNextRewritableSource(Src, Def)) {

1349

1350

1351 if (Def.Reg.isPhysical())

1352 return false;

1353

1354

1355

1356

1357 const TargetRegisterClass *DefRC = MRI->getRegClass(Def.Reg);

1358

1359

1360

1361 if (!findNextSource(DefRC, Def.SubReg, Def, RewriteMap))

1362 return false;

1363

1365 }

1366

1367

1369

1370 MachineInstr &NewCopy = rewriteSource(MI, Def, RewriteMap);

1371 LocalMIs.insert(&NewCopy);

1372 }

1373

1374

1375 LLVM_DEBUG(dbgs() << "Deleting uncoalescable copy: " << MI);

1376 MI.eraseFromParent();

1377 ++NumUncoalescableCopies;

1378 return true;

1379}

1380

1381

1382

1383

1384bool PeepholeOptimizer::isLoadFoldable(

1385 MachineInstr &MI, SmallSet<Register, 16> &FoldAsLoadDefCandidates) {

1386 if (MI.canFoldAsLoad() || MI.mayLoad())

1387 return false;

1388 const MCInstrDesc &MCID = MI.getDesc();

1390 return false;

1391

1393

1394

1395

1396 if (Reg.isVirtual() && MI.getOperand(0).getSubReg() &&

1397 MRI->hasOneNonDBGUser(Reg)) {

1398 FoldAsLoadDefCandidates.insert(Reg);

1399 return true;

1400 }

1401 return false;

1402}

1403

1404bool PeepholeOptimizer::isMoveImmediate(

1405 MachineInstr &MI, SmallSet<Register, 4> &ImmDefRegs,

1406 DenseMap<Register, MachineInstr *> &ImmDefMIs) {

1407 const MCInstrDesc &MCID = MI.getDesc();

1408 if (MCID.getNumDefs() != 1 || MI.getOperand(0).isReg())

1409 return false;

1412 return false;

1413

1414 int64_t ImmVal;

1416 return false;

1417

1418 ImmDefMIs.insert(std::make_pair(Reg, &MI));

1420 return true;

1421}

1422

1423

1424

1425

1426bool PeepholeOptimizer::foldImmediate(

1427 MachineInstr &MI, SmallSet<Register, 4> &ImmDefRegs,

1428 DenseMap<Register, MachineInstr *> &ImmDefMIs, bool &Deleted) {

1430 for (unsigned i = 0, e = MI.getDesc().getNumOperands(); i != e; ++i) {

1431 MachineOperand &MO = MI.getOperand(i);

1433 continue;

1436 continue;

1437 if (ImmDefRegs.count(Reg) == 0)

1438 continue;

1439 DenseMap<Register, MachineInstr *>::iterator II = ImmDefMIs.find(Reg);

1440 assert(II != ImmDefMIs.end() && "couldn't find immediate definition");

1442 ++NumImmFold;

1443

1444

1445

1446 if (MRI->getVRegDef(Reg) &&

1448 Register DstReg = MI.getOperand(0).getReg();

1450 MRI->getRegClass(DstReg) == MRI->getRegClass(Reg)) {

1451 MRI->replaceRegWith(DstReg, Reg);

1452 MI.eraseFromParent();

1454 }

1455 }

1456 return true;

1457 }

1458 }

1459 return false;

1460}

1461

1462

1463

1464

1465

1466

1467

1468

1469

1470

1471

1472

1473

1474

1475

1476bool PeepholeOptimizer::foldRedundantCopy(MachineInstr &MI) {

1477 assert(MI.isCopy() && "expected a COPY machine instruction");

1478

1480 if (!getCopySrc(MI, SrcPair))

1481 return false;

1482

1483 Register DstReg = MI.getOperand(0).getReg();

1485 return false;

1486

1487 if (CopySrcMIs.insert(std::make_pair(SrcPair, &MI)).second) {

1488

1489 return false;

1490 }

1491

1492 MachineInstr *PrevCopy = CopySrcMIs.find(SrcPair)->second;

1493

1495 "Unexpected mismatching subreg!");

1496

1498

1499

1500

1501

1502

1503 if (MRI->getRegClass(DstReg) != MRI->getRegClass(PrevDstReg))

1504 return false;

1505

1506 MRI->replaceRegWith(DstReg, PrevDstReg);

1507

1508

1509 MRI->clearKillFlags(PrevDstReg);

1510 return true;

1511}

1512

1513bool PeepholeOptimizer::isNAPhysCopy(Register Reg) {

1515}

1516

1517bool PeepholeOptimizer::foldRedundantNAPhysCopy(

1518 MachineInstr &MI, DenseMap<Register, MachineInstr *> &NAPhysToVirtMIs) {

1519 assert(MI.isCopy() && "expected a COPY machine instruction");

1520

1522 return false;

1523

1524 Register DstReg = MI.getOperand(0).getReg();

1525 Register SrcReg = MI.getOperand(1).getReg();

1526 if (isNAPhysCopy(SrcReg) && DstReg.isVirtual()) {

1527

1528

1529

1530 NAPhysToVirtMIs.insert({SrcReg, &MI});

1531 return false;

1532 }

1533

1534 if (!(SrcReg.isVirtual() && isNAPhysCopy(DstReg)))

1535 return false;

1536

1537

1538 auto PrevCopy = NAPhysToVirtMIs.find(DstReg);

1539 if (PrevCopy == NAPhysToVirtMIs.end()) {

1540

1541

1542 LLVM_DEBUG(dbgs() << "NAPhysCopy: intervening clobber forbids erasing "

1543 << MI);

1544 return false;

1545 }

1546

1548 if (PrevDstReg == SrcReg) {

1549

1550

1552 ++NumNAPhysCopies;

1553 return true;

1554 }

1555

1556

1557

1558

1559

1560 LLVM_DEBUG(dbgs() << "NAPhysCopy: missed opportunity " << MI);

1561 NAPhysToVirtMIs.erase(PrevCopy);

1562 return false;

1563}

1564

1565

1569

1570bool PeepholeOptimizer::findTargetRecurrence(

1571 Register Reg, const SmallSet<Register, 2> &TargetRegs,

1572 RecurrenceCycle &RC) {

1573

1575 return true;

1576

1577

1578

1579

1580

1581

1582 if (MRI->hasOneNonDBGUse(Reg))

1583 return false;

1584

1585

1587 return false;

1588

1589 MachineInstr &MI = *(MRI->use_instr_nodbg_begin(Reg));

1590 unsigned Idx = MI.findRegisterUseOperandIdx(Reg, nullptr);

1591

1592

1593

1594 if (MI.getDesc().getNumDefs() != 1)

1595 return false;

1596

1597 MachineOperand &DefOp = MI.getOperand(0);

1599 return false;

1600

1601

1602

1603

1604 unsigned TiedUseIdx;

1605 if (MI.isRegTiedToUseOperand(0, &TiedUseIdx))

1606 return false;

1607

1608 if (Idx == TiedUseIdx) {

1609 RC.push_back(RecurrenceInstr(&MI));

1610 return findTargetRecurrence(DefOp.getReg(), TargetRegs, RC);

1611 } else {

1612

1615 RC.push_back(RecurrenceInstr(&MI, Idx, CommIdx));

1616 return findTargetRecurrence(DefOp.getReg(), TargetRegs, RC);

1617 }

1618 }

1619

1620 return false;

1621}

1622

1623

1624

1625

1626

1627

1628

1629

1630

1631

1632

1633

1634

1635

1636

1637

1638

1639

1640

1641bool PeepholeOptimizer::optimizeRecurrence(MachineInstr &PHI) {

1642 SmallSet<Register, 2> TargetRegs;

1643 for (unsigned Idx = 1; Idx < PHI.getNumOperands(); Idx += 2) {

1644 MachineOperand &MO = PHI.getOperand(Idx);

1647 }

1648

1650 RecurrenceCycle RC;

1651 if (findTargetRecurrence(PHI.getOperand(0).getReg(), TargetRegs, RC)) {

1652

1653

1655 for (auto &RI : RC) {

1657 auto CP = RI.getCommutePair();

1658 if (CP) {

1661 (*CP).second);

1662 LLVM_DEBUG(dbgs() << "\t\tCommuted: " << *(RI.getMI()));

1663 }

1664 }

1665 }

1666

1668}

1669

1670PreservedAnalyses

1674 auto *DT =

1677 PeepholeOptimizer Impl(DT, MLI);

1678 bool Changed = Impl.run(MF);

1681

1686 return PA;

1687}

1688

1689bool PeepholeOptimizerLegacy::runOnMachineFunction(MachineFunction &MF) {

1691 return false;

1693 ? &getAnalysis().getDomTree()

1694 : nullptr;

1695 auto *MLI = &getAnalysis().getLI();

1696 PeepholeOptimizer Impl(DT, MLI);

1697 return Impl.run(MF);

1698}

1699

1701

1702 LLVM_DEBUG(dbgs() << "********** PEEPHOLE OPTIMIZER **********\n");

1704

1706 return false;

1707

1712

1714

1716 bool SeenMoveImm = false;

1717

1718

1719

1720

1721

1722

1723

1728

1729

1730

1731

1732

1733

1735

1736 CopySrcMIs.clear();

1737

1739

1741 MII != MIE;) {

1743

1744 ++MII;

1746

1747

1748

1749 if (MI->isDebugInstr())

1750 continue;

1751

1752 if (MI->isPosition())

1753 continue;

1754

1755 if (IsLoopHeader && MI->isPHI()) {

1756 if (optimizeRecurrence(*MI)) {

1758 continue;

1759 }

1760 }

1761

1762 if (MI->isCopy()) {

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

1764

1765 if (MO.isReg()) {

1767 if (MO.isDef() && isNAPhysCopy(Reg)) {

1768 const auto &Def = NAPhysToVirtMIs.find(Reg);

1769 if (Def != NAPhysToVirtMIs.end()) {

1770

1771

1773 << "NAPhysCopy: invalidating because of " << *MI);

1774 NAPhysToVirtMIs.erase(Def);

1775 }

1776 }

1778 const uint32_t *RegMask = MO.getRegMask();

1779 for (auto &RegMI : NAPhysToVirtMIs) {

1783 << "NAPhysCopy: invalidating because of " << *MI);

1784 NAPhysToVirtMIs.erase(Def);

1785 }

1786 }

1787 }

1788 }

1789 }

1790

1791 if (MI->isImplicitDef() || MI->isKill())

1792 continue;

1793

1794 if (MI->isInlineAsm() || MI->hasUnmodeledSideEffects()) {

1795

1796

1797

1798

1799 LLVM_DEBUG(dbgs() << "NAPhysCopy: blowing away all info due to "

1800 << *MI);

1801 NAPhysToVirtMIs.clear();

1802 }

1803

1804 if ((isUncoalescableCopy(*MI) &&

1805 optimizeUncoalescableCopy(*MI, LocalMIs)) ||

1806 (MI->isCompare() && optimizeCmpInstr(*MI)) ||

1807 (MI->isSelect() && optimizeSelect(*MI, LocalMIs))) {

1808

1811 continue;

1812 }

1813

1814 if (MI->isConditionalBranch() && optimizeCondBranch(*MI)) {

1816 continue;

1817 }

1818

1819 if (isCoalescableCopy(*MI) && optimizeCoalescableCopy(*MI)) {

1820

1822 continue;

1823 }

1824

1825 if (MI->isCopy() && (foldRedundantCopy(*MI) ||

1826 foldRedundantNAPhysCopy(*MI, NAPhysToVirtMIs))) {

1828 LLVM_DEBUG(dbgs() << "Deleting redundant copy: " << *MI << "\n");

1829 MI->eraseFromParent();

1831 continue;

1832 }

1833

1834 if (isMoveImmediate(*MI, ImmDefRegs, ImmDefMIs)) {

1835 SeenMoveImm = true;

1836 } else {

1837 Changed |= optimizeExtInstr(*MI, MBB, LocalMIs);

1838

1839

1840

1841 MII = MI;

1842 ++MII;

1843 if (SeenMoveImm) {

1845 Changed |= foldImmediate(*MI, ImmDefRegs, ImmDefMIs, Deleted);

1848 continue;

1849 }

1850 }

1851 }

1852

1853

1854

1855

1856 if (!isLoadFoldable(*MI, FoldAsLoadDefCandidates) &&

1857 !FoldAsLoadDefCandidates.empty()) {

1858

1859

1860

1861

1862

1863

1864 const MCInstrDesc &MIDesc = MI->getDesc();

1865 for (unsigned i = MIDesc.getNumDefs(); i != MI->getNumOperands(); ++i) {

1866 const MachineOperand &MOp = MI->getOperand(i);

1867 if (!MOp.isReg())

1868 continue;

1870 if (FoldAsLoadDefCandidates.count(FoldAsLoadDefReg)) {

1871

1872

1873

1874

1875 Register FoldedReg = FoldAsLoadDefReg;

1876 MachineInstr *DefMI = nullptr;

1877 if (MachineInstr *FoldMI =

1879

1880

1885 LocalMIs.insert(FoldMI);

1886

1887 if (MI->shouldUpdateAdditionalCallInfo())

1888 MI->getMF()->moveAdditionalCallInfo(MI, FoldMI);

1889 MI->eraseFromParent();

1891 MRI->markUsesInDebugValueAsUndef(FoldedReg);

1892 FoldAsLoadDefCandidates.erase(FoldedReg);

1893 ++NumLoadFold;

1894

1895

1897 MI = FoldMI;

1898 }

1899 }

1900 }

1901 }

1902

1903

1904

1905

1906 if (MI->isLoadFoldBarrier()) {

1907 LLVM_DEBUG(dbgs() << "Encountered load fold barrier on " << *MI);

1908 FoldAsLoadDefCandidates.clear();

1909 }

1910 }

1911 }

1912

1913 MF.resetDelegate(this);

1915}

1916

1917ValueTrackerResult ValueTracker::getNextSourceFromCopy() {

1918 assert(Def->isCopy() && "Invalid definition");

1919

1920

1921

1922

1923 assert(Def->getNumOperands() - Def->getNumImplicitOperands() == 2 &&

1924 "Invalid number of operands");

1925 assert(Def->hasImplicitDef() && "Only implicit uses are allowed");

1926 assert(Def->getOperand(DefIdx).getSubReg() && "no subregister defs in SSA");

1927

1928

1929 const MachineOperand &Src = Def->getOperand(1);

1930 if (Src.isUndef())

1931 return ValueTrackerResult();

1932

1933 Register SrcReg = Src.getReg();

1934 unsigned SubReg = Src.getSubReg();

1935 if (DefSubReg) {

1936 const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();

1938

1940

1941 const TargetRegisterClass *RegRC = MRI.getRegClass(SrcReg);

1942 const TargetRegisterClass *SrcWithSubRC =

1943 TRI->getSubClassWithSubReg(RegRC, SubReg);

1944 if (RegRC != SrcWithSubRC)

1945 return ValueTrackerResult();

1946 } else {

1947 if (TRI->getSubReg(SrcReg, SubReg))

1948 return ValueTrackerResult();

1949 }

1950 }

1951

1952 return ValueTrackerResult(SrcReg, SubReg);

1953}

1954

1955ValueTrackerResult ValueTracker::getNextSourceFromBitcast() {

1956 assert(Def->isBitcast() && "Invalid definition");

1957

1958

1959 if (Def->mayRaiseFPException() || Def->hasUnmodeledSideEffects())

1960 return ValueTrackerResult();

1961

1962

1963 if (Def->getDesc().getNumDefs() != 1)

1964 return ValueTrackerResult();

1965

1966 assert(Def->getOperand(DefIdx).getSubReg() && "no subregister defs in SSA");

1967

1968 unsigned SrcIdx = Def->getNumOperands();

1969 for (unsigned OpIdx = DefIdx + 1, EndOpIdx = SrcIdx; OpIdx != EndOpIdx;

1971 const MachineOperand &MO = Def->getOperand(OpIdx);

1973 continue;

1974

1976 continue;

1977 assert(!MO.isDef() && "We should have skipped all the definitions by now");

1978 if (SrcIdx != EndOpIdx)

1979

1980 return ValueTrackerResult();

1982 }

1983

1984

1985

1986 if (SrcIdx >= Def->getNumOperands())

1987 return ValueTrackerResult();

1988

1989 const MachineOperand &DefOp = Def->getOperand(DefIdx);

1990

1991

1992

1993 for (const MachineInstr &UseMI : MRI.use_nodbg_instructions(DefOp.getReg())) {

1994 if (UseMI.isSubregToReg())

1995 return ValueTrackerResult();

1996 }

1997

1998 const MachineOperand &Src = Def->getOperand(SrcIdx);

1999 if (Src.isUndef())

2000 return ValueTrackerResult();

2001 return ValueTrackerResult(Src.getReg(), Src.getSubReg());

2002}

2003

2004ValueTrackerResult ValueTracker::getNextSourceFromRegSequence() {

2005 assert((Def->isRegSequence() || Def->isRegSequenceLike()) &&

2006 "Invalid definition");

2007

2008 assert(Def->getOperand(DefIdx).getSubReg() && "illegal subregister def");

2009

2012 return ValueTrackerResult();

2013

2014

2015

2016

2017

2018

2020 if (RegSeqInput.SubIdx == DefSubReg)

2021 return ValueTrackerResult(RegSeqInput.Reg, RegSeqInput.SubReg);

2022 }

2023

2024 const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();

2025

2026

2027

2029 LaneBitmask DefMask = TRI->getSubRegIndexLaneMask(DefSubReg);

2030 LaneBitmask ThisOpRegMask = TRI->getSubRegIndexLaneMask(RegSeqInput.SubIdx);

2031

2032

2033

2034

2035

2036 if ((DefMask & ThisOpRegMask) != DefMask)

2037 continue;

2038

2039 unsigned ReverseDefCompose =

2040 TRI->reverseComposeSubRegIndices(RegSeqInput.SubIdx, DefSubReg);

2041 if (!ReverseDefCompose)

2042 continue;

2043

2044 unsigned ComposedDefInSrcReg1 =

2045 TRI->composeSubRegIndices(RegSeqInput.SubReg, ReverseDefCompose);

2046

2047

2048

2049

2050

2051 const TargetRegisterClass *SrcRC = MRI.getRegClass(RegSeqInput.Reg);

2052 const TargetRegisterClass *SrcWithSubRC =

2053 TRI->getSubClassWithSubReg(SrcRC, ComposedDefInSrcReg1);

2054 if (SrcRC != SrcWithSubRC)

2055 return ValueTrackerResult();

2056

2057 return ValueTrackerResult(RegSeqInput.Reg, ComposedDefInSrcReg1);

2058 }

2059

2060

2061

2062

2063 return ValueTrackerResult();

2064}

2065

2066ValueTrackerResult ValueTracker::getNextSourceFromInsertSubreg() {

2067 assert((Def->isInsertSubreg() || Def->isInsertSubregLike()) &&

2068 "Invalid definition");

2069 assert(Def->getOperand(DefIdx).getSubReg() && "no subreg defs in SSA");

2070

2074 return ValueTrackerResult();

2075

2076

2077

2078

2079

2080

2081

2082

2083 if (InsertedReg.SubIdx == DefSubReg) {

2084 return ValueTrackerResult(InsertedReg.Reg, InsertedReg.SubReg);

2085 }

2086

2087

2088

2089 const MachineOperand &MODef = Def->getOperand(DefIdx);

2090

2091

2092

2095 return ValueTrackerResult();

2096

2097

2098

2099 const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();

2100 if ((TRI->getSubRegIndexLaneMask(DefSubReg) &

2101 TRI->getSubRegIndexLaneMask(InsertedReg.SubIdx))

2102 .any())

2103 return ValueTrackerResult();

2104

2105

2106 return ValueTrackerResult(BaseReg.Reg, DefSubReg);

2107}

2108

2109ValueTrackerResult ValueTracker::getNextSourceFromExtractSubreg() {

2110 assert((Def->isExtractSubreg() || Def->isExtractSubregLike()) &&

2111 "Invalid definition");

2112

2113

2114

2115

2116

2117 if (DefSubReg)

2118 return ValueTrackerResult();

2119

2122 return ValueTrackerResult();

2123

2124

2125

2126 if (ExtractSubregInputReg.SubReg)

2127 return ValueTrackerResult();

2128

2129 return ValueTrackerResult(ExtractSubregInputReg.Reg,

2130 ExtractSubregInputReg.SubIdx);

2131}

2132

2133ValueTrackerResult ValueTracker::getNextSourceFromSubregToReg() {

2134 assert(Def->isSubregToReg() && "Invalid definition");

2135

2136

2137

2138

2139

2140

2141

2142 if (DefSubReg != Def->getOperand(3).getImm())

2143 return ValueTrackerResult();

2144

2145

2146 if (Def->getOperand(2).getSubReg())

2147 return ValueTrackerResult();

2148

2149 return ValueTrackerResult(Def->getOperand(2).getReg(),

2150 Def->getOperand(3).getImm());

2151}

2152

2153

2154ValueTrackerResult ValueTracker::getNextSourceFromPHI() {

2155 assert(Def->isPHI() && "Invalid definition");

2156 ValueTrackerResult Res;

2157

2158

2159 for (unsigned i = 1, e = Def->getNumOperands(); i < e; i += 2) {

2160 const MachineOperand &MO = Def->getOperand(i);

2161 assert(MO.isReg() && "Invalid PHI instruction");

2162

2163

2165 return ValueTrackerResult();

2167 }

2168

2169 return Res;

2170}

2171

2172ValueTrackerResult ValueTracker::getNextSourceImpl() {

2173 assert(Def && "This method needs a valid definition");

2174

2175 assert(((Def->getOperand(DefIdx).isDef() &&

2176 (DefIdx < Def->getDesc().getNumDefs() ||

2177 Def->getDesc().isVariadic())) ||

2178 Def->getOperand(DefIdx).isImplicit()) &&

2179 "Invalid DefIdx");

2180 if (Def->isCopy())

2181 return getNextSourceFromCopy();

2182 if (Def->isBitcast())

2183 return getNextSourceFromBitcast();

2184

2185

2187 return ValueTrackerResult();

2188 if (Def->isRegSequence() || Def->isRegSequenceLike())

2189 return getNextSourceFromRegSequence();

2190 if (Def->isInsertSubreg() || Def->isInsertSubregLike())

2191 return getNextSourceFromInsertSubreg();

2192 if (Def->isExtractSubreg() || Def->isExtractSubregLike())

2193 return getNextSourceFromExtractSubreg();

2194 if (Def->isSubregToReg())

2195 return getNextSourceFromSubregToReg();

2196 if (Def->isPHI())

2197 return getNextSourceFromPHI();

2198 return ValueTrackerResult();

2199}

2200

2201ValueTrackerResult ValueTracker::getNextSource() {

2202

2203

2204 if (!Def)

2205 return ValueTrackerResult();

2206

2207 ValueTrackerResult Res = getNextSourceImpl();

2208 if (Res.isValid()) {

2209

2210

2211

2212 bool OneRegSrc = Res.getNumSources() == 1;

2213 if (OneRegSrc)

2214 Reg = Res.getSrcReg(0);

2215

2216

2217 Res.setInst(Def);

2218

2219

2220

2223 if (DI != MRI.def_end()) {

2226 DefSubReg = Res.getSrcSubReg(0);

2227 } else {

2228 Def = nullptr;

2229 }

2230 return Res;

2231 }

2232 }

2233

2234

2235

2236 Def = nullptr;

2237 return Res;

2238}

unsigned const MachineRegisterInfo * MRI

for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))

MachineInstrBuilder & UseMI

MachineInstrBuilder MachineInstrBuilder & DefMI

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

const TargetInstrInfo & TII

This file defines the DenseMap class.

A common definition of LaneBitmask for use in TableGen and CodeGen.

TargetInstrInfo::RegSubRegPair RegSubRegPair

Register const TargetRegisterInfo * TRI

Promote Memory to Register

MachineInstr unsigned OpIdx

uint64_t IntrinsicInst * II

#define INITIALIZE_PASS_DEPENDENCY(depName)

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

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

static cl::opt< unsigned > RewritePHILimit("rewrite-phi-limit", cl::Hidden, cl::init(10), cl::desc("Limit the length of PHI chains to lookup"))

static cl::opt< bool > DisablePeephole("disable-peephole", cl::Hidden, cl::init(false), cl::desc("Disable the peephole optimizer"))

static cl::opt< unsigned > MaxRecurrenceChain("recurrence-chain-limit", cl::Hidden, cl::init(3), cl::desc("Maximum length of recurrence chain when evaluating the benefit " "of commuting operands"))

static cl::opt< bool > DisableNAPhysCopyOpt("disable-non-allocatable-phys-copy-opt", cl::Hidden, cl::init(false), cl::desc("Disable non-allocatable physical register copy optimization"))

static bool isVirtualRegisterOperand(MachineOperand &MO)

\bried Returns true if MO is a virtual register operand.

Definition PeepholeOptimizer.cpp:1566

static MachineInstr & insertPHI(MachineRegisterInfo &MRI, const TargetInstrInfo &TII, const SmallVectorImpl< RegSubRegPair > &SrcRegs, MachineInstr &OrigPHI)

Insert a PHI instruction with incoming edges SrcRegs that are guaranteed to have the same register cl...

Definition PeepholeOptimizer.cpp:1092

static cl::opt< bool > Aggressive("aggressive-ext-opt", cl::Hidden, cl::desc("Aggressive extension optimization"))

static cl::opt< bool > DisableAdvCopyOpt("disable-adv-copy-opt", cl::Hidden, cl::init(false), cl::desc("Disable advanced copy optimization"))

Specifiy whether or not the value tracking looks through complex instructions.

TargetInstrInfo::RegSubRegPairAndIdx RegSubRegPairAndIdx

Definition PeepholeOptimizer.cpp:101

static RegSubRegPair getNewSource(MachineRegisterInfo *MRI, const TargetInstrInfo *TII, RegSubRegPair Def, const PeepholeOptimizer::RewriteMapTy &RewriteMap, bool HandleMultipleSources=true)

Given a Def.Reg and Def.SubReg pair, use RewriteMap to find the new source to use for rewrite.

Definition PeepholeOptimizer.cpp:1128

const SmallVectorImpl< MachineOperand > & Cond

Remove Loads Into Fake Uses

static bool isValid(const char C)

Returns true if C is a valid mangled character: <0-9a-zA-Z_>.

This file defines the SmallPtrSet class.

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)

Virtual Register Rewriter

PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)

Get the result of an analysis pass for a given IR unit.

AnalysisUsage & addRequired()

AnalysisUsage & addPreserved()

Add the specified Pass class to the set of analyses preserved by this pass.

LLVM_ABI void setPreservesCFG()

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

Represents analyses that only rely on functions' control flow.

ValueT lookup(const_arg_type_t< KeyT > Val) const

lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...

iterator find(const_arg_type_t< KeyT > Val)

bool erase(const KeyT &Val)

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

bool isLoopHeader(const BlockT *BB) const

unsigned getNumDefs() const

Return the number of MachineOperands that are register definitions.

const MCInstrDesc & get(unsigned Opcode) const

Return the machine instruction descriptor that corresponds to the specified instruction opcode.

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

MachineInstrBundleIterator< MachineInstr > iterator

Analysis pass which computes a MachineDominatorTree.

Analysis pass which computes a MachineDominatorTree.

bool dominates(const MachineInstr *A, const MachineInstr *B) const

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.

StringRef getName() const

getName - Return the name of the corresponding LLVM function.

MachineRegisterInfo & getRegInfo()

getRegInfo - Return information about the registers currently in use.

Function & getFunction()

Return the LLVM function that this machine code represents.

void setDelegate(Delegate *delegate)

Set the delegate.

const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const

Add a new virtual register operand.

const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const

Representation of each machine instruction.

const MachineBasicBlock * getParent() const

const DebugLoc & getDebugLoc() const

Returns the debug location id of this MachineInstr.

LLVM_ABI void eraseFromParent()

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

const MachineOperand & getOperand(unsigned i) const

Analysis pass that exposes the MachineLoopInfo for a machine function.

MachineOperand class - Representation of each machine instruction operand.

void setSubReg(unsigned subReg)

unsigned getSubReg() const

bool isReg() const

isReg - Tests if this is a MO_Register operand.

bool isRegMask() const

isRegMask - Tests if this is a MO_RegisterMask operand.

MachineBasicBlock * getMBB() const

LLVM_ABI void setReg(Register Reg)

Change the register this operand corresponds to.

MachineInstr * getParent()

getParent - Return the instruction that this operand belongs to.

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.

unsigned getOperandNo() const

getOperandNo - Return the operand # of this MachineOperand in its MachineInstr.

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

defusechain_iterator< false, true, false, true, false > def_iterator

def_iterator/def_begin/def_end - Walk all defs of the specified register.

static LLVM_ABI PassRegistry * getPassRegistry()

getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...

PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)

Definition PeepholeOptimizer.cpp:1671

static PreservedAnalyses all()

Construct a special preserved set that preserves all passes.

Wrapper class representing virtual and physical registers.

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.

A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...

bool erase(PtrType Ptr)

Remove pointer from the set.

std::pair< iterator, bool > insert(PtrType Ptr)

Inserts Ptr if and only if there is no element in the container equal to Ptr.

SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.

SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...

size_type count(const T &V) const

count - Return 1 if the element is in the set, 0 otherwise.

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

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

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

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 MachineInstr * optimizeSelect(MachineInstr &MI, SmallPtrSetImpl< MachineInstr * > &NewMIs, bool PreferFalse=false) const

Given a select instruction that was understood by analyzeSelect and returned Optimizable = true,...

virtual bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx1, unsigned &SrcOpIdx2) const

Returns true iff the routine could find two commutable operands in the given machine instruction.

virtual MachineInstr * optimizeLoadInstr(MachineInstr &MI, const MachineRegisterInfo *MRI, Register &FoldAsLoadDefReg, MachineInstr *&DefMI) const

Try to remove the load by folding it to a register operand at the use.

virtual bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t Mask, int64_t Value, const MachineRegisterInfo *MRI) const

See if the comparison instruction can be converted into something more efficient.

virtual bool getConstValDefinedInReg(const MachineInstr &MI, const Register Reg, int64_t &ImmVal) const

Returns true if MI is an instruction that defines Reg to have a constant value and the value is recor...

virtual bool optimizeCondBranch(MachineInstr &MI) const

MachineInstr * commuteInstruction(MachineInstr &MI, bool NewMI=false, unsigned OpIdx1=CommuteAnyOperandIndex, unsigned OpIdx2=CommuteAnyOperandIndex) const

This method commutes the operands of the given machine instruction MI.

virtual bool foldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, Register Reg, MachineRegisterInfo *MRI) const

'Reg' is known to be defined by a move immediate instruction, try to fold the immediate into the use ...

bool getInsertSubregInputs(const MachineInstr &MI, unsigned DefIdx, RegSubRegPair &BaseReg, RegSubRegPairAndIdx &InsertedReg) const

Build the equivalent inputs of a INSERT_SUBREG for the given MI and DefIdx.

virtual bool analyzeSelect(const MachineInstr &MI, SmallVectorImpl< MachineOperand > &Cond, unsigned &TrueOp, unsigned &FalseOp, bool &Optimizable) const

Analyze the given select instruction, returning true if it cannot be understood.

bool getRegSequenceInputs(const MachineInstr &MI, unsigned DefIdx, SmallVectorImpl< RegSubRegPairAndIdx > &InputRegs) const

Build the equivalent inputs of a REG_SEQUENCE for the given MI and DefIdx.

static const unsigned CommuteAnyOperandIndex

bool getExtractSubregInputs(const MachineInstr &MI, unsigned DefIdx, RegSubRegPairAndIdx &InputReg) const

Build the equivalent inputs of a EXTRACT_SUBREG for the given MI and DefIdx.

virtual bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, Register &SrcReg2, int64_t &Mask, int64_t &Value) const

For a comparison instruction, return the source registers in SrcReg and SrcReg2 if having two registe...

virtual const TargetInstrInfo * getInstrInfo() const

virtual const TargetRegisterInfo * getRegisterInfo() const =0

Return the target's register information.

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

MCInstrDesc const & getDesc(MCInstrInfo const &MCII, MCInst const &MCI)

initializer< Ty > init(const Ty &Val)

PointerTypeMap run(const Module &M)

Compute the PointerTypeMap for the module M.

NodeAddr< DefNode * > Def

BaseReg

Stack frame base register. Bit 0 of FREInfo.Info.

This is an optimization pass for GlobalISel generic memory operations.

MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)

Builder interface. Specify how to create the initial instruction itself.

AnalysisManager< MachineFunction > MachineFunctionAnalysisManager

bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)

LLVM_ABI char & PeepholeOptimizerLegacyID

PeepholeOptimizer - This pass performs peephole optimizations - like extension and comparison elimina...

Definition PeepholeOptimizer.cpp:760

LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()

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

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...

LLVM_ABI void initializePeepholeOptimizerLegacyPass(PassRegistry &)

A pair composed of a pair of a register and a sub-register index, and another sub-register index.

A pair composed of a register and a sub-register index.