LLVM: lib/Target/Hexagon/HexagonOptAddrMode.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

39#include

40#include

41

42#define DEBUG_TYPE "opt-addr-mode"

43

44using namespace llvm;

45using namespace rdf;

46

49 "optimization"));

50

52

53namespace {

54

56public:

57 static char ID;

58

60

61 StringRef getPassName() const override {

62 return "Optimize addressing mode of load/store";

63 }

64

65 void getAnalysisUsage(AnalysisUsage &AU) const override {

67 AU.addRequired();

68 AU.addRequired();

70 }

71

72 bool runOnMachineFunction(MachineFunction &MF) override;

73

74private:

75 using MISetType = DenseSet<MachineInstr *>;

76 using InstrEvalMap = DenseMap<MachineInstr *, bool>;

77 DenseSet<MachineInstr *> ProcessedAddiInsts;

78

79 MachineRegisterInfo *MRI = nullptr;

80 const TargetRegisterInfo *TRI = nullptr;

81 const HexagonInstrInfo *HII = nullptr;

82 const HexagonRegisterInfo *HRI = nullptr;

83 MachineDominatorTree *MDT = nullptr;

84 DataFlowGraph *DFG = nullptr;

86 Liveness *LV = nullptr;

87 MISetType Deleted;

88

89 bool processBlock(NodeAddr<BlockNode *> BA);

90 bool xformUseMI(MachineInstr *TfrMI, MachineInstr *UseMI,

91 NodeAddr<UseNode *> UseN, unsigned UseMOnum);

92 bool processAddBases(NodeAddr<StmtNode *> AddSN, MachineInstr *AddMI);

93 bool usedInLoadStore(NodeAddr<StmtNode *> CurrentInstSN, int64_t NewOffset);

94 bool findFirstReachedInst(

95 MachineInstr *AddMI,

96 std::vector<std::pair<NodeAddr<StmtNode *>, NodeAddr<UseNode *>>>

97 &AddiList,

98 NodeAddr<StmtNode *> &UseSN);

99 bool updateAddBases(MachineInstr *CurrentMI, MachineInstr *FirstReachedMI,

100 int64_t NewOffset);

101 bool processAddUses(NodeAddr<StmtNode *> AddSN, MachineInstr *AddMI,

103 bool updateAddUses(MachineInstr *AddMI, MachineInstr *UseMI);

104 bool analyzeUses(unsigned DefR, const NodeList &UNodeList,

105 InstrEvalMap &InstrEvalResult, short &SizeInc);

106 bool hasRepForm(MachineInstr &MI, unsigned TfrDefR);

107 bool canRemoveAddasl(NodeAddr<StmtNode *> AddAslSN, MachineInstr &MI,

109 bool isSafeToExtLR(NodeAddr<StmtNode *> SN, MachineInstr *MI,

111 void getAllRealUses(NodeAddr<StmtNode *> SN, NodeList &UNodeList);

112 bool allValidCandidates(NodeAddr<StmtNode *> SA, NodeList &UNodeList);

113 short getBaseWithLongOffset(const MachineInstr &MI) const;

114 bool changeStore(MachineInstr *OldMI, MachineOperand ImmOp,

115 unsigned ImmOpNum);

116 bool changeLoad(MachineInstr *OldMI, MachineOperand ImmOp, unsigned ImmOpNum);

117 bool changeAddAsl(NodeAddr<UseNode *> AddAslUN, MachineInstr *AddAslMI,

118 const MachineOperand &ImmOp, unsigned ImmOpNum);

119 bool isValidOffset(MachineInstr *MI, int Offset);

120 unsigned getBaseOpPosition(MachineInstr *MI);

121 unsigned getOffsetOpPosition(MachineInstr *MI);

122};

123

124}

125

126char HexagonOptAddrMode::ID = 0;

127

129 "Optimize addressing mode", false, false)

134

135bool HexagonOptAddrMode::hasRepForm(MachineInstr &MI, unsigned TfrDefR) {

137

138 if ((!MID.mayStore() && !MID.mayLoad()) || HII->isPredicated(MI))

139 return false;

140

142 MachineOperand StOp = MI.getOperand(MI.getNumOperands() - 1);

143 if (StOp.isReg() && StOp.getReg() == TfrDefR)

144 return false;

145 }

146

148

149 return (HII->changeAddrMode_rr_ur(MI) >= 0);

151

152 return (HII->changeAddrMode_io_abs(MI) >= 0);

153

154 return false;

155}

156

157

158

159

160

161

162

163

164

165

166

170

171 const MachineOperand &OffsetOp = MI.getOperand(3);

173 return false;

174

175 Register OffsetReg = MI.getOperand(2).getReg();

176 RegisterRef OffsetRR;

177 NodeId OffsetRegRD = 0;

178 for (NodeAddr<UseNode *> UA : AddAslSN.Addr->members_if(DFG->IsUse, *DFG)) {

179 RegisterRef RR = UA.Addr->getRegRef(*DFG);

180 if (OffsetReg == RR.asMCReg()) {

181 OffsetRR = RR;

182 OffsetRegRD = UA.Addr->getReachingDef();

183 }

184 }

185

186 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {

187 NodeAddr<UseNode *> UA = *I;

188 NodeAddr<InstrNode *> IA = UA.Addr->getOwner(*DFG);

190 return false;

192 if ((DFG->IsDef(AA) && AA.Id != OffsetRegRD) ||

193 AA.Addr->getReachingDef() != OffsetRegRD)

194 return false;

195

196 MachineInstr &UseMI = *NodeAddr<StmtNode *>(IA).Addr->getCode();

197 NodeAddr<DefNode *> OffsetRegDN = DFG->addr<DefNode *>(OffsetRegRD);

198

200 MI.getParent() != UseMI.getParent())

201 return false;

202

203 const MCInstrDesc &UseMID = UseMI.getDesc();

206 getBaseWithLongOffset(UseMI) < 0)

207 return false;

208

209

210 if (UseMID.mayStore() && UseMI.getOperand(2).isReg() &&

211 UseMI.getOperand(2).getReg() == MI.getOperand(0).getReg())

212 return false;

213

214 for (auto &Mo : UseMI.operands())

215

216 if (Mo.isFI())

217 return false;

218

219 if (UseMI.getParent()->isLiveIn(OffsetReg) &&

220 MI.getParent() != UseMI.getParent()) {

222 << " is NOT live in to MBB "

223 << UseMI.getParent()->getName() << "\n");

224 return false;

225 }

226 }

227 return true;

228}

229

230bool HexagonOptAddrMode::allValidCandidates(NodeAddr<StmtNode *> SA,

232 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {

233 NodeAddr<UseNode *> UN = *I;

234 RegisterRef UR = UN.Addr->getRegRef(*DFG);

237 if (P.second) {

239 dbgs() << "*** Unable to collect all reaching defs for use ***\n"

240 << PrintNode<UseNode*>(UN, *DFG) << '\n'

241 << "The program's complexity may exceed the limits.\n";

242 });

243 return false;

244 }

245 const auto &ReachingDefs = P.first;

246 if (ReachingDefs.size() > 1) {

248 dbgs() << "*** Multiple Reaching Defs found!!! ***\n";

249 for (auto DI : ReachingDefs) {

250 NodeAddr<UseNode *> DA = DFG->addr<UseNode *>(DI);

251 NodeAddr<StmtNode *> TempIA = DA.Addr->getOwner(*DFG);

252 dbgs() << "\t\t[Reaching Def]: "

254 }

255 });

256 return false;

257 }

258 }

259 return true;

260}

261

262void HexagonOptAddrMode::getAllRealUses(NodeAddr<StmtNode *> SA,

264 for (NodeAddr<DefNode *> DA : SA.Addr->members_if(DFG->IsDef, *DFG)) {

266 << Print<NodeAddr<DefNode *>>(DA, *DFG) << "\n");

267 RegisterRef DR = DA.Addr->getRegRef(*DFG);

268

270

271 for (auto UI : UseSet) {

272 NodeAddr<UseNode *> UA = DFG->addr<UseNode *>(UI);

274 NodeAddr<StmtNode *> TempIA = UA.Addr->getOwner(*DFG);

275 dbgs() << "\t\t\t[Reached Use]: "

277 });

278

280 NodeAddr<PhiNode *> PA = UA.Addr->getOwner(*DFG);

285 if (!phiUse.empty()) {

286 for (auto I : phiUse) {

287 if (!DFG->getPRI().alias(RegisterRef(I.first), DR))

288 continue;

289 auto phiUseSet = I.second;

290 for (auto phiUI : phiUseSet) {

291 NodeAddr<UseNode *> phiUA = DFG->addr<UseNode *>(phiUI.first);

292 UNodeList.push_back(phiUA);

293 }

294 }

295 }

296 } else

297 UNodeList.push_back(UA);

298 }

299 }

300}

301

302bool HexagonOptAddrMode::isSafeToExtLR(NodeAddr<StmtNode *> SN,

305 RegisterRef LRExtRR;

306 NodeId LRExtRegRD = 0;

307

308

309 for (NodeAddr<UseNode *> UA : SN.Addr->members_if(DFG->IsUse, *DFG)) {

310 RegisterRef RR = UA.Addr->getRegRef(*DFG);

311 if (LRExtReg == RR.asMCReg()) {

312 LRExtRR = RR;

313 LRExtRegRD = UA.Addr->getReachingDef();

314 }

315 }

316

317 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {

318 NodeAddr<UseNode *> UA = *I;

319 NodeAddr<InstrNode *> IA = UA.Addr->getOwner(*DFG);

320

321

323 return false;

325 if ((DFG->IsDef(AA) && AA.Id != LRExtRegRD) ||

326 AA.Addr->getReachingDef() != LRExtRegRD) {

328 dbgs() << "isSafeToExtLR: Returning false; another reaching def\n");

329 return false;

330 }

331

332

333

334

335 if (LRExtRegRD == 0)

336 return false;

337

338 MachineInstr *UseMI = NodeAddr<StmtNode *>(IA).Addr->getCode();

339 NodeAddr<DefNode *> LRExtRegDN = DFG->addr<DefNode *>(LRExtRegRD);

340

343 return false;

344

348 << " is NOT live in to MBB "

350 return false;

351 }

352 }

353 return true;

354}

355

356bool HexagonOptAddrMode::isValidOffset(MachineInstr *MI, int Offset) {

358

359

360 switch (MI->getOpcode()) {

361 case Hexagon::V6_vgathermh_pseudo:

362 case Hexagon::V6_vgathermw_pseudo:

363 case Hexagon::V6_vgathermhw_pseudo:

364 case Hexagon::V6_vgathermhq_pseudo:

365 case Hexagon::V6_vgathermwq_pseudo:

366 case Hexagon::V6_vgathermhwq_pseudo:

368 default:

370

372 if ((AlignMask & Offset) == 0)

374 }

375 return false;

376 }

377 }

378

380 return false;

381

382 unsigned AlignMask = 0;

384 case HexagonII::MemAccessSize::DoubleWordAccess:

385 AlignMask = 0x7;

386 break;

387 case HexagonII::MemAccessSize::WordAccess:

388 AlignMask = 0x3;

389 break;

390 case HexagonII::MemAccessSize::HalfWordAccess:

391 AlignMask = 0x1;

392 break;

393 case HexagonII::MemAccessSize::ByteAccess:

394 AlignMask = 0x0;

395 break;

396 default:

397 return false;

398 }

399

400 if ((AlignMask & Offset) != 0)

401 return false;

403}

404

405unsigned HexagonOptAddrMode::getBaseOpPosition(MachineInstr *MI) {

406 const MCInstrDesc &MID = MI->getDesc();

407 switch (MI->getOpcode()) {

408

409

410

411 case Hexagon::V6_vgathermh_pseudo:

412 case Hexagon::V6_vgathermw_pseudo:

413 case Hexagon::V6_vgathermhw_pseudo:

414 case Hexagon::V6_vgathermhq_pseudo:

415 case Hexagon::V6_vgathermwq_pseudo:

416 case Hexagon::V6_vgathermhwq_pseudo:

417 return 0;

418 default:

419 return MID.mayLoad() ? 1 : 0;

420 }

421}

422

423unsigned HexagonOptAddrMode::getOffsetOpPosition(MachineInstr *MI) {

426 "Looking for an offset in non-BaseImmOffset addressing mode instruction");

427

428 const MCInstrDesc &MID = MI->getDesc();

429 switch (MI->getOpcode()) {

430

431

432

433 case Hexagon::V6_vgathermh_pseudo:

434 case Hexagon::V6_vgathermw_pseudo:

435 case Hexagon::V6_vgathermhw_pseudo:

436 case Hexagon::V6_vgathermhq_pseudo:

437 case Hexagon::V6_vgathermwq_pseudo:

438 case Hexagon::V6_vgathermhwq_pseudo:

439 return 1;

440 default:

441 return MID.mayLoad() ? 2 : 1;

442 }

443}

444

445bool HexagonOptAddrMode::usedInLoadStore(NodeAddr<StmtNode *> CurrentInstSN,

446 int64_t NewOffset) {

448

449 getAllRealUses(CurrentInstSN, LoadStoreUseList);

450 bool FoundLoadStoreUse = false;

451 for (NodeAddr<UseNode *> UN : LoadStoreUseList) {

452 NodeAddr<StmtNode *> SN = UN.Addr->getOwner(*DFG);

453 MachineInstr *LoadStoreMI = SN.Addr->getCode();

454 const MCInstrDesc &MID = LoadStoreMI->getDesc();

456 isValidOffset(LoadStoreMI, NewOffset)) {

457 FoundLoadStoreUse = true;

458 break;

459 }

460 }

461 return FoundLoadStoreUse;

462}

463

464bool HexagonOptAddrMode::findFirstReachedInst(

465 MachineInstr *AddMI,

466 std::vector<std::pair<NodeAddr<StmtNode *>, NodeAddr<UseNode *>>> &AddiList,

467 NodeAddr<StmtNode *> &UseSN) {

468

469

470

471

472

473

474

475

476

477

478

479

480 MachineBasicBlock *CurrentMBB = AddMI->getParent();

481 for (auto &InstIter : *CurrentMBB) {

482

483 if (InstIter.getOpcode() == Hexagon::A2_addi) {

484 auto Iter = llvm::find_if(AddiList, [&InstIter](const auto &SUPair) {

485 return SUPair.first.Addr->getCode() == &InstIter;

486 });

487 if (Iter != AddiList.end()) {

488 UseSN = Iter->first;

489 return true;

490 }

491 }

492 }

493 return false;

494}

495

496

497

498

499

500

501

502

503

504

505

506

507

508

509

510

511

512

513

514

515

516

517

518

519

520

521bool HexagonOptAddrMode::processAddBases(NodeAddr<StmtNode *> AddSN,

522 MachineInstr *AddMI) {

523

525

526 LLVM_DEBUG(dbgs() << "\n\t\t[Processing Addi]: " << *AddMI << "\n");

527

528 auto Processed =

529 [](const MachineInstr *MI,

530 const DenseSet<MachineInstr *> &ProcessedAddiInsts) -> bool {

531

532 if (ProcessedAddiInsts.contains(MI)) {

533 LLVM_DEBUG(dbgs() << "\t\t\tAddi already found in ProcessedAddiInsts: "

534 << *MI << "\n\t\t\tSkipping...");

535 return true;

536 }

537 return false;

538 };

539

540 if (Processed(AddMI, ProcessedAddiInsts))

542 ProcessedAddiInsts.insert(AddMI);

543

544

546

547

548

549 std::vector<std::pair<NodeAddr<StmtNode *>, NodeAddr<UseNode *>>> AddiList;

550

551 NodeId UAReachingDefID;

552

553 for (NodeAddr<UseNode *> UA : AddSN.Addr->members_if(DFG->IsUse, *DFG)) {

554 RegisterRef URR = UA.Addr->getRegRef(*DFG);

555 if (BaseReg != URR.asMCReg())

556 continue;

557

558 UAReachingDefID = UA.Addr->getReachingDef();

559 NodeAddr<DefNode *> UADef = DFG->addr<DefNode *>(UAReachingDefID);

561 LLVM_DEBUG(dbgs() << "\t\t\t Could not find reachingDef. Skipping...\n");

562 return false;

563 }

564 }

565

566 NodeAddr<DefNode *> UAReachingDef = DFG->addr<DefNode *>(UAReachingDefID);

567 NodeAddr<StmtNode *> ReachingDefStmt = UAReachingDef.Addr->getOwner(*DFG);

568

569

570

571 MachineInstr *ReachingDefInstr = ReachingDefStmt.Addr->getCode();

573 return false;

574

576

577

578

579 getAllRealUses(ReachingDefStmt, AddiUseList);

580 for (NodeAddr<UseNode *> UN : AddiUseList) {

581 NodeAddr<StmtNode *> SN = UN.Addr->getOwner(*DFG);

582 MachineInstr *MI = SN.Addr->getCode();

583

584

585 if (MI->getOpcode() == Hexagon::A2_addi &&

586 !(MI != AddMI && Processed(MI, ProcessedAddiInsts))) {

587 AddiList.push_back({SN, UN});

588

589

590 ProcessedAddiInsts.insert(MI);

591 }

592 }

593

594

595 if (AddiList.size() <= 1)

597

598 NodeAddr<StmtNode *> FirstReachedUseSN;

599

600 if (!findFirstReachedInst(AddMI, AddiList, FirstReachedUseSN))

602

603

604

605

606 NodeAddr<DefNode *> FirstReachedUseDN =

607 FirstReachedUseSN.Addr->members_if(DFG->IsDef, *DFG).front();

608

609 MachineInstr *FirstReachedMI = FirstReachedUseSN.Addr->getCode();

610 const MachineOperand FirstReachedMIImmOp = FirstReachedMI->getOperand(2);

611 if (!FirstReachedMIImmOp.isImm())

612 return false;

613

614 for (auto &I : AddiList) {

615 NodeAddr<StmtNode *> CurrentInstSN = I.first;

616 NodeAddr<UseNode *> CurrentInstUN = I.second;

617

618 MachineInstr *CurrentMI = CurrentInstSN.Addr->getCode();

619 MachineOperand &CurrentMIImmOp = CurrentMI->getOperand(2);

620

621 int64_t NewOffset;

622

623

624

625 if (!CurrentMIImmOp.isImm())

626 continue;

627

628 NewOffset = CurrentMIImmOp.getImm() - FirstReachedMIImmOp.getImm();

629

630

631 if (CurrentMI == FirstReachedMI) {

632 continue;

633 }

634

636 continue;

637

638

639

640

641

642

643

644

645 if (!usedInLoadStore(CurrentInstSN, NewOffset)) {

646 return false;

647 }

648

649

650

651 RegisterRef FirstReachedDefRR = FirstReachedUseDN.Addr->getRegRef(*DFG);

652 NodeAddr<InstrNode *> CurrentAddiIN = CurrentInstUN.Addr->getOwner(*DFG);

653 NodeAddr<RefNode *> NearestAA =

655 if ((DFG->IsDef(NearestAA) && NearestAA.Id != FirstReachedUseDN.Id) ||

656 (!DFG->IsDef(NearestAA) &&

657 NearestAA.Addr->getReachingDef() != FirstReachedUseDN.Id)) {

658

659 LLVM_DEBUG(dbgs() << "\t\t\tCould not modify below Addi since the first "

660 "defined Addi register was redefined\n");

661 continue;

662 }

663

664 MachineOperand CurrentMIBaseOp = CurrentMI->getOperand(1);

666 continue;

667 }

668

669

670

671 Changed |= updateAddBases(CurrentMI, FirstReachedMI, NewOffset);

672

673

674 CurrentInstUN.Addr->linkToDef(CurrentInstUN.Id, FirstReachedUseDN);

675 }

676

678}

679

680bool HexagonOptAddrMode::updateAddBases(MachineInstr *CurrentMI,

681 MachineInstr *FirstReachedMI,

682 int64_t NewOffset) {

683 LLVM_DEBUG(dbgs() << "[About to modify the Addi]: " << *CurrentMI << "\n");

684 const MachineOperand FirstReachedDef = FirstReachedMI->getOperand(0);

685 Register FirstDefRegister = FirstReachedDef.getReg();

686

687 MachineOperand &CurrentMIBaseOp = CurrentMI->getOperand(1);

688 MachineOperand &CurrentMIImmOp = CurrentMI->getOperand(2);

689

690 CurrentMIBaseOp.setReg(FirstDefRegister);

693 CurrentMIImmOp.setImm(NewOffset);

694 ProcessedAddiInsts.insert(CurrentMI);

695 MRI->clearKillFlags(FirstDefRegister);

696 return true;

697}

698

699bool HexagonOptAddrMode::processAddUses(NodeAddr<StmtNode *> AddSN,

700 MachineInstr *AddMI,

702

705 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {

706 NodeAddr<UseNode *> UN = *I;

707 NodeAddr<StmtNode *> SN = UN.Addr->getOwner(*DFG);

708 MachineInstr *MI = SN.Addr->getCode();

709 const MCInstrDesc &MID = MI->getDesc();

712 return false;

713

714 MachineOperand BaseOp = MI->getOperand(getBaseOpPosition(MI));

715

716 if (!BaseOp.isReg() || BaseOp.getReg() != AddDefR)

717 return false;

718

719 MachineOperand OffsetOp = MI->getOperand(getOffsetOpPosition(MI));

721 return false;

722

724 if (!isValidOffset(MI, newOffset))

725 return false;

726

727

728

729

730

731

732

733

734 if (!isSafeToExtLR(AddSN, AddMI, BaseReg, UNodeList))

735 return false;

736 }

737

738 NodeId LRExtRegRD = 0;

739

740

741 for (NodeAddr<UseNode *> UA : AddSN.Addr->members_if(DFG->IsUse, *DFG)) {

742 RegisterRef RR = UA.Addr->getRegRef(*DFG);

743 if (BaseReg == RR.asMCReg())

744 LRExtRegRD = UA.Addr->getReachingDef();

745 }

746

747

748

750 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {

751 NodeAddr<UseNode *> UseN = *I;

753 "Found a PhiRef node as a real reached use!!");

754

755 NodeAddr<StmtNode *> OwnerN = UseN.Addr->getOwner(*DFG);

756 MachineInstr *UseMI = OwnerN.Addr->getCode();

758 << ">]: " << *UseMI << "\n");

760

761

762

763

764 NodeAddr<DefNode *> LRExtRegDN = DFG->addr<DefNode *>(LRExtRegRD);

765 UseN.Addr->linkToDef(UseN.Id, LRExtRegDN);

766 }

767

770

772}

773

774bool HexagonOptAddrMode::updateAddUses(MachineInstr *AddMI,

775 MachineInstr *UseMI) {

776 const MachineOperand ImmOp = AddMI->getOperand(2);

777 const MachineOperand AddRegOp = AddMI->getOperand(1);

779

782 BaseOp.setReg(NewReg);

786 MRI->clearKillFlags(NewReg);

787

788 return true;

789}

790

791bool HexagonOptAddrMode::analyzeUses(unsigned tfrDefR,

793 InstrEvalMap &InstrEvalResult,

794 short &SizeInc) {

795 bool KeepTfr = false;

796 bool HasRepInstr = false;

797 InstrEvalResult.clear();

798

799 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {

800 bool CanBeReplaced = false;

801 NodeAddr<UseNode *> UN = *I;

802 NodeAddr<StmtNode *> SN = UN.Addr->getOwner(*DFG);

803 MachineInstr &MI = *SN.Addr->getCode();

804 const MCInstrDesc &MID = MI.getDesc();

806 if (!hasRepForm(MI, tfrDefR)) {

807 KeepTfr = true;

808 continue;

809 }

810 SizeInc++;

811 CanBeReplaced = true;

812 } else if (MI.getOpcode() == Hexagon::S2_addasl_rrri) {

814

815 LLVM_DEBUG(dbgs() << "\nGetting ReachedUses for === " << MI << "\n");

816 getAllRealUses(SN, AddaslUseList);

817

818 if (allValidCandidates(SN, AddaslUseList) &&

819 canRemoveAddasl(SN, MI, AddaslUseList)) {

820 SizeInc += AddaslUseList.size();

821 SizeInc -= 1;

822 CanBeReplaced = true;

823 } else

824 SizeInc++;

825 } else

826

827

828

829

830 KeepTfr = true;

831

832 InstrEvalResult[&MI] = CanBeReplaced;

833 HasRepInstr |= CanBeReplaced;

834 }

835

836

837 if (!KeepTfr)

838 SizeInc -= 2;

839

840 return HasRepInstr;

841}

842

843bool HexagonOptAddrMode::changeLoad(MachineInstr *OldMI, MachineOperand ImmOp,

844 unsigned ImmOpNum) {

846 MachineBasicBlock *BB = OldMI->getParent();

849 ++InsertPt;

850 unsigned OpStart;

852 MachineInstrBuilder MIB;

853

854 if (ImmOpNum == 1) {

857 assert(NewOpCode >= 0 && "Invalid New opcode\n");

858 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));

862 MIB.add(ImmOp);

863 OpStart = 4;

868 assert(NewOpCode >= 0 && "Invalid New opcode\n");

869 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode))

871 const GlobalValue *GV = ImmOp.getGlobal();

873

875 OpStart = 3;

877 } else

879

880 LLVM_DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");

882 } else if (ImmOpNum == 2) {

885 assert(NewOpCode >= 0 && "Invalid New opcode\n");

886 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));

889 MIB.add(ImmOp);

890 OpStart = 4;

892 LLVM_DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");

894 }

895 }

896

898 for (unsigned i = OpStart; i < OpEnd; ++i)

900

902}

903

904bool HexagonOptAddrMode::changeStore(MachineInstr *OldMI, MachineOperand ImmOp,

905 unsigned ImmOpNum) {

907 unsigned OpStart = 0;

909 MachineBasicBlock *BB = OldMI->getParent();

912 ++InsertPt;

913 MachineInstrBuilder MIB;

914 if (ImmOpNum == 0) {

917 assert(NewOpCode >= 0 && "Invalid New opcode\n");

918 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));

921 MIB.add(ImmOp);

923 OpStart = 4;

927 assert(NewOpCode >= 0 && "Invalid New opcode\n");

928 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));

929 const GlobalValue *GV = ImmOp.getGlobal();

933 OpStart = 3;

935 }

936 } else if (ImmOpNum == 1 && OldMI->getOperand(2).getImm() == 0) {

938 assert(NewOpCode >= 0 && "Invalid New opcode\n");

939 MIB = BuildMI(*BB, InsertPt, OldMI->getDebugLoc(), HII->get(NewOpCode));

941 MIB.add(ImmOp);

942 OpStart = 3;

944 }

946 LLVM_DEBUG(dbgs() << "[Changing]: " << *OldMI << "\n");

948

949 for (unsigned i = OpStart; i < OpEnd; ++i)

951 }

952

954}

955

956short HexagonOptAddrMode::getBaseWithLongOffset(const MachineInstr &MI) const {

960 }

962}

963

964bool HexagonOptAddrMode::changeAddAsl(NodeAddr<UseNode *> AddAslUN,

965 MachineInstr *AddAslMI,

966 const MachineOperand &ImmOp,

967 unsigned ImmOpNum) {

968 NodeAddr<StmtNode *> SA = AddAslUN.Addr->getOwner(*DFG);

969

970 LLVM_DEBUG(dbgs() << "Processing addasl :" << *AddAslMI << "\n");

971

973 getAllRealUses(SA, UNodeList);

974

975 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {

976 NodeAddr<UseNode *> UseUN = *I;

978 "Can't transform this 'AddAsl' instruction!");

979

980 NodeAddr<StmtNode *> UseIA = UseUN.Addr->getOwner(*DFG);

982 << Print<NodeAddr<InstrNode *>>(UseIA, *DFG) << "\n");

983 MachineInstr *UseMI = UseIA.Addr->getCode();

985 << ">]: " << *UseMI << "\n");

986 const MCInstrDesc &UseMID = UseMI->getDesc();

988

991 short NewOpCode = getBaseWithLongOffset(*UseMI);

992 assert(NewOpCode >= 0 && "Invalid New opcode\n");

993

994 unsigned OpStart;

996

998 MachineInstrBuilder MIB =

1000

1005 const GlobalValue *GV = ImmOp.getGlobal();

1008 OpStart = 3;

1009 } else if (UseMID.mayStore()) {

1012 const GlobalValue *GV = ImmOp.getGlobal();

1016 OpStart = 3;

1017 } else

1019

1020 for (unsigned i = OpStart; i < OpEnd; ++i)

1023 }

1024

1025 return true;

1026}

1027

1028bool HexagonOptAddrMode::xformUseMI(MachineInstr *TfrMI, MachineInstr *UseMI,

1029 NodeAddr<UseNode *> UseN,

1030 unsigned UseMOnum) {

1031 const MachineOperand ImmOp = TfrMI->getOperand(1);

1033 unsigned Changed = false;

1035 Changed = changeLoad(UseMI, ImmOp, UseMOnum);

1037 Changed = changeStore(UseMI, ImmOp, UseMOnum);

1038 else if (UseMI->getOpcode() == Hexagon::S2_addasl_rrri)

1039 Changed = changeAddAsl(UseN, UseMI, ImmOp, UseMOnum);

1040

1043

1045}

1046

1047bool HexagonOptAddrMode::processBlock(NodeAddr<BlockNode *> BA) {

1049

1050 for (auto IA : BA.Addr->members(*DFG)) {

1052 continue;

1053

1054 NodeAddr<StmtNode *> SA = IA;

1055 MachineInstr *MI = SA.Addr->getCode();

1056 if ((MI->getOpcode() != Hexagon::A2_tfrsi ||

1057 MI->getOperand(1).isGlobal()) &&

1058 (MI->getOpcode() != Hexagon::A2_addi ||

1060 continue;

1061

1062 LLVM_DEBUG(dbgs() << "[Analyzing " << HII->getName(MI->getOpcode())

1063 << "]: " << *MI << "\n\t[InstrNode]: "

1064 << Print<NodeAddr<InstrNode *>>(IA, *DFG) << '\n');

1065

1066 if (MI->getOpcode() == Hexagon::A2_addi)

1067 Changed |= processAddBases(SA, MI);

1069 getAllRealUses(SA, UNodeList);

1070

1071 if (!allValidCandidates(SA, UNodeList))

1072 continue;

1073

1074

1075

1076

1077

1078

1079

1080

1081

1082

1083

1084 if (MI->getOpcode() == Hexagon::A2_addi) {

1085 Changed |= processAddUses(SA, MI, UNodeList);

1086 continue;

1087 }

1088

1089 short SizeInc = 0;

1090 Register DefR = MI->getOperand(0).getReg();

1091 InstrEvalMap InstrEvalResult;

1092

1093

1094

1095 if (!analyzeUses(DefR, UNodeList, InstrEvalResult, SizeInc))

1096 continue;

1098 continue;

1099

1100 bool KeepTfr = false;

1101

1102 LLVM_DEBUG(dbgs() << "\t[Total reached uses] : " << UNodeList.size()

1103 << "\n");

1104 LLVM_DEBUG(dbgs() << "\t[Processing Reached Uses] ===\n");

1105 for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {

1106 NodeAddr<UseNode *> UseN = *I;

1108 "Found a PhiRef node as a real reached use!!");

1109

1110 NodeAddr<StmtNode *> OwnerN = UseN.Addr->getOwner(*DFG);

1111 MachineInstr *UseMI = OwnerN.Addr->getCode();

1113 << ">]: " << *UseMI << "\n");

1114

1115 int UseMOnum = -1;

1117 for (unsigned j = 0; j < NumOperands - 1; ++j) {

1119 if (op.isReg() && op.isUse() && DefR == op.getReg())

1120 UseMOnum = j;

1121 }

1122

1123

1124

1125

1126

1127

1128 bool Xformed = false;

1129 if (UseMOnum >= 0 && InstrEvalResult[UseMI])

1130 Xformed = xformUseMI(MI, UseMI, UseN, UseMOnum);

1132 KeepTfr |= !Xformed;

1133 }

1134 if (!KeepTfr)

1136 }

1138}

1139

1140bool HexagonOptAddrMode::runOnMachineFunction(MachineFunction &MF) {

1142 return false;

1143

1144

1145

1148 << ": too many basic blocks\n");

1149 return false;

1150 }

1151

1153 auto &HST = MF.getSubtarget();

1156 HII = HST.getInstrInfo();

1157 HRI = HST.getRegisterInfo();

1158 const auto &MDF = getAnalysis();

1159 MDT = &getAnalysis().getDomTree();

1160

1161 DataFlowGraph G(MF, *HII, *HRI, *MDT, MDF);

1162

1163

1165 DFG = &G;

1166

1167 Liveness L(*MRI, *DFG);

1168 L.computePhiInfo();

1169 LV = &L;

1170

1172 ProcessedAddiInsts.clear();

1173 NodeAddr<FuncNode *> FA = DFG->getFunc();

1175 << Print<NodeAddr<FuncNode *>>(FA, *DFG) << "\n");

1176

1177 for (NodeAddr<BlockNode *> BA : FA.Addr->members(*DFG))

1178 Changed |= processBlock(BA);

1179

1181 MI->eraseFromParent();

1182

1184 G.build();

1185 L.computeLiveIns();

1186 L.resetLiveIns();

1187 L.resetKills();

1188 }

1189

1191}

1192

1193

1194

1195

1196

1198 return new HexagonOptAddrMode();

1199}

unsigned const MachineRegisterInfo * MRI

MachineInstrBuilder & UseMI

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

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

This file defines the DenseMap class.

This file defines the DenseSet and SmallDenseSet classes.

static cl::opt< int > CodeGrowthLimit("hexagon-amode-growth-limit", cl::Hidden, cl::init(0), cl::desc("Code growth limit for address mode " "optimization"))

cl::opt< unsigned > RDFFuncBlockLimit

std::pair< Instruction::BinaryOps, Value * > OffsetOp

Find all possible pairs (BinOp, RHS) that BinOp V, RHS can be simplified.

Register const TargetRegisterInfo * TRI

Promote Memory to Register

#define INITIALIZE_PASS_DEPENDENCY(depName)

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

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

AnalysisUsage & addRequired()

void setPreservesAll()

Set by analyses that do not transform their input at all.

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

bool isPredicated(const MachineInstr &MI) const override

Returns true if the instruction is already predicated.

unsigned getAddrMode(const MachineInstr &MI) const

bool isValidOffset(unsigned Opcode, int Offset, const TargetRegisterInfo *TRI, bool Extend=true) const

bool isConstExtended(const MachineInstr &MI) const

short changeAddrMode_rr_ur(short Opc) const

unsigned getMemAccessSize(const MachineInstr &MI) const

short changeAddrMode_io_abs(short Opc) const

short changeAddrMode_rr_io(short Opc) const

bool isHVXVec(const MachineInstr &MI) const

short changeAddrMode_io_rr(short Opc) const

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

bool mayStore() const

Return true if this instruction could possibly modify memory.

bool mayLoad() const

Return true if this instruction could possibly read memory.

int getNumber() const

MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...

Instructions::iterator instr_iterator

MachineInstrBundleIterator< MachineInstr > iterator

LLVM_ABI StringRef getName() const

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

LLVM_ABI bool isLiveIn(MCRegister Reg, LaneBitmask LaneMask=LaneBitmask::getAll()) const

Return true if the specified register is in the live in set.

Analysis pass which computes a MachineDominatorTree.

MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...

void getAnalysisUsage(AnalysisUsage &AU) const override

getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.

const TargetSubtargetInfo & getSubtarget() const

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

MachineRegisterInfo & getRegInfo()

getRegInfo - Return information about the registers currently in use.

Function & getFunction()

Return the LLVM function that this machine code represents.

Register getReg(unsigned Idx) const

Get the register for the operand index.

const MachineInstrBuilder & add(const MachineOperand &MO) const

const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const

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.

const MCInstrDesc & getDesc() const

Returns the target instruction descriptor of this MachineInstr.

const DebugLoc & getDebugLoc() const

Returns the debug location id of this MachineInstr.

const MachineOperand & getOperand(unsigned i) const

const GlobalValue * getGlobal() const

void setImplicit(bool Val=true)

void setImm(int64_t immVal)

bool isReg() const

isReg - Tests if this is a MO_Register operand.

LLVM_ABI void setReg(Register Reg)

Change the register this operand corresponds to.

bool isImm() const

isImm - Tests if this is a MO_Immediate operand.

unsigned getTargetFlags() const

void setIsUndef(bool Val=true)

Register getReg() const

getReg - Returns the register number.

int64_t getOffset() const

Return the offset from the symbol in this operand.

virtual const TargetRegisterInfo * getRegisterInfo() const =0

Return the target's register information.

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

bool contains(const_arg_type_t< ValueT > V) const

Check if the set contains the given element.

#define llvm_unreachable(msg)

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

unsigned ID

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

initializer< Ty > init(const Ty &Val)

Print(const T &, const DataFlowGraph &) -> Print< T >

std::set< NodeId > NodeSet

SmallVector< Node, 4 > NodeList

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.

LLVM_ABI raw_ostream & dbgs()

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

FunctionPass * createHexagonOptAddrMode()

Definition HexagonOptAddrMode.cpp:1197

auto find_if(R &&Range, UnaryPredicate P)

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

LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)

Prints virtual and physical registers with or without a TRI instance.

LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)

Prints a machine basic block reference.

static bool IsDef(const Node BA)

static bool IsUse(const Node BA)

const PhysicalRegisterInfo & getPRI() const

static bool IsCode(const Node BA)

std::unordered_map< RegisterId, DefStack > DefStackMap

NodeAddr< T > addr(NodeId N) const

const RefMap & getRealUses(NodeId P) const

NodeAddr< RefNode * > getNearestAliasedRef(RegisterRef RefRR, NodeAddr< InstrNode * > IA)

Find the nearest ref node aliased to RefRR, going upwards in the data flow, starting from the instruc...

std::pair< NodeSet, bool > getAllReachingDefsRec(RegisterRef RefRR, NodeAddr< RefNode * > RefA, NodeSet &Visited, const NodeSet &Defs)

std::unordered_map< RegisterId, NodeRefSet > RefMap

NodeSet getAllReachedUses(RegisterRef RefRR, NodeAddr< DefNode * > DefA, const RegisterAggr &DefRRs)

bool alias(RegisterRef RA, RegisterRef RB) const

constexpr MCRegister asMCReg() const