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

1

2

3

4

5

6

7

8

32

33#define DEBUG_TYPE "hexbit"

34

35using namespace llvm;

36

38 cl::init(true), cl::desc("Preserve subregisters in tied operands"));

43

45 cl::init(std::numeric_limits::max()));

48 cl::init(std::numeric_limits::max()));

50

53

54namespace {

55

56

57 struct RegisterSet {

59 explicit RegisterSet(unsigned s, bool t = false) : Bits(s, t) {}

61

64 LRU.clear();

65 }

66

67 unsigned count() const {

68 return Bits.count();

69 }

70

71 unsigned find_first() const {

74 return 0;

75 return x2v(First);

76 }

77

78 unsigned find_next(unsigned Prev) const {

79 int Next = Bits.find_next(v2x(Prev));

81 return 0;

82 return x2v(Next);

83 }

84

86 unsigned Idx = v2x(R);

87 ensure(Idx);

88 bool Exists = Bits.test(Idx);

89 Bits.set(Idx);

90 if (!Exists) {

91 LRU.push_back(Idx);

93 unsigned T = LRU.front();

95 LRU.pop_front();

96 }

97 }

98 return *this;

99 }

101 unsigned Idx = v2x(R);

102 if (Idx < Bits.size()) {

103 bool Exists = Bits.test(Idx);

104 Bits.reset(Idx);

105 if (Exists) {

108 LRU.erase(F);

109 }

110 }

111 return *this;

112 }

113

115 for (unsigned R = Rs.find_first(); R; R = Rs.find_next(R))

117 return *this;

118 }

120 for (unsigned R = Rs.find_first(); R; R = Rs.find_next(R))

122 return *this;

123 }

124

125 bool operator[](unsigned R) const {

126 unsigned Idx = v2x(R);

127 return Idx < Bits.size() ? Bits[Idx] : false;

128 }

129 bool has(unsigned R) const {

130 unsigned Idx = v2x(R);

131 if (Idx >= Bits.size())

132 return false;

133 return Bits.test(Idx);

134 }

135

136 bool empty() const {

137 return Bits.any();

138 }

140 return Rs.Bits.subsetOf(Bits);

141 }

143 return Bits.anyCommon(Rs.Bits);

144 }

145

146 private:

147 BitVector Bits;

148 std::deque LRU;

149

150 void ensure(unsigned Idx) {

151 if (Bits.size() <= Idx)

152 Bits.resize(std::max(Idx+1, 32U));

153 }

154

155 static inline unsigned v2x(unsigned v) {

156 return Register(v).virtRegIndex();

157 }

158

159 static inline unsigned x2v(unsigned x) {

160 return Register::index2VirtReg(x);

161 }

162 };

163

164 struct PrintRegSet {

165 PrintRegSet(const RegisterSet &S, const TargetRegisterInfo *RI)

166 : RS(S), TRI(RI) {}

167

168 friend raw_ostream &operator<< (raw_ostream &OS,

169 const PrintRegSet &P);

170

171 private:

173 const TargetRegisterInfo *TRI;

174 };

175

177 const PrintRegSet &P);

179 OS << '{';

180 for (unsigned R = P.RS.find_first(); R; R = P.RS.find_next(R))

182 OS << " }";

183 return OS;

184 }

185

186 class Transformation;

187

189 public:

190 static char ID;

191

192 HexagonBitSimplify() : MachineFunctionPass(ID) {}

193

194 StringRef getPassName() const override {

195 return "Hexagon bit simplification";

196 }

197

198 void getAnalysisUsage(AnalysisUsage &AU) const override {

199 AU.addRequired();

200 AU.addPreserved();

202 }

203

204 bool runOnMachineFunction(MachineFunction &MF) override;

205

206 static void getInstrDefs(const MachineInstr &MI, RegisterSet &Defs);

207 static void getInstrUses(const MachineInstr &MI, RegisterSet &Uses);

208 static bool isEqual(const BitTracker::RegisterCell &RC1, uint16_t B1,

209 const BitTracker::RegisterCell &RC2, uint16_t B2, uint16_t W);

210 static bool isZero(const BitTracker::RegisterCell &RC, uint16_t B,

211 uint16_t W);

212 static bool getConst(const BitTracker::RegisterCell &RC, uint16_t B,

213 uint16_t W, uint64_t &U);

215 MachineRegisterInfo &MRI);

216 static bool getSubregMask(const BitTracker::RegisterRef &RR,

217 unsigned &Begin, unsigned &Width, MachineRegisterInfo &MRI);

218 static bool replaceRegWithSub(Register OldR, Register NewR, unsigned NewSR,

219 MachineRegisterInfo &MRI);

220 static bool replaceSubWithSub(Register OldR, unsigned OldSR, Register NewR,

221 unsigned NewSR, MachineRegisterInfo &MRI);

222 static bool parseRegSequence(const MachineInstr &I,

223 BitTracker::RegisterRef &SL, BitTracker::RegisterRef &SH,

224 const MachineRegisterInfo &MRI);

225

226 static bool getUsedBitsInStore(unsigned Opc, BitVector &Bits,

227 uint16_t Begin);

228 static bool getUsedBits(unsigned Opc, unsigned OpN, BitVector &Bits,

229 uint16_t Begin, const HexagonInstrInfo &HII);

230

231 static const TargetRegisterClass *getFinalVRegClass(

232 const BitTracker::RegisterRef &RR, MachineRegisterInfo &MRI);

233 static bool isTransparentCopy(const BitTracker::RegisterRef &RD,

234 const BitTracker::RegisterRef &RS, MachineRegisterInfo &MRI);

235

236 private:

237 MachineDominatorTree *MDT = nullptr;

238

239 bool visitBlock(MachineBasicBlock &B, Transformation &T, RegisterSet &AVs);

240 static bool hasTiedUse(unsigned Reg, MachineRegisterInfo &MRI,

241 unsigned NewSub = Hexagon::NoSubRegister);

242 };

243

244 using HBS = HexagonBitSimplify;

245

246

247

248

249 class Transformation {

250 public:

251 bool TopDown;

252

253 Transformation(bool TD) : TopDown(TD) {}

254 virtual ~Transformation() = default;

255

256 virtual bool processBlock(MachineBasicBlock &B, const RegisterSet &AVs) = 0;

257 };

258

259}

260

261char HexagonBitSimplify::ID = 0;

262

264 "Hexagon bit simplification", false, false)

268

269bool HexagonBitSimplify::visitBlock(MachineBasicBlock &B, Transformation &T,

270 RegisterSet &AVs) {

272

273 if (T.TopDown)

274 Changed = T.processBlock(B, AVs);

275

276 RegisterSet Defs;

277 for (auto &I : B)

278 getInstrDefs(I, Defs);

279 RegisterSet NewAVs = AVs;

280 NewAVs.insert(Defs);

281

283 Changed |= visitBlock(*(DTN->getBlock()), T, NewAVs);

284

285 if (T.TopDown)

286 Changed |= T.processBlock(B, AVs);

287

289}

290

291

292

293

294void HexagonBitSimplify::getInstrDefs(const MachineInstr &MI,

295 RegisterSet &Defs) {

296 for (auto &Op : MI.operands()) {

297 if (Op.isReg() || Op.isDef())

298 continue;

300 if (R.isVirtual())

301 continue;

302 Defs.insert(R);

303 }

304}

305

306void HexagonBitSimplify::getInstrUses(const MachineInstr &MI,

308 for (auto &Op : MI.operands()) {

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

310 continue;

312 if (R.isVirtual())

313 continue;

314 Uses.insert(R);

315 }

316}

317

318

319bool HexagonBitSimplify::isEqual(const BitTracker::RegisterCell &RC1,

320 uint16_t B1, const BitTracker::RegisterCell &RC2, uint16_t B2,

321 uint16_t W) {

322 for (uint16_t i = 0; i < W; ++i) {

323

325 return false;

326

328 return false;

329 if (RC1[B1+i] != RC2[B2+i])

330 return false;

331 }

332 return true;

333}

334

335bool HexagonBitSimplify::isZero(const BitTracker::RegisterCell &RC,

336 uint16_t B, uint16_t W) {

338 for (uint16_t i = B; i < B+W; ++i)

339 if (!RC[i].is(0))

340 return false;

341 return true;

342}

343

344bool HexagonBitSimplify::getConst(const BitTracker::RegisterCell &RC,

345 uint16_t B, uint16_t W, uint64_t &U) {

347 int64_t T = 0;

348 for (uint16_t i = B+W; i > B; --i) {

349 const BitTracker::BitValue &BV = RC[i-1];

350 T <<= 1;

351 if (BV.is(1))

352 T |= 1;

353 else if (!BV.is(0))

354 return false;

355 }

356 U = T;

357 return true;

358}

359

360bool HexagonBitSimplify::replaceReg(Register OldR, Register NewR,

361 MachineRegisterInfo &MRI) {

363 return false;

364 auto Begin = MRI.use_begin(OldR), End = MRI.use_end();

365 decltype(End) NextI;

366 for (auto I = Begin; I != End; I = NextI) {

367 NextI = std::next(I);

368 I->setReg(NewR);

369 }

370 return Begin != End;

371}

372

373bool HexagonBitSimplify::replaceRegWithSub(Register OldR, Register NewR,

374 unsigned NewSR,

375 MachineRegisterInfo &MRI) {

377 return false;

378 if (hasTiedUse(OldR, MRI, NewSR))

379 return false;

380 auto Begin = MRI.use_begin(OldR), End = MRI.use_end();

381 decltype(End) NextI;

382 for (auto I = Begin; I != End; I = NextI) {

383 NextI = std::next(I);

384 I->setReg(NewR);

385 I->setSubReg(NewSR);

386 }

387 return Begin != End;

388}

389

390bool HexagonBitSimplify::replaceSubWithSub(Register OldR, unsigned OldSR,

391 Register NewR, unsigned NewSR,

392 MachineRegisterInfo &MRI) {

394 return false;

395 if (OldSR != NewSR && hasTiedUse(OldR, MRI, NewSR))

396 return false;

397 auto Begin = MRI.use_begin(OldR), End = MRI.use_end();

398 decltype(End) NextI;

399 for (auto I = Begin; I != End; I = NextI) {

400 NextI = std::next(I);

401 if (I->getSubReg() != OldSR)

402 continue;

403 I->setReg(NewR);

404 I->setSubReg(NewSR);

405 }

406 return Begin != End;

407}

408

409

410

411

412bool HexagonBitSimplify::getSubregMask(const BitTracker::RegisterRef &RR,

413 unsigned &Begin, unsigned &Width, MachineRegisterInfo &MRI) {

414 const TargetRegisterClass *RC = MRI.getRegClass(RR.Reg);

415 if (RR.Sub == 0) {

416 Begin = 0;

417 Width = MRI.getTargetRegisterInfo()->getRegSizeInBits(*RC);

418 return true;

419 }

420

421 Begin = 0;

422

423 switch (RC->getID()) {

424 case Hexagon::DoubleRegsRegClassID:

425 case Hexagon::HvxWRRegClassID:

426 Width = MRI.getTargetRegisterInfo()->getRegSizeInBits(*RC) / 2;

427 if (RR.Sub == Hexagon::isub_hi || RR.Sub == Hexagon::vsub_hi)

428 Begin = Width;

429 break;

430 default:

431 return false;

432 }

433 return true;

434}

435

436

437

438

439bool HexagonBitSimplify::parseRegSequence(const MachineInstr &I,

440 BitTracker::RegisterRef &SL, BitTracker::RegisterRef &SH,

441 const MachineRegisterInfo &MRI) {

442 assert(I.getOpcode() == TargetOpcode::REG_SEQUENCE);

443 unsigned Sub1 = I.getOperand(2).getImm(), Sub2 = I.getOperand(4).getImm();

444 auto &DstRC = *MRI.getRegClass(I.getOperand(0).getReg());

445 auto &HRI = static_cast<const HexagonRegisterInfo&>(

446 *MRI.getTargetRegisterInfo());

447 unsigned SubLo = HRI.getHexagonSubRegIndex(DstRC, Hexagon::ps_sub_lo);

448 unsigned SubHi = HRI.getHexagonSubRegIndex(DstRC, Hexagon::ps_sub_hi);

449 assert((Sub1 == SubLo && Sub2 == SubHi) || (Sub1 == SubHi && Sub2 == SubLo));

450 if (Sub1 == SubLo && Sub2 == SubHi) {

451 SL = I.getOperand(1);

452 SH = I.getOperand(3);

453 return true;

454 }

455 if (Sub1 == SubHi && Sub2 == SubLo) {

456 SH = I.getOperand(1);

457 SL = I.getOperand(3);

458 return true;

459 }

460 return false;

461}

462

463

464

465

466

467

468

469bool HexagonBitSimplify::getUsedBitsInStore(unsigned Opc, BitVector &Bits,

470 uint16_t Begin) {

471 using namespace Hexagon;

472

473 switch (Opc) {

474

475 case S2_storerb_io:

476 case S2_storerbnew_io:

477 case S2_pstorerbt_io:

478 case S2_pstorerbf_io:

479 case S4_pstorerbtnew_io:

480 case S4_pstorerbfnew_io:

481 case S2_pstorerbnewt_io:

482 case S2_pstorerbnewf_io:

483 case S4_pstorerbnewtnew_io:

484 case S4_pstorerbnewfnew_io:

485 case S2_storerb_pi:

486 case S2_storerbnew_pi:

487 case S2_pstorerbt_pi:

488 case S2_pstorerbf_pi:

489 case S2_pstorerbtnew_pi:

490 case S2_pstorerbfnew_pi:

491 case S2_pstorerbnewt_pi:

492 case S2_pstorerbnewf_pi:

493 case S2_pstorerbnewtnew_pi:

494 case S2_pstorerbnewfnew_pi:

495 case S4_storerb_ap:

496 case S4_storerbnew_ap:

497 case S2_storerb_pr:

498 case S2_storerbnew_pr:

499 case S4_storerb_ur:

500 case S4_storerbnew_ur:

501 case S2_storerb_pbr:

502 case S2_storerbnew_pbr:

503 case S2_storerb_pci:

504 case S2_storerbnew_pci:

505 case S2_storerb_pcr:

506 case S2_storerbnew_pcr:

507 case S4_storerb_rr:

508 case S4_storerbnew_rr:

509 case S4_pstorerbt_rr:

510 case S4_pstorerbf_rr:

511 case S4_pstorerbtnew_rr:

512 case S4_pstorerbfnew_rr:

513 case S4_pstorerbnewt_rr:

514 case S4_pstorerbnewf_rr:

515 case S4_pstorerbnewtnew_rr:

516 case S4_pstorerbnewfnew_rr:

517 case S2_storerbgp:

518 case S2_storerbnewgp:

519 case S4_pstorerbt_abs:

520 case S4_pstorerbf_abs:

521 case S4_pstorerbtnew_abs:

522 case S4_pstorerbfnew_abs:

523 case S4_pstorerbnewt_abs:

524 case S4_pstorerbnewf_abs:

525 case S4_pstorerbnewtnew_abs:

526 case S4_pstorerbnewfnew_abs:

527 Bits.set(Begin, Begin+8);

528 return true;

529

530

531 case S2_storerh_io:

532 case S2_storerhnew_io:

533 case S2_pstorerht_io:

534 case S2_pstorerhf_io:

535 case S4_pstorerhtnew_io:

536 case S4_pstorerhfnew_io:

537 case S2_pstorerhnewt_io:

538 case S2_pstorerhnewf_io:

539 case S4_pstorerhnewtnew_io:

540 case S4_pstorerhnewfnew_io:

541 case S2_storerh_pi:

542 case S2_storerhnew_pi:

543 case S2_pstorerht_pi:

544 case S2_pstorerhf_pi:

545 case S2_pstorerhtnew_pi:

546 case S2_pstorerhfnew_pi:

547 case S2_pstorerhnewt_pi:

548 case S2_pstorerhnewf_pi:

549 case S2_pstorerhnewtnew_pi:

550 case S2_pstorerhnewfnew_pi:

551 case S4_storerh_ap:

552 case S4_storerhnew_ap:

553 case S2_storerh_pr:

554 case S2_storerhnew_pr:

555 case S4_storerh_ur:

556 case S4_storerhnew_ur:

557 case S2_storerh_pbr:

558 case S2_storerhnew_pbr:

559 case S2_storerh_pci:

560 case S2_storerhnew_pci:

561 case S2_storerh_pcr:

562 case S2_storerhnew_pcr:

563 case S4_storerh_rr:

564 case S4_pstorerht_rr:

565 case S4_pstorerhf_rr:

566 case S4_pstorerhtnew_rr:

567 case S4_pstorerhfnew_rr:

568 case S4_storerhnew_rr:

569 case S4_pstorerhnewt_rr:

570 case S4_pstorerhnewf_rr:

571 case S4_pstorerhnewtnew_rr:

572 case S4_pstorerhnewfnew_rr:

573 case S2_storerhgp:

574 case S2_storerhnewgp:

575 case S4_pstorerht_abs:

576 case S4_pstorerhf_abs:

577 case S4_pstorerhtnew_abs:

578 case S4_pstorerhfnew_abs:

579 case S4_pstorerhnewt_abs:

580 case S4_pstorerhnewf_abs:

581 case S4_pstorerhnewtnew_abs:

582 case S4_pstorerhnewfnew_abs:

583 Bits.set(Begin, Begin+16);

584 return true;

585

586

587 case S2_storerf_io:

588 case S2_pstorerft_io:

589 case S2_pstorerff_io:

590 case S4_pstorerftnew_io:

591 case S4_pstorerffnew_io:

592 case S2_storerf_pi:

593 case S2_pstorerft_pi:

594 case S2_pstorerff_pi:

595 case S2_pstorerftnew_pi:

596 case S2_pstorerffnew_pi:

597 case S4_storerf_ap:

598 case S2_storerf_pr:

599 case S4_storerf_ur:

600 case S2_storerf_pbr:

601 case S2_storerf_pci:

602 case S2_storerf_pcr:

603 case S4_storerf_rr:

604 case S4_pstorerft_rr:

605 case S4_pstorerff_rr:

606 case S4_pstorerftnew_rr:

607 case S4_pstorerffnew_rr:

608 case S2_storerfgp:

609 case S4_pstorerft_abs:

610 case S4_pstorerff_abs:

611 case S4_pstorerftnew_abs:

612 case S4_pstorerffnew_abs:

613 Bits.set(Begin+16, Begin+32);

614 return true;

615 }

616

617 return false;

618}

619

620

621

622

623

624

625

626

627

628bool HexagonBitSimplify::getUsedBits(unsigned Opc, unsigned OpN,

629 BitVector &Bits, uint16_t Begin, const HexagonInstrInfo &HII) {

630 using namespace Hexagon;

631

632 const MCInstrDesc &D = HII.get(Opc);

633 if (D.mayStore()) {

634 if (OpN == D.getNumOperands()-1)

635 return getUsedBitsInStore(Opc, Bits, Begin);

636 return false;

637 }

638

639 switch (Opc) {

640

641 case A2_sxtb:

642 case A2_zxtb:

643 case A4_cmpbeqi:

644 case A4_cmpbgti:

645 case A4_cmpbgtui:

646 if (OpN == 1) {

647 Bits.set(Begin, Begin+8);

648 return true;

649 }

650 break;

651

652

653 case A2_aslh:

654 case A2_sxth:

655 case A2_zxth:

656 case A4_cmpheqi:

657 case A4_cmphgti:

658 case A4_cmphgtui:

659 if (OpN == 1) {

660 Bits.set(Begin, Begin+16);

661 return true;

662 }

663 break;

664

665

666 case A2_asrh:

667 if (OpN == 1) {

668 Bits.set(Begin+16, Begin+32);

669 return true;

670 }

671 break;

672

673

674 case A4_cmpbeq:

675 case A4_cmpbgt:

676 case A4_cmpbgtu:

677 if (OpN == 1) {

678 Bits.set(Begin, Begin+8);

679 return true;

680 }

681 break;

682

683

684 case A4_cmpheq:

685 case A4_cmphgt:

686 case A4_cmphgtu:

687 case A2_addh_h16_ll:

688 case A2_addh_h16_sat_ll:

689 case A2_addh_l16_ll:

690 case A2_addh_l16_sat_ll:

691 case A2_combine_ll:

692 case A2_subh_h16_ll:

693 case A2_subh_h16_sat_ll:

694 case A2_subh_l16_ll:

695 case A2_subh_l16_sat_ll:

696 case M2_mpy_acc_ll_s0:

697 case M2_mpy_acc_ll_s1:

698 case M2_mpy_acc_sat_ll_s0:

699 case M2_mpy_acc_sat_ll_s1:

700 case M2_mpy_ll_s0:

701 case M2_mpy_ll_s1:

702 case M2_mpy_nac_ll_s0:

703 case M2_mpy_nac_ll_s1:

704 case M2_mpy_nac_sat_ll_s0:

705 case M2_mpy_nac_sat_ll_s1:

706 case M2_mpy_rnd_ll_s0:

707 case M2_mpy_rnd_ll_s1:

708 case M2_mpy_sat_ll_s0:

709 case M2_mpy_sat_ll_s1:

710 case M2_mpy_sat_rnd_ll_s0:

711 case M2_mpy_sat_rnd_ll_s1:

712 case M2_mpyd_acc_ll_s0:

713 case M2_mpyd_acc_ll_s1:

714 case M2_mpyd_ll_s0:

715 case M2_mpyd_ll_s1:

716 case M2_mpyd_nac_ll_s0:

717 case M2_mpyd_nac_ll_s1:

718 case M2_mpyd_rnd_ll_s0:

719 case M2_mpyd_rnd_ll_s1:

720 case M2_mpyu_acc_ll_s0:

721 case M2_mpyu_acc_ll_s1:

722 case M2_mpyu_ll_s0:

723 case M2_mpyu_ll_s1:

724 case M2_mpyu_nac_ll_s0:

725 case M2_mpyu_nac_ll_s1:

726 case M2_mpyud_acc_ll_s0:

727 case M2_mpyud_acc_ll_s1:

728 case M2_mpyud_ll_s0:

729 case M2_mpyud_ll_s1:

730 case M2_mpyud_nac_ll_s0:

731 case M2_mpyud_nac_ll_s1:

732 if (OpN == 1 || OpN == 2) {

733 Bits.set(Begin, Begin+16);

734 return true;

735 }

736 break;

737

738

739 case A2_addh_h16_lh:

740 case A2_addh_h16_sat_lh:

741 case A2_combine_lh:

742 case A2_subh_h16_lh:

743 case A2_subh_h16_sat_lh:

744 case M2_mpy_acc_lh_s0:

745 case M2_mpy_acc_lh_s1:

746 case M2_mpy_acc_sat_lh_s0:

747 case M2_mpy_acc_sat_lh_s1:

748 case M2_mpy_lh_s0:

749 case M2_mpy_lh_s1:

750 case M2_mpy_nac_lh_s0:

751 case M2_mpy_nac_lh_s1:

752 case M2_mpy_nac_sat_lh_s0:

753 case M2_mpy_nac_sat_lh_s1:

754 case M2_mpy_rnd_lh_s0:

755 case M2_mpy_rnd_lh_s1:

756 case M2_mpy_sat_lh_s0:

757 case M2_mpy_sat_lh_s1:

758 case M2_mpy_sat_rnd_lh_s0:

759 case M2_mpy_sat_rnd_lh_s1:

760 case M2_mpyd_acc_lh_s0:

761 case M2_mpyd_acc_lh_s1:

762 case M2_mpyd_lh_s0:

763 case M2_mpyd_lh_s1:

764 case M2_mpyd_nac_lh_s0:

765 case M2_mpyd_nac_lh_s1:

766 case M2_mpyd_rnd_lh_s0:

767 case M2_mpyd_rnd_lh_s1:

768 case M2_mpyu_acc_lh_s0:

769 case M2_mpyu_acc_lh_s1:

770 case M2_mpyu_lh_s0:

771 case M2_mpyu_lh_s1:

772 case M2_mpyu_nac_lh_s0:

773 case M2_mpyu_nac_lh_s1:

774 case M2_mpyud_acc_lh_s0:

775 case M2_mpyud_acc_lh_s1:

776 case M2_mpyud_lh_s0:

777 case M2_mpyud_lh_s1:

778 case M2_mpyud_nac_lh_s0:

779 case M2_mpyud_nac_lh_s1:

780

781 case A2_addh_l16_hl:

782 case A2_addh_l16_sat_hl:

783 case A2_subh_l16_hl:

784 case A2_subh_l16_sat_hl:

785 if (OpN == 1) {

786 Bits.set(Begin, Begin+16);

787 return true;

788 }

789 if (OpN == 2) {

790 Bits.set(Begin+16, Begin+32);

791 return true;

792 }

793 break;

794

795

796 case A2_addh_h16_hl:

797 case A2_addh_h16_sat_hl:

798 case A2_combine_hl:

799 case A2_subh_h16_hl:

800 case A2_subh_h16_sat_hl:

801 case M2_mpy_acc_hl_s0:

802 case M2_mpy_acc_hl_s1:

803 case M2_mpy_acc_sat_hl_s0:

804 case M2_mpy_acc_sat_hl_s1:

805 case M2_mpy_hl_s0:

806 case M2_mpy_hl_s1:

807 case M2_mpy_nac_hl_s0:

808 case M2_mpy_nac_hl_s1:

809 case M2_mpy_nac_sat_hl_s0:

810 case M2_mpy_nac_sat_hl_s1:

811 case M2_mpy_rnd_hl_s0:

812 case M2_mpy_rnd_hl_s1:

813 case M2_mpy_sat_hl_s0:

814 case M2_mpy_sat_hl_s1:

815 case M2_mpy_sat_rnd_hl_s0:

816 case M2_mpy_sat_rnd_hl_s1:

817 case M2_mpyd_acc_hl_s0:

818 case M2_mpyd_acc_hl_s1:

819 case M2_mpyd_hl_s0:

820 case M2_mpyd_hl_s1:

821 case M2_mpyd_nac_hl_s0:

822 case M2_mpyd_nac_hl_s1:

823 case M2_mpyd_rnd_hl_s0:

824 case M2_mpyd_rnd_hl_s1:

825 case M2_mpyu_acc_hl_s0:

826 case M2_mpyu_acc_hl_s1:

827 case M2_mpyu_hl_s0:

828 case M2_mpyu_hl_s1:

829 case M2_mpyu_nac_hl_s0:

830 case M2_mpyu_nac_hl_s1:

831 case M2_mpyud_acc_hl_s0:

832 case M2_mpyud_acc_hl_s1:

833 case M2_mpyud_hl_s0:

834 case M2_mpyud_hl_s1:

835 case M2_mpyud_nac_hl_s0:

836 case M2_mpyud_nac_hl_s1:

837 if (OpN == 1) {

838 Bits.set(Begin+16, Begin+32);

839 return true;

840 }

841 if (OpN == 2) {

842 Bits.set(Begin, Begin+16);

843 return true;

844 }

845 break;

846

847

848 case A2_addh_h16_hh:

849 case A2_addh_h16_sat_hh:

850 case A2_combine_hh:

851 case A2_subh_h16_hh:

852 case A2_subh_h16_sat_hh:

853 case M2_mpy_acc_hh_s0:

854 case M2_mpy_acc_hh_s1:

855 case M2_mpy_acc_sat_hh_s0:

856 case M2_mpy_acc_sat_hh_s1:

857 case M2_mpy_hh_s0:

858 case M2_mpy_hh_s1:

859 case M2_mpy_nac_hh_s0:

860 case M2_mpy_nac_hh_s1:

861 case M2_mpy_nac_sat_hh_s0:

862 case M2_mpy_nac_sat_hh_s1:

863 case M2_mpy_rnd_hh_s0:

864 case M2_mpy_rnd_hh_s1:

865 case M2_mpy_sat_hh_s0:

866 case M2_mpy_sat_hh_s1:

867 case M2_mpy_sat_rnd_hh_s0:

868 case M2_mpy_sat_rnd_hh_s1:

869 case M2_mpyd_acc_hh_s0:

870 case M2_mpyd_acc_hh_s1:

871 case M2_mpyd_hh_s0:

872 case M2_mpyd_hh_s1:

873 case M2_mpyd_nac_hh_s0:

874 case M2_mpyd_nac_hh_s1:

875 case M2_mpyd_rnd_hh_s0:

876 case M2_mpyd_rnd_hh_s1:

877 case M2_mpyu_acc_hh_s0:

878 case M2_mpyu_acc_hh_s1:

879 case M2_mpyu_hh_s0:

880 case M2_mpyu_hh_s1:

881 case M2_mpyu_nac_hh_s0:

882 case M2_mpyu_nac_hh_s1:

883 case M2_mpyud_acc_hh_s0:

884 case M2_mpyud_acc_hh_s1:

885 case M2_mpyud_hh_s0:

886 case M2_mpyud_hh_s1:

887 case M2_mpyud_nac_hh_s0:

888 case M2_mpyud_nac_hh_s1:

889 if (OpN == 1 || OpN == 2) {

890 Bits.set(Begin+16, Begin+32);

891 return true;

892 }

893 break;

894 }

895

896 return false;

897}

898

899

900

901

902const TargetRegisterClass *HexagonBitSimplify::getFinalVRegClass(

903 const BitTracker::RegisterRef &RR, MachineRegisterInfo &MRI) {

905 return nullptr;

906 auto *RC = MRI.getRegClass(RR.Reg);

907 if (RR.Sub == 0)

908 return RC;

909 auto &HRI = static_cast<const HexagonRegisterInfo&>(

910 *MRI.getTargetRegisterInfo());

911

912 auto VerifySR = [&HRI] (const TargetRegisterClass *RC, unsigned Sub) -> void {

913 (void)HRI;

916 };

917

918 switch (RC->getID()) {

919 case Hexagon::DoubleRegsRegClassID:

920 VerifySR(RC, RR.Sub);

921 return &Hexagon::IntRegsRegClass;

922 case Hexagon::HvxWRRegClassID:

923 VerifySR(RC, RR.Sub);

924 return &Hexagon::HvxVRRegClass;

925 }

926 return nullptr;

927}

928

929

930

931

932

933bool HexagonBitSimplify::isTransparentCopy(const BitTracker::RegisterRef &RD,

934 const BitTracker::RegisterRef &RS, MachineRegisterInfo &MRI) {

936 return false;

937

938 auto *DRC = getFinalVRegClass(RD, MRI);

939 if (!DRC)

940 return false;

941

942 return DRC == getFinalVRegClass(RS, MRI);

943}

944

945bool HexagonBitSimplify::hasTiedUse(unsigned Reg, MachineRegisterInfo &MRI,

946 unsigned NewSub) {

948 return false;

950 [NewSub] (const MachineOperand &Op) -> bool {

951 return Op.getSubReg() != NewSub && Op.isTied();

952 });

953}

954

955namespace {

956

957 class DeadCodeElimination {

958 public:

959 DeadCodeElimination(MachineFunction &mf, MachineDominatorTree &mdt)

960 : MF(mf), HII(*MF.getSubtarget().getInstrInfo()),

961 MDT(mdt), MRI(mf.getRegInfo()) {}

962

963 bool run() {

965 }

966

967 private:

968 bool isDead(unsigned R) const;

970

971 MachineFunction &MF;

972 const HexagonInstrInfo &HII;

973 MachineDominatorTree &MDT;

974 MachineRegisterInfo &MRI;

975 };

976

977}

978

979bool DeadCodeElimination::isDead(unsigned R) const {

980 for (const MachineOperand &MO : MRI.use_operands(R)) {

981 const MachineInstr *UseI = MO.getParent();

983 continue;

984 if (UseI->isPHI()) {

987 if (DR == R)

988 continue;

989 }

990 return false;

991 }

992 return true;

993}

994

997

999 Changed |= runOnNode(DTN);

1000

1001 MachineBasicBlock *B = N->getBlock();

1002 std::vector<MachineInstr*> Instrs;

1004 Instrs.push_back(&MI);

1005

1006 for (auto *MI : Instrs) {

1007 unsigned Opc = MI->getOpcode();

1008

1009

1010 if (Opc == TargetOpcode::LIFETIME_START ||

1011 Opc == TargetOpcode::LIFETIME_END)

1012 continue;

1013 bool Store = false;

1014 if (MI->isInlineAsm())

1015 continue;

1016

1017 if (MI->isPHI() && MI->isSafeToMove(Store))

1018 continue;

1019

1020 bool AllDead = true;

1021 SmallVector<unsigned,2> Regs;

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

1023 if (Op.isReg() || Op.isDef())

1024 continue;

1026 if (R.isVirtual() || isDead(R)) {

1027 AllDead = false;

1028 break;

1029 }

1031 }

1032 if (!AllDead)

1033 continue;

1034

1035 B->erase(MI);

1036 for (unsigned Reg : Regs)

1037 MRI.markUsesInDebugValueAsUndef(Reg);

1039 }

1040

1042}

1043

1044namespace {

1045

1046

1047

1048

1049

1050

1051

1052

1053

1054

1055

1056 class RedundantInstrElimination : public Transformation {

1057 public:

1058 RedundantInstrElimination(BitTracker &bt, const HexagonInstrInfo &hii,

1059 const HexagonRegisterInfo &hri, MachineRegisterInfo &mri)

1060 : Transformation(true), HII(hii), HRI(hri), MRI(mri), BT(bt) {}

1061

1062 bool processBlock(MachineBasicBlock &B, const RegisterSet &AVs) override;

1063

1064 private:

1065 bool isLossyShiftLeft(const MachineInstr &MI, unsigned OpN,

1066 unsigned &LostB, unsigned &LostE);

1067 bool isLossyShiftRight(const MachineInstr &MI, unsigned OpN,

1068 unsigned &LostB, unsigned &LostE);

1069 bool computeUsedBits(unsigned Reg, BitVector &Bits);

1070 bool computeUsedBits(const MachineInstr &MI, unsigned OpN, BitVector &Bits,

1071 uint16_t Begin);

1072 bool usedBitsEqual(BitTracker::RegisterRef RD, BitTracker::RegisterRef RS);

1073

1074 const HexagonInstrInfo &HII;

1075 const HexagonRegisterInfo &HRI;

1076 MachineRegisterInfo &MRI;

1077 BitTracker &BT;

1078 };

1079

1080}

1081

1082

1083

1084

1085bool RedundantInstrElimination::isLossyShiftLeft(const MachineInstr &MI,

1086 unsigned OpN, unsigned &LostB, unsigned &LostE) {

1087 using namespace Hexagon;

1088

1089 unsigned Opc = MI.getOpcode();

1090 unsigned ImN, RegN, Width;

1091 switch (Opc) {

1092 case S2_asl_i_p:

1093 ImN = 2;

1094 RegN = 1;

1095 Width = 64;

1096 break;

1097 case S2_asl_i_p_acc:

1098 case S2_asl_i_p_and:

1099 case S2_asl_i_p_nac:

1100 case S2_asl_i_p_or:

1101 case S2_asl_i_p_xacc:

1102 ImN = 3;

1103 RegN = 2;

1104 Width = 64;

1105 break;

1106 case S2_asl_i_r:

1107 ImN = 2;

1108 RegN = 1;

1109 Width = 32;

1110 break;

1111 case S2_addasl_rrri:

1112 case S4_andi_asl_ri:

1113 case S4_ori_asl_ri:

1114 case S4_addi_asl_ri:

1115 case S4_subi_asl_ri:

1116 case S2_asl_i_r_acc:

1117 case S2_asl_i_r_and:

1118 case S2_asl_i_r_nac:

1119 case S2_asl_i_r_or:

1120 case S2_asl_i_r_sat:

1121 case S2_asl_i_r_xacc:

1122 ImN = 3;

1123 RegN = 2;

1124 Width = 32;

1125 break;

1126 default:

1127 return false;

1128 }

1129

1130 if (RegN != OpN)

1131 return false;

1132

1133 assert(MI.getOperand(ImN).isImm());

1134 unsigned S = MI.getOperand(ImN).getImm();

1135 if (S == 0)

1136 return false;

1137 LostB = Width-S;

1138 LostE = Width;

1139 return true;

1140}

1141

1142

1143

1144

1145bool RedundantInstrElimination::isLossyShiftRight(const MachineInstr &MI,

1146 unsigned OpN, unsigned &LostB, unsigned &LostE) {

1147 using namespace Hexagon;

1148

1149 unsigned Opc = MI.getOpcode();

1150 unsigned ImN, RegN;

1151 switch (Opc) {

1152 case S2_asr_i_p:

1153 case S2_lsr_i_p:

1154 ImN = 2;

1155 RegN = 1;

1156 break;

1157 case S2_asr_i_p_acc:

1158 case S2_asr_i_p_and:

1159 case S2_asr_i_p_nac:

1160 case S2_asr_i_p_or:

1161 case S2_lsr_i_p_acc:

1162 case S2_lsr_i_p_and:

1163 case S2_lsr_i_p_nac:

1164 case S2_lsr_i_p_or:

1165 case S2_lsr_i_p_xacc:

1166 ImN = 3;

1167 RegN = 2;

1168 break;

1169 case S2_asr_i_r:

1170 case S2_lsr_i_r:

1171 ImN = 2;

1172 RegN = 1;

1173 break;

1174 case S4_andi_lsr_ri:

1175 case S4_ori_lsr_ri:

1176 case S4_addi_lsr_ri:

1177 case S4_subi_lsr_ri:

1178 case S2_asr_i_r_acc:

1179 case S2_asr_i_r_and:

1180 case S2_asr_i_r_nac:

1181 case S2_asr_i_r_or:

1182 case S2_lsr_i_r_acc:

1183 case S2_lsr_i_r_and:

1184 case S2_lsr_i_r_nac:

1185 case S2_lsr_i_r_or:

1186 case S2_lsr_i_r_xacc:

1187 ImN = 3;

1188 RegN = 2;

1189 break;

1190

1191 default:

1192 return false;

1193 }

1194

1195 if (RegN != OpN)

1196 return false;

1197

1198 assert(MI.getOperand(ImN).isImm());

1199 unsigned S = MI.getOperand(ImN).getImm();

1200 LostB = 0;

1201 LostE = S;

1202 return true;

1203}

1204

1205

1206

1207

1208

1209bool RedundantInstrElimination::computeUsedBits(unsigned Reg, BitVector &Bits) {

1210 BitVector Used(Bits.size());

1212 std::vector Pending;

1213 Pending.push_back(Reg);

1214

1215 for (unsigned i = 0; i < Pending.size(); ++i) {

1216 unsigned R = Pending[i];

1217 if (Visited.has(R))

1218 continue;

1219 Visited.insert(R);

1220 for (auto I = MRI.use_begin(R), E = MRI.use_end(); I != E; ++I) {

1221 BitTracker::RegisterRef UR = *I;

1222 unsigned B, W;

1223 if (!HBS::getSubregMask(UR, B, W, MRI))

1224 return false;

1225 MachineInstr &UseI = *I->getParent();

1229 return false;

1230 Pending.push_back(DefR);

1231 } else {

1232 if (!computeUsedBits(UseI, I.getOperandNo(), Used, B))

1233 return false;

1234 }

1235 }

1236 }

1238 return true;

1239}

1240

1241

1242

1243

1244

1245

1246

1247

1248

1249

1250

1251

1252

1253

1254

1255bool RedundantInstrElimination::computeUsedBits(const MachineInstr &MI,

1256 unsigned OpN, BitVector &Bits, uint16_t Begin) {

1257 unsigned Opc = MI.getOpcode();

1258 BitVector T(Bits.size());

1259 bool GotBits = HBS::getUsedBits(Opc, OpN, T, Begin, HII);

1260

1261

1262

1263 unsigned LB, LE;

1264 if (isLossyShiftLeft(MI, OpN, LB, LE) || isLossyShiftRight(MI, OpN, LB, LE)) {

1265 assert(MI.getOperand(OpN).isReg());

1266 BitTracker::RegisterRef RR = MI.getOperand(OpN);

1267 const TargetRegisterClass *RC = HBS::getFinalVRegClass(RR, MRI);

1268 uint16_t Width = HRI.getRegSizeInBits(*RC);

1269

1270 if (!GotBits)

1271 T.set(Begin, Begin+Width);

1272 assert(LB <= LE && LB < Width && LE <= Width);

1273 T.reset(Begin+LB, Begin+LE);

1274 GotBits = true;

1275 }

1276 if (GotBits)

1278 return GotBits;

1279}

1280

1281

1282

1283bool RedundantInstrElimination::usedBitsEqual(BitTracker::RegisterRef RD,

1284 BitTracker::RegisterRef RS) {

1285 const BitTracker::RegisterCell &DC = BT.lookup(RD.Reg);

1286 const BitTracker::RegisterCell &SC = BT.lookup(RS.Reg);

1287

1288 unsigned DB, DW;

1289 if (!HBS::getSubregMask(RD, DB, DW, MRI))

1290 return false;

1291 unsigned SB, SW;

1292 if (!HBS::getSubregMask(RS, SB, SW, MRI))

1293 return false;

1294 if (SW != DW)

1295 return false;

1296

1298 if (!computeUsedBits(RD.Reg, Used))

1299 return false;

1300

1301 for (unsigned i = 0; i != DW; ++i)

1302 if (Used[i+DB] && DC[DB+i] != SC[SB+i])

1303 return false;

1304 return true;

1305}

1306

1307bool RedundantInstrElimination::processBlock(MachineBasicBlock &B,

1310 return false;

1312

1313 for (auto I = B.begin(), E = B.end(); I != E; ++I) {

1314 MachineInstr *MI = &*I;

1315

1316 if (MI->getOpcode() == TargetOpcode::COPY)

1317 continue;

1318 if (MI->isPHI() || MI->hasUnmodeledSideEffects() || MI->isInlineAsm())

1319 continue;

1320 unsigned NumD = MI->getDesc().getNumDefs();

1321 if (NumD != 1)

1322 continue;

1323

1324 BitTracker::RegisterRef RD = MI->getOperand(0);

1326 continue;

1327 const BitTracker::RegisterCell &DC = BT.lookup(RD.Reg);

1329

1330

1331 for (auto &Op : MI->uses()) {

1332 if (Op.isReg())

1333 continue;

1334 BitTracker::RegisterRef RS = Op;

1336 continue;

1337 if (!HBS::isTransparentCopy(RD, RS, MRI))

1338 continue;

1339

1340 unsigned BN, BW;

1341 if (!HBS::getSubregMask(RS, BN, BW, MRI))

1342 continue;

1343

1344 const BitTracker::RegisterCell &SC = BT.lookup(RS.Reg);

1345 if (!usedBitsEqual(RD, RS) && !HBS::isEqual(DC, 0, SC, BN, BW))

1346 continue;

1347

1348

1350 const TargetRegisterClass *FRC = HBS::getFinalVRegClass(RD, MRI);

1351 Register NewR = MRI.createVirtualRegister(FRC);

1352 MachineInstr *CopyI =

1353 BuildMI(B, At, DL, HII.get(TargetOpcode::COPY), NewR)

1355 HBS::replaceSubWithSub(RD.Reg, RD.Sub, NewR, 0, MRI);

1356

1357

1358

1359

1360

1361

1362

1363

1364

1367 break;

1368 }

1369 }

1370

1372}

1373

1374namespace {

1375

1376

1377

1378 class ConstGeneration : public Transformation {

1379 public:

1380 ConstGeneration(BitTracker &bt, const HexagonInstrInfo &hii,

1381 MachineRegisterInfo &mri)

1382 : Transformation(true), HII(hii), MRI(mri), BT(bt) {}

1383

1384 bool processBlock(MachineBasicBlock &B, const RegisterSet &AVs) override;

1385 static bool isTfrConst(const MachineInstr &MI);

1386

1387 private:

1388 Register genTfrConst(const TargetRegisterClass *RC, int64_t C,

1391

1392 const HexagonInstrInfo &HII;

1393 MachineRegisterInfo &MRI;

1394 BitTracker &BT;

1395 };

1396

1397}

1398

1399bool ConstGeneration::isTfrConst(const MachineInstr &MI) {

1400 unsigned Opc = MI.getOpcode();

1401 switch (Opc) {

1402 case Hexagon::A2_combineii:

1403 case Hexagon::A4_combineii:

1404 case Hexagon::A2_tfrsi:

1405 case Hexagon::A2_tfrpi:

1406 case Hexagon::PS_true:

1407 case Hexagon::PS_false:

1408 case Hexagon::CONST32:

1409 case Hexagon::CONST64:

1410 return true;

1411 }

1412 return false;

1413}

1414

1415

1416

1417Register ConstGeneration::genTfrConst(const TargetRegisterClass *RC, int64_t C,

1418 MachineBasicBlock &B,

1422 if (RC == &Hexagon::IntRegsRegClass) {

1423 BuildMI(B, At, DL, HII.get(Hexagon::A2_tfrsi), Reg)

1425 return Reg;

1426 }

1427

1428 if (RC == &Hexagon::DoubleRegsRegClass) {

1430 BuildMI(B, At, DL, HII.get(Hexagon::A2_tfrpi), Reg)

1432 return Reg;

1433 }

1434

1437 unsigned Opc = isInt<8>(Lo) ? Hexagon::A2_combineii

1438 : Hexagon::A4_combineii;

1442 return Reg;

1443 }

1444 MachineFunction *MF = B.getParent();

1445 auto &HST = MF->getSubtarget();

1446

1447

1448 if (!HST.isTinyCore() ||

1450 BuildMI(B, At, DL, HII.get(Hexagon::CONST64), Reg)

1452 return Reg;

1453 }

1454 }

1455

1456 if (RC == &Hexagon::PredRegsRegClass) {

1457 unsigned Opc;

1458 if (C == 0)

1459 Opc = Hexagon::PS_false;

1460 else if ((C & 0xFF) == 0xFF)

1461 Opc = Hexagon::PS_true;

1462 else

1463 return 0;

1465 return Reg;

1466 }

1467

1468 return 0;

1469}

1470

1471bool ConstGeneration::processBlock(MachineBasicBlock &B, const RegisterSet&) {

1473 return false;

1476

1477 for (auto I = B.begin(), E = B.end(); I != E; ++I) {

1478 if (isTfrConst(*I))

1479 continue;

1480 Defs.clear();

1481 HBS::getInstrDefs(*I, Defs);

1482 if (Defs.count() != 1)

1483 continue;

1484 Register DR = Defs.find_first();

1486 continue;

1487 uint64_t U;

1488 const BitTracker::RegisterCell &DRC = BT.lookup(DR);

1489 if (HBS::getConst(DRC, 0, DRC.width(), U)) {

1490 int64_t C = U;

1492 auto At = I->isPHI() ? B.getFirstNonPHI() : I;

1493 Register ImmReg = genTfrConst(MRI.getRegClass(DR), C, B, At, DL);

1494 if (ImmReg) {

1495 HBS::replaceReg(DR, ImmReg, MRI);

1496 BT.put(ImmReg, DRC);

1498 }

1499 }

1500 }

1502}

1503

1504namespace {

1505

1506

1507

1508

1509 class CopyGeneration : public Transformation {

1510 public:

1511 CopyGeneration(BitTracker &bt, const HexagonInstrInfo &hii,

1512 const HexagonRegisterInfo &hri, MachineRegisterInfo &mri)

1513 : Transformation(true), HII(hii), HRI(hri), MRI(mri), BT(bt) {}

1514

1515 bool processBlock(MachineBasicBlock &B, const RegisterSet &AVs) override;

1516

1517 private:

1518 bool findMatch(const BitTracker::RegisterRef &Inp,

1519 BitTracker::RegisterRef &Out, const RegisterSet &AVs);

1520

1521 const HexagonInstrInfo &HII;

1522 const HexagonRegisterInfo &HRI;

1523 MachineRegisterInfo &MRI;

1524 BitTracker &BT;

1526 };

1527

1528

1529

1530 class CopyPropagation : public Transformation {

1531 public:

1532 CopyPropagation(const HexagonRegisterInfo &hri, MachineRegisterInfo &mri)

1533 : Transformation(false), HRI(hri), MRI(mri) {}

1534

1535 bool processBlock(MachineBasicBlock &B, const RegisterSet &AVs) override;

1536

1537 static bool isCopyReg(unsigned Opc, bool NoConv);

1538

1539 private:

1540 bool propagateRegCopy(MachineInstr &MI);

1541

1542 const HexagonRegisterInfo &HRI;

1543 MachineRegisterInfo &MRI;

1544 };

1545

1546}

1547

1548

1549

1550bool CopyGeneration::findMatch(const BitTracker::RegisterRef &Inp,

1551 BitTracker::RegisterRef &Out, const RegisterSet &AVs) {

1553 return false;

1554 const BitTracker::RegisterCell &InpRC = BT.lookup(Inp.Reg);

1555 auto *FRC = HBS::getFinalVRegClass(Inp, MRI);

1556 unsigned B, W;

1557 if (!HBS::getSubregMask(Inp, B, W, MRI))

1558 return false;

1559

1560 for (Register R = AVs.find_first(); R; R = AVs.find_next(R)) {

1561 if (BT.has(R) || Forbidden[R])

1562 continue;

1563 const BitTracker::RegisterCell &RC = BT.lookup(R);

1564 unsigned RW = RC.width();

1565 if (W == RW) {

1566 if (FRC != MRI.getRegClass(R))

1567 continue;

1568 if (!HBS::isTransparentCopy(R, Inp, MRI))

1569 continue;

1570 if (!HBS::isEqual(InpRC, B, RC, 0, W))

1571 continue;

1572 Out.Reg = R;

1573 Out.Sub = 0;

1574 return true;

1575 }

1576

1577

1578

1579 if (W*2 != RW)

1580 continue;

1581 if (MRI.getRegClass(R) != &Hexagon::DoubleRegsRegClass)

1582 continue;

1583

1584 if (HBS::isEqual(InpRC, B, RC, 0, W))

1585 Out.Sub = Hexagon::isub_lo;

1586 else if (HBS::isEqual(InpRC, B, RC, W, W))

1587 Out.Sub = Hexagon::isub_hi;

1588 else

1589 continue;

1590 Out.Reg = R;

1591 if (HBS::isTransparentCopy(Out, Inp, MRI))

1592 return true;

1593 }

1594 return false;

1595}

1596

1597bool CopyGeneration::processBlock(MachineBasicBlock &B,

1600 return false;

1604

1605 for (auto I = B.begin(), E = B.end(); I != E; ++I, AVB.insert(Defs)) {

1606 Defs.clear();

1607 HBS::getInstrDefs(*I, Defs);

1608

1609 unsigned Opc = I->getOpcode();

1610 if (CopyPropagation::isCopyReg(Opc, false) ||

1611 ConstGeneration::isTfrConst(*I))

1612 continue;

1613

1615 auto At = I->isPHI() ? B.getFirstNonPHI() : I;

1616

1617 for (Register R = Defs.find_first(); R; R = Defs.find_next(R)) {

1618 BitTracker::RegisterRef MR;

1619 auto *FRC = HBS::getFinalVRegClass(R, MRI);

1620

1621 if (findMatch(R, MR, AVB)) {

1622 Register NewR = MRI.createVirtualRegister(FRC);

1623 BuildMI(B, At, DL, HII.get(TargetOpcode::COPY), NewR)

1625 BT.put(BitTracker::RegisterRef(NewR), BT.get(MR));

1626 HBS::replaceReg(R, NewR, MRI);

1627 Forbidden.insert(R);

1628 continue;

1629 }

1630

1631 if (FRC == &Hexagon::DoubleRegsRegClass ||

1632 FRC == &Hexagon::HvxWRRegClass) {

1633

1636 BitTracker::RegisterRef TL = { R, SubLo };

1637 BitTracker::RegisterRef TH = { R, SubHi };

1638 BitTracker::RegisterRef ML, MH;

1639 if (findMatch(TL, ML, AVB) && findMatch(TH, MH, AVB)) {

1640 auto *FRC = HBS::getFinalVRegClass(R, MRI);

1641 Register NewR = MRI.createVirtualRegister(FRC);

1642 BuildMI(B, At, DL, HII.get(TargetOpcode::REG_SEQUENCE), NewR)

1647 BT.put(BitTracker::RegisterRef(NewR), BT.get(R));

1648 HBS::replaceReg(R, NewR, MRI);

1649 Forbidden.insert(R);

1650 }

1651 }

1652 }

1653 }

1654

1656}

1657

1658bool CopyPropagation::isCopyReg(unsigned Opc, bool NoConv) {

1659 switch (Opc) {

1660 case TargetOpcode::COPY:

1661 case TargetOpcode::REG_SEQUENCE:

1662 case Hexagon::A4_combineir:

1663 case Hexagon::A4_combineri:

1664 return true;

1665 case Hexagon::A2_tfr:

1666 case Hexagon::A2_tfrp:

1667 case Hexagon::A2_combinew:

1668 case Hexagon::V6_vcombine:

1669 return NoConv;

1670 default:

1671 break;

1672 }

1673 return false;

1674}

1675

1676bool CopyPropagation::propagateRegCopy(MachineInstr &MI) {

1678 unsigned Opc = MI.getOpcode();

1679 BitTracker::RegisterRef RD = MI.getOperand(0);

1680 assert(MI.getOperand(0).getSubReg() == 0);

1681

1682 switch (Opc) {

1683 case TargetOpcode::COPY:

1684 case Hexagon::A2_tfr:

1685 case Hexagon::A2_tfrp: {

1686 BitTracker::RegisterRef RS = MI.getOperand(1);

1687 if (!HBS::isTransparentCopy(RD, RS, MRI))

1688 break;

1689 if (RS.Sub != 0)

1691 else

1693 break;

1694 }

1695 case TargetOpcode::REG_SEQUENCE: {

1696 BitTracker::RegisterRef SL, SH;

1697 if (HBS::parseRegSequence(MI, SL, SH, MRI)) {

1698 const TargetRegisterClass &RC = *MRI.getRegClass(RD.Reg);

1703 }

1704 break;

1705 }

1706 case Hexagon::A2_combinew:

1707 case Hexagon::V6_vcombine: {

1708 const TargetRegisterClass &RC = *MRI.getRegClass(RD.Reg);

1711 BitTracker::RegisterRef RH = MI.getOperand(1), RL = MI.getOperand(2);

1712 Changed = HBS::replaceSubWithSub(RD.Reg, SubLo, RL.Reg, RL.Sub, MRI);

1714 break;

1715 }

1716 case Hexagon::A4_combineir:

1717 case Hexagon::A4_combineri: {

1718 unsigned SrcX = (Opc == Hexagon::A4_combineir) ? 2 : 1;

1719 unsigned Sub = (Opc == Hexagon::A4_combineir) ? Hexagon::isub_lo

1720 : Hexagon::isub_hi;

1721 BitTracker::RegisterRef RS = MI.getOperand(SrcX);

1723 break;

1724 }

1725 }

1727}

1728

1729bool CopyPropagation::processBlock(MachineBasicBlock &B, const RegisterSet&) {

1730 std::vector<MachineInstr*> Instrs;

1732 Instrs.push_back(&MI);

1733

1735 for (auto *I : Instrs) {

1736 unsigned Opc = I->getOpcode();

1737 if (!CopyPropagation::isCopyReg(Opc, true))

1738 continue;

1739 Changed |= propagateRegCopy(*I);

1740 }

1741

1743}

1744

1745namespace {

1746

1747

1748

1749

1750 class BitSimplification : public Transformation {

1751 public:

1752 BitSimplification(BitTracker &bt, const MachineDominatorTree &mdt,

1753 const HexagonInstrInfo &hii,

1754 const HexagonRegisterInfo &hri, MachineRegisterInfo &mri,

1755 MachineFunction &mf)

1756 : Transformation(true), MDT(mdt), HII(hii), HRI(hri), MRI(mri), BT(bt) {

1757 }

1758

1759 bool processBlock(MachineBasicBlock &B, const RegisterSet &AVs) override;

1760

1761 private:

1762 struct RegHalf : public BitTracker::RegisterRef {

1763 bool Low;

1764 };

1765

1766 bool matchHalf(unsigned SelfR, const BitTracker::RegisterCell &RC,

1767 unsigned B, RegHalf &RH);

1768 bool validateReg(BitTracker::RegisterRef R, unsigned Opc, unsigned OpNum);

1769

1770 bool matchPackhl(unsigned SelfR, const BitTracker::RegisterCell &RC,

1771 BitTracker::RegisterRef &Rs, BitTracker::RegisterRef &Rt);

1772 unsigned getCombineOpcode(bool HLow, bool LLow);

1773

1774 bool genStoreUpperHalf(MachineInstr *MI);

1775 bool genStoreImmediate(MachineInstr *MI);

1776 bool genPackhl(MachineInstr *MI, BitTracker::RegisterRef RD,

1777 const BitTracker::RegisterCell &RC);

1778 bool genExtractHalf(MachineInstr *MI, BitTracker::RegisterRef RD,

1779 const BitTracker::RegisterCell &RC);

1780 bool genCombineHalf(MachineInstr *MI, BitTracker::RegisterRef RD,

1781 const BitTracker::RegisterCell &RC);

1782 bool genExtractLow(MachineInstr *MI, BitTracker::RegisterRef RD,

1783 const BitTracker::RegisterCell &RC);

1784 bool genBitSplit(MachineInstr *MI, BitTracker::RegisterRef RD,

1785 const BitTracker::RegisterCell &RC, const RegisterSet &AVs);

1786 bool simplifyTstbit(MachineInstr *MI, BitTracker::RegisterRef RD,

1787 const BitTracker::RegisterCell &RC);

1788 bool simplifyExtractLow(MachineInstr *MI, BitTracker::RegisterRef RD,

1789 const BitTracker::RegisterCell &RC, const RegisterSet &AVs);

1790 bool simplifyRCmp0(MachineInstr *MI, BitTracker::RegisterRef RD);

1791

1792

1793

1794 std::vector<MachineInstr*> NewMIs;

1795

1796 const MachineDominatorTree &MDT;

1797 const HexagonInstrInfo &HII;

1798 [[maybe_unused]] const HexagonRegisterInfo &HRI;

1799 MachineRegisterInfo &MRI;

1800 BitTracker &BT;

1801 };

1802

1803}

1804

1805

1806

1807

1808bool BitSimplification::matchHalf(unsigned SelfR,

1809 const BitTracker::RegisterCell &RC, unsigned B, RegHalf &RH) {

1810

1811

1812

1813

1814

1815

1816

1817 bool Low = false;

1818 unsigned I = B;

1819 while (I < B+16 && RC[I].num())

1820 I++;

1821 if (I == B+16)

1822 return false;

1823

1825 unsigned P = RC[I].RefI.Pos;

1826 if (P < I-B)

1827 return false;

1828 unsigned Pos = P - (I-B);

1829

1830 if (Reg == 0 || Reg == SelfR)

1831 return false;

1833 return false;

1835 return false;

1836

1837 const BitTracker::RegisterCell &SC = BT.lookup(Reg);

1838 if (Pos+16 > SC.width())

1839 return false;

1840

1841 for (unsigned i = 0; i < 16; ++i) {

1842 const BitTracker::BitValue &RV = RC[i+B];

1845 return false;

1846 if (RV.RefI.Pos != i+Pos)

1847 return false;

1848 continue;

1849 }

1850 if (RC[i+B] != SC[i+Pos])

1851 return false;

1852 }

1853

1854 unsigned Sub = 0;

1855 switch (Pos) {

1856 case 0:

1857 Sub = Hexagon::isub_lo;

1858 Low = true;

1859 break;

1860 case 16:

1861 Sub = Hexagon::isub_lo;

1862 Low = false;

1863 break;

1864 case 32:

1865 Sub = Hexagon::isub_hi;

1866 Low = true;

1867 break;

1868 case 48:

1869 Sub = Hexagon::isub_hi;

1870 Low = false;

1871 break;

1872 default:

1873 return false;

1874 }

1875

1876 RH.Reg = Reg;

1877 RH.Sub = Sub;

1878 RH.Low = Low;

1879

1880 if (!HBS::getFinalVRegClass(RH, MRI))

1881 RH.Sub = 0;

1882

1883 return true;

1884}

1885

1886bool BitSimplification::validateReg(BitTracker::RegisterRef R, unsigned Opc,

1887 unsigned OpNum) {

1888 auto *OpRC = HII.getRegClass(HII.get(Opc), OpNum);

1889 auto *RRC = HBS::getFinalVRegClass(R, MRI);

1890 return OpRC->hasSubClassEq(RRC);

1891}

1892

1893

1894

1895bool BitSimplification::matchPackhl(unsigned SelfR,

1896 const BitTracker::RegisterCell &RC, BitTracker::RegisterRef &Rs,

1897 BitTracker::RegisterRef &Rt) {

1898 RegHalf L1, H1, L2, H2;

1899

1900 if (!matchHalf(SelfR, RC, 0, L2) || !matchHalf(SelfR, RC, 16, L1))

1901 return false;

1902 if (!matchHalf(SelfR, RC, 32, H2) || !matchHalf(SelfR, RC, 48, H1))

1903 return false;

1904

1905

1906 if (H1.Reg != L1.Reg || H1.Sub != L1.Sub || H1.Low || !L1.Low)

1907 return false;

1908 if (H2.Reg != L2.Reg || H2.Sub != L2.Sub || H2.Low || !L2.Low)

1909 return false;

1910

1911 Rs = H1;

1912 Rt = H2;

1913 return true;

1914}

1915

1916unsigned BitSimplification::getCombineOpcode(bool HLow, bool LLow) {

1917 return HLow ? LLow ? Hexagon::A2_combine_ll

1918 : Hexagon::A2_combine_lh

1919 : LLow ? Hexagon::A2_combine_hl

1920 : Hexagon::A2_combine_hh;

1921}

1922

1923

1924

1925

1926bool BitSimplification::genStoreUpperHalf(MachineInstr *MI) {

1927 unsigned Opc = MI->getOpcode();

1928 if (Opc != Hexagon::S2_storerh_io)

1929 return false;

1930

1931 MachineOperand &ValOp = MI->getOperand(2);

1932 BitTracker::RegisterRef RS = ValOp;

1934 return false;

1935 const BitTracker::RegisterCell &RC = BT.lookup(RS.Reg);

1936 RegHalf H;

1937 unsigned B = (RS.Sub == Hexagon::isub_hi) ? 32 : 0;

1938 if (!matchHalf(0, RC, B, H))

1939 return false;

1940 if (H.Low)

1941 return false;

1942 MI->setDesc(HII.get(Hexagon::S2_storerf_io));

1945 return true;

1946}

1947

1948

1949

1950bool BitSimplification::genStoreImmediate(MachineInstr *MI) {

1951 unsigned Opc = MI->getOpcode();

1952 unsigned Align = 0;

1953 switch (Opc) {

1954 case Hexagon::S2_storeri_io:

1956 [[fallthrough]];

1957 case Hexagon::S2_storerh_io:

1959 [[fallthrough]];

1960 case Hexagon::S2_storerb_io:

1961 break;

1962 default:

1963 return false;

1964 }

1965

1966

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

1968 return false;

1969 MachineOperand &OffOp = MI->getOperand(1);

1970 if (!OffOp.isImm())

1971 return false;

1972

1974

1975 if (isUIntN(6+Align, Off) || (Off & ((1<<Align)-1)))

1976 return false;

1977

1978 BitTracker::RegisterRef RS = MI->getOperand(2);

1980 return false;

1981 const BitTracker::RegisterCell &RC = BT.lookup(RS.Reg);

1982 uint64_t U;

1983 if (!HBS::getConst(RC, 0, RC.width(), U))

1984 return false;

1985

1986

1987 int V;

1988 switch (Opc) {

1989 case Hexagon::S2_storerb_io:

1990 V = int8_t(U);

1991 break;

1992 case Hexagon::S2_storerh_io:

1993 V = int16_t(U);

1994 break;

1995 case Hexagon::S2_storeri_io:

1996 V = int32_t(U);

1997 break;

1998 default:

1999

2000

2002 }

2004 return false;

2005

2006 MI->removeOperand(2);

2007 switch (Opc) {

2008 case Hexagon::S2_storerb_io:

2009 MI->setDesc(HII.get(Hexagon::S4_storeirb_io));

2010 break;

2011 case Hexagon::S2_storerh_io:

2012 MI->setDesc(HII.get(Hexagon::S4_storeirh_io));

2013 break;

2014 case Hexagon::S2_storeri_io:

2015 MI->setDesc(HII.get(Hexagon::S4_storeiri_io));

2016 break;

2017 }

2019 return true;

2020}

2021

2022

2023

2024

2025

2026bool BitSimplification::genPackhl(MachineInstr *MI,

2027 BitTracker::RegisterRef RD, const BitTracker::RegisterCell &RC) {

2028 unsigned Opc = MI->getOpcode();

2029 if (Opc == Hexagon::S2_packhl)

2030 return false;

2031 BitTracker::RegisterRef Rs, Rt;

2032 if (!matchPackhl(RD.Reg, RC, Rs, Rt))

2033 return false;

2034 if (!validateReg(Rs, Hexagon::S2_packhl, 1) ||

2035 !validateReg(Rt, Hexagon::S2_packhl, 2))

2036 return false;

2037

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

2039 Register NewR = MRI.createVirtualRegister(&Hexagon::DoubleRegsRegClass);

2041 auto At = MI->isPHI() ? B.getFirstNonPHI()

2043 BuildMI(B, At, DL, HII.get(Hexagon::S2_packhl), NewR)

2046 HBS::replaceSubWithSub(RD.Reg, RD.Sub, NewR, 0, MRI);

2047 BT.put(BitTracker::RegisterRef(NewR), RC);

2048 return true;

2049}

2050

2051

2052

2053bool BitSimplification::genExtractHalf(MachineInstr *MI,

2054 BitTracker::RegisterRef RD, const BitTracker::RegisterCell &RC) {

2055 RegHalf L;

2056

2057 if (!matchHalf(RD.Reg, RC, 0, L) || !HBS::isZero(RC, 16, 16))

2058 return false;

2059

2060 unsigned Opc = MI->getOpcode();

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

2063

2064

2065

2066 unsigned NewR = 0;

2067 auto At = MI->isPHI() ? B.getFirstNonPHI()

2069 if (L.Low && Opc != Hexagon::A2_zxth) {

2070 if (validateReg(L, Hexagon::A2_zxth, 1)) {

2071 NewR = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);

2072 BuildMI(B, At, DL, HII.get(Hexagon::A2_zxth), NewR)

2074 }

2075 } else if (L.Low && Opc != Hexagon::S2_lsr_i_r) {

2076 if (validateReg(L, Hexagon::S2_lsr_i_r, 1)) {

2077 NewR = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);

2078 BuildMI(B, MI, DL, HII.get(Hexagon::S2_lsr_i_r), NewR)

2081 }

2082 }

2083 if (NewR == 0)

2084 return false;

2085 HBS::replaceSubWithSub(RD.Reg, RD.Sub, NewR, 0, MRI);

2086 BT.put(BitTracker::RegisterRef(NewR), RC);

2087 return true;

2088}

2089

2090

2091

2092bool BitSimplification::genCombineHalf(MachineInstr *MI,

2093 BitTracker::RegisterRef RD, const BitTracker::RegisterCell &RC) {

2094 RegHalf L, H;

2095

2096 if (!matchHalf(RD.Reg, RC, 0, L) || !matchHalf(RD.Reg, RC, 16, H))

2097 return false;

2098

2099 if (L.Reg == H.Reg && L.Sub == H.Sub && H.Low && L.Low)

2100 return false;

2101

2102 unsigned Opc = MI->getOpcode();

2103 unsigned COpc = getCombineOpcode(H.Low, L.Low);

2104 if (COpc == Opc)

2105 return false;

2106 if (!validateReg(H, COpc, 1) || !validateReg(L, COpc, 2))

2107 return false;

2108

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

2111 Register NewR = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);

2112 auto At = MI->isPHI() ? B.getFirstNonPHI()

2114 BuildMI(B, At, DL, HII.get(COpc), NewR)

2117 HBS::replaceSubWithSub(RD.Reg, RD.Sub, NewR, 0, MRI);

2118 BT.put(BitTracker::RegisterRef(NewR), RC);

2119 return true;

2120}

2121

2122

2123

2124bool BitSimplification::genExtractLow(MachineInstr *MI,

2125 BitTracker::RegisterRef RD, const BitTracker::RegisterCell &RC) {

2126 unsigned Opc = MI->getOpcode();

2127 switch (Opc) {

2128 case Hexagon::A2_zxtb:

2129 case Hexagon::A2_zxth:

2130 case Hexagon::S2_extractu:

2131 return false;

2132 }

2133 if (Opc == Hexagon::A2_andir && MI->getOperand(2).isImm()) {

2134 int32_t Imm = MI->getOperand(2).getImm();

2136 return false;

2137 }

2138

2139 if (MI->hasUnmodeledSideEffects() || MI->isInlineAsm())

2140 return false;

2141 unsigned W = RC.width();

2142 while (W > 0 && RC[W-1].is(0))

2143 W--;

2144 if (W == 0 || W == RC.width())

2145 return false;

2146 unsigned NewOpc = (W == 8) ? Hexagon::A2_zxtb

2147 : (W == 16) ? Hexagon::A2_zxth

2148 : (W < 10) ? Hexagon::A2_andir

2149 : Hexagon::S2_extractu;

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

2152

2153 for (auto &Op : MI->uses()) {

2154 if (!Op.isReg())

2155 continue;

2156 BitTracker::RegisterRef RS = Op;

2157 if (!BT.has(RS.Reg))

2158 continue;

2159 const BitTracker::RegisterCell &SC = BT.lookup(RS.Reg);

2160 unsigned BN, BW;

2161 if (!HBS::getSubregMask(RS, BN, BW, MRI))

2162 continue;

2163 if (BW < W || !HBS::isEqual(RC, 0, SC, BN, W))

2164 continue;

2165 if (!validateReg(RS, NewOpc, 1))

2166 continue;

2167

2168 Register NewR = MRI.createVirtualRegister(&Hexagon::IntRegsRegClass);

2169 auto At = MI->isPHI() ? B.getFirstNonPHI()

2170 : MachineBasicBlock::iterator(MI);

2171 auto MIB = BuildMI(B, At, DL, HII.get(NewOpc), NewR)

2172 .addReg(RS.Reg, 0, RS.Sub);

2173 if (NewOpc == Hexagon::A2_andir)

2174 MIB.addImm((1 << W) - 1);

2175 else if (NewOpc == Hexagon::S2_extractu)

2176 MIB.addImm(W).addImm(0);

2177 HBS::replaceSubWithSub(RD.Reg, RD.Sub, NewR, 0, MRI);

2178 BT.put(BitTracker::RegisterRef(NewR), RC);

2179 return true;

2180 }

2181 return false;

2182}

2183

2184bool BitSimplification::genBitSplit(MachineInstr *MI,

2185 BitTracker::RegisterRef RD, const BitTracker::RegisterCell &RC,

2188 return false;

2191 return false;

2192 }

2193

2194 unsigned Opc = MI->getOpcode();

2195 switch (Opc) {

2196 case Hexagon::A4_bitsplit:

2197 case Hexagon::A4_bitspliti:

2198 return false;

2199 }

2200

2201 unsigned W = RC.width();

2202 if (W != 32)

2203 return false;

2204

2205 auto ctlz = [] (const BitTracker::RegisterCell &C) -> unsigned {

2206 unsigned Z = C.width();

2207 while (Z > 0 && C[Z-1].is(0))

2208 --Z;

2209 return C.width() - Z;

2210 };

2211

2212

2213 unsigned Z = ctlz(RC);

2214 if (Z == 0 || Z == W)

2215 return false;

2216

2217

2218

2219 const BitTracker::BitValue &B0 = RC[0];

2221 return false;

2222

2223 unsigned SrcR = B0.RefI.Reg;

2224 unsigned SrcSR = 0;

2225 unsigned Pos = B0.RefI.Pos;

2226

2227

2228 for (unsigned i = 1; i < W-Z; ++i) {

2229 const BitTracker::BitValue &V = RC[i];

2231 return false;

2232 if (V.RefI.Reg != SrcR || V.RefI.Pos != Pos+i)

2233 return false;

2234 }

2235

2236

2237 for (unsigned S = AVs.find_first(); S; S = AVs.find_next(S)) {

2238

2239

2240 unsigned SRC = MRI.getRegClass(S)->getID();

2241 if (SRC != Hexagon::IntRegsRegClassID &&

2242 SRC != Hexagon::DoubleRegsRegClassID)

2243 continue;

2245 continue;

2246 const BitTracker::RegisterCell &SC = BT.lookup(S);

2247 if (SC.width() != W || ctlz(SC) != W-Z)

2248 continue;

2249

2250 const BitTracker::BitValue &S0 = SC[0];

2252 continue;

2254

2255 if (Pos <= P && (Pos + W-Z) != P)

2256 continue;

2257 if (P < Pos && (P + Z) != Pos)

2258 continue;

2259

2260 if (std::min(P, Pos) != 0 && std::min(P, Pos) != 32)

2261 continue;

2262

2263 unsigned I;

2264 for (I = 1; I < Z; ++I) {

2265 const BitTracker::BitValue &V = SC[I];

2267 break;

2268 if (V.RefI.Reg != SrcR || V.RefI.Pos != P+I)

2269 break;

2270 }

2271 if (I != Z)

2272 continue;

2273

2274

2277 MachineInstr *DefS = MRI.getVRegDef(S);

2278 assert(DefS != nullptr);

2280 MachineBasicBlock &B = *DefS->getParent();

2281 auto At = DefS->isPHI() ? B.getFirstNonPHI()

2283 if (MRI.getRegClass(SrcR)->getID() == Hexagon::DoubleRegsRegClassID)

2284 SrcSR = (std::min(Pos, P) == 32) ? Hexagon::isub_hi : Hexagon::isub_lo;

2285 if (!validateReg({SrcR,SrcSR}, Hexagon::A4_bitspliti, 1))

2286 continue;

2287 unsigned ImmOp = Pos <= P ? W-Z : Z;

2288

2289

2290 unsigned NewR = 0;

2291 for (MachineInstr *In : NewMIs) {

2292 if (In->getOpcode() != Hexagon::A4_bitspliti)

2293 continue;

2294 MachineOperand &Op1 = In->getOperand(1);

2296 continue;

2297 if (In->getOperand(2).getImm() != ImmOp)

2298 continue;

2299

2300 MachineOperand &Op0 = In->getOperand(0);

2301 MachineInstr *DefI = MRI.getVRegDef(Op0.getReg());

2302 assert(DefI != nullptr);

2304 continue;

2305

2306

2308 NewR = Op0.getReg();

2309 break;

2310 }

2311 if (!NewR) {

2312 NewR = MRI.createVirtualRegister(&Hexagon::DoubleRegsRegClass);

2313 auto NewBS = BuildMI(B, At, DL, HII.get(Hexagon::A4_bitspliti), NewR)

2314 .addReg(SrcR, 0, SrcSR)

2316 NewMIs.push_back(NewBS);

2317 }

2318 if (Pos <= P) {

2319 HBS::replaceRegWithSub(RD.Reg, NewR, Hexagon::isub_lo, MRI);

2320 HBS::replaceRegWithSub(S, NewR, Hexagon::isub_hi, MRI);

2321 } else {

2322 HBS::replaceRegWithSub(S, NewR, Hexagon::isub_lo, MRI);

2323 HBS::replaceRegWithSub(RD.Reg, NewR, Hexagon::isub_hi, MRI);

2324 }

2325 return true;

2326 }

2327

2328 return false;

2329}

2330

2331

2332

2333

2334

2335

2336

2337bool BitSimplification::simplifyTstbit(MachineInstr *MI,

2338 BitTracker::RegisterRef RD, const BitTracker::RegisterCell &RC) {

2339 unsigned Opc = MI->getOpcode();

2340 if (Opc != Hexagon::S2_tstbit_i)

2341 return false;

2342

2343 unsigned BN = MI->getOperand(2).getImm();

2344 BitTracker::RegisterRef RS = MI->getOperand(1);

2345 unsigned F, W;

2347 if (BT.has(RS.Reg) || !HBS::getSubregMask(RS, F, W, MRI))

2348 return false;

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

2350 auto At = MI->isPHI() ? B.getFirstNonPHI()

2352

2353 const BitTracker::RegisterCell &SC = BT.lookup(RS.Reg);

2354 const BitTracker::BitValue &V = SC[F+BN];

2356 const TargetRegisterClass *TC = MRI.getRegClass(V.RefI.Reg);

2357

2358

2359

2360 unsigned P = std::numeric_limits::max();

2361 BitTracker::RegisterRef RR(V.RefI.Reg, 0);

2362 if (TC == &Hexagon::DoubleRegsRegClass) {

2363 P = V.RefI.Pos;

2364 RR.Sub = Hexagon::isub_lo;

2365 if (P >= 32) {

2366 P -= 32;

2367 RR.Sub = Hexagon::isub_hi;

2368 }

2369 } else if (TC == &Hexagon::IntRegsRegClass) {

2370 P = V.RefI.Pos;

2371 }

2372 if (P != std::numeric_limits::max()) {

2373 Register NewR = MRI.createVirtualRegister(&Hexagon::PredRegsRegClass);

2374 BuildMI(B, At, DL, HII.get(Hexagon::S2_tstbit_i), NewR)

2377 HBS::replaceReg(RD.Reg, NewR, MRI);

2378 BT.put(NewR, RC);

2379 return true;

2380 }

2381 } else if (V.is(0) || V.is(1)) {

2382 Register NewR = MRI.createVirtualRegister(&Hexagon::PredRegsRegClass);

2383 unsigned NewOpc = V.is(0) ? Hexagon::PS_false : Hexagon::PS_true;

2384 BuildMI(B, At, DL, HII.get(NewOpc), NewR);

2385 HBS::replaceReg(RD.Reg, NewR, MRI);

2386 return true;

2387 }

2388

2389 return false;

2390}

2391

2392

2393

2394

2395

2396

2397bool BitSimplification::simplifyExtractLow(MachineInstr *MI,

2398 BitTracker::RegisterRef RD, const BitTracker::RegisterCell &RC,

2401 return false;

2402 if (MaxExtract.getNumOccurrences()) {

2404 return false;

2406 }

2407

2408 unsigned W = RC.width();

2409 unsigned RW = W;

2410 unsigned Len;

2412

2413

2414

2415

2416 const TargetRegisterClass *FRC = HBS::getFinalVRegClass(RD, MRI);

2417 if (FRC != &Hexagon::IntRegsRegClass && FRC != &Hexagon::DoubleRegsRegClass)

2418 return false;

2420

2421

2422

2423

2424

2425

2426

2427

2428

2429

2430

2431 const BitTracker::BitValue &TopV = RC[W-1];

2432

2433

2434

2435

2437 for (unsigned I = 0; I != W; ++I) {

2438 const BitTracker::BitValue &V = RC[I];

2440 return false;

2442 }

2443 if (IsConst)

2444 return false;

2445

2446 if (TopV.is(0) || TopV.is(1)) {

2447 bool S = TopV.is(1);

2448 for (--W; W > 0 && RC[W-1].is(S); --W)

2449 ;

2452

2455 } else {

2456

2459 return false;

2460 for (--W; W > 0 && RC[W-1] == TopV; --W)

2461 ;

2462

2463

2464 Len = W + 1;

2466 }

2467

2468

2469 if (Len == RW)

2470 return false;

2471

2474 << ", MI: " << *MI;

2475 dbgs() << "Cell: " << RC << '\n';

2476 dbgs() << "Expected bitfield size: " << Len << " bits, "

2477 << (Signed ? "sign" : "zero") << "-extended\n";

2478 });

2479

2481

2482 for (unsigned R = AVs.find_first(); R != 0; R = AVs.find_next(R)) {

2484 continue;

2485 const BitTracker::RegisterCell &SC = BT.lookup(R);

2486 unsigned SW = SC.width();

2487

2488

2489

2490

2491

2492 if (SW < RW || (SW % RW) != 0)

2493 continue;

2494

2495

2496

2497

2498 unsigned Off = 0;

2499 while (Off <= SW-Len) {

2500 unsigned OE = (Off+Len)/RW;

2501 if (OE != Off/RW) {

2502

2503

2504

2505

2506

2507

2508 Off = OE*RW;

2509 continue;

2510 }

2511 if (HBS::isEqual(RC, 0, SC, Off, Len))

2512 break;

2514 }

2515

2516 if (Off > SW-Len)

2517 continue;

2518

2519

2520 unsigned ExtOpc = 0;

2521 if (Off == 0) {

2522 if (Len == 8)

2523 ExtOpc = Signed ? Hexagon::A2_sxtb : Hexagon::A2_zxtb;

2524 else if (Len == 16)

2525 ExtOpc = Signed ? Hexagon::A2_sxth : Hexagon::A2_zxth;

2526 else if (Len < 10 && Signed)

2527 ExtOpc = Hexagon::A2_andir;

2528 }

2529 if (ExtOpc == 0) {

2530 ExtOpc =

2531 Signed ? (RW == 32 ? Hexagon::S4_extract : Hexagon::S4_extractp)

2532 : (RW == 32 ? Hexagon::S2_extractu : Hexagon::S2_extractup);

2533 }

2534 unsigned SR = 0;

2535

2536 if (RW != SW && RW*2 != SW)

2537 continue;

2538 if (RW != SW)

2539 SR = (Off/RW == 0) ? Hexagon::isub_lo : Hexagon::isub_hi;

2541

2542 if (!validateReg({R,SR}, ExtOpc, 1))

2543 continue;

2544

2545

2546 if (MI->getOpcode() == ExtOpc) {

2547

2548 const MachineOperand &SrcOp = MI->getOperand(1);

2549 if (SrcOp.getReg() == R)

2550 continue;

2551 }

2552

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

2555 Register NewR = MRI.createVirtualRegister(FRC);

2556 auto At = MI->isPHI() ? B.getFirstNonPHI()

2558 auto MIB = BuildMI(B, At, DL, HII.get(ExtOpc), NewR)

2560 switch (ExtOpc) {

2561 case Hexagon::A2_sxtb:

2562 case Hexagon::A2_zxtb:

2563 case Hexagon::A2_sxth:

2564 case Hexagon::A2_zxth:

2565 break;

2566 case Hexagon::A2_andir:

2567 MIB.addImm((1u << Len) - 1);

2568 break;

2569 case Hexagon::S4_extract:

2570 case Hexagon::S2_extractu:

2571 case Hexagon::S4_extractp:

2572 case Hexagon::S2_extractup:

2573 MIB.addImm(Len)

2574 .addImm(Off);

2575 break;

2576 default:

2578 }

2579

2580 HBS::replaceReg(RD.Reg, NewR, MRI);

2581 BT.put(BitTracker::RegisterRef(NewR), RC);

2583 break;

2584 }

2585

2587}

2588

2589bool BitSimplification::simplifyRCmp0(MachineInstr *MI,

2590 BitTracker::RegisterRef RD) {

2591 unsigned Opc = MI->getOpcode();

2592 if (Opc != Hexagon::A4_rcmpeqi && Opc != Hexagon::A4_rcmpneqi)

2593 return false;

2594 MachineOperand &CmpOp = MI->getOperand(2);

2595 if (!CmpOp.isImm() || CmpOp.getImm() != 0)

2596 return false;

2597

2598 const TargetRegisterClass *FRC = HBS::getFinalVRegClass(RD, MRI);

2599 if (FRC != &Hexagon::IntRegsRegClass && FRC != &Hexagon::DoubleRegsRegClass)

2600 return false;

2602

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

2605 auto At = MI->isPHI() ? B.getFirstNonPHI()

2607 bool KnownZ = true;

2608 bool KnownNZ = false;

2609

2610 BitTracker::RegisterRef SR = MI->getOperand(1);

2612 return false;

2613 const BitTracker::RegisterCell &SC = BT.lookup(SR.Reg);

2614 unsigned F, W;

2615 if (!HBS::getSubregMask(SR, F, W, MRI))

2616 return false;

2617

2618 for (uint16_t I = F; I != F+W; ++I) {

2619 const BitTracker::BitValue &V = SC[I];

2620 if (V.is(0))

2621 KnownZ = false;

2622 if (V.is(1))

2623 KnownNZ = true;

2624 }

2625

2626 auto ReplaceWithConst = [&](int C) {

2627 Register NewR = MRI.createVirtualRegister(FRC);

2628 BuildMI(B, At, DL, HII.get(Hexagon::A2_tfrsi), NewR)

2630 HBS::replaceReg(RD.Reg, NewR, MRI);

2631 BitTracker::RegisterCell NewRC(W);

2632 for (uint16_t I = 0; I != W; ++I) {

2633 NewRC[I] = BitTracker::BitValue(C & 1);

2634 C = unsigned(C) >> 1;

2635 }

2636 BT.put(BitTracker::RegisterRef(NewR), NewRC);

2637 return true;

2638 };

2639

2640 auto IsNonZero = [] (const MachineOperand &Op) {

2641 if (Op.isGlobal() || Op.isBlockAddress())

2642 return true;

2643 if (Op.isImm())

2644 return Op.getImm() != 0;

2645 if (Op.isCImm())

2646 return Op.getCImm()->isZero();

2647 if (Op.isFPImm())

2648 return Op.getFPImm()->isZero();

2649 return false;

2650 };

2651

2652 auto IsZero = [] (const MachineOperand &Op) {

2653 if (Op.isGlobal() || Op.isBlockAddress())

2654 return false;

2655 if (Op.isImm())

2656 return Op.getImm() == 0;

2657 if (Op.isCImm())

2658 return Op.getCImm()->isZero();

2659 if (Op.isFPImm())

2660 return Op.getFPImm()->isZero();

2661 return false;

2662 };

2663

2664

2665

2666 if (KnownZ || KnownNZ) {

2667 assert(KnownZ != KnownNZ && "Register cannot be both 0 and non-0");

2668 return ReplaceWithConst(KnownZ == (Opc == Hexagon::A4_rcmpeqi));

2669 }

2670

2671

2672

2673 MachineInstr *InpDef = MRI.getVRegDef(SR.Reg);

2674 if (!InpDef)

2675 return false;

2676 if (SR.Sub == 0 && InpDef->getOpcode() == Hexagon::C2_muxii) {

2677 MachineOperand &Src1 = InpDef->getOperand(2);

2678 MachineOperand &Src2 = InpDef->getOperand(3);

2679

2680 bool KnownNZ1 = IsNonZero(Src1), KnownNZ2 = IsNonZero(Src2);

2681 if (KnownNZ1 && KnownNZ2)

2682 return ReplaceWithConst(Opc == Hexagon::A4_rcmpneqi);

2683

2684 bool KnownZ1 = IsZero(Src1), KnownZ2 = IsZero(Src2);

2685 if (KnownZ1 && KnownZ2)

2686 return ReplaceWithConst(Opc == Hexagon::A4_rcmpeqi);

2687

2688

2689

2690

2691 if ((KnownZ1 || KnownNZ1) && (KnownZ2 || KnownNZ2)) {

2692 Register NewR = MRI.createVirtualRegister(FRC);

2693 BuildMI(B, At, DL, HII.get(Hexagon::C2_muxii), NewR)

2695 .addImm(KnownZ1 == (Opc == Hexagon::A4_rcmpeqi))

2696 .addImm(KnownZ2 == (Opc == Hexagon::A4_rcmpeqi));

2697 HBS::replaceReg(RD.Reg, NewR, MRI);

2698

2699 BitTracker::RegisterCell NewRC(W);

2702 BT.put(BitTracker::RegisterRef(NewR), NewRC);

2703 return true;

2704 }

2705 }

2706

2707 return false;

2708}

2709

2710bool BitSimplification::processBlock(MachineBasicBlock &B,

2713 return false;

2717

2718 for (auto I = B.begin(), E = B.end(); I != E; ++I, AVB.insert(Defs)) {

2719 MachineInstr *MI = &*I;

2720 Defs.clear();

2721 HBS::getInstrDefs(*MI, Defs);

2722

2723 unsigned Opc = MI->getOpcode();

2724 if (Opc == TargetOpcode::COPY || Opc == TargetOpcode::REG_SEQUENCE)

2725 continue;

2726

2727 if (MI->mayStore()) {

2728 bool T = genStoreUpperHalf(MI);

2729 T = T || genStoreImmediate(MI);

2731 continue;

2732 }

2733

2734 if (Defs.count() != 1)

2735 continue;

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

2738 continue;

2739 BitTracker::RegisterRef RD = Op0;

2741 continue;

2742 const TargetRegisterClass *FRC = HBS::getFinalVRegClass(RD, MRI);

2743 const BitTracker::RegisterCell &RC = BT.lookup(RD.Reg);

2744

2745 if (FRC->getID() == Hexagon::DoubleRegsRegClassID) {

2746 bool T = genPackhl(MI, RD, RC);

2747 T = T || simplifyExtractLow(MI, RD, RC, AVB);

2749 continue;

2750 }

2751

2752 if (FRC->getID() == Hexagon::IntRegsRegClassID) {

2753 bool T = genBitSplit(MI, RD, RC, AVB);

2754 T = T || simplifyExtractLow(MI, RD, RC, AVB);

2755 T = T || genExtractHalf(MI, RD, RC);

2756 T = T || genCombineHalf(MI, RD, RC);

2757 T = T || genExtractLow(MI, RD, RC);

2758 T = T || simplifyRCmp0(MI, RD);

2760 continue;

2761 }

2762

2763 if (FRC->getID() == Hexagon::PredRegsRegClassID) {

2764 bool T = simplifyTstbit(MI, RD, RC);

2766 continue;

2767 }

2768 }

2770}

2771

2772bool HexagonBitSimplify::runOnMachineFunction(MachineFunction &MF) {

2774 return false;

2775

2776 auto &HST = MF.getSubtarget();

2778 auto &HII = *HST.getInstrInfo();

2779

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

2783

2784 Changed = DeadCodeElimination(MF, *MDT).run();

2785

2786 const HexagonEvaluator HE(HRI, MRI, HII, MF);

2787 BitTracker BT(HE, MF);

2790

2791 MachineBasicBlock &Entry = MF.front();

2792

2793 RegisterSet AIG;

2794 ConstGeneration ImmG(BT, HII, MRI);

2795 Changed |= visitBlock(Entry, ImmG, AIG);

2796

2797 RegisterSet ARE;

2798 RedundantInstrElimination RIE(BT, HII, HRI, MRI);

2799 bool Ried = visitBlock(Entry, RIE, ARE);

2800 if (Ried) {

2803 }

2804

2805 RegisterSet ACG;

2806 CopyGeneration CopyG(BT, HII, HRI, MRI);

2807 Changed |= visitBlock(Entry, CopyG, ACG);

2808

2809 RegisterSet ACP;

2810 CopyPropagation CopyP(HRI, MRI);

2811 Changed |= visitBlock(Entry, CopyP, ACP);

2812

2813 Changed = DeadCodeElimination(MF, *MDT).run() || Changed;

2814

2817 BitSimplification BitS(BT, *MDT, HII, HRI, MRI, MF);

2818 Changed |= visitBlock(Entry, BitS, ABS);

2819

2820 Changed = DeadCodeElimination(MF, *MDT).run() || Changed;

2821

2823 for (auto &B : MF)

2824 for (auto &I : B)

2825 I.clearKillInfo();

2826 DeadCodeElimination(MF, *MDT).run();

2827 }

2829}

2830

2831

2832

2833

2834

2835

2836

2837

2838

2839

2840

2841

2842

2843

2844

2845

2846

2847

2848

2849

2850

2851

2852

2853

2854

2855

2856

2857

2858

2859

2860

2861

2862

2863

2864

2865

2866

2867

2868

2869

2870

2871

2872

2873

2874

2875

2876

2877

2878

2879

2880

2881

2882

2883

2884

2885

2886

2887

2888

2889

2890

2891

2892

2893namespace {

2894

2895 class HexagonLoopRescheduling : public MachineFunctionPass {

2896 public:

2897 static char ID;

2898

2899 HexagonLoopRescheduling() : MachineFunctionPass(ID) {}

2900

2901 bool runOnMachineFunction(MachineFunction &MF) override;

2902

2903 private:

2904 const HexagonInstrInfo *HII = nullptr;

2905 const HexagonRegisterInfo *HRI = nullptr;

2906 MachineRegisterInfo *MRI = nullptr;

2907 BitTracker *BTP = nullptr;

2908

2909 struct LoopCand {

2910 LoopCand(MachineBasicBlock *lb, MachineBasicBlock *pb,

2911 MachineBasicBlock *eb) : LB(lb), PB(pb), EB(eb) {}

2912

2913 MachineBasicBlock *LB, *PB, *EB;

2914 };

2915 using InstrList = std::vector<MachineInstr *>;

2916 struct InstrGroup {

2917 BitTracker::RegisterRef Inp, Out;

2919 };

2920 struct PhiInfo {

2921 PhiInfo(MachineInstr &P, MachineBasicBlock &B);

2922

2923 unsigned DefR;

2924 BitTracker::RegisterRef LR, PR;

2925 MachineBasicBlock *LB, *PB;

2926 };

2927

2928 static unsigned getDefReg(const MachineInstr *MI);

2930 bool isBitShuffle(const MachineInstr *MI, unsigned DefR) const;

2931 bool isStoreInput(const MachineInstr *MI, unsigned DefR) const;

2932 bool isShuffleOf(unsigned OutR, unsigned InpR) const;

2933 bool isSameShuffle(unsigned OutR1, unsigned InpR1, unsigned OutR2,

2934 unsigned &InpR2) const;

2935 void moveGroup(InstrGroup &G, MachineBasicBlock &LB, MachineBasicBlock &PB,

2937 bool processLoop(LoopCand &C);

2938 };

2939

2940}

2941

2942char HexagonLoopRescheduling::ID = 0;

2943

2945 "Hexagon Loop Rescheduling", false, false)

2946

2949 DefR = HexagonLoopRescheduling::getDefReg(&P);

2950 LB = &B;

2951 PB = nullptr;

2952 for (unsigned i = 1, n = P.getNumOperands(); i < n; i += 2) {

2954 if (OpB.getMBB() == &B) {

2955 LR = P.getOperand(i);

2956 continue;

2957 }

2959 PR = P.getOperand(i);

2960 }

2961}

2962

2963unsigned HexagonLoopRescheduling::getDefReg(const MachineInstr *MI) {

2965 HBS::getInstrDefs(*MI, Defs);

2966 if (Defs.count() != 1)

2967 return 0;

2968 return Defs.find_first();

2969}

2970

2971bool HexagonLoopRescheduling::isConst(unsigned Reg) const {

2973 return false;

2974 const BitTracker::RegisterCell &RC = BTP->lookup(Reg);

2975 for (unsigned i = 0, w = RC.width(); i < w; ++i) {

2976 const BitTracker::BitValue &V = RC[i];

2977 if (V.is(0) && V.is(1))

2978 return false;

2979 }

2980 return true;

2981}

2982

2983bool HexagonLoopRescheduling::isBitShuffle(const MachineInstr *MI,

2984 unsigned DefR) const {

2985 unsigned Opc = MI->getOpcode();

2986 switch (Opc) {

2987 case TargetOpcode::COPY:

2988 case Hexagon::S2_lsr_i_r:

2989 case Hexagon::S2_asr_i_r:

2990 case Hexagon::S2_asl_i_r:

2991 case Hexagon::S2_lsr_i_p:

2992 case Hexagon::S2_asr_i_p:

2993 case Hexagon::S2_asl_i_p:

2994 case Hexagon::S2_insert:

2995 case Hexagon::A2_or:

2996 case Hexagon::A2_orp:

2997 case Hexagon::A2_and:

2998 case Hexagon::A2_andp:

2999 case Hexagon::A2_combinew:

3000 case Hexagon::A4_combineri:

3001 case Hexagon::A4_combineir:

3002 case Hexagon::A2_combineii:

3003 case Hexagon::A4_combineii:

3004 case Hexagon::A2_combine_ll:

3005 case Hexagon::A2_combine_lh:

3006 case Hexagon::A2_combine_hl:

3007 case Hexagon::A2_combine_hh:

3008 return true;

3009 }

3010 return false;

3011}

3012

3013bool HexagonLoopRescheduling::isStoreInput(const MachineInstr *MI,

3014 unsigned InpR) const {

3015 for (unsigned i = 0, n = MI->getNumOperands(); i < n; ++i) {

3016 const MachineOperand &Op = MI->getOperand(i);

3017 if (Op.isReg())

3018 continue;

3019 if (Op.getReg() == InpR)

3020 return i == n-1;

3021 }

3022 return false;

3023}

3024

3025bool HexagonLoopRescheduling::isShuffleOf(unsigned OutR, unsigned InpR) const {

3026 if (!BTP->has(OutR) || !BTP->has(InpR))

3027 return false;

3028 const BitTracker::RegisterCell &OutC = BTP->lookup(OutR);

3029 for (unsigned i = 0, w = OutC.width(); i < w; ++i) {

3030 const BitTracker::BitValue &V = OutC[i];

3032 continue;

3033 if (V.RefI.Reg != InpR)

3034 return false;

3035 }

3036 return true;

3037}

3038

3039bool HexagonLoopRescheduling::isSameShuffle(unsigned OutR1, unsigned InpR1,

3040 unsigned OutR2, unsigned &InpR2) const {

3041 if (!BTP->has(OutR1) || !BTP->has(InpR1) || !BTP->has(OutR2))

3042 return false;

3043 const BitTracker::RegisterCell &OutC1 = BTP->lookup(OutR1);

3044 const BitTracker::RegisterCell &OutC2 = BTP->lookup(OutR2);

3045 unsigned W = OutC1.width();

3046 unsigned MatchR = 0;

3047 if (W != OutC2.width())

3048 return false;

3049 for (unsigned i = 0; i < W; ++i) {

3050 const BitTracker::BitValue &V1 = OutC1[i], &V2 = OutC2[i];

3052 return false;

3054 continue;

3055 if (V1.RefI.Pos != V2.RefI.Pos)

3056 return false;

3057 if (V1.RefI.Reg != InpR1)

3058 return false;

3059 if (V2.RefI.Reg == 0 || V2.RefI.Reg == OutR2)

3060 return false;

3061 if (!MatchR)

3062 MatchR = V2.RefI.Reg;

3063 else if (V2.RefI.Reg != MatchR)

3064 return false;

3065 }

3066 InpR2 = MatchR;

3067 return true;

3068}

3069

3070void HexagonLoopRescheduling::moveGroup(InstrGroup &G, MachineBasicBlock &LB,

3072 unsigned NewPredR) {

3073 DenseMap<unsigned,unsigned> RegMap;

3074

3075 const TargetRegisterClass *PhiRC = MRI->getRegClass(NewPredR);

3076 Register PhiR = MRI->createVirtualRegister(PhiRC);

3077 BuildMI(LB, At, At->getDebugLoc(), HII->get(TargetOpcode::PHI), PhiR)

3082 RegMap.insert(std::make_pair(G.Inp.Reg, PhiR));

3083

3084 for (const MachineInstr *SI : llvm::reverse(G.Ins)) {

3085 unsigned DR = getDefReg(SI);

3086 const TargetRegisterClass *RC = MRI->getRegClass(DR);

3087 Register NewDR = MRI->createVirtualRegister(RC);

3089

3090 auto MIB = BuildMI(LB, At, DL, HII->get(SI->getOpcode()), NewDR);

3091 for (const MachineOperand &Op : SI->operands()) {

3092 if (Op.isReg()) {

3093 MIB.add(Op);

3094 continue;

3095 }

3096 if (Op.isUse())

3097 continue;

3098 unsigned UseR = RegMap[Op.getReg()];

3099 MIB.addReg(UseR, 0, Op.getSubReg());

3100 }

3101 RegMap.insert(std::make_pair(DR, NewDR));

3102 }

3103

3104 HBS::replaceReg(OldPhiR, RegMap[G.Out.Reg], *MRI);

3105}

3106

3107bool HexagonLoopRescheduling::processLoop(LoopCand &C) {

3109 << "\n");

3110 std::vector Phis;

3111 for (auto &I : *C.LB) {

3112 if (I.isPHI())

3113 break;

3114 unsigned PR = getDefReg(&I);

3116 continue;

3117 bool BadUse = false, GoodUse = false;

3118 for (const MachineOperand &MO : MRI->use_operands(PR)) {

3119 const MachineInstr *UseI = MO.getParent();

3121 BadUse = true;

3122 break;

3123 }

3124 if (isBitShuffle(UseI, PR) || isStoreInput(UseI, PR))

3125 GoodUse = true;

3126 }

3127 if (BadUse || !GoodUse)

3128 continue;

3129

3130 Phis.push_back(PhiInfo(I, *C.LB));

3131 }

3132

3134 dbgs() << "Phis: {";

3135 for (auto &I : Phis) {

3136 dbgs() << ' ' << printReg(I.DefR, HRI) << "=phi("

3137 << printReg(I.PR.Reg, HRI, I.PR.Sub) << ":b" << I.PB->getNumber()

3138 << ',' << printReg(I.LR.Reg, HRI, I.LR.Sub) << ":b"

3139 << I.LB->getNumber() << ')';

3140 }

3141 dbgs() << " }\n";

3142 });

3143

3144 if (Phis.empty())

3145 return false;

3146

3148 InstrList ShufIns;

3149

3150

3151

3152

3153

3155 if (MI.isTerminator())

3156 continue;

3157 if (MI.isPHI())

3158 break;

3159

3161 HBS::getInstrDefs(MI, Defs);

3162 if (Defs.count() != 1)

3163 continue;

3164 Register DefR = Defs.find_first();

3166 continue;

3167 if (!isBitShuffle(&MI, DefR))

3168 continue;

3169

3170 bool BadUse = false;

3171 for (auto UI = MRI->use_begin(DefR), UE = MRI->use_end(); UI != UE; ++UI) {

3172 MachineInstr *UseI = UI->getParent();

3174 if (UseI->isPHI()) {

3175

3176

3177 unsigned Idx = UI.getOperandNo();

3179 BadUse = true;

3180 } else {

3182 BadUse = true;

3183 }

3184 } else {

3185

3186

3187 if (C.EB == nullptr)

3188 BadUse = true;

3189 }

3190 if (BadUse)

3191 break;

3192 }

3193

3194 if (BadUse)

3195 continue;

3196 ShufIns.push_back(&MI);

3197 }

3198

3199

3200

3201

3202

3203

3204

3205

3206

3207

3208 using InstrGroupList = std::vector;

3209 InstrGroupList Groups;

3210

3211 for (unsigned i = 0, n = ShufIns.size(); i < n; ++i) {

3212 MachineInstr *SI = ShufIns[i];

3213 if (SI == nullptr)

3214 continue;

3215

3216 InstrGroup G;

3217 G.Ins.push_back(SI);

3218 G.Out.Reg = getDefReg(SI);

3220 HBS::getInstrUses(*SI, Inputs);

3221

3222 for (unsigned j = i+1; j < n; ++j) {

3223 MachineInstr *MI = ShufIns[j];

3224 if (MI == nullptr)

3225 continue;

3227 HBS::getInstrDefs(*MI, Defs);

3228

3229 if (!Defs.intersects(Inputs))

3230 continue;

3231

3232

3233 G.Ins.push_back(MI);

3234 Inputs.remove(Defs);

3235

3236 HBS::getInstrUses(*MI, Inputs);

3237 ShufIns[j] = nullptr;

3238 }

3239

3240

3241 if (Inputs.count() > 1)

3242 continue;

3243 auto LoopInpEq = [G] (const PhiInfo &P) -> bool {

3244 return G.Out.Reg == P.LR.Reg;

3245 };

3247 continue;

3248

3249 G.Inp.Reg = Inputs.find_first();

3251 }

3252

3254 for (unsigned i = 0, n = Groups.size(); i < n; ++i) {

3255 InstrGroup &G = Groups[i];

3256 dbgs() << "Group[" << i << "] inp: "

3257 << printReg(G.Inp.Reg, HRI, G.Inp.Sub)

3258 << " out: " << printReg(G.Out.Reg, HRI, G.Out.Sub) << "\n";

3259 for (const MachineInstr *MI : G.Ins)

3260 dbgs() << " " << MI;

3261 }

3262 });

3263

3264 for (InstrGroup &G : Groups) {

3265 if (!isShuffleOf(G.Out.Reg, G.Inp.Reg))

3266 continue;

3267 auto LoopInpEq = [G] (const PhiInfo &P) -> bool {

3268 return G.Out.Reg == P.LR.Reg;

3269 };

3271 if (F == Phis.end())

3272 continue;

3273 unsigned PrehR = 0;

3274 if (!isSameShuffle(G.Out.Reg, G.Inp.Reg, F->PR.Reg, PrehR)) {

3275 const MachineInstr *DefPrehR = MRI->getVRegDef(F->PR.Reg);

3277 if (Opc != Hexagon::A2_tfrsi && Opc != Hexagon::A2_tfrpi)

3278 continue;

3280 continue;

3282 continue;

3283 const TargetRegisterClass *RC = MRI->getRegClass(G.Inp.Reg);

3284 if (RC != MRI->getRegClass(F->PR.Reg)) {

3285 PrehR = MRI->createVirtualRegister(RC);

3286 unsigned TfrI = (RC == &Hexagon::IntRegsRegClass) ? Hexagon::A2_tfrsi

3287 : Hexagon::A2_tfrpi;

3288 auto T = C.PB->getFirstTerminator();

3290 BuildMI(*C.PB, T, DL, HII->get(TfrI), PrehR)

3292 } else {

3293 PrehR = F->PR.Reg;

3294 }

3295 }

3296

3297

3298

3299

3300

3301 if (MRI->getRegClass(PrehR) != MRI->getRegClass(G.Inp.Reg))

3302 continue;

3303 moveGroup(G, *F->LB, *F->PB, F->LB->getFirstNonPHI(), F->DefR, PrehR);

3305 }

3306

3308}

3309

3310bool HexagonLoopRescheduling::runOnMachineFunction(MachineFunction &MF) {

3312 return false;

3313

3314 auto &HST = MF.getSubtarget();

3315 HII = HST.getInstrInfo();

3318 const HexagonEvaluator HE(*HRI, *MRI, *HII, MF);

3319 BitTracker BT(HE, MF);

3322 BTP = &BT;

3323

3324 std::vector Cand;

3325

3326 for (auto &B : MF) {

3327 if (B.pred_size() != 2 || B.succ_size() != 2)

3328 continue;

3329 MachineBasicBlock *PB = nullptr;

3330 bool IsLoop = false;

3331 for (MachineBasicBlock *Pred : B.predecessors()) {

3332 if (Pred != &B)

3333 PB = Pred;

3334 else

3335 IsLoop = true;

3336 }

3337 if (!IsLoop)

3338 continue;

3339

3340 MachineBasicBlock *EB = nullptr;

3341 for (MachineBasicBlock *Succ : B.successors()) {

3342 if (Succ == &B)

3343 continue;

3344

3345

3346 if (Succ->pred_size() == 1)

3347 EB = Succ;

3348 break;

3349 }

3350

3351 Cand.push_back(LoopCand(&B, PB, EB));

3352 }

3353

3355 for (auto &C : Cand)

3357

3359}

3360

3361

3362

3363

3364

3366 return new HexagonLoopRescheduling();

3367}

3368

3370 return new HexagonBitSimplify();

3371}

unsigned const MachineRegisterInfo * MRI

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

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

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

Function Alias Analysis false

This file implements the BitVector class.

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")

static std::optional< ArrayRef< InsnRange >::iterator > intersects(const MachineInstr *StartMI, const MachineInstr *EndMI, ArrayRef< InsnRange > Ranges, const InstructionOrdering &Ordering)

Check if the instruction range [StartMI, EndMI] intersects any instruction range in Ranges.

static unsigned CountBitSplit

Definition HexagonBitSimplify.cpp:49

static cl::opt< bool > PreserveTiedOps("hexbit-keep-tied", cl::Hidden, cl::init(true), cl::desc("Preserve subregisters in tied operands"))

static cl::opt< bool > GenExtract("hexbit-extract", cl::Hidden, cl::init(true), cl::desc("Generate extract instructions"))

static cl::opt< unsigned > MaxBitSplit("hexbit-max-bitsplit", cl::Hidden, cl::init(std::numeric_limits< unsigned >::max()))

static cl::opt< bool > GenBitSplit("hexbit-bitsplit", cl::Hidden, cl::init(true), cl::desc("Generate bitsplit instructions"))

static cl::opt< unsigned > MaxExtract("hexbit-max-extract", cl::Hidden, cl::init(std::numeric_limits< unsigned >::max()))

static cl::opt< unsigned > RegisterSetLimit("hexbit-registerset-limit", cl::Hidden, cl::init(1000))

static unsigned CountExtract

Definition HexagonBitSimplify.cpp:46

static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)

Promote Memory to Register

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

#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)

Remove Loads Into Fake Uses

bool isDead(const MachineInstr &MI, const MachineRegisterInfo &MRI)

This file defines the SmallVector class.

SmallSet< unsigned, 4 > RegisterSet

static const X86InstrFMA3Group Groups[]

AnalysisUsage & addRequired()

AnalysisUsage & addPreserved()

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

bool subsetOf(const BitVector &RHS) const

subsetOf - Check if This is a subset of RHS.

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

DomTreeNodeBase< NodeT > * getRootNode()

getRootNode - This returns the entry node for the CFG of the function.

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

bool hasOptSize() const

Optimize this function for size (-Os) or minimum size (-Oz).

unsigned getHexagonSubRegIndex(const TargetRegisterClass &RC, unsigned GenIdx) const

const HexagonRegisterInfo * getRegisterInfo() const override

MachineInstrBundleIterator< MachineInstr > iterator

Analysis pass which computes a MachineDominatorTree.

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

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

void getAnalysisUsage(AnalysisUsage &AU) const override

getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.

const TargetSubtargetInfo & getSubtarget() const

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

MachineRegisterInfo & getRegInfo()

getRegInfo - Return information about the registers currently in use.

Function & getFunction()

Return the LLVM function that this machine code represents.

const MachineBasicBlock & front() const

const MachineInstrBuilder & addImm(int64_t Val) const

Add a new immediate operand.

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

Add a new virtual register operand.

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

Representation of each machine instruction.

unsigned getOpcode() const

Returns the opcode of this MachineInstr.

const MachineBasicBlock * getParent() const

bool isDebugInstr() const

const DebugLoc & getDebugLoc() const

Returns the debug location id of this MachineInstr.

const MachineOperand & getOperand(unsigned i) const

MachineOperand class - Representation of each machine instruction operand.

void setSubReg(unsigned subReg)

unsigned getSubReg() const

bool isReg() const

isReg - Tests if this is a MO_Register operand.

MachineBasicBlock * getMBB() const

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.

static MachineOperand CreateImm(int64_t Val)

Register getReg() const

getReg - Returns the register number.

constexpr bool isVirtual() const

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

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

void push_back(const T &Elt)

unsigned getID() const

Return the register class ID number.

virtual const TargetRegisterInfo * getRegisterInfo() const =0

Return the target's register information.

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 char IsConst[]

Key for Kernel::Arg::Metadata::mIsConst.

unsigned ID

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

@ C

The default llvm calling convention, compatible with C.

@ ABS

ABS - Determine the unsigned absolute value of a signed integer value of the same bitwidth.

SmallVector< const MachineInstr * > InstrList

bool isConst(unsigned Opc)

initializer< Ty > init(const Ty &Val)

PointerTypeMap run(const Module &M)

Compute the PointerTypeMap for the module M.

LLVM_ABI std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)

Remove path.

This is an optimization pass for GlobalISel generic memory operations.

@ Low

Lower the current thread's priority such that it does not affect foreground tasks significantly.

auto find(R &&Range, const T &Val)

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

bool includes(R1 &&Range1, R2 &&Range2)

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

bool isEqual(const GCNRPTracker::LiveRegSet &S1, const GCNRPTracker::LiveRegSet &S2)

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

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

constexpr bool isInt(int64_t x)

Checks if an integer fits into the given bit width.

constexpr bool isUIntN(unsigned N, uint64_t x)

Checks if an unsigned integer fits into the given (dynamic) bit width.

FunctionPass * createHexagonBitSimplify()

Definition HexagonBitSimplify.cpp:3369

bool any_of(R &&range, UnaryPredicate P)

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

auto reverse(ContainerTy &&C)

constexpr uint32_t Hi_32(uint64_t Value)

Return the high 32 bits of a 64 bit value.

LLVM_ABI raw_ostream & dbgs()

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

bool none_of(R &&Range, UnaryPredicate P)

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

constexpr uint32_t Lo_32(uint64_t Value)

Return the low 32 bits of a 64 bit value.

DomTreeNodeBase< MachineBasicBlock > MachineDomTreeNode

FunctionPass * createHexagonLoopRescheduling()

Definition HexagonBitSimplify.cpp:3365

@ First

Helpers to iterate all locations in the MemoryEffectsBase class.

@ Sub

Subtraction of integers.

FunctionAddr VTableAddr Next

auto count(R &&Range, const E &Element)

Wrapper function around std::count to count the number of times an element Element occurs in the give...

DWARFExpression::Operation Op

raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)

auto find_if(R &&Range, UnaryPredicate P)

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

iterator_range< typename GraphTraits< GraphType >::ChildIteratorType > children(const typename GraphTraits< GraphType >::NodeRef &G)

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

Returns true if Element is found in Range.

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.

Maximum remaining allocation size observed for a phi node, and how often the allocation size has alre...

bool is(unsigned T) const

static BitValue self(const BitRef &Self=BitRef())

bool has(unsigned Reg) const

const RegisterCell & lookup(unsigned Reg) const

bool reached(const MachineBasicBlock *B) const

void trace(bool On=false)

void put(RegisterRef RR, const RegisterCell &RC)

void visit(const MachineInstr &MI)

RegisterCell get(RegisterRef RR) const