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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

53#include

54#include

55#include

56#include

57#include

58#include

59#include

60#include

61#include

62

63using namespace llvm;

64

65#define DEBUG_TYPE "hwloops"

66

67#ifndef NDEBUG

69

70

73#endif

74

75

78 cl::desc("Add a preheader to a hardware loop if one doesn't exist"));

79

80

81

82

84 cl::desc("Allow speculation of preheader "

85 "instructions"));

86

87STATISTIC(NumHWLoops, "Number of loops converted to hardware loops");

88

89namespace llvm {

90

93

94}

95

96namespace {

97

98 class CountValue;

99

106#ifndef NDEBUG

107 static int Counter;

108#endif

109

110 public:

111 static char ID;

112

114

116

118

123 }

124

125 private:

126 using LoopFeederMap = std::map<Register, MachineInstr *>;

127

128

131 EQ = 0x01,

132 NE = 0x02,

133 L = 0x04,

134 G = 0x08,

135 U = 0x40,

136 LTs = L,

137 LEs = L | EQ,

138 GTs = G,

139 GEs = G | EQ,

140 LTu = L | U,

141 LEu = L | EQ | U,

142 GTu = G | U,

143 GEu = G | EQ | U

144 };

145

146 static Kind getSwappedComparison(Kind Cmp) {

147 assert ((!((Cmp & L) && (Cmp & G))) && "Malformed comparison operator");

148 if ((Cmp & L) || (Cmp & G))

149 return (Kind)(Cmp ^ (L|G));

150 return Cmp;

151 }

152

153 static Kind getNegatedComparison(Kind Cmp) {

154 if ((Cmp & L) || (Cmp & G))

155 return (Kind)((Cmp ^ (L | G)) ^ EQ);

156 if ((Cmp & NE) || (Cmp & EQ))

157 return (Kind)(Cmp ^ (EQ | NE));

158 return (Kind)0;

159 }

160

161 static bool isSigned(Kind Cmp) {

162 return (Cmp & (L | G) && !(Cmp & U));

163 }

164

165 static bool isUnsigned(Kind Cmp) {

166 return (Cmp & U);

167 }

168 };

169

170

171

172

173

174

175

176

177

178

179

180

181

184

185

186 Comparison::Kind getComparisonKind(unsigned CondOpc,

189 int64_t IVBump) const;

190

191

192

193

194 CountValue *getLoopTripCount(MachineLoop *L,

196

197

198

199

200

201

202

203

206 int64_t IVBump, Comparison::Kind Cmp) const;

207

208

209

211 bool IsInnerHWLoop) const;

212

213

214

215 bool containsInvalidInstruction(MachineLoop *L, bool IsInnerHWLoop) const;

216

217

218

219 bool convertToHardwareLoop(MachineLoop *L, bool &L0used, bool &L1used);

220

221

224

225

227

228

229

230

231

233

234

235

236

239 LoopFeederMap &LoopFeederPhi) const;

240

241

242

245 LoopFeederMap &LoopFeederPhi) const;

246

247

248

249 bool loopCountMayWrapOrUnderFlow(const MachineOperand *InitVal,

252 LoopFeederMap &LoopFeederPhi) const;

253

254

255

256

257 bool checkForImmediate(const MachineOperand &MO, int64_t &Val) const;

258

259

261 int64_t V;

262 return checkForImmediate(MO, V);

263 }

264

265

266 int64_t getImmediate(const MachineOperand &MO) const {

267 int64_t V;

268 if (!checkForImmediate(MO, V))

270 return V;

271 }

272

273

274

275

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297 bool fixupInductionVariable(MachineLoop *L);

298

299

300

302 };

303

304 char HexagonHardwareLoops::ID = 0;

305#ifndef NDEBUG

306 int HexagonHardwareLoops::Counter = 0;

307#endif

308

309

310

311

312 class CountValue {

313 public:

314 enum CountValueType {

315 CV_Register,

316 CV_Immediate

317 };

318

319 private:

320 CountValueType Kind;

321 union Values {

323 Values(const Values&) = default;

324 struct {

326 unsigned Sub;

327 } R;

328 unsigned ImmVal;

329 } Contents;

330

331 public:

332 explicit CountValue(CountValueType t, Register v, unsigned u = 0) {

334 if (Kind == CV_Register) {

335 Contents.R.Reg = v;

336 Contents.R.Sub = u;

337 } else {

338 Contents.ImmVal = v;

339 }

340 }

341

342 bool isReg() const { return Kind == CV_Register; }

343 bool isImm() const { return Kind == CV_Immediate; }

344

346 assert(isReg() && "Wrong CountValue accessor");

347 return Contents.R.Reg;

348 }

349

350 unsigned getSubReg() const {

351 assert(isReg() && "Wrong CountValue accessor");

352 return Contents.R.Sub;

353 }

354

355 unsigned getImm() const {

356 assert(isImm() && "Wrong CountValue accessor");

357 return Contents.ImmVal;

358 }

359

361 if (isReg()) { OS << printReg(Contents.R.Reg, TRI, Contents.R.Sub); }

362 if (isImm()) { OS << Contents.ImmVal; }

363 }

364 };

365

366}

367

369 "Hexagon Hardware Loops", false, false)

374

376 return new HexagonHardwareLoops();

377}

378

379bool HexagonHardwareLoops::runOnMachineFunction(MachineFunction &MF) {

380 LLVM_DEBUG(dbgs() << "********* Hexagon Hardware Loops *********\n");

382 return false;

383

384 bool Changed = false;

385

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

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

392

393 for (auto &L : *MLI)

394 if (L->isOutermost()) {

395 bool L0Used = false;

396 bool L1Used = false;

397 Changed |= convertToHardwareLoop(L, L0Used, L1Used);

398 }

399

400 return Changed;

401}

402

403bool HexagonHardwareLoops::findInductionRegister(MachineLoop *L,

405 int64_t &IVBump,

407 ) const {

412 if (!Header || !Preheader || !Latch || !ExitingBlock)

413 return false;

414

415

416

417 using RegisterBump = std::pair<Register, int64_t>;

418

419

420

421

422

423 using InductionMap = std::map<Register, RegisterBump>;

424

425 InductionMap IndMap;

426

428

429 for (instr_iterator I = Header->instr_begin(), E = Header->instr_end();

430 I != E && I->isPHI(); ++I) {

432

433

434

435

436 for (unsigned i = 1, n = Phi->getNumOperands(); i < n; i += 2) {

437 if (Phi->getOperand(i+1).getMBB() != Latch)

438 continue;

439

440 Register PhiOpReg = Phi->getOperand(i).getReg();

442

444

445

448 int64_t V;

449 if (MRI->getVRegDef(IndReg) == Phi && checkForImmediate(Opnd2, V)) {

451 IndMap.insert(std::make_pair(UpdReg, std::make_pair(IndReg, V)));

452 }

453 }

454 }

455 }

456

460 if (NotAnalyzed)

461 return false;

462

464 unsigned PredPos, PredRegFlags;

466 return false;

467

470 return false;

471

473 int64_t CmpImm = 0, CmpMask = 0;

474 bool CmpAnalyzed =

476

477

478

479 if (!CmpAnalyzed)

480 return false;

481

482

483

484 InductionMap::iterator IndMapEnd = IndMap.end();

485 InductionMap::iterator F = IndMapEnd;

486 if (CmpReg1 != 0) {

487 InductionMap::iterator F1 = IndMap.find(CmpReg1);

488 if (F1 != IndMapEnd)

489 F = F1;

490 }

491 if (CmpReg2 != 0) {

492 InductionMap::iterator F2 = IndMap.find(CmpReg2);

493 if (F2 != IndMapEnd) {

494 if (F != IndMapEnd)

495 return false;

496 F = F2;

497 }

498 }

499 if (F == IndMapEnd)

500 return false;

501

502 Reg = F->second.first;

503 IVBump = F->second.second;

504 IVOp = MRI->getVRegDef(F->first);

505 return true;

506}

507

508

509HexagonHardwareLoops::Comparison::Kind

510HexagonHardwareLoops::getComparisonKind(unsigned CondOpc,

513 int64_t IVBump) const {

514 Comparison::Kind Cmp = (Comparison::Kind)0;

515 switch (CondOpc) {

516 case Hexagon::C2_cmpeq:

517 case Hexagon::C2_cmpeqi:

518 case Hexagon::C2_cmpeqp:

519 Cmp = Comparison::EQ;

520 break;

521 case Hexagon::C4_cmpneq:

522 case Hexagon::C4_cmpneqi:

523 Cmp = Comparison::NE;

524 break;

525 case Hexagon::C2_cmplt:

526 Cmp = Comparison::LTs;

527 break;

528 case Hexagon::C2_cmpltu:

529 Cmp = Comparison::LTu;

530 break;

531 case Hexagon::C4_cmplte:

532 case Hexagon::C4_cmpltei:

533 Cmp = Comparison::LEs;

534 break;

535 case Hexagon::C4_cmplteu:

536 case Hexagon::C4_cmplteui:

537 Cmp = Comparison::LEu;

538 break;

539 case Hexagon::C2_cmpgt:

540 case Hexagon::C2_cmpgti:

541 case Hexagon::C2_cmpgtp:

542 Cmp = Comparison::GTs;

543 break;

544 case Hexagon::C2_cmpgtu:

545 case Hexagon::C2_cmpgtui:

546 case Hexagon::C2_cmpgtup:

547 Cmp = Comparison::GTu;

548 break;

549 case Hexagon::C2_cmpgei:

550 Cmp = Comparison::GEs;

551 break;

552 case Hexagon::C2_cmpgeui:

553 Cmp = Comparison::GEs;

554 break;

555 default:

556 return (Comparison::Kind)0;

557 }

558 return Cmp;

559}

560

561

562

563

564

565

566

567

568CountValue *HexagonHardwareLoops::getLoopTripCount(MachineLoop *L,

573 "Loop must have more than one incoming edge!");

575 if (PI == TopMBB->pred_end())

576 return nullptr;

578 if (PI != TopMBB->pred_end())

579 return nullptr;

580

581

582

584 if (L->contains(Backedge))

585 return nullptr;

587 } else if (L->contains(Backedge))

588 return nullptr;

589

590

591

592

594 if (!ExitingBlock)

595 return nullptr;

596

598 int64_t IVBump = 0;

600 bool FoundIV = findInductionRegister(L, IVReg, IVBump, IVOp);

601 if (!FoundIV)

602 return nullptr;

603

605

609 for (unsigned i = 1, n = IV_Phi->getNumOperands(); i < n; i += 2) {

611 if (MBB == Preheader)

612 InitialValue = &IV_Phi->getOperand(i);

613 else if (MBB == Latch)

614 IVReg = IV_Phi->getOperand(i).getReg();

615 }

616 if (!InitialValue)

617 return nullptr;

618

622 if (NotAnalyzed)

623 return nullptr;

624

626

627

628

629 assert (TB && "Exit block without a branch?");

630 if (ExitingBlock != Latch && (TB == Latch || FB == Latch)) {

633 bool NotAnalyzed = TII->analyzeBranch(*Latch, LTB, LFB, LCond, false);

634 if (NotAnalyzed)

635 return nullptr;

636 if (TB == Latch)

637 TB = (LTB == Header) ? LTB : LFB;

638 else

639 FB = (LTB == Header) ? LTB: LFB;

640 }

641 assert ((!FB || TB == Header || FB == Header) && "Branches not to header?");

642 if (!TB || (FB && TB != Header && FB != Header))

643 return nullptr;

644

645

646

647

648

651 unsigned PredPos, PredRegFlags;

653 return nullptr;

655 unsigned CondOpc = CondI->getOpcode();

656

658 int64_t Mask = 0, ImmValue = 0;

659 bool AnalyzedCmp =

661 if (!AnalyzedCmp)

662 return nullptr;

663

664

665

668

669

670

671

672

673

674 Comparison::Kind Cmp;

675 bool isSwapped = false;

679

680 if (Op1.isReg()) {

681 if (Op2.isImm() || Op1.getReg() == IVReg)

682 EndValue = &Op2;

683 else {

684 EndValue = &Op1;

685 isSwapped = true;

686 }

687 }

688

689 if (!EndValue)

690 return nullptr;

691

692 Cmp = getComparisonKind(CondOpc, InitialValue, EndValue, IVBump);

693 if (!Cmp)

694 return nullptr;

695 if (Negated)

696 Cmp = Comparison::getNegatedComparison(Cmp);

697 if (isSwapped)

698 Cmp = Comparison::getSwappedComparison(Cmp);

699

700 if (InitialValue->isReg()) {

704 int64_t V;

705 if (!checkForImmediate(*InitialValue, V))

706 return nullptr;

707 }

709 }

710 if (EndValue->isReg()) {

714 int64_t V;

715 if (!checkForImmediate(*EndValue, V))

716 return nullptr;

717 }

719 }

720

721 return computeCount(L, InitialValue, EndValue, IVReg, IVBump, Cmp);

722}

723

724

725

726

727

728CountValue *HexagonHardwareLoops::computeCount(MachineLoop *Loop,

732 int64_t IVBump,

733 Comparison::Kind Cmp) const {

734

735 if (Cmp == Comparison::EQ)

736 return nullptr;

737

738

739

740 if (Start->isReg()) {

741 const MachineInstr *StartValInstr = MRI->getVRegDef(Start->getReg());

742 if (StartValInstr && (StartValInstr->getOpcode() == Hexagon::A2_tfrsi ||

743 StartValInstr->getOpcode() == Hexagon::A2_tfrpi))

744 Start = &StartValInstr->getOperand(1);

745 }

746 if (End->isReg()) {

748 if (EndValInstr && (EndValInstr->getOpcode() == Hexagon::A2_tfrsi ||

749 EndValInstr->getOpcode() == Hexagon::A2_tfrpi))

751 }

752

753 if (!Start->isReg() && !Start->isImm())

754 return nullptr;

755 if (End->isReg() && End->isImm())

756 return nullptr;

757

758 bool CmpLess = Cmp & Comparison::L;

759 bool CmpGreater = Cmp & Comparison::G;

760 bool CmpHasEqual = Cmp & Comparison::EQ;

761

762

763 if (CmpLess && IVBump < 0)

764

765 return nullptr;

766

767 if (CmpGreater && IVBump > 0)

768

769 return nullptr;

770

771

772 LoopFeederMap LoopFeederPhi;

773

774

775

776

778 LoopFeederPhi))

779 return nullptr;

780

781 if (Start->isImm() && End->isImm()) {

782

783 int64_t StartV = Start->getImm();

784 int64_t EndV = End->getImm();

785 int64_t Dist = EndV - StartV;

786 if (Dist == 0)

787 return nullptr;

788

789 bool Exact = (Dist % IVBump) == 0;

790

791 if (Cmp == Comparison::NE) {

792 if (!Exact)

793 return nullptr;

794 if ((Dist < 0) ^ (IVBump < 0))

795 return nullptr;

796 }

797

798

799

800 if (CmpHasEqual)

801 Dist = Dist > 0 ? Dist+1 : Dist-1;

802

803

804

805

806

807 if ((CmpLess && Dist < 0) || (CmpGreater && Dist > 0))

808 return nullptr;

809

810

811 int64_t Dist1 = (IVBump > 0) ? (Dist + (IVBump - 1)) / IVBump

812 : (-Dist + (-IVBump - 1)) / (-IVBump);

813 assert (Dist1 > 0 && "Fishy thing. Both operands have the same sign.");

814

816

817 if (Count > 0xFFFFFFFFULL)

818 return nullptr;

819

820 return new CountValue(CountValue::CV_Immediate, Count);

821 }

822

823

824

825

826

827

828

830 return nullptr;

831

833 assert (PH && "Should have a preheader by now");

836 if (InsertPos != PH->end())

837 DL = InsertPos->getDebugLoc();

838

839

840

841

842

843

844

845

846 if (IVBump < 0) {

848 IVBump = -IVBump;

849 }

850

851

852

853 bool RegToImm = Start->isReg() && End->isImm();

854 bool RegToReg = Start->isReg() && End->isReg();

855

856 int64_t StartV = 0, EndV = 0;

857 if (Start->isImm())

858 StartV = Start->getImm();

859 if (End->isImm())

860 EndV = End->getImm();

861

862 int64_t AdjV = 0;

863

864

865

866

867

868

869

870

871 if (CmpHasEqual) {

872

873 if (Start->isImm())

874 StartV--;

875 else if (End->isImm())

876 EndV++;

877 else

878 AdjV += 1;

879 }

880

881 if (Cmp != Comparison::NE) {

882 if (Start->isImm())

883 StartV -= (IVBump-1);

884 else if (End->isImm())

885 EndV += (IVBump-1);

886 else

887 AdjV += (IVBump-1);

888 }

889

891 unsigned SR = 0;

892 if (Start->isReg()) {

893 R = Start->getReg();

894 SR = Start->getSubReg();

895 } else {

896 R = End->getReg();

897 SR = End->getSubReg();

898 }

900

901

902 if (!SR && RC == &Hexagon::DoubleRegsRegClass)

903 return nullptr;

905

906

908 unsigned DistSR;

909

910

911 if (Start->isImm() && StartV == 0) {

912 DistR = End->getReg();

913 DistSR = End->getSubReg();

914 } else {

915 const MCInstrDesc &SubD = RegToReg ? TII->get(Hexagon::A2_sub) :

916 (RegToImm ? TII->get(Hexagon::A2_subri) :

917 TII->get(Hexagon::A2_addi));

918 if (RegToReg || RegToImm) {

919 Register SubR = MRI->createVirtualRegister(IntRC);

921 BuildMI(*PH, InsertPos, DL, SubD, SubR);

922

923 if (RegToReg)

924 SubIB.addReg(End->getReg(), 0, End->getSubReg())

925 .addReg(Start->getReg(), 0, Start->getSubReg());

926 else

928 .addReg(Start->getReg(), 0, Start->getSubReg());

929 DistR = SubR;

930 } else {

931

932

933

935 if (EndValInstr->getOpcode() == Hexagon::A2_addi &&

939 } else {

940 Register SubR = MRI->createVirtualRegister(IntRC);

942 BuildMI(*PH, InsertPos, DL, SubD, SubR);

943 SubIB.addReg(End->getReg(), 0, End->getSubReg())

945 DistR = SubR;

946 }

947 }

948 DistSR = 0;

949 }

950

951

953 unsigned AdjSR;

954

955 if (AdjV == 0) {

956 AdjR = DistR;

957 AdjSR = DistSR;

958 } else {

959

960 Register AddR = MRI->createVirtualRegister(IntRC);

961 MCInstrDesc const &AddD = TII->get(Hexagon::A2_addi);

962 BuildMI(*PH, InsertPos, DL, AddD, AddR)

963 .addReg(DistR, 0, DistSR)

965

966 AdjR = AddR;

967 AdjSR = 0;

968 }

969

970

972 unsigned CountSR;

973

974 if (IVBump == 1) {

975 CountR = AdjR;

976 CountSR = AdjSR;

977 } else {

978

979 unsigned Shift = Log2_32(IVBump);

980

981

982 Register LsrR = MRI->createVirtualRegister(IntRC);

983 const MCInstrDesc &LsrD = TII->get(Hexagon::S2_lsr_i_r);

984 BuildMI(*PH, InsertPos, DL, LsrD, LsrR)

985 .addReg(AdjR, 0, AdjSR)

987

988 CountR = LsrR;

989 CountSR = 0;

990 }

991

992 return new CountValue(CountValue::CV_Register, CountR, CountSR);

993}

994

995

996bool HexagonHardwareLoops::isInvalidLoopOperation(const MachineInstr *MI,

997 bool IsInnerHWLoop) const {

998

999

1000 if (MI->getDesc().isCall())

1002

1003

1004 using namespace Hexagon;

1005

1006 static const Register Regs01[] = { LC0, SA0, LC1, SA1 };

1007 static const Register Regs1[] = { LC1, SA1 };

1008 auto CheckRegs = IsInnerHWLoop ? ArrayRef(Regs01) : ArrayRef(Regs1);

1009 for (Register R : CheckRegs)

1010 if (MI->modifiesRegister(R, TRI))

1011 return true;

1012

1013 return false;

1014}

1015

1016

1017

1018bool HexagonHardwareLoops::containsInvalidInstruction(MachineLoop *L,

1019 bool IsInnerHWLoop) const {

1024 if (isInvalidLoopOperation(&MI, IsInnerHWLoop)) {

1025 LLVM_DEBUG(dbgs() << "\nCannot convert to hw_loop due to:";

1027 return true;

1028 }

1029 }

1030 }

1031 return false;

1032}

1033

1034

1035

1036

1037

1038bool HexagonHardwareLoops::isDead(const MachineInstr *MI,

1040

1043 continue;

1044

1046 if (MRI->use_nodbg_empty(Reg))

1047 continue;

1048

1050

1051

1052

1053

1054 use_nodbg_iterator I = MRI->use_nodbg_begin(Reg);

1055 use_nodbg_iterator End = MRI->use_nodbg_end();

1056 if (std::next(I) != End || I->getParent()->isPHI())

1057 return false;

1058

1061 if (!OPO.isReg() || !OPO.isDef())

1062 continue;

1063

1064 Register OPReg = OPO.getReg();

1065 use_nodbg_iterator nextJ;

1066 for (use_nodbg_iterator J = MRI->use_nodbg_begin(OPReg);

1067 J != End; J = nextJ) {

1068 nextJ = std::next(J);

1071

1072

1074 return false;

1075 }

1076 }

1078 }

1079

1080

1081 return true;

1082}

1083

1084void HexagonHardwareLoops::removeIfDead(MachineInstr *MI) {

1085

1086

1090

1091

1092

1093

1096 continue;

1098

1099

1104 continue;

1107 }

1108 }

1109

1110 MI->eraseFromParent();

1111 for (unsigned i = 0; i < DeadPhis.size(); ++i)

1112 DeadPhis[i]->eraseFromParent();

1113 }

1114}

1115

1116

1117

1118

1119

1120

1121

1122

1123

1124bool HexagonHardwareLoops::convertToHardwareLoop(MachineLoop *L,

1125 bool &RecL0used,

1126 bool &RecL1used) {

1127

1128 assert(L->getHeader() && "Loop without a header?");

1129

1130 bool Changed = false;

1131 bool L0Used = false;

1132 bool L1Used = false;

1133

1134

1136 Changed |= convertToHardwareLoop(I, RecL0used, RecL1used);

1137 L0Used |= RecL0used;

1138 L1Used |= RecL1used;

1139 }

1140

1141

1142 if (Changed && L0Used && L1Used)

1143 return Changed;

1144

1145 unsigned LOOP_i;

1146 unsigned LOOP_r;

1147 unsigned ENDLOOP;

1148

1149

1150

1151

1152 unsigned IsInnerHWLoop = 1;

1153

1154 if (L0Used) {

1155 LOOP_i = Hexagon::J2_loop1i;

1156 LOOP_r = Hexagon::J2_loop1r;

1157 ENDLOOP = Hexagon::ENDLOOP1;

1158 IsInnerHWLoop = 0;

1159 } else {

1160 LOOP_i = Hexagon::J2_loop0i;

1161 LOOP_r = Hexagon::J2_loop0r;

1162 ENDLOOP = Hexagon::ENDLOOP0;

1163 }

1164

1165#ifndef NDEBUG

1166

1168 if (Limit >= 0) {

1170 return false;

1171 Counter++;

1172 }

1173#endif

1174

1175

1176 if (containsInvalidInstruction(L, IsInnerHWLoop))

1177 return false;

1178

1180

1181 if (!LastMBB)

1182 return false;

1183

1185 if (LastI == LastMBB->end())

1186 return false;

1187

1188

1189 if (!fixupInductionVariable(L))

1190 return false;

1191

1192

1193

1195 if (!Preheader) {

1196 Preheader = createPreheaderForLoop(L);

1197 if (!Preheader)

1198 return false;

1199 }

1200

1202

1204

1205 CountValue *TripCount = getLoopTripCount(L, OldInsts);

1206 if (!TripCount)

1207 return false;

1208

1209

1210 if (TripCount->isReg()) {

1211

1212

1213 MachineInstr *TCDef = MRI->getVRegDef(TripCount->getReg());

1215 if (!MDT->dominates(BBDef, Preheader))

1216 return false;

1217 }

1218

1219

1223 if (ExitingBlock != L->getLoopLatch()) {

1226

1228 return false;

1229

1230 if (L->contains(TB))

1231 LoopStart = TB;

1232 else if (L->contains(FB))

1233 LoopStart = FB;

1234 else

1235 return false;

1236 }

1237 else

1238 LoopStart = TopBlock;

1239

1240

1241 LLVM_DEBUG(dbgs() << "Change to hardware loop at "; L->dump());

1243 if (InsertPos != Preheader->end())

1244 DL = InsertPos->getDebugLoc();

1245

1246 if (TripCount->isReg()) {

1247

1248 Register CountReg = MRI->createVirtualRegister(&Hexagon::IntRegsRegClass);

1249 BuildMI(*Preheader, InsertPos, DL, TII->get(TargetOpcode::COPY), CountReg)

1250 .addReg(TripCount->getReg(), 0, TripCount->getSubReg());

1251

1252 BuildMI(*Preheader, InsertPos, DL, TII->get(LOOP_r)).addMBB(LoopStart)

1254 } else {

1255 assert(TripCount->isImm() && "Expecting immediate value for trip count");

1256

1257

1258

1259 int64_t CountImm = TripCount->getImm();

1261 Register CountReg = MRI->createVirtualRegister(&Hexagon::IntRegsRegClass);

1262 BuildMI(*Preheader, InsertPos, DL, TII->get(Hexagon::A2_tfrsi), CountReg)

1264 BuildMI(*Preheader, InsertPos, DL, TII->get(LOOP_r))

1266 } else

1267 BuildMI(*Preheader, InsertPos, DL, TII->get(LOOP_i))

1269 }

1270

1271

1273

1274

1275 DebugLoc LastIDL = LastI->getDebugLoc();

1276 BuildMI(*LastMBB, LastI, LastIDL, TII->get(ENDLOOP)).addMBB(LoopStart);

1277

1278

1279

1280

1281 if (LastI->getOpcode() == Hexagon::J2_jumpt ||

1282 LastI->getOpcode() == Hexagon::J2_jumpf) {

1283

1285 LastI = LastMBB->erase(LastI);

1286 if (L->contains(BranchTarget)) {

1287 if (LastI != LastMBB->end())

1288 LastI = LastMBB->erase(LastI);

1291 }

1292 } else {

1293

1294 LastMBB->erase(LastI);

1295 }

1296 delete TripCount;

1297

1298

1299

1300 for (unsigned i = 0; i < OldInsts.size(); ++i)

1301 removeIfDead(OldInsts[i]);

1302

1303 ++NumHWLoops;

1304

1305

1306

1307

1308 if (L0Used)

1309 RecL1used = true;

1310 else

1311 RecL0used = true;

1312

1313 return true;

1314}

1315

1316bool HexagonHardwareLoops::orderBumpCompare(MachineInstr *BumpI,

1318 assert (BumpI != CmpI && "Bump and compare in the same instruction?");

1319

1322 return false;

1323

1325

1326

1327 for (instr_iterator I(BumpI), E = BB->instr_end(); I != E; ++I)

1328 if (&*I == CmpI)

1329 return true;

1330

1331

1333 bool FoundBump = false;

1334 instr_iterator CmpIt = CmpI->getIterator(), NextIt = std::next(CmpIt);

1335 for (instr_iterator I = NextIt, E = BB->instr_end(); I != E; ++I) {

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

1340 if (MO.getReg() == PredR)

1341 return false;

1342 }

1343 }

1344

1345 if (In == BumpI) {

1347 FoundBump = true;

1348 break;

1349 }

1350 }

1351 assert (FoundBump && "Cannot determine instruction order");

1352 return FoundBump;

1353}

1354

1355

1356

1357

1358

1359

1363 LoopFeederMap &LoopFeederPhi) const {

1364 if (LoopFeederPhi.find(MO->getReg()) == LoopFeederPhi.end()) {

1367

1369 return false;

1371 LoopFeederPhi.insert(std::make_pair(MO->getReg(), Def));

1372 return true;

1373 } else

1374

1375 return false;

1376}

1377

1378

1379

1380bool HexagonHardwareLoops::phiMayWrapOrUnderflow(

1382 MachineLoop *L, LoopFeederMap &LoopFeederPhi) const {

1383 assert(Phi->isPHI() && "Expecting a Phi.");

1384

1385

1386 for (int i = 1, n = Phi->getNumOperands(); i < n; i += 2)

1387 if (isLoopFeeder(L, MBB, Phi, &(Phi->getOperand(i)), LoopFeederPhi))

1388 if (loopCountMayWrapOrUnderFlow(&(Phi->getOperand(i)), EndVal,

1389 Phi->getParent(), L, LoopFeederPhi))

1390 return true;

1391 return false;

1392}

1393

1394

1395

1396

1397

1398

1399

1400

1401

1402

1403

1404

1405

1406

1407

1408bool HexagonHardwareLoops::loopCountMayWrapOrUnderFlow(

1411 LoopFeederMap &LoopFeederPhi) const {

1412

1413 if (!InitVal->isReg())

1414 return false;

1415

1416 if (!EndVal->isImm())

1417 return false;

1418

1419

1420

1421 int64_t Imm;

1422 if (checkForImmediate(*InitVal, Imm))

1423 return (EndVal->getImm() == Imm);

1424

1426

1427

1428 if (Reg.isVirtual())

1429 return true;

1430

1432 if (!Def)

1433 return true;

1434

1435

1436

1437 if (Def->isPHI() && !phiMayWrapOrUnderflow(Def, EndVal, Def->getParent(),

1438 L, LoopFeederPhi))

1439 return false;

1440 if (Def->isCopy() && !loopCountMayWrapOrUnderFlow(&(Def->getOperand(1)),

1441 EndVal, Def->getParent(),

1442 L, LoopFeederPhi))

1443 return false;

1444

1445

1446

1447

1449 E = MRI->use_instr_nodbg_end(); I != E; ++I) {

1452 int64_t CmpMask = 0, CmpValue = 0;

1453

1455 continue;

1456

1460 continue;

1461

1462 Comparison::Kind Cmp =

1463 getComparisonKind(MI->getOpcode(), nullptr, nullptr, 0);

1464 if (Cmp == 0)

1465 continue;

1467 Cmp = Comparison::getNegatedComparison(Cmp);

1468 if (CmpReg2 != 0 && CmpReg2 == Reg)

1469 Cmp = Comparison::getSwappedComparison(Cmp);

1470

1471

1472 if (Comparison::isSigned(Cmp))

1473 return false;

1474

1475

1476

1477

1478 if ((Cmp & Comparison::G) || Cmp == Comparison::NE)

1479 return false;

1480 }

1481

1482

1483

1484

1485 if (Def->isCopy() && Def->isPHI())

1486 return false;

1487

1488 return true;

1489}

1490

1491bool HexagonHardwareLoops::checkForImmediate(const MachineOperand &MO,

1492 int64_t &Val) const {

1493 if (MO.isImm()) {

1495 return true;

1496 }

1497 if (!MO.isReg())

1498 return false;

1499

1500

1501

1502

1503 int64_t TV;

1504

1506 if (R.isVirtual())

1507 return false;

1509 unsigned DOpc = DI->getOpcode();

1510 switch (DOpc) {

1511 case TargetOpcode::COPY:

1512 case Hexagon::A2_tfrsi:

1513 case Hexagon::A2_tfrpi:

1514 case Hexagon::CONST32:

1515 case Hexagon::CONST64:

1516

1517

1518

1519 if (!checkForImmediate(DI->getOperand(1), TV))

1520 return false;

1521 break;

1522 case Hexagon::A2_combineii:

1523 case Hexagon::A4_combineir:

1524 case Hexagon::A4_combineii:

1525 case Hexagon::A4_combineri:

1526 case Hexagon::A2_combinew: {

1529 int64_t V1, V2;

1530 if (!checkForImmediate(S1, V1) || !checkForImmediate(S2, V2))

1531 return false;

1532 TV = V2 | (static_cast<uint64_t>(V1) << 32);

1533 break;

1534 }

1535 case TargetOpcode::REG_SEQUENCE: {

1538 int64_t V1, V3;

1539 if (!checkForImmediate(S1, V1) || !checkForImmediate(S3, V3))

1540 return false;

1543 if (Sub2 == Hexagon::isub_lo && Sub4 == Hexagon::isub_hi)

1544 TV = V1 | (V3 << 32);

1545 else if (Sub2 == Hexagon::isub_hi && Sub4 == Hexagon::isub_lo)

1546 TV = V3 | (V1 << 32);

1547 else

1549 break;

1550 }

1551

1552 default:

1553 return false;

1554 }

1555

1556

1557

1559 case Hexagon::isub_lo:

1560 Val = TV & 0xFFFFFFFFULL;

1561 break;

1562 case Hexagon::isub_hi:

1563 Val = (TV >> 32) & 0xFFFFFFFFULL;

1564 break;

1565 default:

1566 Val = TV;

1567 break;

1568 }

1569 return true;

1570}

1571

1572void HexagonHardwareLoops::setImmediate(MachineOperand &MO, int64_t Val) {

1573 if (MO.isImm()) {

1575 return;

1576 }

1577

1581

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

1588}

1589

1590bool HexagonHardwareLoops::fixupInductionVariable(MachineLoop *L) {

1594

1595 if (!(Header && Latch && ExitingBlock))

1596 return false;

1597

1598

1599

1600 using RegisterBump = std::pair<Register, int64_t>;

1601 using RegisterInduction = std::pair<Register, RegisterBump>;

1602 using RegisterInductionSet = std::set;

1603

1604

1605 RegisterInductionSet IndRegs;

1606

1607

1608

1609

1611

1612 for (instr_iterator I = Header->instr_begin(), E = Header->instr_end();

1613 I != E && I->isPHI(); ++I) {

1615

1616

1617 for (unsigned i = 1, n = Phi->getNumOperands(); i < n; i += 2) {

1618 if (Phi->getOperand(i+1).getMBB() != Latch)

1619 continue;

1620

1621 Register PhiReg = Phi->getOperand(i).getReg();

1623

1625

1626

1629 int64_t V;

1630 if (MRI->getVRegDef(IndReg) == Phi && checkForImmediate(Opnd2, V)) {

1632 IndRegs.insert(std::make_pair(UpdReg, std::make_pair(IndReg, V)));

1633 }

1634 }

1635 }

1636 }

1637

1638 if (IndRegs.empty())

1639 return false;

1640

1643

1645 if (NotAnalyzed || Cond.empty())

1646 return false;

1647

1648 if (ExitingBlock != Latch && (TB == Latch || FB == Latch)) {

1651 bool NotAnalyzed = TII->analyzeBranch(*Latch, LTB, LFB, LCond, false);

1652 if (NotAnalyzed)

1653 return false;

1654

1655

1656

1657 if (TB == Latch)

1658 TB = (LTB == Header) ? LTB : LFB;

1659 else

1660 FB = (LTB == Header) ? LTB : LFB;

1661 }

1662 if (TB != Header) {

1663 if (FB != Header) {

1664

1665 return false;

1666 }

1667

1668

1669

1670

1671

1672

1674 return false;

1675 }

1676

1677

1678

1679

1680

1681

1682 unsigned CSz = Cond.size();

1683 if (CSz != 1 && CSz != 2)

1684 return false;

1685

1687 return false;

1688

1691

1693 return false;

1694

1697

1698

1699

1700

1701

1703 if (MO.isReg()) {

1704

1705

1707 continue;

1708 if (MO.isUse()) {

1709 if (!isImmediate(MO)) {

1711 continue;

1712 }

1713

1714 if (CmpImmOp)

1715 return false;

1716 CmpImmOp = &MO;

1717 }

1718 } else if (MO.isImm()) {

1719 if (CmpImmOp)

1720 return false;

1721 CmpImmOp = &MO;

1722 }

1723 }

1724

1725 if (CmpRegs.empty())

1726 return false;

1727

1728

1729 for (RegisterInductionSet::iterator I = IndRegs.begin(), E = IndRegs.end();

1730 I != E; ++I) {

1731

1732

1733

1734 if (CmpRegs.count(I->first))

1735 return true;

1736

1737

1738

1739

1740 const RegisterBump &RB = I->second;

1741 if (CmpRegs.count(RB.first)) {

1742 if (!CmpImmOp) {

1743

1744

1749

1750 for (unsigned i = 1, n = PredDef->getNumOperands(); i < n; ++i) {

1752 if (MO.isReg() && MO.getReg() == RB.first) {

1754 << ") = " << *(MRI->getVRegDef(I->first)));

1755 if (IndI)

1756 return false;

1757

1758 IndI = MRI->getVRegDef(I->first);

1759 IndMO = &MO;

1760 } else if (MO.isReg()) {

1762 << ") = " << *(MRI->getVRegDef(MO.getReg())));

1763 if (nonIndI)

1764 return false;

1765

1766 nonIndI = MRI->getVRegDef(MO.getReg());

1767 nonIndMO = &MO;

1768 }

1769 }

1770 if (IndI && nonIndI &&

1771 nonIndI->getOpcode() == Hexagon::A2_addi &&

1774 bool Order = orderBumpCompare(IndI, PredDef);

1775 if (Order) {

1776 IndMO->setReg(I->first);

1778 return true;

1779 }

1780 }

1781 return false;

1782 }

1783

1784

1785

1786 Comparison::Kind Cmp =

1787 getComparisonKind(PredDef->getOpcode(), nullptr, nullptr, 0);

1788 if (!Cmp || Comparison::isUnsigned(Cmp))

1789 return false;

1790

1791

1792

1793

1794 int64_t CmpImm = getImmediate(*CmpImmOp);

1795 int64_t V = RB.second;

1796

1797 if (((V > 0) && (CmpImm > INT64_MAX - V)) ||

1798 ((V < 0) && (CmpImm < INT64_MIN - V)))

1799 return false;

1800 CmpImm += V;

1801

1802

1803

1806 return false;

1807

1808

1809

1811 bool Order = orderBumpCompare(BumpI, PredDef);

1812 if (!Order)

1813 return false;

1814

1815

1816 setImmediate(*CmpImmOp, CmpImm);

1818 if (MO.isReg() && MO.getReg() == RB.first) {

1820 return true;

1821 }

1822 }

1823 }

1824 }

1825

1826 return false;

1827}

1828

1829

1833 return TmpPH;

1835 return nullptr;

1836

1842

1843#ifndef NDEBUG

1845 return nullptr;

1846#endif

1847

1848 if (!Latch || !ExitingBlock || Header->hasAddressTaken())

1849 return nullptr;

1850

1852

1853

1854

1855 using MBBVector = std::vector<MachineBasicBlock *>;

1856

1857 MBBVector Preds(Header->pred_begin(), Header->pred_end());

1860

1862 return nullptr;

1863

1866 if (NotAnalyzed)

1867 return nullptr;

1868 }

1869

1871 MF->insert(Header->getIterator(), NewPH);

1872

1873 if (Header->pred_size() > 2) {

1874

1875

1876

1877

1878

1879 for (instr_iterator I = Header->instr_begin(), E = Header->instr_end();

1880 I != E && I->isPHI(); ++I) {

1882

1885 NewPH->insert(NewPH->end(), NewPN);

1886

1889 Register NewPR = MRI->createVirtualRegister(RC);

1891

1892

1893

1894 for (unsigned i = 1, n = PN->getNumOperands(); i < n; i += 2) {

1898 if (PredB == Latch)

1899 continue;

1900

1905 }

1906

1907

1908

1909 for (int i = PN->getNumOperands()-2; i > 0; i -= 2) {

1911 if (PredB != Latch) {

1914 }

1915 }

1918 }

1919 } else {

1920 assert(Header->pred_size() == 2);

1921

1922

1923

1924

1925

1926

1927 for (instr_iterator I = Header->instr_begin(), E = Header->instr_end();

1928 I != E && I->isPHI(); ++I) {

1930 for (unsigned i = 1, n = PN->getNumOperands(); i < n; i += 2) {

1932 if (MO.getMBB() != Latch)

1934 }

1935 }

1936 }

1937

1938

1939

1940

1943

1944 TB = FB = nullptr;

1945

1947 if (PB != Latch) {

1950 (void)NotAnalyzed;

1951 assert (!NotAnalyzed && "Should be analyzable!");

1952 if (TB != Header && (Tmp2.empty() || FB != Header))

1954 PB->ReplaceUsesOfBlockWith(Header, NewPH);

1955 }

1956 }

1957

1958

1959

1960 TB = FB = nullptr;

1961 bool LatchNotAnalyzed = TII->analyzeBranch(*Latch, TB, FB, Tmp2, false);

1962 (void)LatchNotAnalyzed;

1963 assert (!LatchNotAnalyzed && "Should be analyzable!");

1964 if (!TB && !FB)

1966

1967

1970

1971 MachineLoop *ParentLoop = L->getParentLoop();

1972 if (ParentLoop)

1974

1975

1976 if (MDT) {

1979 MDT->addNewBlock(NewPH, DHN->getBlock());

1981 }

1982 }

1983 }

1984

1985 return NewPH;

1986}

unsigned const MachineRegisterInfo * MRI

MachineInstrBuilder & UseMI

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)

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

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

static bool isSigned(unsigned int Opcode)

const HexagonInstrInfo * TII

static cl::opt< bool > HWCreatePreheader("hexagon-hwloop-preheader", cl::Hidden, cl::init(true), cl::desc("Add a preheader to a hardware loop if one doesn't exist"))

static cl::opt< bool > SpecPreheader("hwloop-spec-preheader", cl::Hidden, cl::desc("Allow speculation of preheader " "instructions"))

static cl::opt< std::string > PHFn("hexagon-hwloop-phfn", cl::Hidden, cl::init(""))

static cl::opt< int > HWLoopLimit("hexagon-max-hwloop", cl::Hidden, cl::init(-1))

unsigned const TargetRegisterInfo * TRI

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

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

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)

const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB

const SmallVectorImpl< MachineOperand > & Cond

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

static bool isImm(const MachineOperand &MO, MachineRegisterInfo *MRI)

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

This file defines the SmallSet class.

This file defines the SmallVector class.

This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...

#define STATISTIC(VARNAME, DESC)

Represent the analysis usage information of a pass.

AnalysisUsage & addRequired()

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

Base class for the actual dominator tree node.

DomTreeNodeBase * getIDom() const

void changeImmediateDominator(DomTreeNodeBase< NodeT > *N, DomTreeNodeBase< NodeT > *NewIDom)

changeImmediateDominator - This method is used to update the dominator tree information when a node's...

DomTreeNodeBase< NodeT > * addNewBlock(NodeT *BB, NodeT *DomBB)

Add a new node to the dominator tree information.

DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const

getNode - return the (Post)DominatorTree node for the specified basic block.

bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const

properlyDominates - Returns true iff A dominates B and A != B.

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

bool doesNotReturn(const MachineInstr &CallMI) const

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

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

bool getPredReg(ArrayRef< MachineOperand > Cond, Register &PredReg, unsigned &PredRegPos, unsigned &PredRegFlags) const

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

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

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

unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override

Insert branch code into the end of the specified MachineBasicBlock.

bool predOpcodeHasNot(ArrayRef< MachineOperand > Cond) const

bool isExtendable(const MachineInstr &MI) const

const HexagonInstrInfo * getInstrInfo() const override

const HexagonRegisterInfo * getRegisterInfo() const override

void addBasicBlockToLoop(BlockT *NewBB, LoopInfoBase< BlockT, LoopT > &LI)

This method is used by other analyses to update loop information.

BlockT * getLoopPreheader() const

If there is a preheader for this loop, return it.

Represents a single loop in the control flow graph.

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

bool isAdd() const

Return true if the instruction is an add instruction.

instr_iterator insert(instr_iterator I, MachineInstr *M)

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

iterator getFirstTerminator()

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

void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())

Add Succ as a successor of this MachineBasicBlock.

SmallVectorImpl< MachineBasicBlock * >::iterator pred_iterator

Instructions::iterator instr_iterator

pred_iterator pred_begin()

instr_iterator instr_end()

instr_iterator erase(instr_iterator I)

Remove an instruction from the instruction list and delete it.

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

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

void setMachineBlockAddressTaken()

Set this block to indicate that its address is used as something other than the target of a terminato...

Analysis pass which computes a MachineDominatorTree.

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

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

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

void getAnalysisUsage(AnalysisUsage &AU) const override

getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.

virtual bool runOnMachineFunction(MachineFunction &MF)=0

runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...

const TargetSubtargetInfo & getSubtarget() const

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

StringRef getName() const

getName - Return the name of the corresponding LLVM function.

MachineInstr * CreateMachineInstr(const MCInstrDesc &MCID, DebugLoc DL, bool NoImplicit=false)

CreateMachineInstr - Allocate a new MachineInstr.

MachineRegisterInfo & getRegInfo()

getRegInfo - Return information about the registers currently in use.

Function & getFunction()

Return the LLVM function that this machine code represents.

MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)

CreateMachineBasicBlock - Allocate a new MachineBasicBlock.

void insert(iterator MBBI, MachineBasicBlock *MBB)

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

unsigned getNumOperands() const

Retuns the total number of operands.

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

Add the specified operand to the instruction.

bool isCompare(QueryType Type=IgnoreBundle) const

Return true if this instruction is a comparison.

const MCInstrDesc & getDesc() const

Returns the target instruction descriptor of this MachineInstr.

iterator_range< mop_iterator > operands()

const DebugLoc & getDebugLoc() const

Returns the debug location id of this MachineInstr.

void removeOperand(unsigned OpNo)

Erase an operand from an instruction, leaving it with one fewer operand than it started with.

const MachineOperand & getOperand(unsigned i) const

MachineOperand class - Representation of each machine instruction operand.

void setSubReg(unsigned subReg)

unsigned getSubReg() const

void setImm(int64_t immVal)

bool isReg() const

isReg - Tests if this is a MO_Register operand.

MachineBasicBlock * getMBB() const

void setReg(Register Reg)

Change the register this operand corresponds to.

bool isImm() const

isImm - Tests if this is a MO_Immediate operand.

MachineInstr * getParent()

getParent - Return the instruction that this operand belongs to.

void setMBB(MachineBasicBlock *MBB)

Register getReg() const

getReg - Returns the register number.

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

static MachineOperand CreateMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0)

defusechain_iterator - This class provides iterator support for machine operands in the function that...

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

defusechain_iterator< true, false, true, true, false, false > use_nodbg_iterator

use_nodbg_iterator/use_nodbg_begin/use_nodbg_end - Walk all uses of the specified register,...

PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...

virtual StringRef getPassName() const

getPassName - Return a nice clean name for a pass.

Wrapper class representing virtual and physical registers.

SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...

size_type count(const T &V) const

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

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

insert - Insert an element into the set if it isn't already there.

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

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

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

A Use represents the edge between a Value definition and its users.

self_iterator getIterator()

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 std::underlying_type_t< E > Mask()

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

unsigned ID

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

Reg

All possible values of the reg field in the ModR/M byte.

@ TB

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

@ PD

PD - Prefix code for packed double precision vector floating point operations performed in the SSE re...

initializer< Ty > init(const Ty &Val)

NodeAddr< PhiNode * > Phi

NodeAddr< DefNode * > Def

This is an optimization pass for GlobalISel generic memory operations.

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

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

iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)

Make a range that does early increment to allow mutation of the underlying range without disrupting i...

constexpr bool isPowerOf2_64(uint64_t Value)

Return true if the argument is a power of two > 0 (64 bit edition.)

unsigned Log2_32(uint32_t Value)

Return the floor log base 2 of the specified value, -1 if the value is zero.

raw_ostream & dbgs()

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

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

Returns true if Element is found in Range.

FunctionPass * createHexagonHardwareLoops()

void initializeHexagonHardwareLoopsPass(PassRegistry &)

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.

Printable printMBBReference(const MachineBasicBlock &MBB)

Prints a machine basic block reference.

void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)

Implement std::swap in terms of BitVector swap.

Incoming for lane maks phi as machine instruction, incoming register Reg and incoming block Block are...