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

141 return !Rs.Bits.test(Bits);

142 }

144 return Bits.anyCommon(Rs.Bits);

145 }

146

147 private:

148 BitVector Bits;

149 std::deque LRU;

150

151 void ensure(unsigned Idx) {

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

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

154 }

155

156 static inline unsigned v2x(unsigned v) {

157 return Register(v).virtRegIndex();

158 }

159

160 static inline unsigned x2v(unsigned x) {

161 return Register::index2VirtReg(x);

162 }

163 };

164

165 struct PrintRegSet {

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

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

168

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

170 const PrintRegSet &P);

171

172 private:

174 const TargetRegisterInfo *TRI;

175 };

176

178 const PrintRegSet &P);

180 OS << '{';

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

183 OS << " }";

184 return OS;

185 }

186

187 class Transformation;

188

190 public:

191 static char ID;

192

193 HexagonBitSimplify() : MachineFunctionPass(ID) {}

194

195 StringRef getPassName() const override {

196 return "Hexagon bit simplification";

197 }

198

199 void getAnalysisUsage(AnalysisUsage &AU) const override {

200 AU.addRequired();

201 AU.addPreserved();

203 }

204

205 bool runOnMachineFunction(MachineFunction &MF) override;

206

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

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

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

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

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

212 uint16_t W);

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

214 uint16_t W, uint64_t &U);

216 MachineRegisterInfo &MRI);

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

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

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

220 MachineRegisterInfo &MRI);

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

222 unsigned NewSR, MachineRegisterInfo &MRI);

223 static bool parseRegSequence(const MachineInstr &I,

224 BitTracker::RegisterRef &SL, BitTracker::RegisterRef &SH,

225 const MachineRegisterInfo &MRI);

226

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

228 uint16_t Begin);

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

230 uint16_t Begin, const HexagonInstrInfo &HII);

231

232 static const TargetRegisterClass *getFinalVRegClass(

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

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

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

236

237 private:

238 MachineDominatorTree *MDT = nullptr;

239

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

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

242 unsigned NewSub = Hexagon::NoSubRegister);

243 };

244

245 using HBS = HexagonBitSimplify;

246

247

248

249

250 class Transformation {

251 public:

252 bool TopDown;

253

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

255 virtual ~Transformation() = default;

256

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

258 };

259

260}

261

262char HexagonBitSimplify::ID = 0;

263

265 "Hexagon bit simplification", false, false)

269

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

271 RegisterSet &AVs) {

273

274 if (T.TopDown)

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

276

277 RegisterSet Defs;

278 for (auto &I : B)

279 getInstrDefs(I, Defs);

280 RegisterSet NewAVs = AVs;

281 NewAVs.insert(Defs);

282

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

285

286 if (T.TopDown)

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

288

290}

291

292

293

294

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

296 RegisterSet &Defs) {

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

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

299 continue;

301 if (R.isVirtual())

302 continue;

303 Defs.insert(R);

304 }

305}

306

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

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

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

311 continue;

313 if (R.isVirtual())

314 continue;

315 Uses.insert(R);

316 }

317}

318

319

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

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

322 uint16_t W) {

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

324

326 return false;

327

329 return false;

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

331 return false;

332 }

333 return true;

334}

335

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

337 uint16_t B, uint16_t W) {

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

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

341 return false;

342 return true;

343}

344

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

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

348 int64_t T = 0;

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

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

351 T <<= 1;

352 if (BV.is(1))

353 T |= 1;

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

355 return false;

356 }

357 U = T;

358 return true;

359}

360

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

362 MachineRegisterInfo &MRI) {

364 return false;

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

366 decltype(End) NextI;

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

368 NextI = std::next(I);

369 I->setReg(NewR);

370 }

371 return Begin != End;

372}

373

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

375 unsigned NewSR,

376 MachineRegisterInfo &MRI) {

378 return false;

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

380 return false;

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

382 decltype(End) NextI;

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

384 NextI = std::next(I);

385 I->setReg(NewR);

386 I->setSubReg(NewSR);

387 }

388 return Begin != End;

389}

390

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

392 Register NewR, unsigned NewSR,

393 MachineRegisterInfo &MRI) {

395 return false;

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

397 return false;

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

399 decltype(End) NextI;

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

401 NextI = std::next(I);

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

403 continue;

404 I->setReg(NewR);

405 I->setSubReg(NewSR);

406 }

407 return Begin != End;

408}

409

410

411

412

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

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

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

416 if (RR.Sub == 0) {

417 Begin = 0;

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

419 return true;

420 }

421

422 Begin = 0;

423

424 switch (RC->getID()) {

425 case Hexagon::DoubleRegsRegClassID:

426 case Hexagon::HvxWRRegClassID:

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

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

429 Begin = Width;

430 break;

431 default:

432 return false;

433 }

434 return true;

435}

436

437

438

439

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

441 BitTracker::RegisterRef &SL, BitTracker::RegisterRef &SH,

442 const MachineRegisterInfo &MRI) {

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

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

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

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

447 *MRI.getTargetRegisterInfo());

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

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

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

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

452 SL = I.getOperand(1);

453 SH = I.getOperand(3);

454 return true;

455 }

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

457 SH = I.getOperand(1);

458 SL = I.getOperand(3);

459 return true;

460 }

461 return false;

462}

463

464

465

466

467

468

469

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

471 uint16_t Begin) {

472 using namespace Hexagon;

473

474 switch (Opc) {

475

476 case S2_storerb_io:

477 case S2_storerbnew_io:

478 case S2_pstorerbt_io:

479 case S2_pstorerbf_io:

480 case S4_pstorerbtnew_io:

481 case S4_pstorerbfnew_io:

482 case S2_pstorerbnewt_io:

483 case S2_pstorerbnewf_io:

484 case S4_pstorerbnewtnew_io:

485 case S4_pstorerbnewfnew_io:

486 case S2_storerb_pi:

487 case S2_storerbnew_pi:

488 case S2_pstorerbt_pi:

489 case S2_pstorerbf_pi:

490 case S2_pstorerbtnew_pi:

491 case S2_pstorerbfnew_pi:

492 case S2_pstorerbnewt_pi:

493 case S2_pstorerbnewf_pi:

494 case S2_pstorerbnewtnew_pi:

495 case S2_pstorerbnewfnew_pi:

496 case S4_storerb_ap:

497 case S4_storerbnew_ap:

498 case S2_storerb_pr:

499 case S2_storerbnew_pr:

500 case S4_storerb_ur:

501 case S4_storerbnew_ur:

502 case S2_storerb_pbr:

503 case S2_storerbnew_pbr:

504 case S2_storerb_pci:

505 case S2_storerbnew_pci:

506 case S2_storerb_pcr:

507 case S2_storerbnew_pcr:

508 case S4_storerb_rr:

509 case S4_storerbnew_rr:

510 case S4_pstorerbt_rr:

511 case S4_pstorerbf_rr:

512 case S4_pstorerbtnew_rr:

513 case S4_pstorerbfnew_rr:

514 case S4_pstorerbnewt_rr:

515 case S4_pstorerbnewf_rr:

516 case S4_pstorerbnewtnew_rr:

517 case S4_pstorerbnewfnew_rr:

518 case S2_storerbgp:

519 case S2_storerbnewgp:

520 case S4_pstorerbt_abs:

521 case S4_pstorerbf_abs:

522 case S4_pstorerbtnew_abs:

523 case S4_pstorerbfnew_abs:

524 case S4_pstorerbnewt_abs:

525 case S4_pstorerbnewf_abs:

526 case S4_pstorerbnewtnew_abs:

527 case S4_pstorerbnewfnew_abs:

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

529 return true;

530

531

532 case S2_storerh_io:

533 case S2_storerhnew_io:

534 case S2_pstorerht_io:

535 case S2_pstorerhf_io:

536 case S4_pstorerhtnew_io:

537 case S4_pstorerhfnew_io:

538 case S2_pstorerhnewt_io:

539 case S2_pstorerhnewf_io:

540 case S4_pstorerhnewtnew_io:

541 case S4_pstorerhnewfnew_io:

542 case S2_storerh_pi:

543 case S2_storerhnew_pi:

544 case S2_pstorerht_pi:

545 case S2_pstorerhf_pi:

546 case S2_pstorerhtnew_pi:

547 case S2_pstorerhfnew_pi:

548 case S2_pstorerhnewt_pi:

549 case S2_pstorerhnewf_pi:

550 case S2_pstorerhnewtnew_pi:

551 case S2_pstorerhnewfnew_pi:

552 case S4_storerh_ap:

553 case S4_storerhnew_ap:

554 case S2_storerh_pr:

555 case S2_storerhnew_pr:

556 case S4_storerh_ur:

557 case S4_storerhnew_ur:

558 case S2_storerh_pbr:

559 case S2_storerhnew_pbr:

560 case S2_storerh_pci:

561 case S2_storerhnew_pci:

562 case S2_storerh_pcr:

563 case S2_storerhnew_pcr:

564 case S4_storerh_rr:

565 case S4_pstorerht_rr:

566 case S4_pstorerhf_rr:

567 case S4_pstorerhtnew_rr:

568 case S4_pstorerhfnew_rr:

569 case S4_storerhnew_rr:

570 case S4_pstorerhnewt_rr:

571 case S4_pstorerhnewf_rr:

572 case S4_pstorerhnewtnew_rr:

573 case S4_pstorerhnewfnew_rr:

574 case S2_storerhgp:

575 case S2_storerhnewgp:

576 case S4_pstorerht_abs:

577 case S4_pstorerhf_abs:

578 case S4_pstorerhtnew_abs:

579 case S4_pstorerhfnew_abs:

580 case S4_pstorerhnewt_abs:

581 case S4_pstorerhnewf_abs:

582 case S4_pstorerhnewtnew_abs:

583 case S4_pstorerhnewfnew_abs:

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

585 return true;

586

587

588 case S2_storerf_io:

589 case S2_pstorerft_io:

590 case S2_pstorerff_io:

591 case S4_pstorerftnew_io:

592 case S4_pstorerffnew_io:

593 case S2_storerf_pi:

594 case S2_pstorerft_pi:

595 case S2_pstorerff_pi:

596 case S2_pstorerftnew_pi:

597 case S2_pstorerffnew_pi:

598 case S4_storerf_ap:

599 case S2_storerf_pr:

600 case S4_storerf_ur:

601 case S2_storerf_pbr:

602 case S2_storerf_pci:

603 case S2_storerf_pcr:

604 case S4_storerf_rr:

605 case S4_pstorerft_rr:

606 case S4_pstorerff_rr:

607 case S4_pstorerftnew_rr:

608 case S4_pstorerffnew_rr:

609 case S2_storerfgp:

610 case S4_pstorerft_abs:

611 case S4_pstorerff_abs:

612 case S4_pstorerftnew_abs:

613 case S4_pstorerffnew_abs:

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

615 return true;

616 }

617

618 return false;

619}

620

621

622

623

624

625

626

627

628

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

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

631 using namespace Hexagon;

632

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

634 if (D.mayStore()) {

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

636 return getUsedBitsInStore(Opc, Bits, Begin);

637 return false;

638 }

639

640 switch (Opc) {

641

642 case A2_sxtb:

643 case A2_zxtb:

644 case A4_cmpbeqi:

645 case A4_cmpbgti:

646 case A4_cmpbgtui:

647 if (OpN == 1) {

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

649 return true;

650 }

651 break;

652

653

654 case A2_aslh:

655 case A2_sxth:

656 case A2_zxth:

657 case A4_cmpheqi:

658 case A4_cmphgti:

659 case A4_cmphgtui:

660 if (OpN == 1) {

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

662 return true;

663 }

664 break;

665

666

667 case A2_asrh:

668 if (OpN == 1) {

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

670 return true;

671 }

672 break;

673

674

675 case A4_cmpbeq:

676 case A4_cmpbgt:

677 case A4_cmpbgtu:

678 if (OpN == 1) {

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

680 return true;

681 }

682 break;

683

684

685 case A4_cmpheq:

686 case A4_cmphgt:

687 case A4_cmphgtu:

688 case A2_addh_h16_ll:

689 case A2_addh_h16_sat_ll:

690 case A2_addh_l16_ll:

691 case A2_addh_l16_sat_ll:

692 case A2_combine_ll:

693 case A2_subh_h16_ll:

694 case A2_subh_h16_sat_ll:

695 case A2_subh_l16_ll:

696 case A2_subh_l16_sat_ll:

697 case M2_mpy_acc_ll_s0:

698 case M2_mpy_acc_ll_s1:

699 case M2_mpy_acc_sat_ll_s0:

700 case M2_mpy_acc_sat_ll_s1:

701 case M2_mpy_ll_s0:

702 case M2_mpy_ll_s1:

703 case M2_mpy_nac_ll_s0:

704 case M2_mpy_nac_ll_s1:

705 case M2_mpy_nac_sat_ll_s0:

706 case M2_mpy_nac_sat_ll_s1:

707 case M2_mpy_rnd_ll_s0:

708 case M2_mpy_rnd_ll_s1:

709 case M2_mpy_sat_ll_s0:

710 case M2_mpy_sat_ll_s1:

711 case M2_mpy_sat_rnd_ll_s0:

712 case M2_mpy_sat_rnd_ll_s1:

713 case M2_mpyd_acc_ll_s0:

714 case M2_mpyd_acc_ll_s1:

715 case M2_mpyd_ll_s0:

716 case M2_mpyd_ll_s1:

717 case M2_mpyd_nac_ll_s0:

718 case M2_mpyd_nac_ll_s1:

719 case M2_mpyd_rnd_ll_s0:

720 case M2_mpyd_rnd_ll_s1:

721 case M2_mpyu_acc_ll_s0:

722 case M2_mpyu_acc_ll_s1:

723 case M2_mpyu_ll_s0:

724 case M2_mpyu_ll_s1:

725 case M2_mpyu_nac_ll_s0:

726 case M2_mpyu_nac_ll_s1:

727 case M2_mpyud_acc_ll_s0:

728 case M2_mpyud_acc_ll_s1:

729 case M2_mpyud_ll_s0:

730 case M2_mpyud_ll_s1:

731 case M2_mpyud_nac_ll_s0:

732 case M2_mpyud_nac_ll_s1:

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

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

735 return true;

736 }

737 break;

738

739

740 case A2_addh_h16_lh:

741 case A2_addh_h16_sat_lh:

742 case A2_combine_lh:

743 case A2_subh_h16_lh:

744 case A2_subh_h16_sat_lh:

745 case M2_mpy_acc_lh_s0:

746 case M2_mpy_acc_lh_s1:

747 case M2_mpy_acc_sat_lh_s0:

748 case M2_mpy_acc_sat_lh_s1:

749 case M2_mpy_lh_s0:

750 case M2_mpy_lh_s1:

751 case M2_mpy_nac_lh_s0:

752 case M2_mpy_nac_lh_s1:

753 case M2_mpy_nac_sat_lh_s0:

754 case M2_mpy_nac_sat_lh_s1:

755 case M2_mpy_rnd_lh_s0:

756 case M2_mpy_rnd_lh_s1:

757 case M2_mpy_sat_lh_s0:

758 case M2_mpy_sat_lh_s1:

759 case M2_mpy_sat_rnd_lh_s0:

760 case M2_mpy_sat_rnd_lh_s1:

761 case M2_mpyd_acc_lh_s0:

762 case M2_mpyd_acc_lh_s1:

763 case M2_mpyd_lh_s0:

764 case M2_mpyd_lh_s1:

765 case M2_mpyd_nac_lh_s0:

766 case M2_mpyd_nac_lh_s1:

767 case M2_mpyd_rnd_lh_s0:

768 case M2_mpyd_rnd_lh_s1:

769 case M2_mpyu_acc_lh_s0:

770 case M2_mpyu_acc_lh_s1:

771 case M2_mpyu_lh_s0:

772 case M2_mpyu_lh_s1:

773 case M2_mpyu_nac_lh_s0:

774 case M2_mpyu_nac_lh_s1:

775 case M2_mpyud_acc_lh_s0:

776 case M2_mpyud_acc_lh_s1:

777 case M2_mpyud_lh_s0:

778 case M2_mpyud_lh_s1:

779 case M2_mpyud_nac_lh_s0:

780 case M2_mpyud_nac_lh_s1:

781

782 case A2_addh_l16_hl:

783 case A2_addh_l16_sat_hl:

784 case A2_subh_l16_hl:

785 case A2_subh_l16_sat_hl:

786 if (OpN == 1) {

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

788 return true;

789 }

790 if (OpN == 2) {

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

792 return true;

793 }

794 break;

795

796

797 case A2_addh_h16_hl:

798 case A2_addh_h16_sat_hl:

799 case A2_combine_hl:

800 case A2_subh_h16_hl:

801 case A2_subh_h16_sat_hl:

802 case M2_mpy_acc_hl_s0:

803 case M2_mpy_acc_hl_s1:

804 case M2_mpy_acc_sat_hl_s0:

805 case M2_mpy_acc_sat_hl_s1:

806 case M2_mpy_hl_s0:

807 case M2_mpy_hl_s1:

808 case M2_mpy_nac_hl_s0:

809 case M2_mpy_nac_hl_s1:

810 case M2_mpy_nac_sat_hl_s0:

811 case M2_mpy_nac_sat_hl_s1:

812 case M2_mpy_rnd_hl_s0:

813 case M2_mpy_rnd_hl_s1:

814 case M2_mpy_sat_hl_s0:

815 case M2_mpy_sat_hl_s1:

816 case M2_mpy_sat_rnd_hl_s0:

817 case M2_mpy_sat_rnd_hl_s1:

818 case M2_mpyd_acc_hl_s0:

819 case M2_mpyd_acc_hl_s1:

820 case M2_mpyd_hl_s0:

821 case M2_mpyd_hl_s1:

822 case M2_mpyd_nac_hl_s0:

823 case M2_mpyd_nac_hl_s1:

824 case M2_mpyd_rnd_hl_s0:

825 case M2_mpyd_rnd_hl_s1:

826 case M2_mpyu_acc_hl_s0:

827 case M2_mpyu_acc_hl_s1:

828 case M2_mpyu_hl_s0:

829 case M2_mpyu_hl_s1:

830 case M2_mpyu_nac_hl_s0:

831 case M2_mpyu_nac_hl_s1:

832 case M2_mpyud_acc_hl_s0:

833 case M2_mpyud_acc_hl_s1:

834 case M2_mpyud_hl_s0:

835 case M2_mpyud_hl_s1:

836 case M2_mpyud_nac_hl_s0:

837 case M2_mpyud_nac_hl_s1:

838 if (OpN == 1) {

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

840 return true;

841 }

842 if (OpN == 2) {

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

844 return true;

845 }

846 break;

847

848

849 case A2_addh_h16_hh:

850 case A2_addh_h16_sat_hh:

851 case A2_combine_hh:

852 case A2_subh_h16_hh:

853 case A2_subh_h16_sat_hh:

854 case M2_mpy_acc_hh_s0:

855 case M2_mpy_acc_hh_s1:

856 case M2_mpy_acc_sat_hh_s0:

857 case M2_mpy_acc_sat_hh_s1:

858 case M2_mpy_hh_s0:

859 case M2_mpy_hh_s1:

860 case M2_mpy_nac_hh_s0:

861 case M2_mpy_nac_hh_s1:

862 case M2_mpy_nac_sat_hh_s0:

863 case M2_mpy_nac_sat_hh_s1:

864 case M2_mpy_rnd_hh_s0:

865 case M2_mpy_rnd_hh_s1:

866 case M2_mpy_sat_hh_s0:

867 case M2_mpy_sat_hh_s1:

868 case M2_mpy_sat_rnd_hh_s0:

869 case M2_mpy_sat_rnd_hh_s1:

870 case M2_mpyd_acc_hh_s0:

871 case M2_mpyd_acc_hh_s1:

872 case M2_mpyd_hh_s0:

873 case M2_mpyd_hh_s1:

874 case M2_mpyd_nac_hh_s0:

875 case M2_mpyd_nac_hh_s1:

876 case M2_mpyd_rnd_hh_s0:

877 case M2_mpyd_rnd_hh_s1:

878 case M2_mpyu_acc_hh_s0:

879 case M2_mpyu_acc_hh_s1:

880 case M2_mpyu_hh_s0:

881 case M2_mpyu_hh_s1:

882 case M2_mpyu_nac_hh_s0:

883 case M2_mpyu_nac_hh_s1:

884 case M2_mpyud_acc_hh_s0:

885 case M2_mpyud_acc_hh_s1:

886 case M2_mpyud_hh_s0:

887 case M2_mpyud_hh_s1:

888 case M2_mpyud_nac_hh_s0:

889 case M2_mpyud_nac_hh_s1:

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

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

892 return true;

893 }

894 break;

895 }

896

897 return false;

898}

899

900

901

902

903const TargetRegisterClass *HexagonBitSimplify::getFinalVRegClass(

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

906 return nullptr;

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

908 if (RR.Sub == 0)

909 return RC;

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

911 *MRI.getTargetRegisterInfo());

912

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

914 (void)HRI;

917 };

918

919 switch (RC->getID()) {

920 case Hexagon::DoubleRegsRegClassID:

921 VerifySR(RC, RR.Sub);

922 return &Hexagon::IntRegsRegClass;

923 case Hexagon::HvxWRRegClassID:

924 VerifySR(RC, RR.Sub);

925 return &Hexagon::HvxVRRegClass;

926 }

927 return nullptr;

928}

929

930

931

932

933

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

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

937 return false;

938

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

940 if (!DRC)

941 return false;

942

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

944}

945

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

947 unsigned NewSub) {

949 return false;

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

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

953 });

954}

955

956namespace {

957

958 class DeadCodeElimination {

959 public:

960 DeadCodeElimination(MachineFunction &mf, MachineDominatorTree &mdt)

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

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

963

964 bool run() {

966 }

967

968 private:

969 bool isDead(unsigned R) const;

971

972 MachineFunction &MF;

973 const HexagonInstrInfo &HII;

974 MachineDominatorTree &MDT;

975 MachineRegisterInfo &MRI;

976 };

977

978}

979

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

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

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

984 continue;

985 if (UseI->isPHI()) {

988 if (DR == R)

989 continue;

990 }

991 return false;

992 }

993 return true;

994}

995

998

1000 Changed |= runOnNode(DTN);

1001

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

1003 std::vector<MachineInstr*> Instrs;

1005 Instrs.push_back(&MI);

1006

1007 for (auto *MI : Instrs) {

1008 unsigned Opc = MI->getOpcode();

1009

1010

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

1012 Opc == TargetOpcode::LIFETIME_END)

1013 continue;

1014 bool Store = false;

1015 if (MI->isInlineAsm())

1016 continue;

1017

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

1019 continue;

1020

1021 bool AllDead = true;

1022 SmallVector<unsigned,2> Regs;

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

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

1025 continue;

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

1028 AllDead = false;

1029 break;

1030 }

1032 }

1033 if (!AllDead)

1034 continue;

1035

1036 B->erase(MI);

1037 for (unsigned Reg : Regs)

1038 MRI.markUsesInDebugValueAsUndef(Reg);

1040 }

1041

1043}

1044

1045namespace {

1046

1047

1048

1049

1050

1051

1052

1053

1054

1055

1056

1057 class RedundantInstrElimination : public Transformation {

1058 public:

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

1060 const HexagonRegisterInfo &hri, MachineRegisterInfo &mri)

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

1062

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

1064

1065 private:

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

1067 unsigned &LostB, unsigned &LostE);

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

1069 unsigned &LostB, unsigned &LostE);

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

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

1072 uint16_t Begin);

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

1074

1075 const HexagonInstrInfo &HII;

1076 const HexagonRegisterInfo &HRI;

1077 MachineRegisterInfo &MRI;

1078 BitTracker &BT;

1079 };

1080

1081}

1082

1083

1084

1085

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

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

1088 using namespace Hexagon;

1089

1090 unsigned Opc = MI.getOpcode();

1091 unsigned ImN, RegN, Width;

1092 switch (Opc) {

1093 case S2_asl_i_p:

1094 ImN = 2;

1095 RegN = 1;

1096 Width = 64;

1097 break;

1098 case S2_asl_i_p_acc:

1099 case S2_asl_i_p_and:

1100 case S2_asl_i_p_nac:

1101 case S2_asl_i_p_or:

1102 case S2_asl_i_p_xacc:

1103 ImN = 3;

1104 RegN = 2;

1105 Width = 64;

1106 break;

1107 case S2_asl_i_r:

1108 ImN = 2;

1109 RegN = 1;

1110 Width = 32;

1111 break;

1112 case S2_addasl_rrri:

1113 case S4_andi_asl_ri:

1114 case S4_ori_asl_ri:

1115 case S4_addi_asl_ri:

1116 case S4_subi_asl_ri:

1117 case S2_asl_i_r_acc:

1118 case S2_asl_i_r_and:

1119 case S2_asl_i_r_nac:

1120 case S2_asl_i_r_or:

1121 case S2_asl_i_r_sat:

1122 case S2_asl_i_r_xacc:

1123 ImN = 3;

1124 RegN = 2;

1125 Width = 32;

1126 break;

1127 default:

1128 return false;

1129 }

1130

1131 if (RegN != OpN)

1132 return false;

1133

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

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

1136 if (S == 0)

1137 return false;

1138 LostB = Width-S;

1139 LostE = Width;

1140 return true;

1141}

1142

1143

1144

1145

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

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

1148 using namespace Hexagon;

1149

1150 unsigned Opc = MI.getOpcode();

1151 unsigned ImN, RegN;

1152 switch (Opc) {

1153 case S2_asr_i_p:

1154 case S2_lsr_i_p:

1155 ImN = 2;

1156 RegN = 1;

1157 break;

1158 case S2_asr_i_p_acc:

1159 case S2_asr_i_p_and:

1160 case S2_asr_i_p_nac:

1161 case S2_asr_i_p_or:

1162 case S2_lsr_i_p_acc:

1163 case S2_lsr_i_p_and:

1164 case S2_lsr_i_p_nac:

1165 case S2_lsr_i_p_or:

1166 case S2_lsr_i_p_xacc:

1167 ImN = 3;

1168 RegN = 2;

1169 break;

1170 case S2_asr_i_r:

1171 case S2_lsr_i_r:

1172 ImN = 2;

1173 RegN = 1;

1174 break;

1175 case S4_andi_lsr_ri:

1176 case S4_ori_lsr_ri:

1177 case S4_addi_lsr_ri:

1178 case S4_subi_lsr_ri:

1179 case S2_asr_i_r_acc:

1180 case S2_asr_i_r_and:

1181 case S2_asr_i_r_nac:

1182 case S2_asr_i_r_or:

1183 case S2_lsr_i_r_acc:

1184 case S2_lsr_i_r_and:

1185 case S2_lsr_i_r_nac:

1186 case S2_lsr_i_r_or:

1187 case S2_lsr_i_r_xacc:

1188 ImN = 3;

1189 RegN = 2;

1190 break;

1191

1192 default:

1193 return false;

1194 }

1195

1196 if (RegN != OpN)

1197 return false;

1198

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

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

1201 LostB = 0;

1202 LostE = S;

1203 return true;

1204}

1205

1206

1207

1208

1209

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

1211 BitVector Used(Bits.size());

1213 std::vector Pending;

1214 Pending.push_back(Reg);

1215

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

1217 unsigned R = Pending[i];

1218 if (Visited.has(R))

1219 continue;

1220 Visited.insert(R);

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

1222 BitTracker::RegisterRef UR = *I;

1223 unsigned B, W;

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

1225 return false;

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

1230 return false;

1231 Pending.push_back(DefR);

1232 } else {

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

1234 return false;

1235 }

1236 }

1237 }

1239 return true;

1240}

1241

1242

1243

1244

1245

1246

1247

1248

1249

1250

1251

1252

1253

1254

1255

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

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

1258 unsigned Opc = MI.getOpcode();

1259 BitVector T(Bits.size());

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

1261

1262

1263

1264 unsigned LB, LE;

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

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

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

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

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

1270

1271 if (!GotBits)

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

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

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

1275 GotBits = true;

1276 }

1277 if (GotBits)

1279 return GotBits;

1280}

1281

1282

1283

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

1285 BitTracker::RegisterRef RS) {

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

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

1288

1289 unsigned DB, DW;

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

1291 return false;

1292 unsigned SB, SW;

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

1294 return false;

1295 if (SW != DW)

1296 return false;

1297

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

1300 return false;

1301

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

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

1304 return false;

1305 return true;

1306}

1307

1308bool RedundantInstrElimination::processBlock(MachineBasicBlock &B,

1311 return false;

1313

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

1315 MachineInstr *MI = &*I;

1316

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

1318 continue;

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

1320 continue;

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

1322 if (NumD != 1)

1323 continue;

1324

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

1327 continue;

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

1330

1331

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

1333 if (Op.isReg())

1334 continue;

1335 BitTracker::RegisterRef RS = Op;

1337 continue;

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

1339 continue;

1340

1341 unsigned BN, BW;

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

1343 continue;

1344

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

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

1347 continue;

1348

1349

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

1352 Register NewR = MRI.createVirtualRegister(FRC);

1353 MachineInstr *CopyI =

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

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

1357

1358

1359

1360

1361

1362

1363

1364

1365

1368 break;

1369 }

1370 }

1371

1373}

1374

1375namespace {

1376

1377

1378

1379 class ConstGeneration : public Transformation {

1380 public:

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

1382 MachineRegisterInfo &mri)

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

1384

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

1386 static bool isTfrConst(const MachineInstr &MI);

1387

1388 private:

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

1392

1393 const HexagonInstrInfo &HII;

1394 MachineRegisterInfo &MRI;

1395 BitTracker &BT;

1396 };

1397

1398}

1399

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

1401 unsigned Opc = MI.getOpcode();

1402 switch (Opc) {

1403 case Hexagon::A2_combineii:

1404 case Hexagon::A4_combineii:

1405 case Hexagon::A2_tfrsi:

1406 case Hexagon::A2_tfrpi:

1407 case Hexagon::PS_true:

1408 case Hexagon::PS_false:

1409 case Hexagon::CONST32:

1410 case Hexagon::CONST64:

1411 return true;

1412 }

1413 return false;

1414}

1415

1416

1417

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

1419 MachineBasicBlock &B,

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

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

1426 return Reg;

1427 }

1428

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

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

1433 return Reg;

1434 }

1435

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

1439 : Hexagon::A4_combineii;

1443 return Reg;

1444 }

1445 MachineFunction *MF = B.getParent();

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

1447

1448

1449 if (!HST.isTinyCore() ||

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

1453 return Reg;

1454 }

1455 }

1456

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

1458 unsigned Opc;

1459 if (C == 0)

1460 Opc = Hexagon::PS_false;

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

1462 Opc = Hexagon::PS_true;

1463 else

1464 return 0;

1466 return Reg;

1467 }

1468

1469 return 0;

1470}

1471

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

1474 return false;

1477

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

1479 if (isTfrConst(*I))

1480 continue;

1481 Defs.clear();

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

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

1484 continue;

1485 Register DR = Defs.find_first();

1487 continue;

1488 uint64_t U;

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

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

1491 int64_t C = U;

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

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

1495 if (ImmReg) {

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

1497 BT.put(ImmReg, DRC);

1499 }

1500 }

1501 }

1503}

1504

1505namespace {

1506

1507

1508

1509

1510 class CopyGeneration : public Transformation {

1511 public:

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

1513 const HexagonRegisterInfo &hri, MachineRegisterInfo &mri)

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

1515

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

1517

1518 private:

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

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

1521

1522 const HexagonInstrInfo &HII;

1523 const HexagonRegisterInfo &HRI;

1524 MachineRegisterInfo &MRI;

1525 BitTracker &BT;

1527 };

1528

1529

1530

1531 class CopyPropagation : public Transformation {

1532 public:

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

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

1535

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

1537

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

1539

1540 private:

1541 bool propagateRegCopy(MachineInstr &MI);

1542

1543 const HexagonRegisterInfo &HRI;

1544 MachineRegisterInfo &MRI;

1545 };

1546

1547}

1548

1549

1550

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

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

1554 return false;

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

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

1557 unsigned B, W;

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

1559 return false;

1560

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

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

1563 continue;

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

1565 unsigned RW = RC.width();

1566 if (W == RW) {

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

1568 continue;

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

1570 continue;

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

1572 continue;

1573 Out.Reg = R;

1574 Out.Sub = 0;

1575 return true;

1576 }

1577

1578

1579

1580 if (W*2 != RW)

1581 continue;

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

1583 continue;

1584

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

1586 Out.Sub = Hexagon::isub_lo;

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

1588 Out.Sub = Hexagon::isub_hi;

1589 else

1590 continue;

1591 Out.Reg = R;

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

1593 return true;

1594 }

1595 return false;

1596}

1597

1598bool CopyGeneration::processBlock(MachineBasicBlock &B,

1601 return false;

1605

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

1607 Defs.clear();

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

1609

1610 unsigned Opc = I->getOpcode();

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

1612 ConstGeneration::isTfrConst(*I))

1613 continue;

1614

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

1617

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

1619 BitTracker::RegisterRef MR;

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

1621

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

1623 Register NewR = MRI.createVirtualRegister(FRC);

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

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

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

1628 Forbidden.insert(R);

1629 continue;

1630 }

1631

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

1633 FRC == &Hexagon::HvxWRRegClass) {

1634

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

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

1639 BitTracker::RegisterRef ML, MH;

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

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

1642 Register NewR = MRI.createVirtualRegister(FRC);

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

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

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

1650 Forbidden.insert(R);

1651 }

1652 }

1653 }

1654 }

1655

1657}

1658

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

1660 switch (Opc) {

1661 case TargetOpcode::COPY:

1662 case TargetOpcode::REG_SEQUENCE:

1663 case Hexagon::A4_combineir:

1664 case Hexagon::A4_combineri:

1665 return true;

1666 case Hexagon::A2_tfr:

1667 case Hexagon::A2_tfrp:

1668 case Hexagon::A2_combinew:

1669 case Hexagon::V6_vcombine:

1670 return NoConv;

1671 default:

1672 break;

1673 }

1674 return false;

1675}

1676

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

1679 unsigned Opc = MI.getOpcode();

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

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

1682

1683 switch (Opc) {

1684 case TargetOpcode::COPY:

1685 case Hexagon::A2_tfr:

1686 case Hexagon::A2_tfrp: {

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

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

1689 break;

1690 if (RS.Sub != 0)

1692 else

1694 break;

1695 }

1696 case TargetOpcode::REG_SEQUENCE: {

1697 BitTracker::RegisterRef SL, SH;

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

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

1704 }

1705 break;

1706 }

1707 case Hexagon::A2_combinew:

1708 case Hexagon::V6_vcombine: {

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

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

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

1715 break;

1716 }

1717 case Hexagon::A4_combineir:

1718 case Hexagon::A4_combineri: {

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

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

1721 : Hexagon::isub_hi;

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

1724 break;

1725 }

1726 }

1728}

1729

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

1731 std::vector<MachineInstr*> Instrs;

1733 Instrs.push_back(&MI);

1734

1736 for (auto *I : Instrs) {

1737 unsigned Opc = I->getOpcode();

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

1739 continue;

1740 Changed |= propagateRegCopy(*I);

1741 }

1742

1744}

1745

1746namespace {

1747

1748

1749

1750

1751 class BitSimplification : public Transformation {

1752 public:

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

1754 const HexagonInstrInfo &hii,

1755 const HexagonRegisterInfo &hri, MachineRegisterInfo &mri,

1756 MachineFunction &mf)

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

1758 }

1759

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

1761

1762 private:

1763 struct RegHalf : public BitTracker::RegisterRef {

1764 bool Low;

1765 };

1766

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

1768 unsigned B, RegHalf &RH);

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

1770

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

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

1773 unsigned getCombineOpcode(bool HLow, bool LLow);

1774

1775 bool genStoreUpperHalf(MachineInstr *MI);

1776 bool genStoreImmediate(MachineInstr *MI);

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

1778 const BitTracker::RegisterCell &RC);

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

1780 const BitTracker::RegisterCell &RC);

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

1782 const BitTracker::RegisterCell &RC);

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

1784 const BitTracker::RegisterCell &RC);

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

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

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

1788 const BitTracker::RegisterCell &RC);

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

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

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

1792

1793

1794

1795 std::vector<MachineInstr*> NewMIs;

1796

1797 const MachineDominatorTree &MDT;

1798 const HexagonInstrInfo &HII;

1799 [[maybe_unused]] const HexagonRegisterInfo &HRI;

1800 MachineRegisterInfo &MRI;

1801 BitTracker &BT;

1802 };

1803

1804}

1805

1806

1807

1808

1809bool BitSimplification::matchHalf(unsigned SelfR,

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

1811

1812

1813

1814

1815

1816

1817

1818 bool Low = false;

1819 unsigned I = B;

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

1821 I++;

1822 if (I == B+16)

1823 return false;

1824

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

1827 if (P < I-B)

1828 return false;

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

1830

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

1832 return false;

1834 return false;

1836 return false;

1837

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

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

1840 return false;

1841

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

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

1846 return false;

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

1848 return false;

1849 continue;

1850 }

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

1852 return false;

1853 }

1854

1855 unsigned Sub = 0;

1856 switch (Pos) {

1857 case 0:

1858 Sub = Hexagon::isub_lo;

1859 Low = true;

1860 break;

1861 case 16:

1862 Sub = Hexagon::isub_lo;

1863 Low = false;

1864 break;

1865 case 32:

1866 Sub = Hexagon::isub_hi;

1867 Low = true;

1868 break;

1869 case 48:

1870 Sub = Hexagon::isub_hi;

1871 Low = false;

1872 break;

1873 default:

1874 return false;

1875 }

1876

1877 RH.Reg = Reg;

1878 RH.Sub = Sub;

1879 RH.Low = Low;

1880

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

1882 RH.Sub = 0;

1883

1884 return true;

1885}

1886

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

1888 unsigned OpNum) {

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

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

1891 return OpRC->hasSubClassEq(RRC);

1892}

1893

1894

1895

1896bool BitSimplification::matchPackhl(unsigned SelfR,

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

1898 BitTracker::RegisterRef &Rt) {

1899 RegHalf L1, H1, L2, H2;

1900

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

1902 return false;

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

1904 return false;

1905

1906

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

1908 return false;

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

1910 return false;

1911

1912 Rs = H1;

1913 Rt = H2;

1914 return true;

1915}

1916

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

1918 return HLow ? LLow ? Hexagon::A2_combine_ll

1919 : Hexagon::A2_combine_lh

1920 : LLow ? Hexagon::A2_combine_hl

1921 : Hexagon::A2_combine_hh;

1922}

1923

1924

1925

1926

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

1928 unsigned Opc = MI->getOpcode();

1929 if (Opc != Hexagon::S2_storerh_io)

1930 return false;

1931

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

1933 BitTracker::RegisterRef RS = ValOp;

1935 return false;

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

1937 RegHalf H;

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

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

1940 return false;

1941 if (H.Low)

1942 return false;

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

1946 return true;

1947}

1948

1949

1950

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

1952 unsigned Opc = MI->getOpcode();

1953 unsigned Align = 0;

1954 switch (Opc) {

1955 case Hexagon::S2_storeri_io:

1957 [[fallthrough]];

1958 case Hexagon::S2_storerh_io:

1960 [[fallthrough]];

1961 case Hexagon::S2_storerb_io:

1962 break;

1963 default:

1964 return false;

1965 }

1966

1967

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

1969 return false;

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

1971 if (!OffOp.isImm())

1972 return false;

1973

1975

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

1977 return false;

1978

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

1981 return false;

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

1983 uint64_t U;

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

1985 return false;

1986

1987

1988 int V;

1989 switch (Opc) {

1990 case Hexagon::S2_storerb_io:

1991 V = int8_t(U);

1992 break;

1993 case Hexagon::S2_storerh_io:

1994 V = int16_t(U);

1995 break;

1996 case Hexagon::S2_storeri_io:

1997 V = int32_t(U);

1998 break;

1999 default:

2000

2001

2003 }

2005 return false;

2006

2007 MI->removeOperand(2);

2008 switch (Opc) {

2009 case Hexagon::S2_storerb_io:

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

2011 break;

2012 case Hexagon::S2_storerh_io:

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

2014 break;

2015 case Hexagon::S2_storeri_io:

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

2017 break;

2018 }

2020 return true;

2021}

2022

2023

2024

2025

2026

2027bool BitSimplification::genPackhl(MachineInstr *MI,

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

2029 unsigned Opc = MI->getOpcode();

2030 if (Opc == Hexagon::S2_packhl)

2031 return false;

2032 BitTracker::RegisterRef Rs, Rt;

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

2034 return false;

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

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

2037 return false;

2038

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

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

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

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

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

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

2049 return true;

2050}

2051

2052

2053

2054bool BitSimplification::genExtractHalf(MachineInstr *MI,

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

2056 RegHalf L;

2057

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

2059 return false;

2060

2061 unsigned Opc = MI->getOpcode();

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

2064

2065

2066

2067 unsigned NewR = 0;

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

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

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

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

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

2075 }

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

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

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

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

2082 }

2083 }

2084 if (NewR == 0)

2085 return false;

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

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

2088 return true;

2089}

2090

2091

2092

2093bool BitSimplification::genCombineHalf(MachineInstr *MI,

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

2095 RegHalf L, H;

2096

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

2098 return false;

2099

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

2101 return false;

2102

2103 unsigned Opc = MI->getOpcode();

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

2105 if (COpc == Opc)

2106 return false;

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

2108 return false;

2109

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

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

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

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

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

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

2120 return true;

2121}

2122

2123

2124

2125bool BitSimplification::genExtractLow(MachineInstr *MI,

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

2127 unsigned Opc = MI->getOpcode();

2128 switch (Opc) {

2129 case Hexagon::A2_zxtb:

2130 case Hexagon::A2_zxth:

2131 case Hexagon::S2_extractu:

2132 return false;

2133 }

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

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

2137 return false;

2138 }

2139

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

2141 return false;

2142 unsigned W = RC.width();

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

2144 W--;

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

2146 return false;

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

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

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

2150 : Hexagon::S2_extractu;

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

2153

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

2155 if (!Op.isReg())

2156 continue;

2157 BitTracker::RegisterRef RS = Op;

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

2159 continue;

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

2161 unsigned BN, BW;

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

2163 continue;

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

2165 continue;

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

2167 continue;

2168

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

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

2171 : MachineBasicBlock::iterator(MI);

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

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

2174 if (NewOpc == Hexagon::A2_andir)

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

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

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

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

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

2180 return true;

2181 }

2182 return false;

2183}

2184

2185bool BitSimplification::genBitSplit(MachineInstr *MI,

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

2189 return false;

2192 return false;

2193 }

2194

2195 unsigned Opc = MI->getOpcode();

2196 switch (Opc) {

2197 case Hexagon::A4_bitsplit:

2198 case Hexagon::A4_bitspliti:

2199 return false;

2200 }

2201

2202 unsigned W = RC.width();

2203 if (W != 32)

2204 return false;

2205

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

2207 unsigned Z = C.width();

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

2209 --Z;

2210 return C.width() - Z;

2211 };

2212

2213

2214 unsigned Z = ctlz(RC);

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

2216 return false;

2217

2218

2219

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

2222 return false;

2223

2224 unsigned SrcR = B0.RefI.Reg;

2225 unsigned SrcSR = 0;

2226 unsigned Pos = B0.RefI.Pos;

2227

2228

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

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

2232 return false;

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

2234 return false;

2235 }

2236

2237

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

2239

2240

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

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

2243 SRC != Hexagon::DoubleRegsRegClassID)

2244 continue;

2246 continue;

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

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

2249 continue;

2250

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

2253 continue;

2255

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

2257 continue;

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

2259 continue;

2260

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

2262 continue;

2263

2264 unsigned I;

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

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

2268 break;

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

2270 break;

2271 }

2272 if (I != Z)

2273 continue;

2274

2275

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

2279 assert(DefS != nullptr);

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

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

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

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

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

2287 continue;

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

2289

2290

2291 unsigned NewR = 0;

2292 for (MachineInstr *In : NewMIs) {

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

2294 continue;

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

2297 continue;

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

2299 continue;

2300

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

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

2303 assert(DefI != nullptr);

2305 continue;

2306

2307

2309 NewR = Op0.getReg();

2310 break;

2311 }

2312 if (!NewR) {

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

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

2315 .addReg(SrcR, 0, SrcSR)

2317 NewMIs.push_back(NewBS);

2318 }

2319 if (Pos <= P) {

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

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

2322 } else {

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

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

2325 }

2326 return true;

2327 }

2328

2329 return false;

2330}

2331

2332

2333

2334

2335

2336

2337

2338bool BitSimplification::simplifyTstbit(MachineInstr *MI,

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

2340 unsigned Opc = MI->getOpcode();

2341 if (Opc != Hexagon::S2_tstbit_i)

2342 return false;

2343

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

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

2346 unsigned F, W;

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

2349 return false;

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

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

2353

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

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

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

2358

2359

2360

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

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

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

2364 P = V.RefI.Pos;

2365 RR.Sub = Hexagon::isub_lo;

2366 if (P >= 32) {

2367 P -= 32;

2368 RR.Sub = Hexagon::isub_hi;

2369 }

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

2371 P = V.RefI.Pos;

2372 }

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

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

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

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

2379 BT.put(NewR, RC);

2380 return true;

2381 }

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

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

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

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

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

2387 return true;

2388 }

2389

2390 return false;

2391}

2392

2393

2394

2395

2396

2397

2398bool BitSimplification::simplifyExtractLow(MachineInstr *MI,

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

2402 return false;

2403 if (MaxExtract.getNumOccurrences()) {

2405 return false;

2407 }

2408

2409 unsigned W = RC.width();

2410 unsigned RW = W;

2411 unsigned Len;

2413

2414

2415

2416

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

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

2419 return false;

2421

2422

2423

2424

2425

2426

2427

2428

2429

2430

2431

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

2433

2434

2435

2436

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

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

2441 return false;

2443 }

2444 if (IsConst)

2445 return false;

2446

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

2448 bool S = TopV.is(1);

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

2450 ;

2453

2456 } else {

2457

2460 return false;

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

2462 ;

2463

2464

2465 Len = W + 1;

2467 }

2468

2469

2470 if (Len == RW)

2471 return false;

2472

2475 << ", MI: " << *MI;

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

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

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

2479 });

2480

2482

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

2485 continue;

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

2487 unsigned SW = SC.width();

2488

2489

2490

2491

2492

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

2494 continue;

2495

2496

2497

2498

2499 unsigned Off = 0;

2500 while (Off <= SW-Len) {

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

2502 if (OE != Off/RW) {

2503

2504

2505

2506

2507

2508

2509 Off = OE*RW;

2510 continue;

2511 }

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

2513 break;

2515 }

2516

2517 if (Off > SW-Len)

2518 continue;

2519

2520

2521 unsigned ExtOpc = 0;

2522 if (Off == 0) {

2523 if (Len == 8)

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

2525 else if (Len == 16)

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

2527 else if (Len < 10 && Signed)

2528 ExtOpc = Hexagon::A2_andir;

2529 }

2530 if (ExtOpc == 0) {

2531 ExtOpc =

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

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

2534 }

2535 unsigned SR = 0;

2536

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

2538 continue;

2539 if (RW != SW)

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

2542

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

2544 continue;

2545

2546

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

2548

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

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

2551 continue;

2552 }

2553

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

2556 Register NewR = MRI.createVirtualRegister(FRC);

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

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

2561 switch (ExtOpc) {

2562 case Hexagon::A2_sxtb:

2563 case Hexagon::A2_zxtb:

2564 case Hexagon::A2_sxth:

2565 case Hexagon::A2_zxth:

2566 break;

2567 case Hexagon::A2_andir:

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

2569 break;

2570 case Hexagon::S4_extract:

2571 case Hexagon::S2_extractu:

2572 case Hexagon::S4_extractp:

2573 case Hexagon::S2_extractup:

2574 MIB.addImm(Len)

2575 .addImm(Off);

2576 break;

2577 default:

2579 }

2580

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

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

2584 break;

2585 }

2586

2588}

2589

2590bool BitSimplification::simplifyRCmp0(MachineInstr *MI,

2591 BitTracker::RegisterRef RD) {

2592 unsigned Opc = MI->getOpcode();

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

2594 return false;

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

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

2597 return false;

2598

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

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

2601 return false;

2603

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

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

2608 bool KnownZ = true;

2609 bool KnownNZ = false;

2610

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

2613 return false;

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

2615 unsigned F, W;

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

2617 return false;

2618

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

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

2621 if (V.is(0))

2622 KnownZ = false;

2623 if (V.is(1))

2624 KnownNZ = true;

2625 }

2626

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

2628 Register NewR = MRI.createVirtualRegister(FRC);

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

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

2632 BitTracker::RegisterCell NewRC(W);

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

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

2635 C = unsigned(C) >> 1;

2636 }

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

2638 return true;

2639 };

2640

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

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

2643 return true;

2644 if (Op.isImm())

2645 return Op.getImm() != 0;

2646 if (Op.isCImm())

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

2648 if (Op.isFPImm())

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

2650 return false;

2651 };

2652

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

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

2655 return false;

2656 if (Op.isImm())

2657 return Op.getImm() == 0;

2658 if (Op.isCImm())

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

2660 if (Op.isFPImm())

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

2662 return false;

2663 };

2664

2665

2666

2667 if (KnownZ || KnownNZ) {

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

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

2670 }

2671

2672

2673

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

2675 if (!InpDef)

2676 return false;

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

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

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

2680

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

2682 if (KnownNZ1 && KnownNZ2)

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

2684

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

2686 if (KnownZ1 && KnownZ2)

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

2688

2689

2690

2691

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

2693 Register NewR = MRI.createVirtualRegister(FRC);

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

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

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

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

2699

2700 BitTracker::RegisterCell NewRC(W);

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

2704 return true;

2705 }

2706 }

2707

2708 return false;

2709}

2710

2711bool BitSimplification::processBlock(MachineBasicBlock &B,

2714 return false;

2718

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

2720 MachineInstr *MI = &*I;

2721 Defs.clear();

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

2723

2724 unsigned Opc = MI->getOpcode();

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

2726 continue;

2727

2728 if (MI->mayStore()) {

2729 bool T = genStoreUpperHalf(MI);

2730 T = T || genStoreImmediate(MI);

2732 continue;

2733 }

2734

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

2736 continue;

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

2739 continue;

2740 BitTracker::RegisterRef RD = Op0;

2742 continue;

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

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

2745

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

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

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

2750 continue;

2751 }

2752

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

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

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

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

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

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

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

2761 continue;

2762 }

2763

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

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

2767 continue;

2768 }

2769 }

2771}

2772

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

2775 return false;

2776

2777 auto &HST = MF.getSubtarget();

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

2780

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

2784

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

2786

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

2788 BitTracker BT(HE, MF);

2791

2792 MachineBasicBlock &Entry = MF.front();

2793

2794 RegisterSet AIG;

2795 ConstGeneration ImmG(BT, HII, MRI);

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

2797

2798 RegisterSet ARE;

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

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

2801 if (Ried) {

2804 }

2805

2806 RegisterSet ACG;

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

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

2809

2810 RegisterSet ACP;

2811 CopyPropagation CopyP(HRI, MRI);

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

2813

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

2815

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

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

2820

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

2822

2824 for (auto &B : MF)

2825 for (auto &I : B)

2826 I.clearKillInfo();

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

2828 }

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

2893

2894namespace {

2895

2896 class HexagonLoopRescheduling : public MachineFunctionPass {

2897 public:

2898 static char ID;

2899

2900 HexagonLoopRescheduling() : MachineFunctionPass(ID) {}

2901

2902 bool runOnMachineFunction(MachineFunction &MF) override;

2903

2904 private:

2905 const HexagonInstrInfo *HII = nullptr;

2906 const HexagonRegisterInfo *HRI = nullptr;

2907 MachineRegisterInfo *MRI = nullptr;

2908 BitTracker *BTP = nullptr;

2909

2910 struct LoopCand {

2911 LoopCand(MachineBasicBlock *lb, MachineBasicBlock *pb,

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

2913

2914 MachineBasicBlock *LB, *PB, *EB;

2915 };

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

2917 struct InstrGroup {

2918 BitTracker::RegisterRef Inp, Out;

2920 };

2921 struct PhiInfo {

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

2923

2924 unsigned DefR;

2925 BitTracker::RegisterRef LR, PR;

2926 MachineBasicBlock *LB, *PB;

2927 };

2928

2929 static unsigned getDefReg(const MachineInstr *MI);

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

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

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

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

2935 unsigned &InpR2) const;

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

2938 bool processLoop(LoopCand &C);

2939 };

2940

2941}

2942

2943char HexagonLoopRescheduling::ID = 0;

2944

2946 "Hexagon Loop Rescheduling", false, false)

2947

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

2951 LB = &B;

2952 PB = nullptr;

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

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

2956 LR = P.getOperand(i);

2957 continue;

2958 }

2960 PR = P.getOperand(i);

2961 }

2962}

2963

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

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

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

2968 return 0;

2969 return Defs.find_first();

2970}

2971

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

2974 return false;

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

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

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

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

2979 return false;

2980 }

2981 return true;

2982}

2983

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

2985 unsigned DefR) const {

2986 unsigned Opc = MI->getOpcode();

2987 switch (Opc) {

2988 case TargetOpcode::COPY:

2989 case Hexagon::S2_lsr_i_r:

2990 case Hexagon::S2_asr_i_r:

2991 case Hexagon::S2_asl_i_r:

2992 case Hexagon::S2_lsr_i_p:

2993 case Hexagon::S2_asr_i_p:

2994 case Hexagon::S2_asl_i_p:

2995 case Hexagon::S2_insert:

2996 case Hexagon::A2_or:

2997 case Hexagon::A2_orp:

2998 case Hexagon::A2_and:

2999 case Hexagon::A2_andp:

3000 case Hexagon::A2_combinew:

3001 case Hexagon::A4_combineri:

3002 case Hexagon::A4_combineir:

3003 case Hexagon::A2_combineii:

3004 case Hexagon::A4_combineii:

3005 case Hexagon::A2_combine_ll:

3006 case Hexagon::A2_combine_lh:

3007 case Hexagon::A2_combine_hl:

3008 case Hexagon::A2_combine_hh:

3009 return true;

3010 }

3011 return false;

3012}

3013

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

3015 unsigned InpR) const {

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

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

3018 if (Op.isReg())

3019 continue;

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

3021 return i == n-1;

3022 }

3023 return false;

3024}

3025

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

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

3028 return false;

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

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

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

3033 continue;

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

3035 return false;

3036 }

3037 return true;

3038}

3039

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

3041 unsigned OutR2, unsigned &InpR2) const {

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

3043 return false;

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

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

3046 unsigned W = OutC1.width();

3047 unsigned MatchR = 0;

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

3049 return false;

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

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

3053 return false;

3055 continue;

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

3057 return false;

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

3059 return false;

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

3061 return false;

3062 if (!MatchR)

3063 MatchR = V2.RefI.Reg;

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

3065 return false;

3066 }

3067 InpR2 = MatchR;

3068 return true;

3069}

3070

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

3073 unsigned NewPredR) {

3074 DenseMap<unsigned,unsigned> RegMap;

3075

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

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

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

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

3084

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

3086 unsigned DR = getDefReg(SI);

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

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

3090

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

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

3093 if (Op.isReg()) {

3094 MIB.add(Op);

3095 continue;

3096 }

3097 if (Op.isUse())

3098 continue;

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

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

3101 }

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

3103 }

3104

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

3106}

3107

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

3110 << "\n");

3111 std::vector Phis;

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

3113 if (I.isPHI())

3114 break;

3115 unsigned PR = getDefReg(&I);

3117 continue;

3118 bool BadUse = false, GoodUse = false;

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

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

3122 BadUse = true;

3123 break;

3124 }

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

3126 GoodUse = true;

3127 }

3128 if (BadUse || !GoodUse)

3129 continue;

3130

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

3132 }

3133

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

3136 for (auto &I : Phis) {

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

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

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

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

3141 }

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

3143 });

3144

3145 if (Phis.empty())

3146 return false;

3147

3149 InstrList ShufIns;

3150

3151

3152

3153

3154

3156 if (MI.isTerminator())

3157 continue;

3158 if (MI.isPHI())

3159 break;

3160

3162 HBS::getInstrDefs(MI, Defs);

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

3164 continue;

3165 Register DefR = Defs.find_first();

3167 continue;

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

3169 continue;

3170

3171 bool BadUse = false;

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

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

3175 if (UseI->isPHI()) {

3176

3177

3178 unsigned Idx = UI.getOperandNo();

3180 BadUse = true;

3181 } else {

3183 BadUse = true;

3184 }

3185 } else {

3186

3187

3188 if (C.EB == nullptr)

3189 BadUse = true;

3190 }

3191 if (BadUse)

3192 break;

3193 }

3194

3195 if (BadUse)

3196 continue;

3197 ShufIns.push_back(&MI);

3198 }

3199

3200

3201

3202

3203

3204

3205

3206

3207

3208

3209 using InstrGroupList = std::vector;

3210 InstrGroupList Groups;

3211

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

3213 MachineInstr *SI = ShufIns[i];

3214 if (SI == nullptr)

3215 continue;

3216

3217 InstrGroup G;

3218 G.Ins.push_back(SI);

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

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

3222

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

3224 MachineInstr *MI = ShufIns[j];

3225 if (MI == nullptr)

3226 continue;

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

3229

3230 if (!Defs.intersects(Inputs))

3231 continue;

3232

3233

3234 G.Ins.push_back(MI);

3235 Inputs.remove(Defs);

3236

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

3238 ShufIns[j] = nullptr;

3239 }

3240

3241

3242 if (Inputs.count() > 1)

3243 continue;

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

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

3246 };

3248 continue;

3249

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

3252 }

3253

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

3256 InstrGroup &G = Groups[i];

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

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

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

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

3261 dbgs() << " " << MI;

3262 }

3263 });

3264

3265 for (InstrGroup &G : Groups) {

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

3267 continue;

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

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

3270 };

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

3273 continue;

3274 unsigned PrehR = 0;

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

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

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

3279 continue;

3281 continue;

3283 continue;

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

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

3286 PrehR = MRI->createVirtualRegister(RC);

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

3288 : Hexagon::A2_tfrpi;

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

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

3293 } else {

3294 PrehR = F->PR.Reg;

3295 }

3296 }

3297

3298

3299

3300

3301

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

3303 continue;

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

3306 }

3307

3309}

3310

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

3313 return false;

3314

3315 auto &HST = MF.getSubtarget();

3316 HII = HST.getInstrInfo();

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

3320 BitTracker BT(HE, MF);

3323 BTP = &BT;

3324

3325 std::vector Cand;

3326

3327 for (auto &B : MF) {

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

3329 continue;

3330 MachineBasicBlock *PB = nullptr;

3331 bool IsLoop = false;

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

3333 if (Pred != &B)

3334 PB = Pred;

3335 else

3336 IsLoop = true;

3337 }

3338 if (!IsLoop)

3339 continue;

3340

3341 MachineBasicBlock *EB = nullptr;

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

3343 if (Succ == &B)

3344 continue;

3345

3346

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

3348 EB = Succ;

3349 break;

3350 }

3351

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

3353 }

3354

3356 for (auto &C : Cand)

3358

3360}

3361

3362

3363

3364

3365

3367 return new HexagonLoopRescheduling();

3368}

3369

3371 return new HexagonBitSimplify();

3372}

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 test(unsigned Idx) const

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:3370

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:3366

@ 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