LLVM: lib/Target/ARM/ARMLoadStoreOptimizer.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

63#include

64#include

65#include

66#include

67#include

68#include

69

70using namespace llvm;

71

72#define DEBUG_TYPE "arm-ldst-opt"

73

74STATISTIC(NumLDMGened , "Number of ldm instructions generated");

75STATISTIC(NumSTMGened , "Number of stm instructions generated");

76STATISTIC(NumVLDMGened, "Number of vldm instructions generated");

77STATISTIC(NumVSTMGened, "Number of vstm instructions generated");

78STATISTIC(NumLdStMoved, "Number of load / store instructions moved");

79STATISTIC(NumLDRDFormed,"Number of ldrd created before allocation");

80STATISTIC(NumSTRDFormed,"Number of strd created before allocation");

81STATISTIC(NumLDRD2LDM, "Number of ldrd instructions turned back into ldm");

82STATISTIC(NumSTRD2STM, "Number of strd instructions turned back into stm");

83STATISTIC(NumLDRD2LDR, "Number of ldrd instructions turned back into ldr's");

84STATISTIC(NumSTRD2STR, "Number of strd instructions turned back into str's");

85

86

87

88

89

90

93 cl::init(false), cl::desc("Be more conservative in ARM load/store opt"));

94

95#define ARM_LOAD_STORE_OPT_NAME "ARM load / store optimization pass"

96

97namespace {

98

99

100

102 static char ID;

103

113 bool LiveRegsValid;

114 bool RegClassInfoValid;

115 bool isThumb1, isThumb2;

116

118

120

123 }

124

126

127 private:

128

129

130 struct MemOpQueueEntry {

132 int Offset;

133 unsigned Position;

134

137 };

139

140

141

142 struct MergeCandidate {

143

145

146

147 unsigned LatestMIIdx;

148

149

150 unsigned EarliestMIIdx;

151

152

153

154 unsigned InsertPos;

155

156

157 bool CanMergeToLSMulti;

158

159

160 bool CanMergeToLSDouble;

161 };

165

171 unsigned Base, unsigned WordOffset,

175 int Offset, unsigned Base, bool BaseKill, unsigned Opcode,

177 ArrayRef<std::pair<unsigned, bool>> Regs,

181 int Offset, unsigned Base, bool BaseKill, unsigned Opcode,

183 ArrayRef<std::pair<unsigned, bool>> Regs,

185 void FormCandidates(const MemOpQueue &MemOps);

186 MachineInstr *MergeOpsUpdate(const MergeCandidate &Cand);

191 bool MergeBaseUpdateLSDouble(MachineInstr &MI) const;

195 };

196

197}

198

199char ARMLoadStoreOpt::ID = 0;

200

202 false)

203

205 for (const auto &MO : MI.operands()) {

206 if (!MO.isReg())

207 continue;

208 if (MO.isDef() && MO.getReg() == ARM::CPSR && !MO.isDead())

209

210

211 return true;

212 }

213

214 return false;

215}

216

218 unsigned Opcode = MI.getOpcode();

219 bool isAM3 = Opcode == ARM::LDRD || Opcode == ARM::STRD;

220 unsigned NumOperands = MI.getDesc().getNumOperands();

221 unsigned OffField = MI.getOperand(NumOperands - 3).getImm();

222

223 if (Opcode == ARM::t2LDRi12 || Opcode == ARM::t2LDRi8 ||

224 Opcode == ARM::t2STRi12 || Opcode == ARM::t2STRi8 ||

225 Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8 ||

226 Opcode == ARM::LDRi12 || Opcode == ARM::STRi12)

227 return OffField;

228

229

230 if (Opcode == ARM::tLDRi || Opcode == ARM::tSTRi ||

231 Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi)

232 return OffField * 4;

233

238

241

243}

244

246 return MI.getOperand(1);

247}

248

250 return MI.getOperand(0);

251}

252

254 switch (Opcode) {

256 case ARM::LDRi12:

257 ++NumLDMGened;

258 switch (Mode) {

264 }

265 case ARM::STRi12:

266 ++NumSTMGened;

267 switch (Mode) {

273 }

274 case ARM::tLDRi:

275 case ARM::tLDRspi:

276

277

278 ++NumLDMGened;

279 switch (Mode) {

282 }

283 case ARM::tSTRi:

284 case ARM::tSTRspi:

285

286 ++NumSTMGened;

287 switch (Mode) {

289 case ARM_AM::ia: return ARM::tSTMIA_UPD;

290 }

291 case ARM::t2LDRi8:

292 case ARM::t2LDRi12:

293 ++NumLDMGened;

294 switch (Mode) {

296 case ARM_AM::ia: return ARM::t2LDMIA;

297 case ARM_AM::db: return ARM::t2LDMDB;

298 }

299 case ARM::t2STRi8:

300 case ARM::t2STRi12:

301 ++NumSTMGened;

302 switch (Mode) {

304 case ARM_AM::ia: return ARM::t2STMIA;

305 case ARM_AM::db: return ARM::t2STMDB;

306 }

307 case ARM::VLDRS:

308 ++NumVLDMGened;

309 switch (Mode) {

311 case ARM_AM::ia: return ARM::VLDMSIA;

312 case ARM_AM::db: return 0;

313 }

314 case ARM::VSTRS:

315 ++NumVSTMGened;

316 switch (Mode) {

318 case ARM_AM::ia: return ARM::VSTMSIA;

319 case ARM_AM::db: return 0;

320 }

321 case ARM::VLDRD:

322 ++NumVLDMGened;

323 switch (Mode) {

325 case ARM_AM::ia: return ARM::VLDMDIA;

326 case ARM_AM::db: return 0;

327 }

328 case ARM::VSTRD:

329 ++NumVSTMGened;

330 switch (Mode) {

332 case ARM_AM::ia: return ARM::VSTMDIA;

333 case ARM_AM::db: return 0;

334 }

335 }

336}

337

339 switch (Opcode) {

341 case ARM::LDMIA_RET:

342 case ARM::LDMIA:

343 case ARM::LDMIA_UPD:

344 case ARM::STMIA:

345 case ARM::STMIA_UPD:

346 case ARM::tLDMIA:

347 case ARM::tLDMIA_UPD:

348 case ARM::tSTMIA_UPD:

349 case ARM::t2LDMIA_RET:

350 case ARM::t2LDMIA:

351 case ARM::t2LDMIA_UPD:

352 case ARM::t2STMIA:

353 case ARM::t2STMIA_UPD:

354 case ARM::VLDMSIA:

355 case ARM::VLDMSIA_UPD:

356 case ARM::VSTMSIA:

357 case ARM::VSTMSIA_UPD:

358 case ARM::VLDMDIA:

359 case ARM::VLDMDIA_UPD:

360 case ARM::VSTMDIA:

361 case ARM::VSTMDIA_UPD:

363

364 case ARM::LDMDA:

365 case ARM::LDMDA_UPD:

366 case ARM::STMDA:

367 case ARM::STMDA_UPD:

369

370 case ARM::LDMDB:

371 case ARM::LDMDB_UPD:

372 case ARM::STMDB:

373 case ARM::STMDB_UPD:

374 case ARM::t2LDMDB:

375 case ARM::t2LDMDB_UPD:

376 case ARM::t2STMDB:

377 case ARM::t2STMDB_UPD:

378 case ARM::VLDMSDB_UPD:

379 case ARM::VSTMSDB_UPD:

380 case ARM::VLDMDDB_UPD:

381 case ARM::VSTMDDB_UPD:

383

384 case ARM::LDMIB:

385 case ARM::LDMIB_UPD:

386 case ARM::STMIB:

387 case ARM::STMIB_UPD:

389 }

390}

391

393 return Opc == ARM::tLDRi || Opc == ARM::tLDRspi;

394}

395

397 return Opc == ARM::t2LDRi12 || Opc == ARM::t2LDRi8;

398}

399

403

405 return Opc == ARM::tSTRi || Opc == ARM::tSTRspi;

406}

407

409 return Opc == ARM::t2STRi12 || Opc == ARM::t2STRi8;

410}

411

415

419

421 switch (Opc) {

423 case ARM::tLDRi:

424 case ARM::tSTRi:

425 case ARM::tLDRspi:

426 case ARM::tSTRspi:

427 return 1;

428 case ARM::tLDRHi:

429 case ARM::tSTRHi:

430 return 2;

431 case ARM::tLDRBi:

432 case ARM::tSTRBi:

433 return 4;

434 }

435}

436

438 switch (MI->getOpcode()) {

439 default: return 0;

440 case ARM::LDRi12:

441 case ARM::STRi12:

442 case ARM::tLDRi:

443 case ARM::tSTRi:

444 case ARM::tLDRspi:

445 case ARM::tSTRspi:

446 case ARM::t2LDRi8:

447 case ARM::t2LDRi12:

448 case ARM::t2STRi8:

449 case ARM::t2STRi12:

450 case ARM::VLDRS:

451 case ARM::VSTRS:

452 return 4;

453 case ARM::VLDRD:

454 case ARM::VSTRD:

455 return 8;

456 case ARM::LDMIA:

457 case ARM::LDMDA:

458 case ARM::LDMDB:

459 case ARM::LDMIB:

460 case ARM::STMIA:

461 case ARM::STMDA:

462 case ARM::STMDB:

463 case ARM::STMIB:

464 case ARM::tLDMIA:

465 case ARM::tLDMIA_UPD:

466 case ARM::tSTMIA_UPD:

467 case ARM::t2LDMIA:

468 case ARM::t2LDMDB:

469 case ARM::t2STMIA:

470 case ARM::t2STMDB:

471 case ARM::VLDMSIA:

472 case ARM::VSTMSIA:

473 return (MI->getNumOperands() - MI->getDesc().getNumOperands() + 1) * 4;

474 case ARM::VLDMDIA:

475 case ARM::VSTMDIA:

476 return (MI->getNumOperands() - MI->getDesc().getNumOperands() + 1) * 8;

477 }

478}

479

480

481

485 unsigned WordOffset,

487 unsigned PredReg) {

488 assert(isThumb1 && "Can only update base register uses for Thumb1!");

489

490

492 bool InsertSub = false;

493 unsigned Opc = MBBI->getOpcode();

494

495 if (MBBI->readsRegister(Base, nullptr)) {

497 bool IsLoad =

498 Opc == ARM::tLDRi || Opc == ARM::tLDRHi || Opc == ARM::tLDRBi;

499 bool IsStore =

500 Opc == ARM::tSTRi || Opc == ARM::tSTRHi || Opc == ARM::tSTRBi;

501

502 if (IsLoad || IsStore) {

503

504

505

506

507 MachineOperand &MO =

508 MBBI->getOperand(MBBI->getDesc().getNumOperands() - 3);

509

511

512

514

515 if (Offset >= 0 && !(IsStore && InstrSrcReg == Base))

517 else

518 InsertSub = true;

519 } else if ((Opc == ARM::tSUBi8 || Opc == ARM::tADDi8) &&

520 !definesCPSR(*MBBI)) {

521

522

523

524 MachineOperand &MO =

525 MBBI->getOperand(MBBI->getDesc().getNumOperands() - 3);

527 MO.getImm() + WordOffset * 4 :

528 MO.getImm() - WordOffset * 4 ;

530

531

533

534 return;

535 } else {

536 InsertSub = true;

537 }

538 } else {

539

540 InsertSub = true;

541 }

542 } else if (definesCPSR(*MBBI) || MBBI->isCall() || MBBI->isBranch()) {

543

544

545

546 InsertSub = true;

547 }

548

549 if (InsertSub) {

550

554 .addImm(WordOffset * 4)

557 return;

558 }

559

560 if (MBBI->killsRegister(Base, nullptr) ||

561 MBBI->definesRegister(Base, nullptr))

562

563 return;

564 }

565

566

568

569

570

571

576 .addImm(WordOffset * 4)

579 }

580}

581

582

583unsigned ARMLoadStoreOpt::findFreeReg(const TargetRegisterClass &RegClass) {

584 if (!RegClassInfoValid) {

586 RegClassInfoValid = true;

587 }

588

589 for (unsigned Reg : RegClassInfo.getOrder(&RegClass))

591 return Reg;

592 return 0;

593}

594

595

596

597

598void ARMLoadStoreOpt::moveLiveRegsBefore(const MachineBasicBlock &MBB,

600

601 if (!LiveRegsValid) {

604 LiveRegPos = MBB.end();

605 LiveRegsValid = true;

606 }

607

608 while (LiveRegPos != Before) {

609 --LiveRegPos;

611 }

612}

613

615 unsigned Reg) {

616 for (const std::pair<unsigned, bool> &R : Regs)

617 if (R.first == Reg)

618 return true;

619 return false;

620}

621

622

623

624

625MachineInstr *ARMLoadStoreOpt::CreateLoadStoreMulti(

627 int Offset, unsigned Base, bool BaseKill, unsigned Opcode,

629 ArrayRef<std::pair<unsigned, bool>> Regs,

631 unsigned NumRegs = Regs.size();

633

634

635

636 bool SafeToClobberCPSR = !isThumb1 ||

639

640 bool Writeback = isThumb1;

641

642

643

644

646 assert(Base != ARM::SP && "Thumb1 does not allow SP in register list");

647 if (Opcode == ARM::tLDRi)

648 Writeback = false;

649 else if (Opcode == ARM::tSTRi)

650 return nullptr;

651 }

652

654

656 bool haveIBAndDA = isNotVFP && !isThumb2 && !isThumb1;

657

658 if (Offset == 4 && haveIBAndDA) {

660 } else if (Offset == -4 * (int)NumRegs + 4 && haveIBAndDA) {

662 } else if (Offset == -4 * (int)NumRegs && isNotVFP && !isThumb1) {

663

665 } else if (Offset != 0 || Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi) {

666

667

669

670

671

672

673 if (NumRegs <= 2)

674 return nullptr;

675

676

677

678 if (!SafeToClobberCPSR)

679 return nullptr;

680

681 unsigned NewBase;

683

684

685 NewBase = Regs[NumRegs-1].first;

686 Writeback = false;

687 } else {

688

689 moveLiveRegsBefore(MBB, InsertBefore);

690

691

693 for (const std::pair<unsigned, bool> &R : Regs)

694 LiveRegs.addReg(R.first);

695

696 NewBase = findFreeReg(isThumb1 ? ARM::tGPRRegClass : ARM::GPRRegClass);

697 if (NewBase == 0)

698 return nullptr;

699 }

700

701 int BaseOpc = isThumb2 ? (BaseKill && Base == ARM::SP ? ARM::t2ADDspImm

702 : ARM::t2ADDri)

704 ? ARM::tADDrSPi

705 : (isThumb1 && Offset < 8)

706 ? ARM::tADDi3

707 : isThumb1 ? ARM::tADDi8 : ARM::ADDri;

708

710

711

713 BaseOpc = isThumb2 ? (BaseKill && Base == ARM::SP ? ARM::t2SUBspImm

714 : ARM::t2SUBri)

716 ? ARM::tSUBi3

717 : isThumb1 ? ARM::tSUBi8 : ARM::SUBri;

718 }

719

721

722 return nullptr;

723

724

725

726 bool KillOldBase = BaseKill &&

728

729 if (isThumb1) {

730

731

732

733

734

735 if (Base != NewBase &&

736 (BaseOpc == ARM::tADDi8 || BaseOpc == ARM::tSUBi8)) {

737

739 !STI->hasV6Ops()) {

740

742 return nullptr;

745 } else

749

750

751 Base = NewBase;

752 KillOldBase = true;

753 }

754 if (BaseOpc == ARM::tADDrSPi) {

755 assert(Offset % 4 == 0 && "tADDrSPi offset is scaled by 4");

760 } else

766 } else {

772 }

773 Base = NewBase;

774 BaseKill = true;

775 }

776

778

779

780

782 if (!Opcode)

783 return nullptr;

784

785

786

787

788

789

790

791

792

793 if (isThumb1 && !SafeToClobberCPSR && Writeback && !BaseKill)

794 return nullptr;

795

796 MachineInstrBuilder MIB;

797

798 if (Writeback) {

799 assert(isThumb1 && "expected Writeback only inThumb1");

800 if (Opcode == ARM::tLDMIA) {

802

803 Opcode = ARM::tLDMIA_UPD;

804 }

805

807

808

811

812

813

814 if (!BaseKill)

815 UpdateBaseRegUses(MBB, InsertBefore, DL, Base, NumRegs, Pred, PredReg);

816 } else {

817

820 }

821

823

824 for (const std::pair<unsigned, bool> &R : Regs)

826

828

830}

831

832MachineInstr *ARMLoadStoreOpt::CreateLoadStoreDouble(

834 int Offset, unsigned Base, bool BaseKill, unsigned Opcode,

836 ArrayRef<std::pair<unsigned, bool>> Regs,

839 assert((IsLoad || isi32Store(Opcode)) && "Must have integer load or store");

840 unsigned LoadStoreOpcode = IsLoad ? ARM::t2LDRDi8 : ARM::t2STRDi8;

841

842 assert(Regs.size() == 2);

843 MachineInstrBuilder MIB = BuildMI(MBB, InsertBefore, DL,

844 TII->get(LoadStoreOpcode));

845 if (IsLoad) {

848 } else {

851 }

855}

856

857

858MachineInstr *ARMLoadStoreOpt::MergeOpsUpdate(const MergeCandidate &Cand) {

859 const MachineInstr *First = Cand.Instrs.front();

860 unsigned Opcode = First->getOpcode();

863 SmallVector<unsigned, 4> ImpDefs;

864 DenseSet KilledRegs;

865 DenseSet UsedRegs;

866

867 for (const MachineInstr *MI : Cand.Instrs) {

870 bool IsKill = MO.isKill();

871 if (IsKill)

875

876 if (IsLoad) {

877

878

879

880 for (const MachineOperand &MO : MI->implicit_operands()) {

882 continue;

885

887 continue;

888

889 if (MI->readsRegister(DefReg, nullptr))

890 continue;

892 }

893 }

894 }

895

896

898

899 MachineInstr *LatestMI = Cand.Instrs[Cand.LatestMIIdx];

901 MachineBasicBlock &MBB = *LatestMI->getParent();

908 MachineInstr *Merged = nullptr;

909 if (Cand.CanMergeToLSDouble)

910 Merged = CreateLoadStoreDouble(MBB, InsertBefore, Offset, Base, BaseKill,

911 Opcode, Pred, PredReg, DL, Regs,

912 Cand.Instrs);

913 if (!Merged && Cand.CanMergeToLSMulti)

914 Merged = CreateLoadStoreMulti(MBB, InsertBefore, Offset, Base, BaseKill,

915 Opcode, Pred, PredReg, DL, Regs, Cand.Instrs);

916 if (!Merged)

917 return nullptr;

918

919

920

921 iterator EarliestI(Cand.Instrs[Cand.EarliestMIIdx]);

922 bool EarliestAtBegin = false;

923 if (EarliestI == MBB.begin()) {

924 EarliestAtBegin = true;

925 } else {

926 EarliestI = std::prev(EarliestI);

927 }

928

929

930 for (MachineInstr *MI : Cand.Instrs)

932

933

934 if (EarliestAtBegin)

936 else

937 EarliestI = std::next(EarliestI);

939

941

942

943 for (MachineInstr &MI : FixupRange) {

944 for (unsigned &ImpDefReg : ImpDefs) {

945 for (MachineOperand &MO : MI.implicit_operands()) {

946 if (!MO.isReg() || MO.getReg() != ImpDefReg)

947 continue;

950 else if (MO.isDef())

951 ImpDefReg = 0;

952 }

953 }

954 }

955

957 for (unsigned ImpDef : ImpDefs)

959 } else {

960

961 assert(isi32Store(Opcode) || Opcode == ARM::VSTRS || Opcode == ARM::VSTRD);

962 for (MachineInstr &MI : FixupRange) {

963 for (MachineOperand &MO : MI.uses()) {

965 continue;

968 }

969 }

970 assert(ImpDefs.empty());

971 }

972

973 return Merged;

974}

975

978

979

980 return (Value % 4) == 0 && Value < 1024;

981}

982

983

984

987

988

989 unsigned Opcode = MI.getOpcode();

991 return true;

992

993

994

997 return true;

998 return false;

999}

1000

1001

1002void ARMLoadStoreOpt::FormCandidates(const MemOpQueue &MemOps) {

1003 const MachineInstr *FirstMI = MemOps[0].MI;

1004 unsigned Opcode = FirstMI->getOpcode();

1007

1008 unsigned SIndex = 0;

1009 unsigned EIndex = MemOps.size();

1010 do {

1011

1012 const MachineInstr *MI = MemOps[SIndex].MI;

1013 int Offset = MemOps[SIndex].Offset;

1016 unsigned PRegNum = PMO.isUndef() ? std::numeric_limits::max()

1017 : TRI->getEncodingValue(PReg);

1018 unsigned Latest = SIndex;

1019 unsigned Earliest = SIndex;

1020 unsigned Count = 1;

1021 bool CanMergeToLSDouble =

1023

1024

1027 CanMergeToLSDouble = false;

1028

1029 bool CanMergeToLSMulti = true;

1030

1031

1032 if (STI->hasSlowOddRegister() && !isNotVFP && (PRegNum % 2) == 1)

1033 CanMergeToLSMulti = false;

1034

1035

1036

1037 if (PReg == ARM::SP || PReg == ARM::PC)

1038 CanMergeToLSMulti = CanMergeToLSDouble = false;

1039

1040

1042 CanMergeToLSMulti = CanMergeToLSDouble = false;

1043

1044

1045 unsigned Limit;

1046 switch (Opcode) {

1047 default:

1048 Limit = UINT_MAX;

1049 break;

1050 case ARM::VLDRD:

1051 case ARM::VSTRD:

1052 Limit = 16;

1053 break;

1054 }

1055

1056

1057 for (unsigned I = SIndex+1; I < EIndex; ++I, ++Count) {

1058 int NewOffset = MemOps[I].Offset;

1059 if (NewOffset != Offset + (int)Size)

1060 break;

1063 if (Reg == ARM::SP || Reg == ARM::PC)

1064 break;

1065 if (Count == Limit)

1066 break;

1067

1068

1069 unsigned RegNum = MO.isUndef() ? std::numeric_limits::max()

1070 : TRI->getEncodingValue(Reg);

1071 bool PartOfLSMulti = CanMergeToLSMulti;

1072 if (PartOfLSMulti) {

1073

1074 if (RegNum <= PRegNum)

1075 PartOfLSMulti = false;

1076

1077

1078

1079 else if (!isNotVFP && RegNum != PRegNum+1)

1080 PartOfLSMulti = false;

1081 }

1082

1083 bool PartOfLSDouble = CanMergeToLSDouble && Count <= 1;

1084

1085 if (!PartOfLSMulti && !PartOfLSDouble)

1086 break;

1087 CanMergeToLSMulti &= PartOfLSMulti;

1088 CanMergeToLSDouble &= PartOfLSDouble;

1089

1090

1091 unsigned Position = MemOps[I].Position;

1092 if (Position < MemOps[Latest].Position)

1093 Latest = I;

1094 else if (Position > MemOps[Earliest].Position)

1095 Earliest = I;

1096

1098 PRegNum = RegNum;

1099 }

1100

1101

1102 MergeCandidate *Candidate = new(Allocator.Allocate()) MergeCandidate;

1103 for (unsigned C = SIndex, CE = SIndex + Count; C < CE; ++C)

1104 Candidate->Instrs.push_back(MemOps[C].MI);

1105 Candidate->LatestMIIdx = Latest - SIndex;

1106 Candidate->EarliestMIIdx = Earliest - SIndex;

1107 Candidate->InsertPos = MemOps[Latest].Position;

1109 CanMergeToLSMulti = CanMergeToLSDouble = false;

1110 Candidate->CanMergeToLSMulti = CanMergeToLSMulti;

1111 Candidate->CanMergeToLSDouble = CanMergeToLSDouble;

1112 Candidates.push_back(Candidate);

1113

1114 SIndex += Count;

1115 } while (SIndex < EIndex);

1116}

1117

1120 switch (Opc) {

1122 case ARM::LDMIA:

1123 case ARM::LDMDA:

1124 case ARM::LDMDB:

1125 case ARM::LDMIB:

1126 switch (Mode) {

1128 case ARM_AM::ia: return ARM::LDMIA_UPD;

1129 case ARM_AM::ib: return ARM::LDMIB_UPD;

1130 case ARM_AM::da: return ARM::LDMDA_UPD;

1131 case ARM_AM::db: return ARM::LDMDB_UPD;

1132 }

1133 case ARM::STMIA:

1134 case ARM::STMDA:

1135 case ARM::STMDB:

1136 case ARM::STMIB:

1137 switch (Mode) {

1139 case ARM_AM::ia: return ARM::STMIA_UPD;

1140 case ARM_AM::ib: return ARM::STMIB_UPD;

1141 case ARM_AM::da: return ARM::STMDA_UPD;

1142 case ARM_AM::db: return ARM::STMDB_UPD;

1143 }

1144 case ARM::t2LDMIA:

1145 case ARM::t2LDMDB:

1146 switch (Mode) {

1148 case ARM_AM::ia: return ARM::t2LDMIA_UPD;

1149 case ARM_AM::db: return ARM::t2LDMDB_UPD;

1150 }

1151 case ARM::t2STMIA:

1152 case ARM::t2STMDB:

1153 switch (Mode) {

1155 case ARM_AM::ia: return ARM::t2STMIA_UPD;

1156 case ARM_AM::db: return ARM::t2STMDB_UPD;

1157 }

1158 case ARM::VLDMSIA:

1159 switch (Mode) {

1161 case ARM_AM::ia: return ARM::VLDMSIA_UPD;

1162 case ARM_AM::db: return ARM::VLDMSDB_UPD;

1163 }

1164 case ARM::VLDMDIA:

1165 switch (Mode) {

1167 case ARM_AM::ia: return ARM::VLDMDIA_UPD;

1168 case ARM_AM::db: return ARM::VLDMDDB_UPD;

1169 }

1170 case ARM::VSTMSIA:

1171 switch (Mode) {

1173 case ARM_AM::ia: return ARM::VSTMSIA_UPD;

1174 case ARM_AM::db: return ARM::VSTMSDB_UPD;

1175 }

1176 case ARM::VSTMDIA:

1177 switch (Mode) {

1179 case ARM_AM::ia: return ARM::VSTMDIA_UPD;

1180 case ARM_AM::db: return ARM::VSTMDDB_UPD;

1181 }

1182 }

1183}

1184

1185

1186

1187

1190 bool CheckCPSRDef;

1191 int Scale;

1192 switch (MI.getOpcode()) {

1193 case ARM::tADDi8: Scale = 4; CheckCPSRDef = true; break;

1194 case ARM::tSUBi8: Scale = -4; CheckCPSRDef = true; break;

1195 case ARM::t2SUBri:

1196 case ARM::t2SUBspImm:

1197 case ARM::SUBri: Scale = -1; CheckCPSRDef = true; break;

1198 case ARM::t2ADDri:

1199 case ARM::t2ADDspImm:

1200 case ARM::ADDri: Scale = 1; CheckCPSRDef = true; break;

1201 case ARM::tADDspi: Scale = 4; CheckCPSRDef = false; break;

1202 case ARM::tSUBspi: Scale = -4; CheckCPSRDef = false; break;

1203 default: return 0;

1204 }

1205

1207 if (MI.getOperand(0).getReg() != Reg ||

1208 MI.getOperand(1).getReg() != Reg ||

1210 MIPredReg != PredReg)

1211 return 0;

1212

1213 if (CheckCPSRDef && definesCPSR(MI))

1214 return 0;

1215 return MI.getOperand(2).getImm() * Scale;

1216}

1217

1218

1226 if (MBBI == BeginMBBI)

1227 return EndMBBI;

1228

1229

1231 while (PrevMBBI->isDebugInstr() && PrevMBBI != BeginMBBI)

1232 --PrevMBBI;

1233

1235 return Offset == 0 ? EndMBBI : PrevMBBI;

1236}

1237

1238

1247 while (NextMBBI != EndMBBI) {

1248

1249 while (NextMBBI != EndMBBI && NextMBBI->isDebugInstr())

1250 ++NextMBBI;

1251 if (NextMBBI == EndMBBI)

1252 return EndMBBI;

1253

1255 if (Off) {

1257 return NextMBBI;

1258 }

1259

1260

1261

1262

1263

1264

1265 if (Reg == ARM::SP || NextMBBI->readsRegister(Reg, TRI) ||

1266 NextMBBI->definesRegister(Reg, TRI))

1267 return EndMBBI;

1268

1269 ++NextMBBI;

1270 }

1271 return EndMBBI;

1272}

1273

1274

1275

1276

1277

1278

1279

1280

1281

1282

1283

1284

1285

1286bool ARMLoadStoreOpt::MergeBaseUpdateLSMultiple(MachineInstr *MI) {

1287

1288 if (isThumb1) return false;

1289 LLVM_DEBUG(dbgs() << "Attempting to merge update of: " << *MI);

1290

1291 const MachineOperand &BaseOP = MI->getOperand(0);

1293 bool BaseKill = BaseOP.isKill();

1296 unsigned Opcode = MI->getOpcode();

1298

1299

1300

1301 for (const MachineOperand &MO : llvm::drop_begin(MI->operands(), 2))

1303 return false;

1304

1306 MachineBasicBlock &MBB = *MI->getParent();

1316 } else {

1320

1321

1322

1323

1324

1325 if (!STI->hasMinSize() || !BaseKill)

1326 return false;

1327

1328 bool HighRegsUsed = false;

1329 for (const MachineOperand &MO : llvm::drop_begin(MI->operands(), 2))

1330 if (MO.getReg() >= ARM::R8) {

1331 HighRegsUsed = true;

1332 break;

1333 }

1334

1335 if (!HighRegsUsed)

1336 MergeInstr = MBB.end();

1337 else

1338 return false;

1339 }

1340 }

1341 if (MergeInstr != MBB.end()) {

1342 LLVM_DEBUG(dbgs() << " Erasing old increment: " << *MergeInstr);

1344 }

1345

1351

1352

1353 for (const MachineOperand &MO : llvm::drop_begin(MI->operands(), 3))

1354 MIB.add(MO);

1355

1356

1358

1359 LLVM_DEBUG(dbgs() << " Added new load/store: " << *MIB);

1361 return true;

1362}

1363

1366 switch (Opc) {

1367 case ARM::LDRi12:

1368 return ARM::LDR_PRE_IMM;

1369 case ARM::STRi12:

1370 return ARM::STR_PRE_IMM;

1371 case ARM::VLDRS:

1372 return Mode == ARM_AM::add ? ARM::VLDMSIA_UPD : ARM::VLDMSDB_UPD;

1373 case ARM::VLDRD:

1374 return Mode == ARM_AM::add ? ARM::VLDMDIA_UPD : ARM::VLDMDDB_UPD;

1375 case ARM::VSTRS:

1376 return Mode == ARM_AM::add ? ARM::VSTMSIA_UPD : ARM::VSTMSDB_UPD;

1377 case ARM::VSTRD:

1378 return Mode == ARM_AM::add ? ARM::VSTMDIA_UPD : ARM::VSTMDDB_UPD;

1379 case ARM::t2LDRi8:

1380 case ARM::t2LDRi12:

1381 return ARM::t2LDR_PRE;

1382 case ARM::t2STRi8:

1383 case ARM::t2STRi12:

1384 return ARM::t2STR_PRE;

1386 }

1387}

1388

1391 switch (Opc) {

1392 case ARM::LDRi12:

1393 return ARM::LDR_POST_IMM;

1394 case ARM::STRi12:

1395 return ARM::STR_POST_IMM;

1396 case ARM::VLDRS:

1397 return Mode == ARM_AM::add ? ARM::VLDMSIA_UPD : ARM::VLDMSDB_UPD;

1398 case ARM::VLDRD:

1399 return Mode == ARM_AM::add ? ARM::VLDMDIA_UPD : ARM::VLDMDDB_UPD;

1400 case ARM::VSTRS:

1401 return Mode == ARM_AM::add ? ARM::VSTMSIA_UPD : ARM::VSTMSDB_UPD;

1402 case ARM::VSTRD:

1403 return Mode == ARM_AM::add ? ARM::VSTMDIA_UPD : ARM::VSTMDDB_UPD;

1404 case ARM::t2LDRi8:

1405 case ARM::t2LDRi12:

1406 return ARM::t2LDR_POST;

1407 case ARM::t2LDRBi8:

1408 case ARM::t2LDRBi12:

1409 return ARM::t2LDRB_POST;

1410 case ARM::t2LDRSBi8:

1411 case ARM::t2LDRSBi12:

1412 return ARM::t2LDRSB_POST;

1413 case ARM::t2LDRHi8:

1414 case ARM::t2LDRHi12:

1415 return ARM::t2LDRH_POST;

1416 case ARM::t2LDRSHi8:

1417 case ARM::t2LDRSHi12:

1418 return ARM::t2LDRSH_POST;

1419 case ARM::t2STRi8:

1420 case ARM::t2STRi12:

1421 return ARM::t2STR_POST;

1422 case ARM::t2STRBi8:

1423 case ARM::t2STRBi12:

1424 return ARM::t2STRB_POST;

1425 case ARM::t2STRHi8:

1426 case ARM::t2STRHi12:

1427 return ARM::t2STRH_POST;

1428

1429 case ARM::MVE_VLDRBS16:

1430 return ARM::MVE_VLDRBS16_post;

1431 case ARM::MVE_VLDRBS32:

1432 return ARM::MVE_VLDRBS32_post;

1433 case ARM::MVE_VLDRBU16:

1434 return ARM::MVE_VLDRBU16_post;

1435 case ARM::MVE_VLDRBU32:

1436 return ARM::MVE_VLDRBU32_post;

1437 case ARM::MVE_VLDRHS32:

1438 return ARM::MVE_VLDRHS32_post;

1439 case ARM::MVE_VLDRHU32:

1440 return ARM::MVE_VLDRHU32_post;

1441 case ARM::MVE_VLDRBU8:

1442 return ARM::MVE_VLDRBU8_post;

1443 case ARM::MVE_VLDRHU16:

1444 return ARM::MVE_VLDRHU16_post;

1445 case ARM::MVE_VLDRWU32:

1446 return ARM::MVE_VLDRWU32_post;

1447 case ARM::MVE_VSTRB16:

1448 return ARM::MVE_VSTRB16_post;

1449 case ARM::MVE_VSTRB32:

1450 return ARM::MVE_VSTRB32_post;

1451 case ARM::MVE_VSTRH32:

1452 return ARM::MVE_VSTRH32_post;

1453 case ARM::MVE_VSTRBU8:

1454 return ARM::MVE_VSTRBU8_post;

1455 case ARM::MVE_VSTRHU16:

1456 return ARM::MVE_VSTRHU16_post;

1457 case ARM::MVE_VSTRWU32:

1458 return ARM::MVE_VSTRWU32_post;

1459

1461 }

1462}

1463

1464

1465

1466bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineInstr *MI) {

1467

1468

1469 if (isThumb1) return false;

1470 LLVM_DEBUG(dbgs() << "Attempting to merge update of: " << *MI);

1471

1474 unsigned Opcode = MI->getOpcode();

1476 bool isAM5 = (Opcode == ARM::VLDRD || Opcode == ARM::VLDRS ||

1477 Opcode == ARM::VSTRD || Opcode == ARM::VSTRS);

1478 bool isAM2 = (Opcode == ARM::LDRi12 || Opcode == ARM::STRi12);

1480 if (MI->getOperand(2).getImm() != 0)

1481 return false;

1483 return false;

1484

1485

1486

1487 if (MI->getOperand(0).getReg() == Base)

1488 return false;

1489

1493 MachineBasicBlock &MBB = *MI->getParent();

1498 unsigned NewOpc;

1499 if (!isAM5 && Offset == Bytes) {

1501 } else if (Offset == -Bytes) {

1503 } else {

1505 if (MergeInstr == MBB.end())

1506 return false;

1507

1509 if ((isAM5 && Offset != Bytes) ||

1513 return false;

1514 }

1515 }

1516 LLVM_DEBUG(dbgs() << " Erasing old increment: " << *MergeInstr);

1518

1520

1522 if (isAM5) {

1523

1524

1525

1526

1527 MachineOperand &MO = MI->getOperand(0);

1536 (void)MIB;

1537 LLVM_DEBUG(dbgs() << " Added new instruction: " << *MIB);

1538 } else if (isLd) {

1539 if (isAM2) {

1540

1541 if (NewOpc == ARM::LDR_PRE_IMM || NewOpc == ARM::LDRB_PRE_IMM) {

1542 auto MIB =

1550 (void)MIB;

1551 LLVM_DEBUG(dbgs() << " Added new instruction: " << *MIB);

1552 } else {

1554 auto MIB =

1562 (void)MIB;

1563 LLVM_DEBUG(dbgs() << " Added new instruction: " << *MIB);

1564 }

1565 } else {

1566

1567 auto MIB =

1574 (void)MIB;

1575 LLVM_DEBUG(dbgs() << " Added new instruction: " << *MIB);

1576 }

1577 } else {

1578 MachineOperand &MO = MI->getOperand(0);

1579

1580

1581

1582 if (isAM2 && NewOpc == ARM::STR_POST_IMM) {

1584

1592 (void)MIB;

1593 LLVM_DEBUG(dbgs() << " Added new instruction: " << *MIB);

1594 } else {

1595

1602 (void)MIB;

1603 LLVM_DEBUG(dbgs() << " Added new instruction: " << *MIB);

1604 }

1605 }

1607

1608 return true;

1609}

1610

1611bool ARMLoadStoreOpt::MergeBaseUpdateLSDouble(MachineInstr &MI) const {

1612 unsigned Opcode = MI.getOpcode();

1613 assert((Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8) &&

1614 "Must have t2STRDi8 or t2LDRDi8");

1615 if (MI.getOperand(3).getImm() != 0)

1616 return false;

1617 LLVM_DEBUG(dbgs() << "Attempting to merge update of: " << MI);

1618

1619

1620

1621 const MachineOperand &BaseOp = MI.getOperand(2);

1623 const MachineOperand &Reg0Op = MI.getOperand(0);

1624 const MachineOperand &Reg1Op = MI.getOperand(1);

1626 return false;

1627

1631 MachineBasicBlock &MBB = *MI.getParent();

1635 unsigned NewOpc;

1637 NewOpc = Opcode == ARM::t2LDRDi8 ? ARM::t2LDRD_PRE : ARM::t2STRD_PRE;

1638 } else {

1640 if (MergeInstr == MBB.end())

1641 return false;

1642 NewOpc = Opcode == ARM::t2LDRDi8 ? ARM::t2LDRD_POST : ARM::t2STRD_POST;

1644 return false;

1645 }

1646 LLVM_DEBUG(dbgs() << " Erasing old increment: " << *MergeInstr);

1648

1651 if (NewOpc == ARM::t2LDRD_PRE || NewOpc == ARM::t2LDRD_POST) {

1653 } else {

1654 assert(NewOpc == ARM::t2STRD_PRE || NewOpc == ARM::t2STRD_POST);

1656 }

1661 "Unexpected number of operands in Opcode specification.");

1662

1663

1664 for (const MachineOperand &MO : MI.implicit_operands())

1665 MIB.add(MO);

1667

1668 LLVM_DEBUG(dbgs() << " Added new load/store: " << *MIB);

1670 return true;

1671}

1672

1673

1674

1676 unsigned Opcode = MI.getOpcode();

1677 switch (Opcode) {

1678 case ARM::VLDRS:

1679 case ARM::VSTRS:

1680 case ARM::VLDRD:

1681 case ARM::VSTRD:

1682 case ARM::LDRi12:

1683 case ARM::STRi12:

1684 case ARM::tLDRi:

1685 case ARM::tSTRi:

1686 case ARM::tLDRspi:

1687 case ARM::tSTRspi:

1688 case ARM::t2LDRi8:

1689 case ARM::t2LDRi12:

1690 case ARM::t2STRi8:

1691 case ARM::t2STRi12:

1692 break;

1693 default:

1694 return false;

1695 }

1696 if (MI.getOperand(1).isReg())

1697 return false;

1698

1699

1700

1701 if (MI.hasOneMemOperand())

1702 return false;

1703

1705

1706

1707

1708

1710 return false;

1711

1712

1713

1715 return false;

1716

1717

1718

1719

1720 if (MI.getOperand(0).isReg() && MI.getOperand(0).isUndef())

1721 return false;

1722

1723

1724 if (MI.getOperand(1).isUndef())

1725 return false;

1726

1727 return true;

1728}

1729

1732 bool isDef, unsigned NewOpc, unsigned Reg,

1733 bool RegDeadKill, bool RegUndef, unsigned BaseReg,

1737 if (isDef) {

1739 TII->get(NewOpc))

1743

1744

1746 } else {

1748 TII->get(NewOpc))

1752

1753

1755 }

1756}

1757

1758bool ARMLoadStoreOpt::FixInvalidRegPairOp(MachineBasicBlock &MBB,

1760 MachineInstr *MI = &*MBBI;

1761 unsigned Opcode = MI->getOpcode();

1762

1763

1764 if (Opcode != ARM::LDRD && Opcode != ARM::STRD && Opcode != ARM::t2LDRDi8)

1765 return false;

1766

1767 const MachineOperand &BaseOp = MI->getOperand(2);

1769 Register EvenReg = MI->getOperand(0).getReg();

1770 Register OddReg = MI->getOperand(1).getReg();

1771 unsigned EvenRegNum = TRI->getDwarfRegNum(EvenReg, false);

1772 unsigned OddRegNum = TRI->getDwarfRegNum(OddReg, false);

1773

1774

1775

1776 bool Errata602117 = EvenReg == BaseReg &&

1777 (Opcode == ARM::LDRD || Opcode == ARM::t2LDRDi8) && STI->isCortexM3();

1778

1779 bool NonConsecutiveRegs = (Opcode == ARM::LDRD || Opcode == ARM::STRD) &&

1780 (EvenRegNum % 2 != 0 || EvenRegNum + 1 != OddRegNum);

1781

1782 if (!Errata602117 && !NonConsecutiveRegs)

1783 return false;

1784

1785 bool isT2 = Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8;

1786 bool isLd = Opcode == ARM::LDRD || Opcode == ARM::t2LDRDi8;

1787 bool EvenDeadKill = isLd ?

1788 MI->getOperand(0).isDead() : MI->getOperand(0).isKill();

1789 bool EvenUndef = MI->getOperand(0).isUndef();

1790 bool OddDeadKill = isLd ?

1791 MI->getOperand(1).isDead() : MI->getOperand(1).isKill();

1792 bool OddUndef = MI->getOperand(1).isUndef();

1793 bool BaseKill = BaseOp.isKill();

1794 bool BaseUndef = BaseOp.isUndef();

1795 assert((isT2 || MI->getOperand(3).getReg() == ARM::NoRegister) &&

1796 "register offset not handled below");

1800

1801 if (OddRegNum > EvenRegNum && OffImm == 0) {

1802

1803

1804 unsigned NewOpc = (isLd)

1805 ? (isT2 ? ARM::t2LDMIA : ARM::LDMIA)

1806 : (isT2 ? ARM::t2STMIA : ARM::STMIA);

1807 if (isLd) {

1814 ++NumLDRD2LDM;

1815 } else {

1824 ++NumSTRD2STM;

1825 }

1826 } else {

1827

1828 unsigned NewOpc = (isLd)

1829 ? (isT2 ? (OffImm < 0 ? ARM::t2LDRi8 : ARM::t2LDRi12) : ARM::LDRi12)

1830 : (isT2 ? (OffImm < 0 ? ARM::t2STRi8 : ARM::t2STRi12) : ARM::STRi12);

1831

1832

1833 unsigned NewOpc2 = (isLd)

1834 ? (isT2 ? (OffImm+4 < 0 ? ARM::t2LDRi8 : ARM::t2LDRi12) : ARM::LDRi12)

1835 : (isT2 ? (OffImm+4 < 0 ? ARM::t2STRi8 : ARM::t2STRi12) : ARM::STRi12);

1836

1837

1838 if (isLd && TRI->regsOverlap(EvenReg, BaseReg)) {

1839 assert(TRI->regsOverlap(OddReg, BaseReg));

1841 false, BaseReg, false, BaseUndef, Pred, PredReg, TII, MI);

1843 false, BaseReg, BaseKill, BaseUndef, Pred, PredReg, TII,

1844 MI);

1845 } else {

1846 if (OddReg == EvenReg && EvenDeadKill) {

1847

1848

1849

1850 EvenDeadKill = false;

1851 OddDeadKill = true;

1852 }

1853

1854 if (EvenReg == BaseReg)

1855 EvenDeadKill = false;

1857 EvenUndef, BaseReg, false, BaseUndef, Pred, PredReg, TII,

1858 MI);

1860 OddUndef, BaseReg, BaseKill, BaseUndef, Pred, PredReg, TII,

1861 MI);

1862 }

1863 if (isLd)

1864 ++NumLDRD2LDR;

1865 else

1866 ++NumSTRD2STR;

1867 }

1868

1870 return true;

1871}

1872

1873

1874

1875bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) {

1876 MemOpQueue MemOps;

1877 unsigned CurrBase = 0;

1878 unsigned CurrOpc = ~0u;

1880 unsigned Position = 0;

1881 assert(Candidates.size() == 0);

1882 assert(MergeBaseCandidates.size() == 0);

1883 LiveRegsValid = false;

1884

1887

1888 MBBI = std::prev(I);

1889 if (FixInvalidRegPairOp(MBB, MBBI))

1890 continue;

1891 ++Position;

1892

1894 unsigned Opcode = MBBI->getOpcode();

1895 const MachineOperand &MO = MBBI->getOperand(0);

1901 if (CurrBase == 0) {

1902

1903 CurrBase = Base;

1904 CurrOpc = Opcode;

1905 CurrPred = Pred;

1906 MemOps.push_back(MemOpQueueEntry(*MBBI, Offset, Position));

1907 continue;

1908 }

1909

1910 if (CurrOpc == Opcode && CurrBase == Base && CurrPred == Pred) {

1911

1912

1913

1914

1915

1916

1917

1918 bool Overlap = false;

1920 Overlap = (Base == Reg);

1921 if (!Overlap) {

1922 for (const MemOpQueueEntry &E : MemOps) {

1923 if (TRI->regsOverlap(Reg, E.MI->getOperand(0).getReg())) {

1924 Overlap = true;

1925 break;

1926 }

1927 }

1928 }

1929 }

1930

1931 if (!Overlap) {

1932

1933 if (Offset > MemOps.back().Offset) {

1934 MemOps.push_back(MemOpQueueEntry(*MBBI, Offset, Position));

1935 continue;

1936 } else {

1937 MemOpQueue::iterator MI, ME;

1938 for (MI = MemOps.begin(), ME = MemOps.end(); MI != ME; ++MI) {

1940

1941 break;

1942 }

1944

1945 MI = ME;

1946 break;

1947 }

1948 }

1949 if (MI != MemOps.end()) {

1950 MemOps.insert(MI, MemOpQueueEntry(*MBBI, Offset, Position));

1951 continue;

1952 }

1953 }

1954 }

1955 }

1956

1957

1959 --Position;

1960

1961 } else if (MBBI->isDebugInstr()) {

1962 continue;

1963 } else if (MBBI->getOpcode() == ARM::t2LDRDi8 ||

1964 MBBI->getOpcode() == ARM::t2STRDi8) {

1965

1966

1968 }

1969

1970

1971 if (MemOps.size() > 0) {

1972 FormCandidates(MemOps);

1973

1974 CurrBase = 0;

1975 CurrOpc = ~0u;

1977 MemOps.clear();

1978 }

1979 }

1980 if (MemOps.size() > 0)

1981 FormCandidates(MemOps);

1982

1983

1984

1985 auto LessThan = [](const MergeCandidate* M0, const MergeCandidate *M1) {

1986 return M0->InsertPos < M1->InsertPos;

1987 };

1989

1990

1992 for (const MergeCandidate *Candidate : Candidates) {

1993 if (Candidate->CanMergeToLSMulti || Candidate->CanMergeToLSDouble) {

1994 MachineInstr *Merged = MergeOpsUpdate(*Candidate);

1995

1996 if (Merged) {

1998 unsigned Opcode = Merged->getOpcode();

1999 if (Opcode == ARM::t2STRDi8 || Opcode == ARM::t2LDRDi8)

2000 MergeBaseUpdateLSDouble(*Merged);

2001 else

2002 MergeBaseUpdateLSMultiple(Merged);

2003 } else {

2004 for (MachineInstr *MI : Candidate->Instrs) {

2005 if (MergeBaseUpdateLoadStore(MI))

2007 }

2008 }

2009 } else {

2010 assert(Candidate->Instrs.size() == 1);

2011 if (MergeBaseUpdateLoadStore(Candidate->Instrs.front()))

2013 }

2014 }

2015 Candidates.clear();

2016

2017 for (MachineInstr *MI : MergeBaseCandidates)

2018 MergeBaseUpdateLSDouble(*MI);

2019 MergeBaseCandidates.clear();

2020

2022}

2023

2024

2025

2026

2027

2028

2029

2030

2031

2032

2033

2034bool ARMLoadStoreOpt::MergeReturnIntoLDM(MachineBasicBlock &MBB) {

2035

2036 if (isThumb1) return false;

2037 if (MBB.empty()) return false;

2038

2041 (MBBI->getOpcode() == ARM::BX_RET ||

2042 MBBI->getOpcode() == ARM::tBX_RET ||

2043 MBBI->getOpcode() == ARM::MOVPCLR)) {

2045

2046 while (PrevI->isDebugInstr() && PrevI != MBB.begin())

2047 --PrevI;

2048 MachineInstr &PrevMI = *PrevI;

2049 unsigned Opcode = PrevMI.getOpcode();

2050 if (Opcode == ARM::LDMIA_UPD || Opcode == ARM::LDMDA_UPD ||

2051 Opcode == ARM::LDMDB_UPD || Opcode == ARM::LDMIB_UPD ||

2052 Opcode == ARM::t2LDMIA_UPD || Opcode == ARM::t2LDMDB_UPD) {

2054 if (MO.getReg() != ARM::LR)

2055 return false;

2056 unsigned NewOpc = (isThumb2 ? ARM::t2LDMIA_RET : ARM::LDMIA_RET);

2057 assert(((isThumb2 && Opcode == ARM::t2LDMIA_UPD) ||

2058 Opcode == ARM::LDMIA_UPD) && "Unsupported multiple load-return!");

2063 return true;

2064 }

2065 }

2066 return false;

2067}

2068

2069bool ARMLoadStoreOpt::CombineMovBx(MachineBasicBlock &MBB) {

2072 MBBI->getOpcode() != ARM::tBX_RET)

2073 return false;

2074

2076 --Prev;

2077 if (Prev->getOpcode() != ARM::tMOVr ||

2078 !Prev->definesRegister(ARM::LR, nullptr))

2079 return false;

2080

2081 for (auto Use : Prev->uses())

2082 if (Use.isKill()) {

2083 assert(STI->hasV4TOps());

2090 return true;

2091 }

2092

2093 llvm_unreachable("tMOVr doesn't kill a reg before tBX_RET?");

2094}

2095

2096bool ARMLoadStoreOpt::runOnMachineFunction(MachineFunction &Fn) {

2098 return false;

2099

2100 MF = &Fn;

2103 AFI = Fn.getInfo();

2106

2107 RegClassInfoValid = false;

2110

2111 bool Modified = false, ModifiedLDMReturn = false;

2112 for (MachineBasicBlock &MBB : Fn) {

2115 ModifiedLDMReturn |= MergeReturnIntoLDM(MBB);

2116 if (isThumb1)

2118 }

2119 Modified |= ModifiedLDMReturn;

2120

2121

2122

2123

2124

2125 if (ModifiedLDMReturn)

2127

2130}

2131

2132#define ARM_PREALLOC_LOAD_STORE_OPT_NAME \

2133 "ARM pre- register allocation load / store optimization pass"

2134

2135namespace {

2136

2137

2138

2140 static char ID;

2141

2150

2152

2153 bool runOnMachineFunction(MachineFunction &Fn) override;

2154

2155 StringRef getPassName() const override {

2157 }

2158

2159 void getAnalysisUsage(AnalysisUsage &AU) const override {

2164 }

2165

2166 private:

2171 bool RescheduleOps(

2176 bool DistributeIncrements();

2178 };

2179

2180}

2181

2182char ARMPreAllocLoadStoreOpt::ID = 0;

2183

2189

2190

2191

2193 cl::init(8), cl::Hidden);

2194

2195bool ARMPreAllocLoadStoreOpt::runOnMachineFunction(MachineFunction &Fn) {

2197 return false;

2198

2199 TD = &Fn.getDataLayout();

2201 TII = STI->getInstrInfo();

2202 TRI = STI->getRegisterInfo();

2203 MRI = &Fn.getRegInfo();

2204 DT = &getAnalysis().getDomTree();

2205 MF = &Fn;

2206 AA = &getAnalysis().getAAResults();

2207

2208 bool Modified = DistributeIncrements();

2210 Modified |= RescheduleLoadStoreInstrs(&MFI);

2211

2213}

2214

2222

2224 while (++I != E) {

2225 if (I->isDebugInstr() || MemOps.count(&*I))

2226 continue;

2227 if (I->isCall() || I->isTerminator() || I->hasUnmodeledSideEffects())

2228 return false;

2229 if (I->mayStore() || (!isLd && I->mayLoad()))

2231 if (I->mayAlias(AA, *MemOp, false))

2232 return false;

2233 for (unsigned j = 0, NumOps = I->getNumOperands(); j != NumOps; ++j) {

2235 if (!MO.isReg())

2236 continue;

2239 return false;

2242 }

2243 }

2244

2245

2246 if (MemRegs.size() <= 4)

2247

2248 return true;

2249 return AddedRegPressure.size() <= MemRegs.size() * 2;

2250}

2251

2252bool ARMPreAllocLoadStoreOpt::CanFormLdStDWord(

2253 MachineInstr *Op0, MachineInstr *Op1, DebugLoc &dl, unsigned &NewOpc,

2256

2257 if (!STI->hasV5TEOps())

2258 return false;

2259

2260

2261 unsigned Scale = 1;

2262 unsigned Opcode = Op0->getOpcode();

2263 if (Opcode == ARM::LDRi12) {

2264 NewOpc = ARM::LDRD;

2265 } else if (Opcode == ARM::STRi12) {

2266 NewOpc = ARM::STRD;

2267 } else if (Opcode == ARM::t2LDRi8 || Opcode == ARM::t2LDRi12) {

2268 NewOpc = ARM::t2LDRDi8;

2269 Scale = 4;

2270 isT2 = true;

2271 } else if (Opcode == ARM::t2STRi8 || Opcode == ARM::t2STRi12) {

2272 NewOpc = ARM::t2STRDi8;

2273 Scale = 4;

2274 isT2 = true;

2275 } else {

2276 return false;

2277 }

2278

2279

2280

2281

2285 return false;

2286

2289 if (Alignment < ReqAlign)

2290 return false;

2291

2292

2294 if (isT2) {

2295 int Limit = (1 << 8) * Scale;

2296 if (OffImm >= Limit || (OffImm <= -Limit) || (OffImm & (Scale-1)))

2297 return false;

2299 } else {

2301 if (OffImm < 0) {

2303 OffImm = - OffImm;

2304 }

2305 int Limit = (1 << 8) * Scale;

2306 if (OffImm >= Limit || (OffImm & (Scale-1)))

2307 return false;

2309 }

2312 if (FirstReg == SecondReg)

2313 return false;

2317 return true;

2318}

2319

2320bool ARMPreAllocLoadStoreOpt::RescheduleOps(

2321 MachineBasicBlock *MBB, SmallVectorImpl<MachineInstr *> &Ops, unsigned Base,

2322 bool isLd, DenseMap<MachineInstr *, unsigned> &MI2LocMap,

2324 bool RetVal = false;

2325

2326

2331 return LOffset > ROffset;

2332 });

2333

2334

2335

2336

2337

2338 while (Ops.size() > 1) {

2339 unsigned FirstLoc = ~0U;

2340 unsigned LastLoc = 0;

2341 MachineInstr *FirstOp = nullptr;

2342 MachineInstr *LastOp = nullptr;

2343 int LastOffset = 0;

2344 unsigned LastOpcode = 0;

2345 unsigned LastBytes = 0;

2346 unsigned NumMove = 0;

2348

2349 unsigned LSMOpcode

2351 if (LastOpcode && LSMOpcode != LastOpcode)

2352 break;

2353

2354

2357 if (LastBytes) {

2358 if (Bytes != LastBytes || Offset != (LastOffset + (int)Bytes))

2359 break;

2360 }

2361

2362

2364 break;

2365

2366

2367 ++NumMove;

2368 LastOffset = Offset;

2369 LastBytes = Bytes;

2370 LastOpcode = LSMOpcode;

2371

2372 unsigned Loc = MI2LocMap[Op];

2373 if (Loc <= FirstLoc) {

2374 FirstLoc = Loc;

2375 FirstOp = Op;

2376 }

2377 if (Loc >= LastLoc) {

2378 LastLoc = Loc;

2379 LastOp = Op;

2380 }

2381 }

2382

2383 if (NumMove <= 1)

2384 Ops.pop_back();

2385 else {

2386 SmallPtrSet<MachineInstr*, 4> MemOps;

2387 SmallSet<unsigned, 4> MemRegs;

2388 for (size_t i = Ops.size() - NumMove, e = Ops.size(); i != e; ++i) {

2391 }

2392

2393

2394

2395 bool DoMove = (LastLoc - FirstLoc) <= NumMove*4;

2396 if (DoMove)

2398 MemOps, MemRegs, TRI, AA);

2399 if (!DoMove) {

2400 for (unsigned i = 0; i != NumMove; ++i)

2401 Ops.pop_back();

2402 } else {

2403

2405 while (InsertPos != MBB->end() &&

2406 (MemOps.count(&*InsertPos) || InsertPos->isDebugInstr()))

2407 ++InsertPos;

2408

2409

2410

2411 MachineInstr *Op0 = Ops.back();

2412 MachineInstr *Op1 = Ops[Ops.size()-2];

2413 Register FirstReg, SecondReg;

2416 bool isT2 = false;

2417 unsigned NewOpc = 0;

2420 if (NumMove == 2 && CanFormLdStDWord(Op0, Op1, dl, NewOpc,

2421 FirstReg, SecondReg, BaseReg,

2422 Offset, PredReg, Pred, isT2)) {

2423 Ops.pop_back();

2424 Ops.pop_back();

2425

2426 const MCInstrDesc &MCID = TII->get(NewOpc);

2427 const TargetRegisterClass *TRC = TII->getRegClass(MCID, 0);

2428 MRI->constrainRegClass(FirstReg, TRC);

2429 MRI->constrainRegClass(SecondReg, TRC);

2430

2431

2432 if (isLd) {

2433 MachineInstrBuilder MIB = BuildMI(*MBB, InsertPos, dl, MCID)

2437

2438

2439

2440 if (!isT2)

2445 ++NumLDRDFormed;

2446 } else {

2447 MachineInstrBuilder MIB = BuildMI(*MBB, InsertPos, dl, MCID)

2451

2452

2453

2454 if (!isT2)

2459 ++NumSTRDFormed;

2460 }

2463

2464 if (!isT2) {

2465

2468 }

2469 } else {

2470 for (unsigned i = 0; i != NumMove; ++i) {

2471 MachineInstr *Op = Ops.pop_back_val();

2472 if (isLd) {

2473

2475 RegisterMap[Reg];

2476 }

2477

2479 }

2480 }

2481

2482 NumLdStMoved += NumMove;

2483 RetVal = true;

2484 }

2485 }

2486 }

2487

2488 return RetVal;

2489}

2490

2493 if (MI->isNonListDebugValue()) {

2494 auto &Op = MI->getOperand(0);

2495 if (Op.isReg())

2496 Fn(Op);

2497 } else {

2498 for (unsigned I = 2; I < MI->getNumOperands(); I++) {

2499 auto &Op = MI->getOperand(I);

2500 if (Op.isReg())

2501 Fn(Op);

2502 }

2503 }

2504}

2505

2506

2507

2511

2513 auto RegIt = RegisterMap.find(Op.getReg());

2514 if (RegIt == RegisterMap.end())

2515 return;

2516 auto &InstrVec = RegIt->getSecond();

2517 llvm::replace(InstrVec, InstrToReplace, DbgValueListInstr);

2518 });

2519}

2520

2522 auto DbgVar = DebugVariable(MI->getDebugVariable(), MI->getDebugExpression(),

2523 MI->getDebugLoc()->getInlinedAt());

2524 return DbgVar;

2525}

2526

2527bool

2528ARMPreAllocLoadStoreOpt::RescheduleLoadStoreInstrs(MachineBasicBlock *MBB) {

2529 bool RetVal = false;

2530

2531 DenseMap<MachineInstr *, unsigned> MI2LocMap;

2532 using Base2InstMap = DenseMap<unsigned, SmallVector<MachineInstr *, 4>>;

2533 using BaseVec = SmallVector<unsigned, 4>;

2534 Base2InstMap Base2LdsMap;

2535 Base2InstMap Base2StsMap;

2536 BaseVec LdBases;

2537 BaseVec StBases;

2538

2539

2540

2541 SmallDenseMap<Register, SmallVector<MachineInstr *>, 8> RegisterMap;

2542

2543 unsigned Loc = 0;

2546 while (MBBI != E) {

2548 MachineInstr &MI = *MBBI;

2549 if (MI.isCall() || MI.isTerminator()) {

2550

2552 break;

2553 }

2554

2555 if (MI.isDebugInstr())

2556 MI2LocMap[&MI] = ++Loc;

2557

2559 continue;

2562 continue;

2563

2564 int Opc = MI.getOpcode();

2568 bool StopHere = false;

2569 auto FindBases = [&](Base2InstMap &Base2Ops, BaseVec &Bases) {

2570 auto [BI, Inserted] = Base2Ops.try_emplace(Base);

2571 if (Inserted) {

2572 BI->second.push_back(&MI);

2573 Bases.push_back(Base);

2574 return;

2575 }

2576 for (const MachineInstr *MI : BI->second) {

2578 StopHere = true;

2579 break;

2580 }

2581 }

2582 if (!StopHere)

2583 BI->second.push_back(&MI);

2584 };

2585

2586 if (isLd)

2587 FindBases(Base2LdsMap, LdBases);

2588 else

2589 FindBases(Base2StsMap, StBases);

2590

2591 if (StopHere) {

2592

2593

2594 --Loc;

2595 break;

2596 }

2597 }

2598

2599

2600 for (unsigned Base : LdBases) {

2601 SmallVectorImpl<MachineInstr *> &Lds = Base2LdsMap[Base];

2602 if (Lds.size() > 1)

2603 RetVal |= RescheduleOps(MBB, Lds, Base, true, MI2LocMap, RegisterMap);

2604 }

2605

2606

2607 for (unsigned Base : StBases) {

2608 SmallVectorImpl<MachineInstr *> &Sts = Base2StsMap[Base];

2609 if (Sts.size() > 1)

2610 RetVal |= RescheduleOps(MBB, Sts, Base, false, MI2LocMap, RegisterMap);

2611 }

2612

2613 if (MBBI != E) {

2614 Base2LdsMap.clear();

2615 Base2StsMap.clear();

2616 LdBases.clear();

2617 StBases.clear();

2618 }

2619 }

2620

2621

2622

2623

2624

2625

2626

2627

2628

2629

2630

2631

2632

2633

2634

2635

2636

2637

2638

2639

2640

2641

2642

2643

2644

2645

2646

2647

2648

2649

2650

2651

2652

2653

2654

2655

2656

2657

2658

2659

2660

2661

2662

2663

2664

2665

2666

2667

2668

2669

2670

2671

2672

2673

2674

2675

2676

2677

2678

2679

2680

2681

2682

2683

2684

2685

2686

2687

2688

2689

2690

2691

2692

2693

2694

2695

2696

2697

2698

2699

2700

2701

2702

2703

2704

2705

2706

2707

2708

2709

2710

2711

2712

2713

2714

2715

2716

2717

2718

2719

2720

2721

2722

2723

2724

2725

2726

2727

2728

2729

2730

2731

2732

2733

2734

2735

2736

2737

2738

2739

2740

2741

2742

2743

2744

2745

2746

2747

2748

2749

2750

2751

2752

2753

2754

2755

2756

2757

2758

2759

2760

2761

2762

2763

2764

2765

2766

2767

2768

2769

2770

2771 SmallDenseMap<DebugVariable, MachineInstr *, 8> DbgValueSinkCandidates;

2772

2773

2774 SmallDenseMap<MachineInstr *, SmallVector, 8> InstrMap;

2776 MachineInstr &MI = *MBBI;

2777

2778 auto PopulateRegisterAndInstrMapForDebugInstr = [&](Register Reg) {

2779 auto RegIt = RegisterMap.find(Reg);

2780 if (RegIt == RegisterMap.end())

2781 return;

2782 auto &InstrVec = RegIt->getSecond();

2783 InstrVec.push_back(&MI);

2784 InstrMap[&MI].push_back(Reg);

2785 };

2786

2787 if (MI.isDebugValue()) {

2788 assert(MI.getDebugVariable() &&

2789 "DBG_VALUE or DBG_VALUE_LIST must contain a DILocalVariable");

2790

2792

2793

2794

2795

2797 PopulateRegisterAndInstrMapForDebugInstr(Op.getReg());

2798 });

2799

2800

2801

2802

2803

2804

2805 auto InstrIt = DbgValueSinkCandidates.find(DbgVar);

2806 if (InstrIt != DbgValueSinkCandidates.end()) {

2807 auto *Instr = InstrIt->getSecond();

2808 auto RegIt = InstrMap.find(Instr);

2809 if (RegIt != InstrMap.end()) {

2810 const auto &RegVec = RegIt->getSecond();

2811

2812

2813 for (auto &Reg : RegVec) {

2814 auto RegIt = RegisterMap.find(Reg);

2815 if (RegIt == RegisterMap.end())

2816 continue;

2817 auto &InstrVec = RegIt->getSecond();

2818 auto IsDbgVar = [&](MachineInstr *I) -> bool {

2820 return Var == DbgVar;

2821 };

2822

2824 }

2826 [&](MachineOperand &Op) { Op.setReg(0); });

2827 }

2828 }

2829 DbgValueSinkCandidates[DbgVar] = &MI;

2830 } else {

2831

2832

2833 auto Opc = MI.getOpcode();

2835 continue;

2836 auto Reg = MI.getOperand(0).getReg();

2837 auto RegIt = RegisterMap.find(Reg);

2838 if (RegIt == RegisterMap.end())

2839 continue;

2840 auto &DbgInstrVec = RegIt->getSecond();

2841 if (!DbgInstrVec.size())

2842 continue;

2843 for (auto *DbgInstr : DbgInstrVec) {

2845 auto *ClonedMI = MI.getMF()->CloneMachineInstr(DbgInstr);

2846 MBB->insert(InsertPos, ClonedMI);

2848

2849

2851

2852

2853

2854 DbgValueSinkCandidates.erase(DbgVar);

2855

2857 [&](MachineOperand &Op) { Op.setReg(0); });

2858

2859

2860 if (DbgInstr->isDebugValueList())

2862 DbgInstr);

2863 }

2864 }

2865 }

2866 return RetVal;

2867}

2868

2869

2870

2871

2872

2874 switch (MI.getOpcode()) {

2875 case ARM::MVE_VLDRBS16:

2876 case ARM::MVE_VLDRBS32:

2877 case ARM::MVE_VLDRBU16:

2878 case ARM::MVE_VLDRBU32:

2879 case ARM::MVE_VLDRHS32:

2880 case ARM::MVE_VLDRHU32:

2881 case ARM::MVE_VLDRBU8:

2882 case ARM::MVE_VLDRHU16:

2883 case ARM::MVE_VLDRWU32:

2884 case ARM::MVE_VSTRB16:

2885 case ARM::MVE_VSTRB32:

2886 case ARM::MVE_VSTRH32:

2887 case ARM::MVE_VSTRBU8:

2888 case ARM::MVE_VSTRHU16:

2889 case ARM::MVE_VSTRWU32:

2890 case ARM::t2LDRHi8:

2891 case ARM::t2LDRHi12:

2892 case ARM::t2LDRSHi8:

2893 case ARM::t2LDRSHi12:

2894 case ARM::t2LDRBi8:

2895 case ARM::t2LDRBi12:

2896 case ARM::t2LDRSBi8:

2897 case ARM::t2LDRSBi12:

2898 case ARM::t2STRBi8:

2899 case ARM::t2STRBi12:

2900 case ARM::t2STRHi8:

2901 case ARM::t2STRHi12:

2902 return 1;

2903 case ARM::MVE_VLDRBS16_post:

2904 case ARM::MVE_VLDRBS32_post:

2905 case ARM::MVE_VLDRBU16_post:

2906 case ARM::MVE_VLDRBU32_post:

2907 case ARM::MVE_VLDRHS32_post:

2908 case ARM::MVE_VLDRHU32_post:

2909 case ARM::MVE_VLDRBU8_post:

2910 case ARM::MVE_VLDRHU16_post:

2911 case ARM::MVE_VLDRWU32_post:

2912 case ARM::MVE_VSTRB16_post:

2913 case ARM::MVE_VSTRB32_post:

2914 case ARM::MVE_VSTRH32_post:

2915 case ARM::MVE_VSTRBU8_post:

2916 case ARM::MVE_VSTRHU16_post:

2917 case ARM::MVE_VSTRWU32_post:

2918 case ARM::MVE_VLDRBS16_pre:

2919 case ARM::MVE_VLDRBS32_pre:

2920 case ARM::MVE_VLDRBU16_pre:

2921 case ARM::MVE_VLDRBU32_pre:

2922 case ARM::MVE_VLDRHS32_pre:

2923 case ARM::MVE_VLDRHU32_pre:

2924 case ARM::MVE_VLDRBU8_pre:

2925 case ARM::MVE_VLDRHU16_pre:

2926 case ARM::MVE_VLDRWU32_pre:

2927 case ARM::MVE_VSTRB16_pre:

2928 case ARM::MVE_VSTRB32_pre:

2929 case ARM::MVE_VSTRH32_pre:

2930 case ARM::MVE_VSTRBU8_pre:

2931 case ARM::MVE_VSTRHU16_pre:

2932 case ARM::MVE_VSTRWU32_pre:

2933 return 2;

2934 }

2935 return -1;

2936}

2937

2939 switch (MI.getOpcode()) {

2940 case ARM::MVE_VLDRBS16_post:

2941 case ARM::MVE_VLDRBS32_post:

2942 case ARM::MVE_VLDRBU16_post:

2943 case ARM::MVE_VLDRBU32_post:

2944 case ARM::MVE_VLDRHS32_post:

2945 case ARM::MVE_VLDRHU32_post:

2946 case ARM::MVE_VLDRBU8_post:

2947 case ARM::MVE_VLDRHU16_post:

2948 case ARM::MVE_VLDRWU32_post:

2949 case ARM::MVE_VSTRB16_post:

2950 case ARM::MVE_VSTRB32_post:

2951 case ARM::MVE_VSTRH32_post:

2952 case ARM::MVE_VSTRBU8_post:

2953 case ARM::MVE_VSTRHU16_post:

2954 case ARM::MVE_VSTRWU32_post:

2955 return true;

2956 }

2957 return false;

2958}

2959

2961 switch (MI.getOpcode()) {

2962 case ARM::MVE_VLDRBS16_pre:

2963 case ARM::MVE_VLDRBS32_pre:

2964 case ARM::MVE_VLDRBU16_pre:

2965 case ARM::MVE_VLDRBU32_pre:

2966 case ARM::MVE_VLDRHS32_pre:

2967 case ARM::MVE_VLDRHU32_pre:

2968 case ARM::MVE_VLDRBU8_pre:

2969 case ARM::MVE_VLDRHU16_pre:

2970 case ARM::MVE_VLDRWU32_pre:

2971 case ARM::MVE_VSTRB16_pre:

2972 case ARM::MVE_VSTRB32_pre:

2973 case ARM::MVE_VSTRH32_pre:

2974 case ARM::MVE_VSTRBU8_pre:

2975 case ARM::MVE_VSTRHU16_pre:

2976 case ARM::MVE_VSTRWU32_pre:

2977 return true;

2978 }

2979 return false;

2980}

2981

2982

2983

2984

2985

2986

2989 int &CodesizeEstimate) {

2991 return true;

2992

2993

2998 CodesizeEstimate += 1;

2999 return Imm < 0 && -Imm < ((1 << 8) * 1);

3000 }

3001 return false;

3002}

3003

3004

3005

3006

3010

3012 MI->getOperand(BaseOp).setReg(NewBaseReg);

3013

3018 MRI.constrainRegClass(NewBaseReg, TRC);

3019

3020 int OldOffset = MI->getOperand(BaseOp + 1).getImm();

3022 MI->getOperand(BaseOp + 1).setImm(OldOffset - Offset);

3023 else {

3024 unsigned ConvOpcode;

3025 switch (MI->getOpcode()) {

3026 case ARM::t2LDRHi12:

3027 ConvOpcode = ARM::t2LDRHi8;

3028 break;

3029 case ARM::t2LDRSHi12:

3030 ConvOpcode = ARM::t2LDRSHi8;

3031 break;

3032 case ARM::t2LDRBi12:

3033 ConvOpcode = ARM::t2LDRBi8;

3034 break;

3035 case ARM::t2LDRSBi12:

3036 ConvOpcode = ARM::t2LDRSBi8;

3037 break;

3038 case ARM::t2STRHi12:

3039 ConvOpcode = ARM::t2STRHi8;

3040 break;

3041 case ARM::t2STRBi12:

3042 ConvOpcode = ARM::t2STRBi8;

3043 break;

3044 default:

3046 }

3048 "Illegal Address Immediate after convert!");

3049

3052 .add(MI->getOperand(0))

3053 .add(MI->getOperand(1))

3055 .add(MI->getOperand(3))

3056 .add(MI->getOperand(4))

3058 MI->eraseFromParent();

3059 }

3060}

3061

3068

3071

3073

3075 MRI.constrainRegClass(NewReg, TRC);

3076

3077 TRC = TII->getRegClass(MCID, 2);

3078 MRI.constrainRegClass(MI->getOperand(1).getReg(), TRC);

3079

3085

3088 .add(MI->getOperand(0))

3089 .add(MI->getOperand(1))

3091 .add(MI->getOperand(3))

3092 .add(MI->getOperand(4))

3093 .add(MI->getOperand(5))

3096 if (MI->mayLoad()) {

3098 .add(MI->getOperand(0))

3100 .add(MI->getOperand(1))

3102 .add(MI->getOperand(3))

3103 .add(MI->getOperand(4))

3105 } else {

3108 .add(MI->getOperand(0))

3109 .add(MI->getOperand(1))

3111 .add(MI->getOperand(3))

3112 .add(MI->getOperand(4))

3114 }

3115 default:

3117 }

3118}

3119

3120

3121

3122

3123

3124

3125

3126

3127

3128

3129

3130

3131

3132

3133

3134

3135

3136bool ARMPreAllocLoadStoreOpt::DistributeIncrements(Register Base) {

3137

3138

3139 MachineInstr *BaseAccess = nullptr;

3140 MachineInstr *PrePostInc = nullptr;

3141

3142 MachineInstr *Increment = nullptr;

3143

3144

3145 SmallPtrSet<MachineInstr *, 8> OtherAccesses;

3146 for (auto &Use : MRI->use_nodbg_instructions(Base)) {

3149 continue;

3150 }

3151

3153 if (BaseOp == -1)

3154 return false;

3155

3156 if (Use.getOperand(BaseOp).isReg() ||

3157 Use.getOperand(BaseOp).getReg() != Base)

3158 return false;

3160 PrePostInc = &Use;

3161 else if (Use.getOperand(BaseOp + 1).getImm() == 0)

3162 BaseAccess = &Use;

3163 else

3164 OtherAccesses.insert(&Use);

3165 }

3166

3167 int IncrementOffset;

3171 return false;

3173 if (Increment->definesRegister(ARM::CPSR, nullptr) ||

3175 return false;

3176

3177 LLVM_DEBUG(dbgs() << "\nAttempting to distribute increments on VirtualReg "

3178 << Base.virtRegIndex() << "\n");

3179

3180

3181

3182 for (MachineInstr &Use :

3183 MRI->use_nodbg_instructions(Increment->getOperand(0).getReg())) {

3184 if (&Use == BaseAccess || (Use.getOpcode() != TargetOpcode::PHI &&

3185 !DT->dominates(BaseAccess, &Use))) {

3186 LLVM_DEBUG(dbgs() << " BaseAccess doesn't dominate use of increment\n");

3187 return false;

3188 }

3189 }

3190

3191

3196 LLVM_DEBUG(dbgs() << " Illegal addressing mode immediate on postinc\n");

3197 return false;

3198 }

3199 }

3200 else if (PrePostInc) {

3201

3202

3203

3204

3206 return false;

3207

3208 LLVM_DEBUG(dbgs() << "\nAttempting to distribute increments on already "

3209 << "indexed VirtualReg " << Base.virtRegIndex() << "\n");

3211 IncrementOffset = PrePostInc->getOperand(BaseOp+1).getImm();

3212 BaseAccess = PrePostInc;

3214 }

3215 else

3216 return false;

3217

3218

3219

3220

3221

3222

3223

3224

3225

3226 SmallPtrSet<MachineInstr *, 4> SuccessorAccesses;

3227 int CodesizeEstimate = -1;

3228 for (auto *Use : OtherAccesses) {

3229 if (DT->dominates(BaseAccess, Use)) {

3230 SuccessorAccesses.insert(Use);

3233 Use->getOperand(BaseOp + 1).getImm() -

3234 IncrementOffset,

3235 TII, CodesizeEstimate)) {

3236 LLVM_DEBUG(dbgs() << " Illegal addressing mode immediate on use\n");

3237 return false;

3238 }

3239 } else if (!DT->dominates(Use, BaseAccess)) {

3241 dbgs() << " Unknown dominance relation between Base and Use\n");

3242 return false;

3243 }

3244 }

3245 if (STI->hasMinSize() && CodesizeEstimate > 0) {

3246 LLVM_DEBUG(dbgs() << " Expected to grow instructions under minsize\n");

3247 return false;

3248 }

3249

3250 if (!PrePostInc) {

3251

3254 NewBaseReg = Increment->getOperand(0).getReg();

3255 MachineInstr *BaseAccessPost =

3259 (void)BaseAccessPost;

3261 }

3262

3263 for (auto *Use : SuccessorAccesses) {

3267 }

3268

3269

3270

3271 for (MachineOperand &Op : MRI->use_nodbg_operands(NewBaseReg))

3272 Op.setIsKill(false);

3273 return true;

3274}

3275

3276bool ARMPreAllocLoadStoreOpt::DistributeIncrements() {

3278 SmallSetVector<Register, 4> Visited;

3279 for (auto &MBB : *MF) {

3280 for (auto &MI : MBB) {

3282 if (BaseOp == -1 || MI.getOperand(BaseOp).isReg())

3283 continue;

3284

3286 if (Base.isVirtual())

3287 continue;

3288

3290 }

3291 }

3292

3293 for (auto Base : Visited)

3295

3297}

3298

3299

3301 if (PreAlloc)

3302 return new ARMPreAllocLoadStoreOpt();

3303 return new ARMLoadStoreOpt();

3304}

unsigned const MachineRegisterInfo * MRI

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

const TargetInstrInfo & TII

static bool isLoadSingle(unsigned Opc)

Definition ARMLoadStoreOptimizer.cpp:416

static int getMemoryOpOffset(const MachineInstr &MI)

Definition ARMLoadStoreOptimizer.cpp:217

static unsigned getPostIndexedLoadStoreOpcode(unsigned Opc, ARM_AM::AddrOpc Mode)

Definition ARMLoadStoreOptimizer.cpp:1389

static bool IsSafeAndProfitableToMove(bool isLd, unsigned Base, MachineBasicBlock::iterator I, MachineBasicBlock::iterator E, SmallPtrSetImpl< MachineInstr * > &MemOps, SmallSet< unsigned, 4 > &MemRegs, const TargetRegisterInfo *TRI, AliasAnalysis *AA)

Definition ARMLoadStoreOptimizer.cpp:2215

static bool ContainsReg(ArrayRef< std::pair< unsigned, bool > > Regs, unsigned Reg)

Definition ARMLoadStoreOptimizer.cpp:614

static bool isPreIndex(MachineInstr &MI)

Definition ARMLoadStoreOptimizer.cpp:2960

static void forEachDbgRegOperand(MachineInstr *MI, std::function< void(MachineOperand &)> Fn)

Definition ARMLoadStoreOptimizer.cpp:2491

static bool isPostIndex(MachineInstr &MI)

Definition ARMLoadStoreOptimizer.cpp:2938

static int getLoadStoreMultipleOpcode(unsigned Opcode, ARM_AM::AMSubMode Mode)

Definition ARMLoadStoreOptimizer.cpp:253

static unsigned getLSMultipleTransferSize(const MachineInstr *MI)

Definition ARMLoadStoreOptimizer.cpp:437

static ARM_AM::AMSubMode getLoadStoreMultipleSubMode(unsigned Opcode)

Definition ARMLoadStoreOptimizer.cpp:338

static bool isT1i32Load(unsigned Opc)

Definition ARMLoadStoreOptimizer.cpp:392

static void AdjustBaseAndOffset(MachineInstr *MI, Register NewBaseReg, int Offset, const TargetInstrInfo *TII, const TargetRegisterInfo *TRI)

Definition ARMLoadStoreOptimizer.cpp:3007

static unsigned getPreIndexedLoadStoreOpcode(unsigned Opc, ARM_AM::AddrOpc Mode)

Definition ARMLoadStoreOptimizer.cpp:1364

static MachineInstr * createPostIncLoadStore(MachineInstr *MI, int Offset, Register NewReg, const TargetInstrInfo *TII, const TargetRegisterInfo *TRI)

Definition ARMLoadStoreOptimizer.cpp:3062

static bool isi32Store(unsigned Opc)

Definition ARMLoadStoreOptimizer.cpp:412

static MachineBasicBlock::iterator findIncDecAfter(MachineBasicBlock::iterator MBBI, Register Reg, ARMCC::CondCodes Pred, Register PredReg, int &Offset, const TargetRegisterInfo *TRI)

Searches for a increment or decrement of Reg after MBBI.

Definition ARMLoadStoreOptimizer.cpp:1240

static MachineBasicBlock::iterator findIncDecBefore(MachineBasicBlock::iterator MBBI, Register Reg, ARMCC::CondCodes Pred, Register PredReg, int &Offset)

Searches for an increment or decrement of Reg before MBBI.

Definition ARMLoadStoreOptimizer.cpp:1220

static const MachineOperand & getLoadStoreBaseOp(const MachineInstr &MI)

Definition ARMLoadStoreOptimizer.cpp:245

static void updateRegisterMapForDbgValueListAfterMove(SmallDenseMap< Register, SmallVector< MachineInstr * >, 8 > &RegisterMap, MachineInstr *DbgValueListInstr, MachineInstr *InstrToReplace)

Definition ARMLoadStoreOptimizer.cpp:2508

arm prera ldst static false cl::opt< unsigned > InstReorderLimit("arm-prera-ldst-opt-reorder-limit", cl::init(8), cl::Hidden)

static void InsertLDR_STR(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, int Offset, bool isDef, unsigned NewOpc, unsigned Reg, bool RegDeadKill, bool RegUndef, unsigned BaseReg, bool BaseKill, bool BaseUndef, ARMCC::CondCodes Pred, unsigned PredReg, const TargetInstrInfo *TII, MachineInstr *MI)

Definition ARMLoadStoreOptimizer.cpp:1730

static int isIncrementOrDecrement(const MachineInstr &MI, Register Reg, ARMCC::CondCodes Pred, Register PredReg)

Check if the given instruction increments or decrements a register and return the amount it is increm...

Definition ARMLoadStoreOptimizer.cpp:1188

static bool isT2i32Store(unsigned Opc)

Definition ARMLoadStoreOptimizer.cpp:408

static bool isLegalOrConvertableAddressImm(unsigned Opcode, int Imm, const TargetInstrInfo *TII, int &CodesizeEstimate)

Definition ARMLoadStoreOptimizer.cpp:2987

static bool mayCombineMisaligned(const TargetSubtargetInfo &STI, const MachineInstr &MI)

Return true for loads/stores that can be combined to a double/multi operation without increasing the ...

Definition ARMLoadStoreOptimizer.cpp:985

static int getBaseOperandIndex(MachineInstr &MI)

Definition ARMLoadStoreOptimizer.cpp:2873

static bool isT2i32Load(unsigned Opc)

Definition ARMLoadStoreOptimizer.cpp:396

static bool isi32Load(unsigned Opc)

Definition ARMLoadStoreOptimizer.cpp:400

static unsigned getImmScale(unsigned Opc)

Definition ARMLoadStoreOptimizer.cpp:420

static bool isT1i32Store(unsigned Opc)

Definition ARMLoadStoreOptimizer.cpp:404

#define ARM_PREALLOC_LOAD_STORE_OPT_NAME

Definition ARMLoadStoreOptimizer.cpp:2132

#define ARM_LOAD_STORE_OPT_NAME

Definition ARMLoadStoreOptimizer.cpp:95

static unsigned getUpdatingLSMultipleOpcode(unsigned Opc, ARM_AM::AMSubMode Mode)

Definition ARMLoadStoreOptimizer.cpp:1118

static bool isMemoryOp(const MachineInstr &MI)

Returns true if instruction is a memory operation that this pass is capable of operating on.

Definition ARMLoadStoreOptimizer.cpp:1675

static const MachineOperand & getLoadStoreRegOp(const MachineInstr &MI)

Definition ARMLoadStoreOptimizer.cpp:249

static bool isValidLSDoubleOffset(int Offset)

Definition ARMLoadStoreOptimizer.cpp:976

static DebugVariable createDebugVariableFromMachineInstr(MachineInstr *MI)

Definition ARMLoadStoreOptimizer.cpp:2521

static cl::opt< bool > AssumeMisalignedLoadStores("arm-assume-misaligned-load-store", cl::Hidden, cl::init(false), cl::desc("Be more conservative in ARM load/store opt"))

This switch disables formation of double/multi instructions that could potentially lead to (new) alig...

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

MachineBasicBlock MachineBasicBlock::iterator MBBI

This file defines the BumpPtrAllocator interface.

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

This file defines the DenseMap class.

This file defines the DenseSet and SmallDenseSet classes.

const size_t AbstractManglingParser< Derived, Alloc >::NumOps

const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]

Register const TargetRegisterInfo * TRI

Promote Memory to Register

static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)

#define INITIALIZE_PASS_DEPENDENCY(depName)

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

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

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

static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))

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

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)

This file describes how to lower LLVM code to machine code.

A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.

static void updateLRRestored(MachineFunction &MF)

Update the IsRestored flag on LR if it is spilled, based on the return instructions.

ARMFunctionInfo - This class is derived from MachineFunctionInfo and contains private ARM-specific in...

bool isThumb2Function() const

bool isThumbFunction() const

bool shouldSignReturnAddress() const

const ARMBaseInstrInfo * getInstrInfo() const override

const ARMTargetLowering * getTargetLowering() const override

const ARMBaseRegisterInfo * getRegisterInfo() const override

Align getDualLoadStoreAlignment() const

Represent the analysis usage information of a pass.

AnalysisUsage & addRequired()

AnalysisUsage & addPreserved()

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

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

A parsed version of the target data layout string in and methods for querying it.

Identifies a unique instance of a variable.

iterator find(const_arg_type_t< KeyT > Val)

bool erase(const KeyT &Val)

FunctionPass class - This class is used to implement most global optimizations.

A set of register units used to track register liveness.

bool available(MCRegister Reg) const

Returns true if no part of physical register Reg is live.

void init(const TargetRegisterInfo &TRI)

Initialize and clear the set.

void addReg(MCRegister Reg)

Adds register units covered by physical register Reg.

LLVM_ABI void stepBackward(const MachineInstr &MI)

Updates liveness when stepping backwards over the instruction MI.

LLVM_ABI void addLiveOuts(const MachineBasicBlock &MBB)

Adds registers living out of block MBB.

Describe properties that are true of each instruction in the target description file.

unsigned getNumOperands() const

Return the number of declared MachineOperands for this MachineInstruction.

const MCInstrDesc & get(unsigned Opcode) const

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

MachineInstrBundleIterator< const MachineInstr > const_iterator

LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)

Insert MI into the instruction list before I, possibly inside a bundle.

LLVM_ABI LivenessQueryResult computeRegisterLiveness(const TargetRegisterInfo *TRI, MCRegister Reg, const_iterator Before, unsigned Neighborhood=10) const

Return whether (physical) register Reg has been defined and not killed as of just before Before.

LLVM_ABI iterator getFirstTerminator()

Returns an iterator to the first terminator instruction of this basic block.

LLVM_ABI iterator getLastNonDebugInstr(bool SkipPseudoOp=true)

Returns an iterator to the last non-debug instruction in the basic block, or end().

const MachineFunction * getParent() const

Return the MachineFunction containing this basic block.

LLVM_ABI instr_iterator erase(instr_iterator I)

Remove an instruction from the instruction list and delete it.

void splice(iterator Where, MachineBasicBlock *Other, iterator From)

Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...

MachineInstrBundleIterator< MachineInstr > iterator

@ LQR_Dead

Register is known to be fully dead.

Analysis pass which computes a MachineDominatorTree.

DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...

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.

Properties which a MachineFunction may have at a given point in time.

const TargetSubtargetInfo & getSubtarget() const

getSubtarget - Return the subtarget for which this machine code is being compiled.

MachineRegisterInfo & getRegInfo()

getRegInfo - Return information about the registers currently in use.

Function & getFunction()

Return the LLVM function that this machine code represents.

Ty * getInfo()

getInfo - Keep track of various per-function pieces of information for backends that would like to do...

const MachineInstrBuilder & cloneMergedMemRefs(ArrayRef< const MachineInstr * > OtherMIs) const

const MachineInstrBuilder & setMemRefs(ArrayRef< MachineMemOperand * > MMOs) const

const MachineInstrBuilder & addImm(int64_t Val) const

Add a new immediate operand.

const MachineInstrBuilder & add(const MachineOperand &MO) const

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

Add a new virtual register operand.

const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const

const MachineInstrBuilder & copyImplicitOps(const MachineInstr &OtherMI) const

Copy all the implicit operands from OtherMI onto this one.

MachineInstr * getInstr() const

If conversion operators fail, use this method to get the MachineInstr explicitly.

Representation of each machine instruction.

unsigned getOpcode() const

Returns the opcode of this MachineInstr.

const MachineBasicBlock * getParent() const

unsigned getNumOperands() const

Retuns the total number of operands.

LLVM_ABI void copyImplicitOps(MachineFunction &MF, const MachineInstr &MI)

Copy implicit register operands from specified instruction to this instruction.

bool killsRegister(Register Reg, const TargetRegisterInfo *TRI) const

Return true if the MachineInstr kills the specified register.

LLVM_ABI void setDesc(const MCInstrDesc &TID)

Replace the instruction descriptor (thus opcode) of the current instruction with a new one.

bool hasOneMemOperand() const

Return true if this instruction has exactly one MachineMemOperand.

mmo_iterator memoperands_begin() const

Access to memory operands of the instruction.

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.

LLVM_ABI void dump() const

const MachineOperand & getOperand(unsigned i) const

A description of a memory reference used in the backend.

bool isAtomic() const

Returns true if this operation has an atomic ordering requirement of unordered or higher,...

LLVM_ABI Align getAlign() const

Return the minimum known alignment in bytes of the actual memory reference.

MachineOperand class - Representation of each machine instruction operand.

void setImm(int64_t immVal)

bool readsReg() const

readsReg - Returns true if this operand reads the previous value of its register.

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.

void setIsKill(bool Val=true)

void setIsUndef(bool Val=true)

Register getReg() const

getReg - Returns the register number.

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

bool isReserved(MCRegister PhysReg) const

isReserved - Returns true when PhysReg is a reserved register.

LLVM_ABI void runOnMachineFunction(const MachineFunction &MF, bool Rev=false)

runOnFunction - Prepare to answer questions about MF.

ArrayRef< MCPhysReg > getOrder(const TargetRegisterClass *RC) const

getOrder - Returns the preferred allocation order for RC.

Wrapper class representing virtual and physical registers.

bool insert(const value_type &X)

Insert a new element into the SetVector.

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

size_type count(ConstPtrType Ptr) const

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

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

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

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.

A BumpPtrAllocator that allows only elements of a specific type to be allocated.

StringRef - Represent a constant reference to a string, i.e.

Align getTransientStackAlign() const

getTransientStackAlignment - This method returns the number of bytes to which the stack pointer must ...

TargetInstrInfo - Interface to description of machine instruction set.

virtual const TargetRegisterClass * getRegClass(const MCInstrDesc &MCID, unsigned OpNum) const

Given a machine instruction descriptor, returns the register class constraint for OpNum,...

virtual bool isLegalAddImmediate(int64_t) const

Return true if the specified immediate is legal add immediate, that is the target has add instruction...

This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...

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

TargetSubtargetInfo - Generic base class for all target subtargets.

virtual const TargetFrameLowering * getFrameLowering() const

LLVM Value Representation.

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.

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

#define llvm_unreachable(msg)

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

Abstract Attribute helper functions.

constexpr char Align[]

Key for Kernel::Arg::Metadata::mAlign.

unsigned char getAM3Offset(unsigned AM3Opc)

unsigned getAM2Opc(AddrOpc Opc, unsigned Imm12, ShiftOpc SO, unsigned IdxMode=0)

AddrOpc getAM5Op(unsigned AM5Opc)

unsigned getAM3Opc(AddrOpc Opc, unsigned char Offset, unsigned IdxMode=0)

getAM3Opc - This function encodes the addrmode3 opc field.

unsigned char getAM5Offset(unsigned AM5Opc)

AddrOpc getAM3Op(unsigned AM3Opc)

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

@ C

The default llvm calling convention, compatible with C.

@ Define

Register definition.

@ Kill

The last use of a register.

@ CE

Windows NT (Windows on ARM)

This namespace contains all of the command line option processing machinery.

initializer< Ty > init(const Ty &Val)

NodeAddr< InstrNode * > Instr

NodeAddr< UseNode * > Use

BaseReg

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

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.

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

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

static bool isARMLowRegister(MCRegister Reg)

isARMLowRegister - Returns true if the register is a low register (r0-r7).

APFloat abs(APFloat X)

Returns the absolute value of the argument.

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

Convenience function for iterating over sub-ranges.

bool isLegalAddressImm(unsigned Opcode, int Imm, const TargetInstrInfo *TII)

unsigned getDeadRegState(bool B)

static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)

Get the operands corresponding to the given Pred value.

FunctionPass * createARMLoadStoreOptimizationPass(bool PreAlloc=false)

Returns an instance of the load / store optimization pass.

Definition ARMLoadStoreOptimizer.cpp:3300

unsigned M1(unsigned Val)

auto reverse(ContainerTy &&C)

void sort(IteratorTy Start, IteratorTy End)

LLVM_ABI raw_ostream & dbgs()

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

FunctionAddr VTableAddr Count

class LLVM_GSL_OWNER SmallVector

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

@ First

Helpers to iterate all locations in the MemoryEffectsBase class.

unsigned getUndefRegState(bool B)

unsigned getDefRegState(bool B)

void replace(R &&Range, const T &OldValue, const T &NewValue)

Provide wrappers to std::replace which take ranges instead of having to pass begin/end explicitly.

unsigned getKillRegState(bool B)

ARMCC::CondCodes getInstrPredicate(const MachineInstr &MI, Register &PredReg)

getInstrPredicate - If instruction is predicated, returns its predicate condition,...

DWARFExpression::Operation Op

unsigned M0(unsigned Val)

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

static MachineOperand t1CondCodeOp(bool isDead=false)

Get the operand corresponding to the conditional code result for Thumb1.

void erase_if(Container &C, UnaryPredicate P)

Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...

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

Returns true if Element is found in Range.

static MachineOperand condCodeOp(unsigned CCReg=0)

Get the operand corresponding to the conditional code result.

@ Increment

Incrementally increasing token ID.

int getAddSubImmediate(MachineInstr &MI)

AAResults AliasAnalysis

Temporary typedef for legacy code that uses a generic AliasAnalysis pointer or reference.

This struct is a compact representation of a valid (non-zero power of two) alignment.