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

1

2

3

4

5

6

7

8

27#include "llvm/Config/llvm-config.h"

35#include

36#include

37#include

38#include

39#include

40#include

41#include

42#include

43

44#define DEBUG_TYPE "hsdr"

45

46using namespace llvm;

47

49 cl::desc("Maximum number of split partitions"));

51 cl::desc("Do not split loads or stores"));

53 cl::desc("Split all partitions"));

54

55namespace {

56

58 public:

59 static char ID;

60

62

63 StringRef getPassName() const override {

64 return "Hexagon Split Double Registers";

65 }

66

67 void getAnalysisUsage(AnalysisUsage &AU) const override {

68 AU.addRequired();

69 AU.addPreserved();

71 }

72

73 bool runOnMachineFunction(MachineFunction &MF) override;

74

75 private:

76 static const TargetRegisterClass *const DoubleRC;

77

78 const HexagonRegisterInfo *TRI = nullptr;

79 const HexagonInstrInfo *TII = nullptr;

80 const MachineLoopInfo *MLI;

81 MachineRegisterInfo *MRI;

82

83 using USet = std::set;

84 using UUSetMap = std::map<unsigned, USet>;

85 using UUPair = std::pair<unsigned, unsigned>;

86 using UUPairMap = std::map<unsigned, UUPair>;

87 using LoopRegMap = std::map<const MachineLoop *, USet>;

88

89 bool isInduction(unsigned Reg, LoopRegMap &IRM) const;

90 bool isVolatileInstr(const MachineInstr *MI) const;

91 bool isFixedInstr(const MachineInstr *MI) const;

92 void partitionRegisters(UUSetMap &P2Rs);

93 int32_t profit(const MachineInstr *MI) const;

95 bool isProfitable(const USet &Part, LoopRegMap &IRM) const;

96

97 void collectIndRegsForLoop(const MachineLoop *L, USet &Rs);

98 void collectIndRegs(LoopRegMap &IRM);

99

100 void createHalfInstr(unsigned Opc, MachineInstr *MI,

101 const UUPairMap &PairMap, unsigned SubR);

102 void splitMemRef(MachineInstr *MI, const UUPairMap &PairMap);

103 void splitImmediate(MachineInstr *MI, const UUPairMap &PairMap);

104 void splitCombine(MachineInstr *MI, const UUPairMap &PairMap);

105 void splitExt(MachineInstr *MI, const UUPairMap &PairMap);

106 void splitShift(MachineInstr *MI, const UUPairMap &PairMap);

107 void splitAslOr(MachineInstr *MI, const UUPairMap &PairMap);

108 bool splitInstr(MachineInstr *MI, const UUPairMap &PairMap);

109 void replaceSubregUses(MachineInstr *MI, const UUPairMap &PairMap);

110 void collapseRegPairs(MachineInstr *MI, const UUPairMap &PairMap);

111 bool splitPartition(const USet &Part);

112

113 static int Counter;

114

115 static void dump_partition(raw_ostream&, const USet&,

116 const TargetRegisterInfo&);

117 };

118

119}

120

121char HexagonSplitDoubleRegs::ID;

122int HexagonSplitDoubleRegs::Counter = 0;

124 &Hexagon::DoubleRegsRegClass;

125

127 "Hexagon Split Double Registers", false, false)

128

129#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

132 dbgs() << '{';

133 for (auto I : Part)

135 dbgs() << " }";

136}

137#endif

138

139bool HexagonSplitDoubleRegs::isInduction(unsigned Reg, LoopRegMap &IRM) const {

140 for (auto I : IRM) {

141 const USet &Rs = I.second;

142 if (Rs.find(Reg) != Rs.end())

143 return true;

144 }

145 return false;

146}

147

148bool HexagonSplitDoubleRegs::isVolatileInstr(const MachineInstr *MI) const {

149 for (auto &MO : MI->memoperands())

150 if (MO->isVolatile() || MO->isAtomic())

151 return true;

152 return false;

153}

154

155bool HexagonSplitDoubleRegs::isFixedInstr(const MachineInstr *MI) const {

156 if (MI->mayLoadOrStore())

158 return true;

159 if (MI->isDebugInstr())

160 return false;

161

162 unsigned Opc = MI->getOpcode();

163 switch (Opc) {

164 default:

165 return true;

166

167 case TargetOpcode::PHI:

168 case TargetOpcode::COPY:

169 break;

170

171 case Hexagon::L2_loadrd_io:

172

173 if (MI->getOperand(1).isReg())

174 break;

175 return true;

176 case Hexagon::S2_storerd_io:

177

178 if (MI->getOperand(0).isReg())

179 break;

180 return true;

181 case Hexagon::L2_loadrd_pi:

182 case Hexagon::S2_storerd_pi:

183

184 case Hexagon::A2_tfrpi:

185 case Hexagon::A2_combineii:

186 case Hexagon::A4_combineir:

187 case Hexagon::A4_combineii:

188 case Hexagon::A4_combineri:

189 case Hexagon::A2_combinew:

190 case Hexagon::CONST64:

191

192 case Hexagon::A2_sxtw:

193

194 case Hexagon::A2_andp:

195 case Hexagon::A2_orp:

196 case Hexagon::A2_xorp:

197 case Hexagon::S2_asl_i_p_or:

198 case Hexagon::S2_asl_i_p:

199 case Hexagon::S2_asr_i_p:

200 case Hexagon::S2_lsr_i_p:

201 break;

202 }

203

204 for (auto &Op : MI->operands()) {

205 if (Op.isReg())

206 continue;

208 if (R.isVirtual())

209 return true;

210 }

211 return false;

212}

213

214void HexagonSplitDoubleRegs::partitionRegisters(UUSetMap &P2Rs) {

215 using UUMap = std::map<unsigned, unsigned>;

216 using UVect = std::vector;

217

218 unsigned NumRegs = MRI->getNumVirtRegs();

220 for (unsigned i = 0; i < NumRegs; ++i) {

221 Register R = Register::index2VirtReg(i);

222 if (MRI->getRegClass(R) == DoubleRC)

224 }

225

226 BitVector FixedRegs(NumRegs);

228 Register R = Register::index2VirtReg(x);

229 MachineInstr *DefI = MRI->getVRegDef(R);

230

231

232

233 if (!DefI || isFixedInstr(DefI))

234 FixedRegs.set(x);

235 }

236

237 UUSetMap AssocMap;

239 if (FixedRegs[x])

240 continue;

241 Register R = Register::index2VirtReg(x);

243 USet &Asc = AssocMap[R];

244 for (auto U = MRI->use_nodbg_begin(R), Z = MRI->use_nodbg_end();

245 U != Z; ++U) {

246 MachineOperand &Op = *U;

247 MachineInstr *UseI = Op.getParent();

248 if (isFixedInstr(UseI))

249 continue;

250 for (MachineOperand &MO : UseI->operands()) {

251

252 if (&MO == &Op || !MO.isReg() || MO.getSubReg())

253 continue;

255 if (T.isVirtual()) {

256 FixedRegs.set(x);

257 continue;

258 }

259 if (MRI->getRegClass(T) != DoubleRC)

260 continue;

261 unsigned u = T.virtRegIndex();

262 if (FixedRegs[u])

263 continue;

265 Asc.insert(T);

266

267 AssocMap[T].insert(R);

268 }

269 }

271 }

272

273 UUMap R2P;

274 unsigned NextP = 1;

275 USet Visited;

277 Register R = Register::index2VirtReg(x);

278 if (Visited.count(R))

279 continue;

280

281 unsigned ThisP = FixedRegs[x] ? 0 : NextP++;

282 UVect WorkQ;

283 WorkQ.push_back(R);

284 for (unsigned i = 0; i < WorkQ.size(); ++i) {

285 unsigned T = WorkQ[i];

286 if (Visited.count(T))

287 continue;

288 R2P[T] = ThisP;

289 Visited.insert(T);

290

291 USet &Asc = AssocMap[T];

293 }

294 }

295

296 for (auto I : R2P)

297 P2Rs[I.second].insert(I.first);

298}

299

300static inline int32_t profitImm(unsigned Imm) {

301 int32_t P = 0;

302 if (Imm == 0 || Imm == 0xFFFFFFFF)

303 P += 10;

304 return P;

305}

306

307int32_t HexagonSplitDoubleRegs::profit(const MachineInstr *MI) const {

308 unsigned ImmX = 0;

309 unsigned Opc = MI->getOpcode();

310 switch (Opc) {

311 case TargetOpcode::PHI:

312 for (const auto &Op : MI->operands())

313 if (Op.getSubReg())

314 return 0;

315 return 10;

316 case TargetOpcode::COPY:

317 if (MI->getOperand(1).getSubReg() != 0)

318 return 10;

319 return 0;

320

321 case Hexagon::L2_loadrd_io:

322 case Hexagon::S2_storerd_io:

323 return -1;

324 case Hexagon::L2_loadrd_pi:

325 case Hexagon::S2_storerd_pi:

326 return 2;

327

328 case Hexagon::A2_tfrpi:

329 case Hexagon::CONST64: {

330 uint64_t D = MI->getOperand(1).getImm();

331 unsigned Lo = D & 0xFFFFFFFFULL;

332 unsigned Hi = D >> 32;

334 }

335 case Hexagon::A2_combineii:

336 case Hexagon::A4_combineii: {

337 const MachineOperand &Op1 = MI->getOperand(1);

338 const MachineOperand &Op2 = MI->getOperand(2);

341 return Prof1 + Prof2;

342 }

343 case Hexagon::A4_combineri:

344 ImmX++;

345

346 [[fallthrough]];

347 case Hexagon::A4_combineir: {

348 ImmX++;

349 const MachineOperand &OpX = MI->getOperand(ImmX);

350 if (OpX.isImm()) {

351 int64_t V = OpX.getImm();

352 if (V == 0 || V == -1)

353 return 10;

354 }

355

356 [[fallthrough]];

357 }

358 case Hexagon::A2_combinew:

359 return 2;

360

361 case Hexagon::A2_sxtw:

362 return 3;

363

364 case Hexagon::A2_andp:

365 case Hexagon::A2_orp:

366 case Hexagon::A2_xorp: {

367 Register Rs = MI->getOperand(1).getReg();

368 Register Rt = MI->getOperand(2).getReg();

369 return profit(Rs) + profit(Rt);

370 }

371

372 case Hexagon::S2_asl_i_p_or: {

373 unsigned S = MI->getOperand(3).getImm();

374 if (S == 0 || S == 32)

375 return 10;

376 return -1;

377 }

378 case Hexagon::S2_asl_i_p:

379 case Hexagon::S2_asr_i_p:

380 case Hexagon::S2_lsr_i_p:

381 unsigned S = MI->getOperand(2).getImm();

382 if (S == 0 || S == 32)

383 return 10;

384 if (S == 16)

385 return 5;

386 if (S == 48)

387 return 7;

388 return -10;

389 }

390

391 return 0;

392}

393

394int32_t HexagonSplitDoubleRegs::profit(Register Reg) const {

396

397 const MachineInstr *DefI = MRI->getVRegDef(Reg);

399 case Hexagon::A2_tfrpi:

400 case Hexagon::CONST64:

401 case Hexagon::A2_combineii:

402 case Hexagon::A4_combineii:

403 case Hexagon::A4_combineri:

404 case Hexagon::A4_combineir:

405 case Hexagon::A2_combinew:

406 return profit(DefI);

407 default:

408 break;

409 }

410 return 0;

411}

412

413bool HexagonSplitDoubleRegs::isProfitable(const USet &Part, LoopRegMap &IRM)

414 const {

415 unsigned FixedNum = 0, LoopPhiNum = 0;

416 int32_t TotalP = 0;

417

418 for (unsigned DR : Part) {

419 MachineInstr *DefI = MRI->getVRegDef(DR);

420 int32_t P = profit(DefI);

421 if (P == std::numeric_limits::min())

422 return false;

423 TotalP += P;

424

425 if (isInduction(DR, IRM))

426 TotalP -= 30;

427

428 for (auto U = MRI->use_nodbg_begin(DR), W = MRI->use_nodbg_end();

429 U != W; ++U) {

430 MachineInstr *UseI = U->getParent();

431 if (isFixedInstr(UseI)) {

432 FixedNum++;

433

435 if (Op.isReg() && Part.count(Op.getReg()))

436 if (Op.getSubReg())

437 TotalP -= 2;

438 }

439 continue;

440 }

441

442

443

444

445 if (UseI->isPHI()) {

446 const MachineBasicBlock *PB = UseI->getParent();

448 if (L && L->getHeader() == PB)

449 LoopPhiNum++;

450 }

451

452 int32_t P = profit(UseI);

453 if (P == std::numeric_limits::min())

454 return false;

455 TotalP += P;

456 }

457 }

458

459 if (FixedNum > 0 && LoopPhiNum > 0)

460 TotalP -= 20*LoopPhiNum;

461

462 LLVM_DEBUG(dbgs() << "Partition profit: " << TotalP << '\n');

464 return true;

465 return TotalP > 0;

466}

467

468void HexagonSplitDoubleRegs::collectIndRegsForLoop(const MachineLoop *L,

469 USet &Rs) {

470 const MachineBasicBlock *HB = L->getHeader();

471 const MachineBasicBlock *LB = L->getLoopLatch();

472 if (!HB || !LB)

473 return;

474

475

476

477 MachineBasicBlock *TB = nullptr, *FB = nullptr;

478 MachineBasicBlock *TmpLB = const_cast<MachineBasicBlock*>(LB);

481

482

483

484 if (BadLB || Cond.size() != 2)

485 return;

486

487 if (TII->PredOpcodeHasJMP_c(Cond[0].getImm()))

488 return;

489

490 if (TB != HB && FB != HB)

491 return;

492 assert(Cond[1].isReg() && "Unexpected Cond vector from analyzeBranch");

493

495 assert(MRI->getRegClass(PR) == &Hexagon::PredRegsRegClass);

496

497

498

500 const MachineInstr *CmpI = MRI->getVRegDef(PR);

501 while (CmpI->getOpcode() == Hexagon::C2_not)

503

504 int64_t Mask = 0, Val = 0;

506 if (!OkCI)

507 return;

508

509 if (CmpR1 && MRI->getRegClass(CmpR1) != DoubleRC)

510 CmpR1 = 0;

511 if (CmpR2 && MRI->getRegClass(CmpR2) != DoubleRC)

512 CmpR2 = 0;

513 if (!CmpR1 && !CmpR2)

514 return;

515

516

517

518

519

520

521

522

523 using UVect = std::vector;

524

525 UVect DP;

526 for (auto &MI : *HB) {

527 if (MI.isPHI())

528 break;

529 const MachineOperand &MD = MI.getOperand(0);

531 if (MRI->getRegClass(R) == DoubleRC)

532 DP.push_back(R);

533 }

534 if (DP.empty())

535 return;

536

537 auto NoIndOp = [this, CmpR1, CmpR2] (unsigned R) -> bool {

538 for (auto I = MRI->use_nodbg_begin(R), E = MRI->use_nodbg_end();

539 I != E; ++I) {

540 const MachineInstr *UseI = I->getParent();

541 if (UseI->getOpcode() != Hexagon::A2_addp)

542 continue;

543

544

545

547 if (T == CmpR1 || T == CmpR2)

548 return false;

549 }

550 return true;

551 };

553 Rs.insert(DP.begin(), End);

554 Rs.insert(CmpR1);

555 Rs.insert(CmpR2);

556

559 dump_partition(dbgs(), Rs, *TRI);

560 dbgs() << '\n';

561 });

562}

563

564void HexagonSplitDoubleRegs::collectIndRegs(LoopRegMap &IRM) {

565 using LoopVector = std::vector<MachineLoop *>;

566

568

570 for (unsigned i = 0; i < WorkQ.size(); ++i)

572

573 USet Rs;

574 for (MachineLoop *L : WorkQ) {

575 Rs.clear();

576 collectIndRegsForLoop(L, Rs);

577 if (!Rs.empty())

578 IRM.insert(std::make_pair(L, Rs));

579 }

580}

581

582void HexagonSplitDoubleRegs::createHalfInstr(unsigned Opc, MachineInstr *MI,

583 const UUPairMap &PairMap, unsigned SubR) {

584 MachineBasicBlock &B = *MI->getParent();

587

588 for (auto &Op : MI->operands()) {

589 if (Op.isReg()) {

591 continue;

592 }

593

595 unsigned SR = Op.getSubReg();

596 bool isVirtReg = R.isVirtual();

597 bool isKill = Op.isKill();

598 if (isVirtReg && MRI->getRegClass(R) == DoubleRC) {

599 isKill = false;

600 UUPairMap::const_iterator F = PairMap.find(R);

601 if (F == PairMap.end()) {

602 SR = SubR;

603 } else {

604 const UUPair &P = F->second;

605 R = (SubR == Hexagon::isub_lo) ? P.first : P.second;

606 SR = 0;

607 }

608 }

610 Op.isDead(), Op.isUndef(), Op.isEarlyClobber(), SR, Op.isDebug(),

611 Op.isInternalRead());

613 }

614}

615

616void HexagonSplitDoubleRegs::splitMemRef(MachineInstr *MI,

617 const UUPairMap &PairMap) {

618 bool Load = MI->mayLoad();

619 unsigned OrigOpc = MI->getOpcode();

620 bool PostInc = (OrigOpc == Hexagon::L2_loadrd_pi ||

621 OrigOpc == Hexagon::S2_storerd_pi);

622 MachineInstr *LowI, *HighI;

623 MachineBasicBlock &B = *MI->getParent();

625

626

628 : (Load ? 1 : 0);

629 MachineOperand &AdrOp = MI->getOperand(AdrX);

631 MachineOperand &ValOp = Load ? MI->getOperand(0)

633 : MI->getOperand(2));

634 UUPairMap::const_iterator F = PairMap.find(ValOp.getReg());

635 assert(F != PairMap.end());

636

637 if (Load) {

638 const UUPair &P = F->second;

639 int64_t Off = PostInc ? 0 : MI->getOperand(2).getImm();

646 } else {

647 const UUPair &P = F->second;

648 int64_t Off = PostInc ? 0 : MI->getOperand(1).getImm();

657 }

658

660

661 int64_t Inc = Load ? MI->getOperand(3).getImm()

662 : MI->getOperand(2).getImm();

663 MachineOperand &UpdOp = Load ? MI->getOperand(1) : MI->getOperand(0);

664 const TargetRegisterClass *RC = MRI->getRegClass(UpdOp.getReg());

665 Register NewR = MRI->createVirtualRegister(RC);

670 MRI->replaceRegWith(UpdOp.getReg(), NewR);

671

672 }

673

674

675 MachineFunction &MF = *B.getParent();

676 for (auto &MO : MI->memoperands()) {

677 const MachinePointerInfo &Ptr = MO->getPointerInfo();

679 Align A = MO->getAlign();

680

683 auto *Tmp2 =

686 }

687}

688

689void HexagonSplitDoubleRegs::splitImmediate(MachineInstr *MI,

690 const UUPairMap &PairMap) {

691 MachineOperand &Op0 = MI->getOperand(0);

692 MachineOperand &Op1 = MI->getOperand(1);

694 uint64_t V = Op1.getImm();

695

696 MachineBasicBlock &B = *MI->getParent();

698 UUPairMap::const_iterator F = PairMap.find(Op0.getReg());

699 assert(F != PairMap.end());

700 const UUPair &P = F->second;

701

702

703

704

705

706

707

708

709

711 .addImm(int32_t(V & 0xFFFFFFFFULL));

713 .addImm(int32_t(V >> 32));

714}

715

716void HexagonSplitDoubleRegs::splitCombine(MachineInstr *MI,

717 const UUPairMap &PairMap) {

718 MachineOperand &Op0 = MI->getOperand(0);

719 MachineOperand &Op1 = MI->getOperand(1);

720 MachineOperand &Op2 = MI->getOperand(2);

722

723 MachineBasicBlock &B = *MI->getParent();

725 UUPairMap::const_iterator F = PairMap.find(Op0.getReg());

726 assert(F != PairMap.end());

727 const UUPair &P = F->second;

728

729 if (!Op1.isReg()) {

731 .add(Op1);

732 } else {

735 }

736

737 if (!Op2.isReg()) {

739 .add(Op2);

740 } else {

743 }

744}

745

746void HexagonSplitDoubleRegs::splitExt(MachineInstr *MI,

747 const UUPairMap &PairMap) {

748 MachineOperand &Op0 = MI->getOperand(0);

749 MachineOperand &Op1 = MI->getOperand(1);

751

752 MachineBasicBlock &B = *MI->getParent();

754 UUPairMap::const_iterator F = PairMap.find(Op0.getReg());

755 assert(F != PairMap.end());

756 const UUPair &P = F->second;

758

764}

765

766void HexagonSplitDoubleRegs::splitShift(MachineInstr *MI,

767 const UUPairMap &PairMap) {

768 using namespace Hexagon;

769

770 MachineOperand &Op0 = MI->getOperand(0);

771 MachineOperand &Op1 = MI->getOperand(1);

772 MachineOperand &Op2 = MI->getOperand(2);

774 int64_t Sh64 = Op2.getImm();

775 assert(Sh64 >= 0 && Sh64 < 64);

776 unsigned S = Sh64;

777

778 UUPairMap::const_iterator F = PairMap.find(Op0.getReg());

779 assert(F != PairMap.end());

780 const UUPair &P = F->second;

783

784 unsigned Opc = MI->getOpcode();

785 bool Right = (Opc == S2_lsr_i_p || Opc == S2_asr_i_p);

787 bool Signed = (Opc == S2_asr_i_p);

788

789 MachineBasicBlock &B = *MI->getParent();

793 : (Signed ? S2_asr_i_r : S2_lsr_i_r);

794 unsigned LoSR = isub_lo;

795 unsigned HiSR = isub_hi;

796

797 if (S == 0) {

798

803 } else if (S < 32) {

804 const TargetRegisterClass *IntRC = &IntRegsRegClass;

805 Register TmpR = MRI->createVirtualRegister(IntRC);

806

807

808

809

810

811

812

813

814

815

816

817

818

819

820

821

822

823 if (S == 16 && Left)

826 else if (S == 16 && Signed)

829 else

833

835

840

845 } else {

846

850

856 }

857 } else if (S == 32) {

863 else

867 } else if (S < 64) {

868 S -= 32;

869 if (S == 16 && Left)

872 else if (S == 16 && Signed)

875 else

879

884 else

887 }

888}

889

890void HexagonSplitDoubleRegs::splitAslOr(MachineInstr *MI,

891 const UUPairMap &PairMap) {

892 using namespace Hexagon;

893

894 MachineOperand &Op0 = MI->getOperand(0);

895 MachineOperand &Op1 = MI->getOperand(1);

896 MachineOperand &Op2 = MI->getOperand(2);

897 MachineOperand &Op3 = MI->getOperand(3);

899 int64_t Sh64 = Op3.getImm();

900 assert(Sh64 >= 0 && Sh64 < 64);

901 unsigned S = Sh64;

902

903 UUPairMap::const_iterator F = PairMap.find(Op0.getReg());

904 assert(F != PairMap.end());

905 const UUPair &P = F->second;

906 unsigned LoR = P.first;

907 unsigned HiR = P.second;

908

909 MachineBasicBlock &B = *MI->getParent();

913 const TargetRegisterClass *IntRC = &IntRegsRegClass;

914

915 unsigned LoSR = isub_lo;

916 unsigned HiSR = isub_hi;

917

918

919

920

921

922

923

924

925

926

927

928

929 if (S == 0) {

930

931

932

933

940 } else if (S < 32) {

945 Register TmpR1 = MRI->createVirtualRegister(IntRC);

950 Register TmpR2 = MRI->createVirtualRegister(IntRC);

958 } else if (S == 32) {

959

960

961

962

968 } else if (S < 64) {

969

970

971

972

973 S -= 32;

980 }

981}

982

983bool HexagonSplitDoubleRegs::splitInstr(MachineInstr *MI,

984 const UUPairMap &PairMap) {

985 using namespace Hexagon;

986

988 bool Split = false;

989 unsigned Opc = MI->getOpcode();

990

991 switch (Opc) {

992 case TargetOpcode::PHI:

993 case TargetOpcode::COPY: {

994 Register DstR = MI->getOperand(0).getReg();

995 if (MRI->getRegClass(DstR) == DoubleRC) {

996 createHalfInstr(Opc, MI, PairMap, isub_lo);

997 createHalfInstr(Opc, MI, PairMap, isub_hi);

999 }

1000 break;

1001 }

1002 case A2_andp:

1003 createHalfInstr(A2_and, MI, PairMap, isub_lo);

1004 createHalfInstr(A2_and, MI, PairMap, isub_hi);

1006 break;

1007 case A2_orp:

1008 createHalfInstr(A2_or, MI, PairMap, isub_lo);

1009 createHalfInstr(A2_or, MI, PairMap, isub_hi);

1011 break;

1012 case A2_xorp:

1013 createHalfInstr(A2_xor, MI, PairMap, isub_lo);

1014 createHalfInstr(A2_xor, MI, PairMap, isub_hi);

1016 break;

1017

1018 case L2_loadrd_io:

1019 case L2_loadrd_pi:

1020 case S2_storerd_io:

1021 case S2_storerd_pi:

1022 splitMemRef(MI, PairMap);

1024 break;

1025

1026 case A2_tfrpi:

1027 case CONST64:

1028 splitImmediate(MI, PairMap);

1030 break;

1031

1032 case A2_combineii:

1033 case A4_combineir:

1034 case A4_combineii:

1035 case A4_combineri:

1036 case A2_combinew:

1037 splitCombine(MI, PairMap);

1039 break;

1040

1041 case A2_sxtw:

1042 splitExt(MI, PairMap);

1044 break;

1045

1046 case S2_asl_i_p:

1047 case S2_asr_i_p:

1048 case S2_lsr_i_p:

1049 splitShift(MI, PairMap);

1051 break;

1052

1053 case S2_asl_i_p_or:

1054 splitAslOr(MI, PairMap);

1056 break;

1057

1058 default:

1060 return false;

1061 }

1062

1064}

1065

1066void HexagonSplitDoubleRegs::replaceSubregUses(MachineInstr *MI,

1067 const UUPairMap &PairMap) {

1068 for (auto &Op : MI->operands()) {

1069 if (Op.isReg() || Op.isUse() || Op.getSubReg())

1070 continue;

1072 UUPairMap::const_iterator F = PairMap.find(R);

1073 if (F == PairMap.end())

1074 continue;

1075 const UUPair &P = F->second;

1076 switch (Op.getSubReg()) {

1077 case Hexagon::isub_lo:

1078 Op.setReg(P.first);

1079 break;

1080 case Hexagon::isub_hi:

1081 Op.setReg(P.second);

1082 break;

1083 }

1084 Op.setSubReg(0);

1085 }

1086}

1087

1088void HexagonSplitDoubleRegs::collapseRegPairs(MachineInstr *MI,

1089 const UUPairMap &PairMap) {

1090 MachineBasicBlock &B = *MI->getParent();

1092

1093 for (auto &Op : MI->operands()) {

1094 if (Op.isReg() || Op.isUse())

1095 continue;

1097 if (R.isVirtual())

1098 continue;

1099 if (MRI->getRegClass(R) != DoubleRC || Op.getSubReg())

1100 continue;

1101 UUPairMap::const_iterator F = PairMap.find(R);

1102 if (F == PairMap.end())

1103 continue;

1104 const UUPair &Pr = F->second;

1105 Register NewDR = MRI->createVirtualRegister(DoubleRC);

1108 .addImm(Hexagon::isub_lo)

1110 .addImm(Hexagon::isub_hi);

1111 Op.setReg(NewDR);

1112 }

1113}

1114

1115bool HexagonSplitDoubleRegs::splitPartition(const USet &Part) {

1116 using MISet = std::set<MachineInstr *>;

1117

1118 const TargetRegisterClass *IntRC = &Hexagon::IntRegsRegClass;

1120

1122 dump_partition(dbgs(), Part, *TRI); dbgs() << '\n');

1123

1124 UUPairMap PairMap;

1125

1126 MISet SplitIns;

1127 for (unsigned DR : Part) {

1128 MachineInstr *DefI = MRI->getVRegDef(DR);

1129 SplitIns.insert(DefI);

1130

1131

1132

1133 for (auto U = MRI->use_nodbg_begin(DR), W = MRI->use_nodbg_end();

1134 U != W; ++U)

1135 SplitIns.insert(U->getParent());

1136

1137 Register LoR = MRI->createVirtualRegister(IntRC);

1138 Register HiR = MRI->createVirtualRegister(IntRC);

1141 << '\n');

1142 PairMap.insert(std::make_pair(DR, UUPair(LoR, HiR)));

1143 }

1144

1145 MISet Erase;

1146 for (auto *MI : SplitIns) {

1147 if (isFixedInstr(MI)) {

1148 collapseRegPairs(MI, PairMap);

1149 } else {

1150 bool Done = splitInstr(MI, PairMap);

1152 Erase.insert(MI);

1154 }

1155 }

1156

1157 for (unsigned DR : Part) {

1158

1159

1160

1162 for (auto U = MRI->use_nodbg_begin(DR), W = MRI->use_nodbg_end();

1163 U != W; ++U)

1164 Uses.insert(U->getParent());

1165 for (auto *M : Uses)

1166 replaceSubregUses(M, PairMap);

1167 }

1168

1169 for (auto *MI : Erase) {

1170 MachineBasicBlock *B = MI->getParent();

1171 B->erase(MI);

1172 }

1173

1175}

1176

1177bool HexagonSplitDoubleRegs::runOnMachineFunction(MachineFunction &MF) {

1179 return false;

1180

1181 LLVM_DEBUG(dbgs() << "Splitting double registers in function: "

1182 << MF.getName() << '\n');

1183

1185 TRI = ST.getRegisterInfo();

1186 TII = ST.getInstrInfo();

1188 MLI = &getAnalysis().getLI();

1189

1190 UUSetMap P2Rs;

1191 LoopRegMap IRM;

1192

1193 collectIndRegs(IRM);

1194 partitionRegisters(P2Rs);

1195

1197 dbgs() << "Register partitioning: (partition #0 is fixed)\n";

1198 for (UUSetMap::iterator I = P2Rs.begin(), E = P2Rs.end(); I != E; ++I) {

1199 dbgs() << '#' << I->first << " -> ";

1200 dump_partition(dbgs(), I->second, *TRI);

1201 dbgs() << '\n';

1202 }

1203 });

1204

1207

1208 for (UUSetMap::iterator I = P2Rs.begin(), E = P2Rs.end(); I != E; ++I) {

1209 if (I->first == 0)

1210 continue;

1211 if (Limit >= 0 && Counter >= Limit)

1212 break;

1213 USet &Part = I->second;

1214 LLVM_DEBUG(dbgs() << "Calculating profit for partition #" << I->first

1215 << '\n');

1217 continue;

1218 Counter++;

1219 Changed |= splitPartition(Part);

1220 }

1221

1223}

1224

1226 return new HexagonSplitDoubleRegs();

1227}

unsigned const MachineRegisterInfo * MRI

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

const TargetInstrInfo & TII

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

This file implements the BitVector class.

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")

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

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

#define LLVM_DUMP_METHOD

Mark debug helper function definitions like dump() that should not be stripped from debug builds.

static cl::opt< bool > MemRefsFixed("hsdr-no-mem", cl::Hidden, cl::init(true), cl::desc("Do not split loads or stores"))

static cl::opt< bool > SplitAll("hsdr-split-all", cl::Hidden, cl::init(false), cl::desc("Split all partitions"))

static cl::opt< int > MaxHSDR("max-hsdr", cl::Hidden, cl::init(-1), cl::desc("Maximum number of split partitions"))

static int32_t profitImm(unsigned Imm)

Definition HexagonSplitDouble.cpp:300

SmallVector< Loop *, 4 > LoopVector

Register const TargetRegisterInfo * TRI

Promote Memory to Register

static bool isReg(const MCInst &MI, unsigned OpNo)

PassBuilder PB(Machine, PassOpts->PTO, std::nullopt, &PIC)

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

const SmallVectorImpl< MachineOperand > & Cond

Remove Loads Into Fake Uses

This file defines the SmallVector class.

static const MCPhysReg DoubleRegs[32]

static bool isProfitable(const StableFunctionMap::StableFunctionEntries &SFS)

AnalysisUsage & addRequired()

AnalysisUsage & addPreserved()

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

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

LoopT * getLoopFor(const BlockT *BB) const

Return the inner most loop that BB lives in.

const MCInstrDesc & get(unsigned Opcode) const

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

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

void getAnalysisUsage(AnalysisUsage &AU) const override

getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.

const TargetSubtargetInfo & getSubtarget() const

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

StringRef getName() const

getName - Return the name of the corresponding LLVM function.

MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)

getMachineMemOperand - Allocate a new MachineMemOperand.

MachineRegisterInfo & getRegInfo()

getRegInfo - Return information about the registers currently in use.

Function & getFunction()

Return the LLVM function that this machine code represents.

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.

unsigned getOpcode() const

Returns the opcode of this MachineInstr.

const MachineBasicBlock * getParent() const

LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)

Add the specified operand to the instruction.

const MachineOperand & getOperand(unsigned i) const

LLVM_ABI void addMemOperand(MachineFunction &MF, MachineMemOperand *MO)

Add a MachineMemOperand to the machine instruction.

Flags

Flags values. These may be or'd together.

unsigned getSubReg() const

bool isReg() const

isReg - Tests if this is a MO_Register operand.

bool isImm() const

isImm - Tests if this is a MO_Immediate operand.

Register getReg() const

getReg - Returns the register number.

static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)

constexpr bool isVirtual() const

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

virtual bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const

Analyze the branching code at the end of MBB, returning true if it cannot be understood (e....

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

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

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

This class implements an extremely fast bulk output stream that can only output to a stream.

#define llvm_unreachable(msg)

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

constexpr char Align[]

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

constexpr std::underlying_type_t< E > Mask()

Get a bitmask with 1s in all places up to the high-order bit of E's largest value.

unsigned ID

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

@ Kill

The last use of a register.

@ TB

TB - TwoByte - Set if this instruction has a two byte opcode, which starts with a 0x0F byte before th...

initializer< Ty > init(const Ty &Val)

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.

void append_range(Container &C, Range &&R)

Wrapper function to append range R to container C.

LLVM_ABI raw_ostream & dbgs()

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

class LLVM_GSL_OWNER SmallVector

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

auto remove_if(R &&Range, UnaryPredicate P)

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

unsigned getRegState(const MachineOperand &RegOp)

Get all register state flags from machine operand RegOp.

DWARFExpression::Operation Op

FunctionPass * createHexagonSplitDoubleRegs()

Definition HexagonSplitDouble.cpp:1225

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.