LLVM: lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

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

50#include

51#include

52#include

53#include

54#include

55#include

56#include

57#include

58#include

59

60using namespace llvm;

61

62#define DEBUG_TYPE "pre-RA-sched"

63

64STATISTIC(NumBacktracks, "Number of times scheduler backtracked");

65STATISTIC(NumUnfolds, "Number of nodes unfolded");

66STATISTIC(NumDups, "Number of duplicated nodes");

67STATISTIC(NumPRCopies, "Number of physical register copies");

68

71 "Bottom-up register reduction list scheduling",

73

76 "Similar to list-burr but schedules in source "

77 "order when possible",

79

82 "Bottom-up register pressure aware list scheduling "

83 "which tries to balance latency and register pressure",

85

88 "Bottom-up register pressure aware list scheduling "

89 "which tries to balance ILP and register pressure",

91

94 cl::desc("Disable cycle-level precision during preRA scheduling"));

95

96

97

100 cl::desc("Disable regpressure priority in sched=list-ilp"));

103 cl::desc("Disable live use priority in sched=list-ilp"));

106 cl::desc("Disable virtual register cycle interference checks"));

109 cl::desc("Disable physreg def-use affinity"));

112 cl::desc("Disable no-stall priority in sched=list-ilp"));

115 cl::desc("Disable critical path priority in sched=list-ilp"));

118 cl::desc("Disable scheduled-height priority in sched=list-ilp"));

121 cl::desc("Disable scheduler's two-address hack"));

122

125 cl::desc("Number of instructions to allow ahead of the critical path "

126 "in sched=list-ilp"));

127

130 cl::desc("Average inst/cycle when no target itinerary exists."));

131

132namespace {

133

134

135

136

137

139private:

140

141 bool NeedLatency;

142

143

145

146

147

148

149

150 std::vector<SUnit *> PendingQueue;

151

152

154

155

156 unsigned CurCycle = 0;

157

158

159 unsigned MinAvailableCycle = ~0u;

160

161

162

163 unsigned IssueCount = 0u;

164

165

166

167

168 unsigned NumLiveRegs = 0u;

169 std::unique_ptr<SUnit*[]> LiveRegDefs;

170 std::unique_ptr<SUnit*[]> LiveRegGens;

171

172

173

175

177

178 LRegsMapT LRegsMap;

179

180

181

183

184

185

187

188public:

193 AvailableQueue(availqueue), Topo(SUnits, nullptr) {

197 else

198 HazardRec = STI.getInstrInfo()->CreateTargetHazardRecognizer(&STI, this);

199 }

200

201 ~ScheduleDAGRRList() override {

202 delete HazardRec;

203 delete AvailableQueue;

204 }

205

206 void Schedule() override;

207

208 ScheduleHazardRecognizer *getHazardRec() { return HazardRec; }

209

210

211 bool IsReachable(const SUnit *SU, const SUnit *TargetSU) {

212 return Topo.IsReachable(SU, TargetSU);

213 }

214

215

216

217 bool WillCreateCycle(SUnit *SU, SUnit *TargetSU) {

218 return Topo.WillCreateCycle(SU, TargetSU);

219 }

220

221

222

223

224 void AddPredQueued(SUnit *SU, const SDep &D) {

225 Topo.AddPredQueued(SU, D.getSUnit());

227 }

228

229

230

231

232 void AddPred(SUnit *SU, const SDep &D) {

233 Topo.AddPred(SU, D.getSUnit());

235 }

236

237

238

239

240 void RemovePred(SUnit *SU, const SDep &D) {

241 Topo.RemovePred(SU, D.getSUnit());

243 }

244

245private:

246 bool isReady(SUnit *SU) {

248 AvailableQueue->isReady(SU);

249 }

250

251 void ReleasePred(SUnit *SU, const SDep *PredEdge);

252 void ReleasePredecessors(SUnit *SU);

253 void ReleasePending();

254 void AdvanceToCycle(unsigned NextCycle);

255 void AdvancePastStalls(SUnit *SU);

256 void EmitNode(SUnit *SU);

257 void ScheduleNodeBottomUp(SUnit*);

258 void CapturePred(SDep *PredEdge);

259 void UnscheduleNodeBottomUp(SUnit*);

260 void RestoreHazardCheckerBottomUp();

261 void BacktrackBottomUp(SUnit*, SUnit*);

262 SUnit *TryUnfoldSU(SUnit *);

263 SUnit *CopyAndMoveSuccessors(SUnit*);

264 void InsertCopiesAndMoveSuccs(SUnit*, unsigned,

265 const TargetRegisterClass*,

266 const TargetRegisterClass*,

267 SmallVectorImpl<SUnit*>&);

268 bool DelayForLiveRegsBottomUp(SUnit*, SmallVectorImpl&);

269

270 void releaseInterferences(unsigned Reg = 0);

271

272 SUnit *PickNodeToScheduleBottomUp();

273 void ListScheduleBottomUp();

274

275

276 SUnit *CreateNewSUnit(SDNode *N) {

277 unsigned NumSUnits = SUnits.size();

278 SUnit *NewNode = newSUnit(N);

279

280 if (NewNode->NodeNum >= NumSUnits)

281 Topo.AddSUnitWithoutPredecessors(NewNode);

282 return NewNode;

283 }

284

285

286 SUnit *CreateClone(SUnit *N) {

287 unsigned NumSUnits = SUnits.size();

288 SUnit *NewNode = Clone(N);

289

290 if (NewNode->NodeNum >= NumSUnits)

291 Topo.AddSUnitWithoutPredecessors(NewNode);

292 return NewNode;

293 }

294

295

296

297 bool forceUnitLatencies() const override {

298 return !NeedLatency;

299 }

300};

301

302}

303

305

306

307

308

309

314 unsigned &RegClass, unsigned &Cost,

317

318

319

320 if (VT == MVT::Untyped) {

322

323

327 RegClass = RC->getID();

328 Cost = 1;

329 return;

330 }

331

332 unsigned Opcode = Node->getMachineOpcode();

333 if (Opcode == TargetOpcode::REG_SEQUENCE) {

334 unsigned DstRCIdx = Node->getConstantOperandVal(0);

336 RegClass = RC->getID();

338 return;

339 }

340

341 unsigned Idx = RegDefPos.GetIdx();

344 assert(RC && "Not a valid register class");

345 RegClass = RC->getID();

346

347

348 Cost = 1;

349 } else {

352 }

353}

354

355

356void ScheduleDAGRRList::Schedule() {

358 << " '" << BB->getName() << "' **********\n");

359

360 CurCycle = 0;

361 IssueCount = 0;

362 MinAvailableCycle =

364 NumLiveRegs = 0;

365

366

367 LiveRegDefs.reset(new SUnit*[TRI->getNumRegs() + 1]());

368 LiveRegGens.reset(new SUnit*[TRI->getNumRegs() + 1]());

369 CallSeqEndForStart.clear();

370 assert(Interferences.empty() && LRegsMap.empty() && "stale Interferences");

371

372

373 BuildSchedGraph();

374

377

378 AvailableQueue->initNodes(SUnits);

379

380 HazardRec->Reset();

381

382

383 ListScheduleBottomUp();

384

386

388 dbgs() << "*** Final schedule ***\n";

389 dumpSchedule();

390 dbgs() << '\n';

391 });

392}

393

394

395

396

397

398

399

400void ScheduleDAGRRList::ReleasePred(SUnit *SU, const SDep *PredEdge) {

401 SUnit *PredSU = PredEdge->getSUnit();

402

403#ifndef NDEBUG

405 dbgs() << "*** Scheduling failed! ***\n";

406 dumpNode(*PredSU);

407 dbgs() << " has been released too many times!\n";

409 }

410#endif

412

413 if (!forceUnitLatencies()) {

414

415

417 }

418

419

420

421 if (PredSU->NumSuccsLeft == 0 && PredSU != &EntrySU) {

423

424 unsigned Height = PredSU->getHeight();

425 if (Height < MinAvailableCycle)

426 MinAvailableCycle = Height;

427

428 if (isReady(PredSU)) {

429 AvailableQueue->push(PredSU);

430 }

431

432

435 PendingQueue.push_back(PredSU);

436 }

437 }

438}

439

440

441

443 unsigned NestLevel,

446 while (true) {

447 if (N == Inner)

448 return true;

449

450

451

453 for (const SDValue &Op : N->op_values())

455 return true;

456 return false;

457 }

458

459 if (N->isMachineOpcode()) {

460 if (N->getMachineOpcode() == TII->getCallFrameDestroyOpcode()) {

461 ++NestLevel;

462 } else if (N->getMachineOpcode() == TII->getCallFrameSetupOpcode()) {

463 if (NestLevel == 0)

464 return false;

465 --NestLevel;

466 }

467 }

468

469 for (const SDValue &Op : N->op_values())

470 if (Op.getValueType() == MVT::Other) {

471 N = Op.getNode();

472 goto found_chain_operand;

473 }

474 return false;

475 found_chain_operand:;

477 return false;

478 }

479}

480

481

482

483

484

485

486

487

488

489

490static SDNode *

493 while (true) {

494

495

496

498 SDNode *Best = nullptr;

499 unsigned BestMaxNest = MaxNest;

500 for (const SDValue &Op : N->op_values()) {

501 unsigned MyNestLevel = NestLevel;

502 unsigned MyMaxNest = MaxNest;

504 MyNestLevel, MyMaxNest, TII))

505 if (!Best || (MyMaxNest > BestMaxNest)) {

506 Best = New;

507 BestMaxNest = MyMaxNest;

508 }

509 }

511 MaxNest = BestMaxNest;

512 return Best;

513 }

514

515 if (N->isMachineOpcode()) {

516 if (N->getMachineOpcode() == TII->getCallFrameDestroyOpcode()) {

517 ++NestLevel;

518 MaxNest = std::max(MaxNest, NestLevel);

519 } else if (N->getMachineOpcode() == TII->getCallFrameSetupOpcode()) {

520 assert(NestLevel != 0);

521 --NestLevel;

522 if (NestLevel == 0)

523 return N;

524 }

525 }

526

527 for (const SDValue &Op : N->op_values())

528 if (Op.getValueType() == MVT::Other) {

529 N = Op.getNode();

530 goto found_chain_operand;

531 }

532 return nullptr;

533 found_chain_operand:;

535 return nullptr;

536 }

537}

538

539

540

541

542

543

544

545

546

547

548

549

550

551

552

553

554

555

556void ScheduleDAGRRList::ReleasePredecessors(SUnit *SU) {

557

558 for (SDep &Pred : SU->Preds) {

559 ReleasePred(SU, &Pred);

561

562

563

564

565 SUnit *RegDef = LiveRegDefs[Pred.getReg()]; (void)RegDef;

566 assert((!RegDef || RegDef == SU || RegDef == Pred.getSUnit()) &&

567 "interference on register dependence");

569 if (!LiveRegGens[Pred.getReg()]) {

570 ++NumLiveRegs;

571 LiveRegGens[Pred.getReg()] = SU;

572 }

573 }

574 }

575

576

577

578

579 unsigned CallResource = TRI->getNumRegs();

580 if (!LiveRegDefs[CallResource])

581 for (SDNode *Node = SU->getNode(); Node; Node = Node->getGluedNode())

582 if (Node->isMachineOpcode() &&

584 unsigned NestLevel = 0;

585 unsigned MaxNest = 0;

587 assert(N && "Must find call sequence start");

588

589 SUnit *Def = &SUnits[N->getNodeId()];

590 CallSeqEndForStart[Def] = SU;

591

592 ++NumLiveRegs;

593 LiveRegDefs[CallResource] = Def;

594 LiveRegGens[CallResource] = SU;

595 break;

596 }

597}

598

599

600

601void ScheduleDAGRRList::ReleasePending() {

603 assert(PendingQueue.empty() && "pending instrs not allowed in this mode");

604 return;

605 }

606

607

608 if (AvailableQueue->empty())

609 MinAvailableCycle = std::numeric_limits::max();

610

611

612

613 for (unsigned i = 0, e = PendingQueue.size(); i != e; ++i) {

614 unsigned ReadyCycle = PendingQueue[i]->getHeight();

615 if (ReadyCycle < MinAvailableCycle)

616 MinAvailableCycle = ReadyCycle;

617

618 if (PendingQueue[i]->isAvailable) {

619 if (!isReady(PendingQueue[i]))

620 continue;

621 AvailableQueue->push(PendingQueue[i]);

622 }

623 PendingQueue[i]->isPending = false;

624 PendingQueue[i] = PendingQueue.back();

625 PendingQueue.pop_back();

626 --i; --e;

627 }

628}

629

630

631void ScheduleDAGRRList::AdvanceToCycle(unsigned NextCycle) {

632 if (NextCycle <= CurCycle)

633 return;

634

635 IssueCount = 0;

638

639 CurCycle = NextCycle;

640 }

641 else {

642 for (; CurCycle != NextCycle; ++CurCycle) {

644 }

645 }

646

647

648 ReleasePending();

649}

650

651

652

653void ScheduleDAGRRList::AdvancePastStalls(SUnit *SU) {

655 return;

656

657

658

659

660

661

662

663

664 unsigned ReadyCycle = SU->getHeight();

665

666

667

668

669

670 AdvanceToCycle(ReadyCycle);

671

672

673

674

676 return;

677

678

679

680 int Stalls = 0;

681 while (true) {

684

686 break;

687

688 ++Stalls;

689 }

690 AdvanceToCycle(CurCycle + Stalls);

691}

692

693

694

695void ScheduleDAGRRList::EmitNode(SUnit *SU) {

697 return;

698

699

701 return;

702

704 default:

706 "This target-independent node should not be scheduled.");

707 break;

710 case ISD::LIFETIME_START:

711 case ISD::LIFETIME_END:

714 case ISD::EH_LABEL:

715

716

717 return;

718 case ISD::INLINEASM:

719 case ISD::INLINEASM_BR:

720

721 HazardRec->Reset();

722 return;

723 }

725

726

727 HazardRec->Reset();

728 }

729

731}

732

734

735

736

737

738void ScheduleDAGRRList::ScheduleNodeBottomUp(SUnit *SU) {

739 LLVM_DEBUG(dbgs() << "\n*** Scheduling [" << CurCycle << "]: ");

741

742#ifndef NDEBUG

743 if (CurCycle < SU->getHeight())

745 << "] pipeline stall!\n");

746#endif

747

748

749

750

751

753

754

755 EmitNode(SU);

756

758

760

761

762

763

765 AdvanceToCycle(CurCycle + 1);

766

767

768

769 ReleasePredecessors(SU);

770

771

772 for (SDep &Succ : SU->Succs) {

773

775 assert(NumLiveRegs > 0 && "NumLiveRegs is already zero!");

776 --NumLiveRegs;

777 LiveRegDefs[Succ.getReg()] = nullptr;

778 LiveRegGens[Succ.getReg()] = nullptr;

779 releaseInterferences(Succ.getReg());

780 }

781 }

782

783

784 unsigned CallResource = TRI->getNumRegs();

785 if (LiveRegDefs[CallResource] == SU)

786 for (const SDNode *SUNode = SU->getNode(); SUNode;

788 if (SUNode->isMachineOpcode() &&

790 assert(NumLiveRegs > 0 && "NumLiveRegs is already zero!");

791 --NumLiveRegs;

792 LiveRegDefs[CallResource] = nullptr;

793 LiveRegGens[CallResource] = nullptr;

794 releaseInterferences(CallResource);

795 }

796 }

797

799

801

802

803

804

805

806

807

808

809

812 ++IssueCount;

815 AdvanceToCycle(CurCycle + 1);

816 }

817}

818

819

820

821

822void ScheduleDAGRRList::CapturePred(SDep *PredEdge) {

823 SUnit *PredSU = PredEdge->getSUnit();

827 AvailableQueue->remove(PredSU);

828 }

829

830 assert(PredSU->NumSuccsLeft < std::numeric_limits::max() &&

831 "NumSuccsLeft will overflow!");

833}

834

835

836

837void ScheduleDAGRRList::UnscheduleNodeBottomUp(SUnit *SU) {

840

841 for (SDep &Pred : SU->Preds) {

842 CapturePred(&Pred);

844 assert(NumLiveRegs > 0 && "NumLiveRegs is already zero!");

846 "Physical register dependency violated?");

847 --NumLiveRegs;

848 LiveRegDefs[Pred.getReg()] = nullptr;

849 LiveRegGens[Pred.getReg()] = nullptr;

850 releaseInterferences(Pred.getReg());

851 }

852 }

853

854

855

856 unsigned CallResource = TRI->getNumRegs();

857 for (const SDNode *SUNode = SU->getNode(); SUNode;

859 if (SUNode->isMachineOpcode() &&

861 SUnit *SeqEnd = CallSeqEndForStart[SU];

862 assert(SeqEnd && "Call sequence start/end must be known");

863 assert(!LiveRegDefs[CallResource]);

864 assert(!LiveRegGens[CallResource]);

865 ++NumLiveRegs;

866 LiveRegDefs[CallResource] = SU;

867 LiveRegGens[CallResource] = SeqEnd;

868 }

869 }

870

871

872

873 if (LiveRegGens[CallResource] == SU)

874 for (const SDNode *SUNode = SU->getNode(); SUNode;

876 if (SUNode->isMachineOpcode() &&

878 assert(NumLiveRegs > 0 && "NumLiveRegs is already zero!");

879 assert(LiveRegDefs[CallResource]);

880 assert(LiveRegGens[CallResource]);

881 --NumLiveRegs;

882 LiveRegDefs[CallResource] = nullptr;

883 LiveRegGens[CallResource] = nullptr;

884 releaseInterferences(CallResource);

885 }

886 }

887

888 for (auto &Succ : SU->Succs) {

891 if (!LiveRegDefs[Reg])

892 ++NumLiveRegs;

893

894

895 LiveRegDefs[Reg] = SU;

896

897

898

899 if (!LiveRegGens[Reg]) {

900

902 for (auto &Succ2 : SU->Succs) {

903 if (Succ2.isAssignedRegDep() && Succ2.getReg() == Reg &&

904 Succ2.getSUnit()->getHeight() < LiveRegGens[Reg]->getHeight())

905 LiveRegGens[Reg] = Succ2.getSUnit();

906 }

907 }

908 }

909 }

910 if (SU->getHeight() < MinAvailableCycle)

911 MinAvailableCycle = SU->getHeight();

912

917

919 PendingQueue.push_back(SU);

920 }

921 else {

922 AvailableQueue->push(SU);

923 }

925}

926

927

928

929void ScheduleDAGRRList::RestoreHazardCheckerBottomUp() {

930 HazardRec->Reset();

931

932 unsigned LookAhead = std::min((unsigned)Sequence.size(),

934 if (LookAhead == 0)

935 return;

936

937 std::vector<SUnit *>::const_iterator I = (Sequence.end() - LookAhead);

938 unsigned HazardCycle = (*I)->getHeight();

940 SUnit *SU = *I;

941 for (; SU->getHeight() > HazardCycle; ++HazardCycle) {

943 }

944 EmitNode(SU);

945 }

946}

947

948

949

950void ScheduleDAGRRList::BacktrackBottomUp(SUnit *SU, SUnit *BtSU) {

951 SUnit *OldSU = Sequence.back();

952 while (true) {

954

956 UnscheduleNodeBottomUp(OldSU);

958 if (OldSU == BtSU)

959 break;

961 }

962

963 assert(!SU->isSucc(OldSU) && "Something is wrong!");

964

965 RestoreHazardCheckerBottomUp();

966

967 ReleasePending();

968

969 ++NumBacktracks;

970}

971

973 for (const SDNode *SUNode = SU->getNode(); SUNode;

975 if (SUNode->isOperandOf(N))

976 return true;

977 }

978 return false;

979}

980

981

982SUnit *ScheduleDAGRRList::TryUnfoldSU(SUnit *SU) {

984

987 return nullptr;

988

989 assert(NewNodes.size() == 2 && "Expected a load folding node!");

990

991 N = NewNodes[1];

992 SDNode *LoadNode = NewNodes[0];

993 unsigned NumVals = N->getNumValues();

995

996

997

998

999 bool isNewLoad = true;

1000 SUnit *LoadSU;

1001 if (LoadNode->getNodeId() != -1) {

1002 LoadSU = &SUnits[LoadNode->getNodeId()];

1003

1004

1006 return SU;

1007 isNewLoad = false;

1008 } else {

1009 LoadSU = CreateNewSUnit(LoadNode);

1011

1012 InitNumRegDefsLeft(LoadSU);

1013 computeLatency(LoadSU);

1014 }

1015

1016 bool isNewN = true;

1017 SUnit *NewSU;

1018

1019 if (N->getNodeId() != -1) {

1020 NewSU = &SUnits[N->getNodeId()];

1021

1022

1024 return SU;

1025 }

1026 isNewN = false;

1027 } else {

1028 NewSU = CreateNewSUnit(N);

1029 N->setNodeId(NewSU->NodeNum);

1030

1031 const MCInstrDesc &MCID = TII->get(N->getMachineOpcode());

1032 for (unsigned i = 0; i != MCID.getNumOperands(); ++i) {

1035 break;

1036 }

1037 }

1040

1041 InitNumRegDefsLeft(NewSU);

1042 computeLatency(NewSU);

1043 }

1044

1046

1047

1048 for (unsigned i = 0; i != NumVals; ++i)

1050 DAG->ReplaceAllUsesOfValueWith(SDValue(SU->getNode(), OldNumVals - 1),

1052

1053

1059 for (SDep &Pred : SU->Preds) {

1064 else

1066 }

1067 for (SDep &Succ : SU->Succs) {

1070 else

1072 }

1073

1074

1075 for (const SDep &Pred : ChainPreds) {

1076 RemovePred(SU, Pred);

1077 if (isNewLoad)

1078 AddPredQueued(LoadSU, Pred);

1079 }

1080 for (const SDep &Pred : LoadPreds) {

1081 RemovePred(SU, Pred);

1082 if (isNewLoad)

1083 AddPredQueued(LoadSU, Pred);

1084 }

1085 for (const SDep &Pred : NodePreds) {

1086 RemovePred(SU, Pred);

1087 AddPredQueued(NewSU, Pred);

1088 }

1089 for (SDep &D : NodeSuccs) {

1090 SUnit *SuccDep = D.getSUnit();

1091 D.setSUnit(SU);

1092 RemovePred(SuccDep, D);

1093 D.setSUnit(NewSU);

1094 AddPredQueued(SuccDep, D);

1095

1099 }

1100 for (SDep &D : ChainSuccs) {

1101 SUnit *SuccDep = D.getSUnit();

1102 D.setSUnit(SU);

1103 RemovePred(SuccDep, D);

1104 if (isNewLoad) {

1105 D.setSUnit(LoadSU);

1106 AddPredQueued(SuccDep, D);

1107 }

1108 }

1109

1110

1111

1113 D.setLatency(LoadSU->Latency);

1114 AddPredQueued(NewSU, D);

1115

1116 if (isNewLoad)

1117 AvailableQueue->addNode(LoadSU);

1118 if (isNewN)

1119 AvailableQueue->addNode(NewSU);

1120

1121 ++NumUnfolds;

1122

1125

1126 return NewSU;

1127}

1128

1129

1130

1131SUnit *ScheduleDAGRRList::CopyAndMoveSuccessors(SUnit *SU) {

1133 if (N)

1134 return nullptr;

1135

1136 LLVM_DEBUG(dbgs() << "Considering duplicating the SU\n");

1138

1139 if (N->getGluedNode() &&

1143 << "Giving up because it has incoming glue and the target does not "

1144 "want to copy it\n");

1145 return nullptr;

1146 }

1147

1148 SUnit *NewSU;

1149 bool TryUnfold = false;

1150 for (unsigned i = 0, e = N->getNumValues(); i != e; ++i) {

1151 MVT VT = N->getSimpleValueType(i);

1152 if (VT == MVT::Glue) {

1153 LLVM_DEBUG(dbgs() << "Giving up because it has outgoing glue\n");

1154 return nullptr;

1155 } else if (VT == MVT::Other)

1156 TryUnfold = true;

1157 }

1158 for (const SDValue &Op : N->op_values()) {

1159 MVT VT = Op.getNode()->getSimpleValueType(Op.getResNo());

1162 dbgs() << "Giving up because it one of the operands is glue and "

1163 "the target does not want to copy it\n");

1164 return nullptr;

1165 }

1166 }

1167

1168

1169 if (TryUnfold) {

1170 SUnit *UnfoldSU = TryUnfoldSU(SU);

1171 if (!UnfoldSU)

1172 return nullptr;

1173 SU = UnfoldSU;

1175

1177 return SU;

1178 }

1179

1181 NewSU = CreateClone(SU);

1182

1183

1184 for (SDep &Pred : SU->Preds)

1186 AddPredQueued(NewSU, Pred);

1187

1188

1189

1191

1192

1193

1195 for (SDep &Succ : SU->Succs) {

1197 continue;

1198 SUnit *SuccSU = Succ.getSUnit();

1200 SDep D = Succ;

1202 AddPredQueued(SuccSU, D);

1203 D.setSUnit(SU);

1205 }

1206 }

1207 for (const auto &[DelSU, DelD] : DelDeps)

1208 RemovePred(DelSU, DelD);

1209

1211 AvailableQueue->addNode(NewSU);

1212

1213 ++NumDups;

1214 return NewSU;

1215}

1216

1217

1218

1219void ScheduleDAGRRList::InsertCopiesAndMoveSuccs(SUnit *SU, unsigned Reg,

1220 const TargetRegisterClass *DestRC,

1221 const TargetRegisterClass *SrcRC,

1222 SmallVectorImpl<SUnit*> &Copies) {

1223 SUnit *CopyFromSU = CreateNewSUnit(nullptr);

1226

1227 SUnit *CopyToSU = CreateNewSUnit(nullptr);

1230

1231

1232

1234 for (SDep &Succ : SU->Succs) {

1236 continue;

1237 SUnit *SuccSU = Succ.getSUnit();

1239 SDep D = Succ;

1241 AddPredQueued(SuccSU, D);

1243 }

1244 else {

1245

1246

1247

1249 }

1250 }

1251 for (const auto &[DelSU, DelD] : DelDeps)

1252 RemovePred(DelSU, DelD);

1253

1255 FromDep.setLatency(SU->Latency);

1256 AddPredQueued(CopyFromSU, FromDep);

1257 SDep ToDep(CopyFromSU, SDep::Data, 0);

1258 ToDep.setLatency(CopyFromSU->Latency);

1259 AddPredQueued(CopyToSU, ToDep);

1260

1262 AvailableQueue->addNode(CopyFromSU);

1263 AvailableQueue->addNode(CopyToSU);

1264 Copies.push_back(CopyFromSU);

1265 Copies.push_back(CopyToSU);

1266

1267 ++NumPRCopies;

1268}

1269

1270

1271

1272

1275 unsigned NumRes;

1277

1278 NumRes = 1;

1279 } else {

1281 assert(MCID.implicit_defs().empty() &&

1282 "Physical reg def must be in implicit def list!");

1283 NumRes = MCID.getNumDefs();

1285 if (Reg == ImpDef)

1286 break;

1287 ++NumRes;

1288 }

1289 }

1290 return N->getSimpleValueType(NumRes);

1291}

1292

1293

1294

1301

1302

1303 if (!LiveRegDefs[*AliasI]) continue;

1304

1305

1306 if (LiveRegDefs[*AliasI] == SU) continue;

1307

1308

1310 continue;

1311

1312

1313 if (RegAdded.insert(*AliasI).second) {

1315 }

1316 }

1317}

1318

1319

1320

1325

1326 for (unsigned i = 1, e = LiveRegDefs.size()-1; i != e; ++i) {

1327 if (!LiveRegDefs[i]) continue;

1328 if (LiveRegDefs[i] == SU) continue;

1330 if (RegAdded.insert(i).second)

1332 }

1333}

1334

1335

1337 for (const SDValue &Op : N->op_values())

1339 return RegOp->getRegMask();

1340 return nullptr;

1341}

1342

1343

1344

1345

1346

1347bool ScheduleDAGRRList::

1348DelayForLiveRegsBottomUp(SUnit *SU, SmallVectorImpl &LRegs) {

1349 if (NumLiveRegs == 0)

1350 return false;

1351

1352 SmallSet<unsigned, 4> RegAdded;

1353

1354

1355

1356

1357 for (SDep &Pred : SU->Preds) {

1360 RegAdded, LRegs, TRI);

1361 }

1362

1363 for (SDNode *Node = SU->getNode(); Node; Node = Node->getGluedNode()) {

1364 if (Node->getOpcode() == ISD::INLINEASM ||

1365 Node->getOpcode() == ISD::INLINEASM_BR) {

1366

1367 unsigned NumOps = Node->getNumOperands();

1368 if (Node->getOperand(NumOps-1).getValueType() == MVT::Glue)

1369 --NumOps;

1370

1372 unsigned Flags = Node->getConstantOperandVal(i);

1373 const InlineAsm::Flag F(Flags);

1374 unsigned NumVals = F.getNumOperandRegisters();

1375

1376 ++i;

1377 if (F.isRegDefKind() || F.isRegDefEarlyClobberKind() ||

1378 F.isClobberKind()) {

1379

1380 for (; NumVals; --NumVals, ++i) {

1384 }

1385 } else

1386 i += NumVals;

1387 }

1388 continue;

1389 }

1390

1394 SDNode *SrcNode = Node->getOperand(2).getNode();

1396 SrcNode);

1397 }

1398 }

1399

1400 if (Node->isMachineOpcode())

1401 continue;

1402

1403

1404

1406

1407 unsigned CallResource = TRI->getNumRegs();

1408 if (LiveRegDefs[CallResource]) {

1409 SDNode *Gen = LiveRegGens[CallResource]->getNode();

1411 Gen = Glued;

1413 RegAdded.insert(CallResource).second)

1415 }

1416 }

1419 ArrayRef(LiveRegDefs.get(), TRI->getNumRegs()),

1420 RegAdded, LRegs);

1421

1422 const MCInstrDesc &MCID = TII->get(Node->getMachineOpcode());

1424

1425

1426

1427

1428 for (unsigned i = 0; i < MCID.getNumDefs(); ++i)

1429 if (MCID.operands()[i].isOptionalDef()) {

1433 }

1434 }

1437 }

1438

1439 return !LRegs.empty();

1440}

1441

1442void ScheduleDAGRRList::releaseInterferences(unsigned Reg) {

1443

1444 for (unsigned i = Interferences.size(); i > 0; --i) {

1445 SUnit *SU = Interferences[i-1];

1446 LRegsMapT::iterator LRegsPos = LRegsMap.find(SU);

1447 if (Reg) {

1448 SmallVectorImpl &LRegs = LRegsPos->second;

1450 continue;

1451 }

1453

1454

1455

1458 AvailableQueue->push(SU);

1459 }

1460 if (i < Interferences.size())

1461 Interferences[i-1] = Interferences.back();

1463 LRegsMap.erase(LRegsPos);

1464 }

1465}

1466

1467

1468

1469

1470

1471SUnit *ScheduleDAGRRList::PickNodeToScheduleBottomUp() {

1472 SUnit *CurSU = AvailableQueue->empty() ? nullptr : AvailableQueue->pop();

1473 auto FindAvailableNode = [&]() {

1474 while (CurSU) {

1475 SmallVector<unsigned, 4> LRegs;

1476 if (!DelayForLiveRegsBottomUp(CurSU, LRegs))

1477 break;

1479 if (LRegs[0] == TRI->getNumRegs()) dbgs() << "CallResource";

1481 dbgs() << " SU #" << CurSU->NodeNum << '\n');

1482 auto [LRegsIter, LRegsInserted] = LRegsMap.try_emplace(CurSU, LRegs);

1483 if (LRegsInserted) {

1484 CurSU->isPending = true;

1486 }

1487 else {

1488 assert(CurSU->isPending && "Interferences are pending");

1489

1490 LRegsIter->second = LRegs;

1491 }

1492 CurSU = AvailableQueue->pop();

1493 }

1494 };

1495 FindAvailableNode();

1496 if (CurSU)

1497 return CurSU;

1498

1499

1500

1501

1502

1503

1504

1505

1506

1507 for (SUnit *TrySU : Interferences) {

1508 SmallVectorImpl &LRegs = LRegsMap[TrySU];

1509

1510

1511

1512 SUnit *BtSU = nullptr;

1513 unsigned LiveCycle = std::numeric_limits::max();

1514 for (unsigned Reg : LRegs) {

1515 if (LiveRegGens[Reg]->getHeight() < LiveCycle) {

1516 BtSU = LiveRegGens[Reg];

1518 }

1519 }

1520 if (!WillCreateCycle(TrySU, BtSU)) {

1521

1522 BacktrackBottomUp(TrySU, BtSU);

1523

1524

1525

1529 AvailableQueue->remove(BtSU);

1530 }

1532 << ") to SU(" << TrySU->NodeNum << ")\n");

1534

1535

1536

1537 if (!TrySU->isAvailable || !TrySU->NodeQueueId) {

1538 LLVM_DEBUG(dbgs() << "TrySU not available; choosing node from queue\n");

1539 CurSU = AvailableQueue->pop();

1540 } else {

1542

1543 AvailableQueue->remove(TrySU);

1544 CurSU = TrySU;

1545 }

1546 FindAvailableNode();

1547

1548 break;

1549 }

1550 }

1551

1552 if (!CurSU) {

1553

1554

1555

1556

1557

1558 SUnit *TrySU = Interferences[0];

1559 SmallVectorImpl &LRegs = LRegsMap[TrySU];

1560 assert(LRegs.size() == 1 && "Can't handle this yet!");

1561 unsigned Reg = LRegs[0];

1562 SUnit *LRDef = LiveRegDefs[Reg];

1564 const TargetRegisterClass *RC =

1565 TRI->getMinimalPhysRegClass(Reg, VT);

1566 const TargetRegisterClass *DestRC = TRI->getCrossCopyRegClass(RC);

1567

1568

1569

1570

1571

1572

1573

1574

1575 SUnit *NewDef = nullptr;

1576 if (DestRC != RC) {

1577 NewDef = CopyAndMoveSuccessors(LRDef);

1578 if (!DestRC && !NewDef)

1579 report_fatal_error("Can't handle live physical register dependency!");

1580 }

1581 if (!NewDef) {

1582

1584 InsertCopiesAndMoveSuccs(LRDef, Reg, DestRC, RC, Copies);

1586 << " to SU #" << Copies.front()->NodeNum << "\n");

1588 NewDef = Copies.back();

1589 }

1590

1592 << " to SU #" << TrySU->NodeNum << "\n");

1593 LiveRegDefs[Reg] = NewDef;

1596 CurSU = NewDef;

1597 }

1598 assert(CurSU && "Unable to resolve live physical register dependencies!");

1599 return CurSU;

1600}

1601

1602

1603

1604void ScheduleDAGRRList::ListScheduleBottomUp() {

1605

1606 ReleasePredecessors(&ExitSU);

1607

1608

1609 if (!SUnits.empty()) {

1610 SUnit *RootSU = &SUnits[DAG->getRoot().getNode()->getNodeId()];

1611 assert(RootSU->Succs.empty() && "Graph root shouldn't have successors!");

1613 AvailableQueue->push(RootSU);

1614 }

1615

1616

1617

1618 Sequence.reserve(SUnits.size());

1619 while (!AvailableQueue->empty() || !Interferences.empty()) {

1621 AvailableQueue->dump(this));

1622

1623

1624

1625 SUnit *SU = PickNodeToScheduleBottomUp();

1626

1627 AdvancePastStalls(SU);

1628

1629 ScheduleNodeBottomUp(SU);

1630

1631 while (AvailableQueue->empty() && !PendingQueue.empty()) {

1632

1633 assert(MinAvailableCycle < std::numeric_limits::max() &&

1634 "MinAvailableCycle uninitialized");

1635 AdvanceToCycle(std::max(CurCycle + 1, MinAvailableCycle));

1636 }

1637 }

1638

1639

1641

1642#ifndef NDEBUG

1643 VerifyScheduledSequence(true);

1644#endif

1645}

1646

1647namespace {

1648

1649class RegReductionPQBase;

1650

1651struct queue_sort {

1652 bool isReady(SUnit* SU, unsigned CurCycle) const { return true; }

1653};

1654

1655#ifndef NDEBUG

1656template

1657struct reverse_sort : public queue_sort {

1658 SF &SortFunc;

1659

1660 reverse_sort(SF &sf) : SortFunc(sf) {}

1661

1662 bool operator()(SUnit* left, SUnit* right) const {

1663

1664

1665 return SortFunc(right, left);

1666 }

1667};

1668#endif

1669

1670

1671

1672struct bu_ls_rr_sort : public queue_sort {

1673 enum {

1674 IsBottomUp = true,

1675 HasReadyFilter = false

1676 };

1677

1678 RegReductionPQBase *SPQ;

1679

1680 bu_ls_rr_sort(RegReductionPQBase *spq) : SPQ(spq) {}

1681

1682 bool operator()(SUnit* left, SUnit* right) const;

1683};

1684

1685

1686struct src_ls_rr_sort : public queue_sort {

1687 enum {

1688 IsBottomUp = true,

1689 HasReadyFilter = false

1690 };

1691

1692 RegReductionPQBase *SPQ;

1693

1694 src_ls_rr_sort(RegReductionPQBase *spq) : SPQ(spq) {}

1695

1696 bool operator()(SUnit* left, SUnit* right) const;

1697};

1698

1699

1700struct hybrid_ls_rr_sort : public queue_sort {

1701 enum {

1702 IsBottomUp = true,

1703 HasReadyFilter = false

1704 };

1705

1706 RegReductionPQBase *SPQ;

1707

1708 hybrid_ls_rr_sort(RegReductionPQBase *spq) : SPQ(spq) {}

1709

1710 bool isReady(SUnit *SU, unsigned CurCycle) const;

1711

1712 bool operator()(SUnit* left, SUnit* right) const;

1713};

1714

1715

1716

1717struct ilp_ls_rr_sort : public queue_sort {

1718 enum {

1719 IsBottomUp = true,

1720 HasReadyFilter = false

1721 };

1722

1723 RegReductionPQBase *SPQ;

1724

1725 ilp_ls_rr_sort(RegReductionPQBase *spq) : SPQ(spq) {}

1726

1727 bool isReady(SUnit *SU, unsigned CurCycle) const;

1728

1729 bool operator()(SUnit* left, SUnit* right) const;

1730};

1731

1732class RegReductionPQBase : public SchedulingPriorityQueue {

1733protected:

1734 std::vector<SUnit *> Queue;

1735 unsigned CurQueueId = 0;

1736 bool TracksRegPressure;

1737 bool SrcOrder;

1738

1739

1740 std::vector *SUnits = nullptr;

1741

1742 MachineFunction &MF;

1743 const TargetInstrInfo *TII = nullptr;

1744 const TargetRegisterInfo *TRI = nullptr;

1745 const TargetLowering *TLI = nullptr;

1746 ScheduleDAGRRList *scheduleDAG = nullptr;

1747

1748

1749 std::vector SethiUllmanNumbers;

1750

1751

1752 std::vector RegPressure;

1753

1754

1755

1756 std::vector RegLimit;

1757

1758public:

1759 RegReductionPQBase(MachineFunction &mf,

1760 bool hasReadyFilter,

1761 bool tracksrp,

1762 bool srcorder,

1763 const TargetInstrInfo *tii,

1764 const TargetRegisterInfo *tri,

1765 const TargetLowering *tli)

1766 : SchedulingPriorityQueue(hasReadyFilter), TracksRegPressure(tracksrp),

1767 SrcOrder(srcorder), MF(mf), TII(tii), TRI(tri), TLI(tli) {

1768 if (TracksRegPressure) {

1769 unsigned NumRC = TRI->getNumRegClasses();

1770 RegLimit.resize(NumRC);

1774 for (const TargetRegisterClass *RC : TRI->regclasses())

1776 }

1777 }

1778

1779 void setScheduleDAG(ScheduleDAGRRList *scheduleDag) {

1780 scheduleDAG = scheduleDag;

1781 }

1782

1783 ScheduleHazardRecognizer* getHazardRec() {

1784 return scheduleDAG->getHazardRec();

1785 }

1786

1787 void initNodes(std::vector &sunits) override;

1788

1789 void addNode(const SUnit *SU) override;

1790

1791 void updateNode(const SUnit *SU) override;

1792

1793 void releaseState() override {

1794 SUnits = nullptr;

1795 SethiUllmanNumbers.clear();

1797 }

1798

1799 unsigned getNodePriority(const SUnit *SU) const;

1800

1801 unsigned getNodeOrdering(const SUnit *SU) const {

1802 if (!SU->getNode()) return 0;

1803

1805 }

1806

1807 bool empty() const override { return Queue.empty(); }

1808

1809 void push(SUnit *U) override {

1810 assert(U->NodeQueueId && "Node in the queue already");

1811 U->NodeQueueId = ++CurQueueId;

1812 Queue.push_back(U);

1813 }

1814

1815 void remove(SUnit *SU) override {

1816 assert(Queue.empty() && "Queue is empty!");

1818 std::vector<SUnit *>::iterator I = llvm::find(Queue, SU);

1819 if (I != std::prev(Queue.end()))

1821 Queue.pop_back();

1823 }

1824

1825 bool tracksRegPressure() const override { return TracksRegPressure; }

1826

1827 void dumpRegPressure() const;

1828

1829 bool HighRegPressure(const SUnit *SU) const;

1830

1831 bool MayReduceRegPressure(SUnit *SU) const;

1832

1833 int RegPressureDiff(SUnit *SU, unsigned &LiveUses) const;

1834

1835 void scheduledNode(SUnit *SU) override;

1836

1837 void unscheduledNode(SUnit *SU) override;

1838

1839protected:

1840 bool canClobber(const SUnit *SU, const SUnit *Op);

1841 void AddPseudoTwoAddrDeps();

1842 void PrescheduleNodesWithMultipleUses();

1843 void CalculateSethiUllmanNumbers();

1844};

1845

1846template

1847static SUnit *popFromQueueImpl(std::vector<SUnit *> &Q, SF &Picker) {

1848 unsigned BestIdx = 0;

1849

1850

1851 for (unsigned I = 1, E = std::min(Q.size(), (decltype(Q.size()))1000); I != E;

1852 I++)

1853 if (Picker(Q[BestIdx], Q[I]))

1854 BestIdx = I;

1855 SUnit *V = Q[BestIdx];

1856 if (BestIdx + 1 != Q.size())

1857 std::swap(Q[BestIdx], Q.back());

1858 Q.pop_back();

1859 return V;

1860}

1861

1862template

1863SUnit *popFromQueue(std::vector<SUnit *> &Q, SF &Picker, ScheduleDAG *DAG) {

1864#ifndef NDEBUG

1866 reverse_sort RPicker(Picker);

1867 return popFromQueueImpl(Q, RPicker);

1868 }

1869#endif

1870 (void)DAG;

1871 return popFromQueueImpl(Q, Picker);

1872}

1873

1874

1875

1876

1877

1878

1879

1880

1881template

1882class RegReductionPriorityQueue : public RegReductionPQBase {

1883 SF Picker;

1884

1885public:

1886 RegReductionPriorityQueue(MachineFunction &mf,

1887 bool tracksrp,

1888 bool srcorder,

1889 const TargetInstrInfo *tii,

1890 const TargetRegisterInfo *tri,

1891 const TargetLowering *tli)

1892 : RegReductionPQBase(mf, SF::HasReadyFilter, tracksrp, srcorder,

1893 tii, tri, tli),

1894 Picker(this) {}

1895

1896 bool isBottomUp() const override { return SF::IsBottomUp; }

1897

1898 bool isReady(SUnit *U) const override {

1899 return Picker.HasReadyFilter && Picker.isReady(U, getCurCycle());

1900 }

1901

1902 SUnit *pop() override {

1903 if (Queue.empty()) return nullptr;

1904

1905 SUnit *V = popFromQueue(Queue, Picker, scheduleDAG);

1906 V->NodeQueueId = 0;

1907 return V;

1908 }

1909

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

1912

1913 std::vector<SUnit *> DumpQueue = Queue;

1914 SF DumpPicker = Picker;

1915 while (!DumpQueue.empty()) {

1916 SUnit *SU = popFromQueue(DumpQueue, DumpPicker, scheduleDAG);

1919 }

1920 }

1921#endif

1922};

1923

1924using BURegReductionPriorityQueue = RegReductionPriorityQueue<bu_ls_rr_sort>;

1925using SrcRegReductionPriorityQueue = RegReductionPriorityQueue<src_ls_rr_sort>;

1926using HybridBURRPriorityQueue = RegReductionPriorityQueue<hybrid_ls_rr_sort>;

1927using ILPBURRPriorityQueue = RegReductionPriorityQueue<ilp_ls_rr_sort>;

1928

1929}

1930

1931

1932

1933

1934

1935

1936

1937

1938

1939

1940

1944 if (LSchedLow != RSchedLow)

1945 return LSchedLow < RSchedLow ? 1 : -1;

1946 return 0;

1947}

1948

1949

1950

1951static unsigned

1953 if (SUNumbers[SU->NodeNum] != 0)

1954 return SUNumbers[SU->NodeNum];

1955

1956

1957 struct WorkState {

1958 WorkState(const SUnit *SU) : SU(SU) {}

1959 const SUnit *SU;

1960 unsigned PredsProcessed = 0;

1961 };

1962

1965 while (!WorkList.empty()) {

1966 auto &Temp = WorkList.back();

1967 auto *TempSU = Temp.SU;

1968 bool AllPredsKnown = true;

1969

1970 for (unsigned P = Temp.PredsProcessed; P < TempSU->Preds.size(); ++P) {

1971 auto &Pred = TempSU->Preds[P];

1972 if (Pred.isCtrl()) continue;

1973 SUnit *PredSU = Pred.getSUnit();

1974 if (SUNumbers[PredSU->NodeNum] == 0) {

1975#ifndef NDEBUG

1976

1977 for (auto It : WorkList)

1978 assert(It.SU != PredSU && "Trying to push an element twice?");

1979#endif

1980

1981 Temp.PredsProcessed = P + 1;

1982 WorkList.push_back(PredSU);

1983 AllPredsKnown = false;

1984 break;

1985 }

1986 }

1987

1988 if (!AllPredsKnown)

1989 continue;

1990

1991

1992 unsigned SethiUllmanNumber = 0;

1993 unsigned Extra = 0;

1994 for (const SDep &Pred : TempSU->Preds) {

1995 if (Pred.isCtrl()) continue;

1996 SUnit *PredSU = Pred.getSUnit();

1997 unsigned PredSethiUllman = SUNumbers[PredSU->NodeNum];

1998 assert(PredSethiUllman > 0 && "We should have evaluated this pred!");

1999 if (PredSethiUllman > SethiUllmanNumber) {

2000 SethiUllmanNumber = PredSethiUllman;

2001 Extra = 0;

2002 } else if (PredSethiUllman == SethiUllmanNumber)

2003 ++Extra;

2004 }

2005

2006 SethiUllmanNumber += Extra;

2007 if (SethiUllmanNumber == 0)

2008 SethiUllmanNumber = 1;

2009 SUNumbers[TempSU->NodeNum] = SethiUllmanNumber;

2011 }

2012

2013 assert(SUNumbers[SU->NodeNum] > 0 && "SethiUllman should never be zero!");

2014 return SUNumbers[SU->NodeNum];

2015}

2016

2017

2018

2019void RegReductionPQBase::CalculateSethiUllmanNumbers() {

2020 SethiUllmanNumbers.assign(SUnits->size(), 0);

2021

2022 for (const SUnit &SU : *SUnits)

2024}

2025

2026void RegReductionPQBase::addNode(const SUnit *SU) {

2027 unsigned SUSize = SethiUllmanNumbers.size();

2028 if (SUnits->size() > SUSize)

2029 SethiUllmanNumbers.resize(SUSize*2, 0);

2031}

2032

2033void RegReductionPQBase::updateNode(const SUnit *SU) {

2034 SethiUllmanNumbers[SU->NodeNum] = 0;

2036}

2037

2038

2039

2040unsigned RegReductionPQBase::getNodePriority(const SUnit *SU) const {

2041 assert(SU->NodeNum < SethiUllmanNumbers.size());

2044

2045

2046 return 0;

2047 if (Opc == TargetOpcode::EXTRACT_SUBREG ||

2048 Opc == TargetOpcode::SUBREG_TO_REG ||

2049 Opc == TargetOpcode::INSERT_SUBREG)

2050

2051

2052 return 0;

2054

2055

2056

2057

2058

2059 return 0xffff;

2061

2062

2063 return 0;

2064#if 1

2065 return SethiUllmanNumbers[SU->NodeNum];

2066#else

2067 unsigned Priority = SethiUllmanNumbers[SU->NodeNum];

2069

2071 return (NP > 0) ? NP : 0;

2072 }

2073 return Priority;

2074#endif

2075}

2076

2077

2078

2079

2080

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

2082LLVM_DUMP_METHOD void RegReductionPQBase::dumpRegPressure() const {

2083 for (const TargetRegisterClass *RC : TRI->regclasses()) {

2084 unsigned Id = RC->getID();

2086 if (!RP) continue;

2087 LLVM_DEBUG(dbgs() << TRI->getRegClassName(RC) << ": " << RP << " / "

2088 << RegLimit[Id] << '\n');

2089 }

2090}

2091#endif

2092

2093bool RegReductionPQBase::HighRegPressure(const SUnit *SU) const {

2094 if (!TLI)

2095 return false;

2096

2097 for (const SDep &Pred : SU->Preds) {

2099 continue;

2100 SUnit *PredSU = Pred.getSUnit();

2101

2102

2104 continue;

2105 }

2106 for (ScheduleDAGSDNodes::RegDefIter RegDefPos(PredSU, scheduleDAG);

2107 RegDefPos.IsValid(); RegDefPos.Advance()) {

2108 unsigned RCId, Cost;

2110

2111 if ((RegPressure[RCId] + Cost) >= RegLimit[RCId])

2112 return true;

2113 }

2114 }

2115 return false;

2116}

2117

2118bool RegReductionPQBase::MayReduceRegPressure(SUnit *SU) const {

2119 const SDNode *N = SU->getNode();

2120

2121 if (N->isMachineOpcode() || !SU->NumSuccs)

2122 return false;

2123

2124 unsigned NumDefs = TII->get(N->getMachineOpcode()).getNumDefs();

2125 for (unsigned i = 0; i != NumDefs; ++i) {

2126 MVT VT = N->getSimpleValueType(i);

2127 if (N->hasAnyUseOfValue(i))

2128 continue;

2130 if (RegPressure[RCId] >= RegLimit[RCId])

2131 return true;

2132 }

2133 return false;

2134}

2135

2136

2137

2138

2139

2140

2141

2142

2143int RegReductionPQBase::RegPressureDiff(SUnit *SU, unsigned &LiveUses) const {

2144 LiveUses = 0;

2145 int PDiff = 0;

2146 for (const SDep &Pred : SU->Preds) {

2148 continue;

2149 SUnit *PredSU = Pred.getSUnit();

2150

2151

2154 ++LiveUses;

2155 continue;

2156 }

2157 for (ScheduleDAGSDNodes::RegDefIter RegDefPos(PredSU, scheduleDAG);

2158 RegDefPos.IsValid(); RegDefPos.Advance()) {

2159 MVT VT = RegDefPos.GetValue();

2161 if (RegPressure[RCId] >= RegLimit[RCId])

2162 ++PDiff;

2163 }

2164 }

2165 const SDNode *N = SU->getNode();

2166

2167 if (N || N->isMachineOpcode() || !SU->NumSuccs)

2168 return PDiff;

2169

2170 unsigned NumDefs = TII->get(N->getMachineOpcode()).getNumDefs();

2171 for (unsigned i = 0; i != NumDefs; ++i) {

2172 MVT VT = N->getSimpleValueType(i);

2173 if (N->hasAnyUseOfValue(i))

2174 continue;

2176 if (RegPressure[RCId] >= RegLimit[RCId])

2177 --PDiff;

2178 }

2179 return PDiff;

2180}

2181

2182void RegReductionPQBase::scheduledNode(SUnit *SU) {

2183 if (!TracksRegPressure)

2184 return;

2185

2187 return;

2188

2189 for (const SDep &Pred : SU->Preds) {

2191 continue;

2192 SUnit *PredSU = Pred.getSUnit();

2193

2194

2196 continue;

2197 }

2198

2199

2200

2201

2202

2203

2204

2205

2206

2207

2208

2209

2210

2211

2212

2215 for (ScheduleDAGSDNodes::RegDefIter RegDefPos(PredSU, scheduleDAG);

2216 RegDefPos.IsValid(); RegDefPos.Advance(), --SkipRegDefs) {

2217 if (SkipRegDefs)

2218 continue;

2219

2220 unsigned RCId, Cost;

2223 break;

2224 }

2225 }

2226

2227

2228

2229

2231 for (ScheduleDAGSDNodes::RegDefIter RegDefPos(SU, scheduleDAG);

2232 RegDefPos.IsValid(); RegDefPos.Advance(), --SkipRegDefs) {

2233 if (SkipRegDefs > 0)

2234 continue;

2235 unsigned RCId, Cost;

2237 if (RegPressure[RCId] < Cost) {

2238

2239

2241 << ") has too many regdefs\n");

2243 }

2244 else {

2246 }

2247 }

2249}

2250

2251void RegReductionPQBase::unscheduledNode(SUnit *SU) {

2252 if (!TracksRegPressure)

2253 return;

2254

2255 const SDNode *N = SU->getNode();

2256 if (N) return;

2257

2258 if (N->isMachineOpcode()) {

2260 return;

2261 } else {

2262 unsigned Opc = N->getMachineOpcode();

2263 if (Opc == TargetOpcode::EXTRACT_SUBREG ||

2264 Opc == TargetOpcode::INSERT_SUBREG ||

2265 Opc == TargetOpcode::SUBREG_TO_REG ||

2266 Opc == TargetOpcode::REG_SEQUENCE ||

2267 Opc == TargetOpcode::IMPLICIT_DEF)

2268 return;

2269 }

2270

2271 for (const SDep &Pred : SU->Preds) {

2273 continue;

2274 SUnit *PredSU = Pred.getSUnit();

2275

2276

2278 continue;

2279 const SDNode *PN = PredSU->getNode();

2285 }

2286 continue;

2287 }

2289 if (POpc == TargetOpcode::IMPLICIT_DEF)

2290 continue;

2291 if (POpc == TargetOpcode::EXTRACT_SUBREG ||

2292 POpc == TargetOpcode::INSERT_SUBREG ||

2293 POpc == TargetOpcode::SUBREG_TO_REG) {

2297 continue;

2298 }

2299 if (POpc == TargetOpcode::REG_SEQUENCE) {

2301 const TargetRegisterClass *RC = TRI->getRegClass(DstRCIdx);

2302 unsigned RCId = RC->getID();

2303

2304

2306 continue;

2307 }

2309 for (unsigned i = 0; i != NumDefs; ++i) {

2312 continue;

2315

2317 else

2319 }

2320 }

2321

2322

2323

2324 if (SU->NumSuccs && N->isMachineOpcode()) {

2325 unsigned NumDefs = TII->get(N->getMachineOpcode()).getNumDefs();

2326 for (unsigned i = NumDefs, e = N->getNumValues(); i != e; ++i) {

2327 MVT VT = N->getSimpleValueType(i);

2328 if (VT == MVT::Glue || VT == MVT::Other)

2329 continue;

2330 if (N->hasAnyUseOfValue(i))

2331 continue;

2334 }

2335 }

2336

2338}

2339

2340

2341

2342

2343

2344

2345

2347 unsigned MaxHeight = 0;

2348 for (const SDep &Succ : SU->Succs) {

2349 if (Succ.isCtrl()) continue;

2351

2352

2356 if (Height > MaxHeight)

2357 MaxHeight = Height;

2358 }

2359 return MaxHeight;

2360}

2361

2362

2363

2365 unsigned Scratches = 0;

2366 for (const SDep &Pred : SU->Preds) {

2367 if (Pred.isCtrl()) continue;

2368 Scratches++;

2369 }

2370 return Scratches;

2371}

2372

2373

2374

2376 bool RetVal = false;

2377 for (const SDep &Pred : SU->Preds) {

2378 if (Pred.isCtrl()) continue;

2379 const SUnit *PredSU = Pred.getSUnit();

2380 if (PredSU->getNode() &&

2384 if (Reg.isVirtual()) {

2385 RetVal = true;

2386 continue;

2387 }

2388 }

2389 return false;

2390 }

2391 return RetVal;

2392}

2393

2394

2395

2396

2398 bool RetVal = false;

2399 for (const SDep &Succ : SU->Succs) {

2400 if (Succ.isCtrl()) continue;

2405 if (Reg.isVirtual()) {

2406 RetVal = true;

2407 continue;

2408 }

2409 }

2410 return false;

2411 }

2412 return RetVal;

2413}

2414

2415

2416

2417

2418

2419

2420

2421

2422

2423

2424

2427 return;

2428

2430 return;

2431

2433

2435

2436 for (const SDep &Pred : SU->Preds) {

2437 if (Pred.isCtrl()) continue;

2438 Pred.getSUnit()->isVRegCycle = true;

2439 }

2440}

2441

2442

2443

2446 return;

2447

2448 for (const SDep &Pred : SU->Preds) {

2449 if (Pred.isCtrl()) continue;

2450 SUnit *PredSU = Pred.getSUnit();

2453 "VRegCycle def must be CopyFromReg");

2454 Pred.getSUnit()->isVRegCycle = false;

2455 }

2456 }

2457}

2458

2459

2460

2462

2464 return false;

2465

2466 for (const SDep &Pred : SU->Preds) {

2467 if (Pred.isCtrl()) continue;

2468 if (Pred.getSUnit()->isVRegCycle &&

2469 Pred.getSUnit()->getNode()->getOpcode() == ISD::CopyFromReg) {

2471 return true;

2472 }

2473 }

2474 return false;

2475}

2476

2477

2478

2479

2481 if ((int)SPQ->getCurCycle() < Height) return true;

2482 if (SPQ->getHazardRec()->getHazardType(SU, 0)

2484 return true;

2485 return false;

2486}

2487

2488

2489

2491 RegReductionPQBase *SPQ) {

2492

2493

2496 int LHeight = (int)left->getHeight() + LPenalty;

2497 int RHeight = (int)right->getHeight() + RPenalty;

2498

2503

2504

2505

2506

2507 if (LStall) {

2508 if (!RStall)

2509 return 1;

2510 if (LHeight != RHeight)

2511 return LHeight > RHeight ? 1 : -1;

2512 } else if (RStall)

2513 return -1;

2514

2515

2516

2519

2520

2521

2522

2523 if (!SPQ->getHazardRec()->isEnabled()) {

2524 if (LHeight != RHeight)

2525 return LHeight > RHeight ? 1 : -1;

2526 }

2527 int LDepth = left->getDepth() - LPenalty;

2528 int RDepth = right->getDepth() - RPenalty;

2529 if (LDepth != RDepth) {

2531 << ") depth " << LDepth << " vs SU (" << right->NodeNum

2532 << ") depth " << RDepth << "\n");

2533 return LDepth < RDepth ? 1 : -1;

2534 }

2537 }

2538 return 0;

2539}

2540

2542

2543

2544

2545

2549 if (LHasPhysReg != RHasPhysReg) {

2550 #ifndef NDEBUG

2551 static const char *const PhysRegMsg[] = { " has no physreg",

2552 " defines a physreg" };

2553 #endif

2555 << PhysRegMsg[LHasPhysReg] << " SU(" << right->NodeNum

2556 << ") " << PhysRegMsg[RHasPhysReg] << "\n");

2557 return LHasPhysReg < RHasPhysReg;

2558 }

2559 }

2560

2561

2562 unsigned LPriority = SPQ->getNodePriority(left);

2563 unsigned RPriority = SPQ->getNodePriority(right);

2564

2565

2566

2569 RPriority = (RPriority > RNumVals) ? (RPriority - RNumVals) : 0;

2570 }

2573 LPriority = (LPriority > LNumVals) ? (LPriority - LNumVals) : 0;

2574 }

2575

2576 if (LPriority != RPriority)

2577 return LPriority > RPriority;

2578

2579

2580

2582 unsigned LOrder = SPQ->getNodeOrdering(left);

2583 unsigned ROrder = SPQ->getNodeOrdering(right);

2584

2585

2586

2587 if ((LOrder || ROrder) && LOrder != ROrder)

2588 return LOrder != 0 && (LOrder < ROrder || ROrder == 0);

2589 }

2590

2591

2592

2593

2594

2595

2596

2597

2598

2599

2600

2601

2602

2603

2604

2605

2606

2607

2610 if (LDist != RDist)

2611 return LDist < RDist;

2612

2613

2616 if (LScratch != RScratch)

2617 return LScratch > RScratch;

2618

2619

2620

2621 if ((left->isCall && RPriority > 0) || (right->isCall && LPriority > 0))

2623

2624

2627 int result = BUCompareLatency(left, right, false , SPQ);

2628 if (result != 0)

2629 return result > 0;

2630 }

2631 else {

2634

2637 }

2638

2640 "NodeQueueId cannot be zero");

2642}

2643

2644

2645bool bu_ls_rr_sort::operator()(SUnit *left, SUnit *right) const {

2647 return res > 0;

2648

2649 return BURRSort(left, right, SPQ);

2650}

2651

2652

2653bool src_ls_rr_sort::operator()(SUnit *left, SUnit *right) const {

2655 return res > 0;

2656

2657 unsigned LOrder = SPQ->getNodeOrdering(left);

2658 unsigned ROrder = SPQ->getNodeOrdering(right);

2659

2660

2661

2662 if ((LOrder || ROrder) && LOrder != ROrder)

2663 return LOrder != 0 && (LOrder < ROrder || ROrder == 0);

2664

2665 return BURRSort(left, right, SPQ);

2666}

2667

2668

2669

2670

2671

2672bool hybrid_ls_rr_sort::isReady(SUnit *SU, unsigned CurCycle) const {

2673 static const unsigned ReadyDelay = 3;

2674

2675 if (SPQ->MayReduceRegPressure(SU)) return true;

2676

2677 if (SU->getHeight() > (CurCycle + ReadyDelay)) return false;

2678

2679 if (SPQ->getHazardRec()->getHazardType(SU, -ReadyDelay)

2681 return false;

2682

2683 return true;

2684}

2685

2686

2687bool hybrid_ls_rr_sort::operator()(SUnit *left, SUnit *right) const {

2689 return res > 0;

2690

2692

2693 return BURRSort(left, right, SPQ);

2694

2695 bool LHigh = SPQ->HighRegPressure(left);

2696 bool RHigh = SPQ->HighRegPressure(right);

2697

2698

2699 if (LHigh && !RHigh) {

2701 << right->NodeNum << ")\n");

2702 return true;

2703 }

2704 else if (!LHigh && RHigh) {

2706 << left->NodeNum << ")\n");

2707 return false;

2708 }

2709 if (!LHigh && !RHigh) {

2710 int result = BUCompareLatency(left, right, true , SPQ);

2711 if (result != 0)

2712 return result > 0;

2713 }

2714 return BURRSort(left, right, SPQ);

2715}

2716

2717

2718

2719bool ilp_ls_rr_sort::isReady(SUnit *SU, unsigned CurCycle) const {

2720 if (SU->getHeight() > CurCycle) return false;

2721

2722 if (SPQ->getHazardRec()->getHazardType(SU, 0)

2724 return false;

2725

2726 return true;

2727}

2728

2732

2733

2734 return true;

2735

2736 if (Opc == TargetOpcode::EXTRACT_SUBREG ||

2737 Opc == TargetOpcode::SUBREG_TO_REG ||

2738 Opc == TargetOpcode::INSERT_SUBREG)

2739

2740

2741 return true;

2742

2744

2745

2746 return true;

2747

2748 return false;

2749}

2750

2751

2752

2753bool ilp_ls_rr_sort::operator()(SUnit *left, SUnit *right) const {

2755 return res > 0;

2756

2758

2759 return BURRSort(left, right, SPQ);

2760

2761 unsigned LLiveUses = 0, RLiveUses = 0;

2762 int LPDiff = 0, RPDiff = 0;

2764 LPDiff = SPQ->RegPressureDiff(left, LLiveUses);

2765 RPDiff = SPQ->RegPressureDiff(right, RLiveUses);

2766 }

2769 << "): " << LPDiff << " != SU(" << right->NodeNum

2770 << "): " << RPDiff << "\n");

2771 return LPDiff > RPDiff;

2772 }

2773

2777 if (LReduce && !RReduce) return false;

2778 if (RReduce && !LReduce) return true;

2779 }

2780

2783 << " != SU(" << right->NodeNum << "): " << RLiveUses

2784 << "\n");

2785 return LLiveUses < RLiveUses;

2786 }

2787

2791 if (LStall != RStall)

2793 }

2794

2796 int spread = (int)left->getDepth() - (int)right->getDepth();

2800 << "): " << right->getDepth() << "\n");

2802 }

2803 }

2804

2809 }

2810

2811 return BURRSort(left, right, SPQ);

2812}

2813

2814void RegReductionPQBase::initNodes(std::vector &sunits) {

2815 SUnits = &sunits;

2816

2818 AddPseudoTwoAddrDeps();

2819

2820 if (!TracksRegPressure && !SrcOrder)

2821 PrescheduleNodesWithMultipleUses();

2822

2823 CalculateSethiUllmanNumbers();

2824

2825

2826 if (scheduleDAG->BB->isSuccessor(scheduleDAG->BB))

2827 for (SUnit &SU : sunits)

2829}

2830

2831

2832

2833

2834

2835bool RegReductionPQBase::canClobber(const SUnit *SU, const SUnit *Op) {

2838 const MCInstrDesc &MCID = TII->get(Opc);

2839 unsigned NumRes = MCID.getNumDefs();

2841 for (unsigned i = 0; i != NumOps; ++i) {

2845 Op->OrigNode == &(*SUnits)[DU->getNodeId()])

2846 return true;

2847 }

2848 }

2849 }

2850 return false;

2851}

2852

2853

2854

2855

2857 ScheduleDAGRRList *scheduleDAG,

2863 if (ImpDefs.empty() && !RegMask)

2864 return false;

2865

2866 for (const SDep &Succ : SU->Succs) {

2868 for (const SDep &SuccPred : SuccSU->Preds) {

2870 continue;

2871

2872 if (RegMask &&

2874 scheduleDAG->IsReachable(DepSU, SuccPred.getSUnit()))

2875 return true;

2876

2877 for (MCPhysReg ImpDef : ImpDefs) {

2878

2879

2880

2881 if (TRI->regsOverlap(ImpDef, SuccPred.getReg()) &&

2882 scheduleDAG->IsReachable(DepSU, SuccPred.getSUnit()))

2883 return true;

2884 }

2885 }

2886 }

2887 return false;

2888}

2889

2890

2891

2896 unsigned NumDefs = TII->get(N->getMachineOpcode()).getNumDefs();

2898 assert(!ImpDefs.empty() && "Caller should check hasPhysRegDefs");

2899 for (const SDNode *SUNode = SU->getNode(); SUNode;

2901 if (!SUNode->isMachineOpcode())

2902 continue;

2904 TII->get(SUNode->getMachineOpcode()).implicit_defs();

2906 if (SUImpDefs.empty() && !SURegMask)

2907 continue;

2908 for (unsigned i = NumDefs, e = N->getNumValues(); i != e; ++i) {

2909 MVT VT = N->getSimpleValueType(i);

2910 if (VT == MVT::Glue || VT == MVT::Other)

2911 continue;

2912 if (N->hasAnyUseOfValue(i))

2913 continue;

2916 return true;

2917 for (MCPhysReg SUReg : SUImpDefs) {

2918 if (TRI->regsOverlap(Reg, SUReg))

2919 return true;

2920 }

2921 }

2922 }

2923 return false;

2924}

2925

2926

2927

2928

2929

2930

2931

2932

2933

2934

2935

2936

2937

2938

2939

2940

2941

2942

2943

2944

2945

2946

2947

2948

2949

2950

2951

2952

2953

2954

2955

2956void RegReductionPQBase::PrescheduleNodesWithMultipleUses() {

2957

2958 for (SUnit &SU : *SUnits) {

2959

2960

2961

2963 continue;

2964

2966 continue;

2967

2968

2969 if (SDNode *N = SU.getNode())

2972 continue;

2973

2974 SDNode *PredFrameSetup = nullptr;

2975 for (const SDep &Pred : SU.Preds)

2977

2979

2980

2981

2982

2983

2984

2985

2986

2989 PredFrameSetup = PredND;

2990 break;

2991 }

2992 }

2993

2994 if (PredFrameSetup != nullptr)

2995 continue;

2996

2997

2998 SUnit *PredSU = nullptr;

2999 for (const SDep &Pred : SU.Preds)

3000 if (!Pred.isCtrl()) {

3002 break;

3003 }

3005

3006

3007

3009 continue;

3010

3012 continue;

3013

3014

3015 if (SDNode *N = SU.getNode())

3018 continue;

3019

3020

3021 for (const SDep &PredSucc : PredSU->Succs) {

3022 SUnit *PredSuccSU = PredSucc.getSUnit();

3023 if (PredSuccSU == &SU) continue;

3024

3025

3026 if (PredSuccSU->NumSuccs == 0)

3027 goto outer_loop_continue;

3028

3031 goto outer_loop_continue;

3032

3033 if (scheduleDAG->IsReachable(&SU, PredSuccSU))

3034 goto outer_loop_continue;

3035 }

3036

3037

3038

3040 dbgs() << " Prescheduling SU #" << SU.NodeNum << " next to PredSU #"

3042 << " to guide scheduling in the presence of multiple uses\n");

3043 for (unsigned i = 0; i != PredSU->Succs.size(); ++i) {

3046 SUnit *SuccSU = Edge.getSUnit();

3047 if (SuccSU != &SU) {

3048 Edge.setSUnit(PredSU);

3049 scheduleDAG->RemovePred(SuccSU, Edge);

3050 scheduleDAG->AddPredQueued(&SU, Edge);

3051 Edge.setSUnit(&SU);

3052 scheduleDAG->AddPredQueued(SuccSU, Edge);

3053 --i;

3054 }

3055 }

3056 outer_loop_continue:;

3057 }

3058}

3059

3060

3061

3062

3063

3064

3065

3066

3067void RegReductionPQBase::AddPseudoTwoAddrDeps() {

3068 for (SUnit &SU : *SUnits) {

3070 continue;

3071

3074 continue;

3075

3077 unsigned Opc = Node->getMachineOpcode();

3078 const MCInstrDesc &MCID = TII->get(Opc);

3079 unsigned NumRes = MCID.getNumDefs();

3081 for (unsigned j = 0; j != NumOps; ++j) {

3083 continue;

3086 continue;

3087 const SUnit *DUSU = &(*SUnits)[DU->getNodeId()];

3088 if (!DUSU)

3089 continue;

3090 for (const SDep &Succ : DUSU->Succs) {

3092 continue;

3093 SUnit *SuccSU = Succ.getSUnit();

3094 if (SuccSU == &SU)

3095 continue;

3096

3097

3100 continue;

3101

3102

3103

3104

3105 while (SuccSU->Succs.size() == 1 &&

3108 TargetOpcode::COPY_TO_REGCLASS)

3109 SuccSU = SuccSU->Succs.front().getSUnit();

3110

3112 continue;

3113

3114

3117 continue;

3118 }

3119

3120

3122 if (SuccOpc == TargetOpcode::EXTRACT_SUBREG ||

3123 SuccOpc == TargetOpcode::INSERT_SUBREG ||

3124 SuccOpc == TargetOpcode::SUBREG_TO_REG)

3125 continue;

3127 (!canClobber(SuccSU, DUSU) ||

3130 !scheduleDAG->IsReachable(SuccSU, &SU)) {

3132 << " Adding a pseudo-two-addr edge from SU #"

3133 << SU.NodeNum << " to SU #" << SuccSU->NodeNum << "\n");

3134 scheduleDAG->AddPredQueued(&SU, SDep(SuccSU, SDep::Artificial));

3135 }

3136 }

3137 }

3138 }

3139}

3140

3141

3142

3143

3144

3150

3151 BURegReductionPriorityQueue *PQ =

3152 new BURegReductionPriorityQueue(*IS->MF, false, false, TII, TRI, nullptr);

3153 ScheduleDAGRRList *SD = new ScheduleDAGRRList(*IS->MF, false, PQ, OptLevel);

3154 PQ->setScheduleDAG(SD);

3155 return SD;

3156}

3157

3164

3165 SrcRegReductionPriorityQueue *PQ =

3166 new SrcRegReductionPriorityQueue(*IS->MF, false, true, TII, TRI, nullptr);

3167 ScheduleDAGRRList *SD = new ScheduleDAGRRList(*IS->MF, false, PQ, OptLevel);

3168 PQ->setScheduleDAG(SD);

3169 return SD;

3170}

3171

3179

3180 HybridBURRPriorityQueue *PQ =

3181 new HybridBURRPriorityQueue(*IS->MF, true, false, TII, TRI, TLI);

3182

3183 ScheduleDAGRRList *SD = new ScheduleDAGRRList(*IS->MF, true, PQ, OptLevel);

3184 PQ->setScheduleDAG(SD);

3185 return SD;

3186}

3187

3194

3195 ILPBURRPriorityQueue *PQ =

3196 new ILPBURRPriorityQueue(*IS->MF, true, false, TII, TRI, TLI);

3197 ScheduleDAGRRList *SD = new ScheduleDAGRRList(*IS->MF, true, PQ, OptLevel);

3198 PQ->setScheduleDAG(SD);

3199 return SD;

3200}

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

const TargetInstrInfo & TII

static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)

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

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

#define LLVM_DUMP_METHOD

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

This file defines the DenseMap class.

const size_t AbstractManglingParser< Derived, Alloc >::NumOps

Register const TargetRegisterInfo * TRI

Promote Memory to Register

static bool isLiveOut(const MachineBasicBlock &MBB, unsigned Reg)

std::pair< BasicBlock *, BasicBlock * > Edge

static MVT getPhysicalRegisterVT(SDNode *N, unsigned Reg, const TargetInstrInfo *TII)

getPhysicalRegisterVT - Returns the ValueType of the physical register definition of the specified no...

static bool CheckForLiveRegDef(SUnit *SU, MCRegister Reg, std::vector< SUnit * > &LiveRegDefs, SmallSet< unsigned, 4 > &RegAdded, SmallVectorImpl< unsigned > &LRegs, const TargetRegisterInfo *TRI, const SDNode *Node=nullptr)

CheckForLiveRegDef - Return true and update live register vector if the specified register def of the...

static bool canEnableCoalescing(SUnit *SU)

Definition ScheduleDAGRRList.cpp:2729

static RegisterScheduler sourceListDAGScheduler("source", "Similar to list-burr but schedules in source " "order when possible", createSourceListDAGScheduler)

static cl::opt< bool > DisableSchedCycles("disable-sched-cycles", cl::Hidden, cl::init(false), cl::desc("Disable cycle-level precision during preRA scheduling"))

static cl::opt< bool > DisableSchedStalls("disable-sched-stalls", cl::Hidden, cl::init(true), cl::desc("Disable no-stall priority in sched=list-ilp"))

static bool hasOnlyLiveInOpers(const SUnit *SU)

hasOnlyLiveInOpers - Return true if SU has only value predecessors that are CopyFromReg from a virtua...

Definition ScheduleDAGRRList.cpp:2375

static bool IsChainDependent(SDNode *Outer, SDNode *Inner, unsigned NestLevel, const TargetInstrInfo *TII)

IsChainDependent - Test if Outer is reachable from Inner through chain dependencies.

Definition ScheduleDAGRRList.cpp:442

static bool hasOnlyLiveOutUses(const SUnit *SU)

hasOnlyLiveOutUses - Return true if SU has only value successors that are CopyToReg to a virtual regi...

Definition ScheduleDAGRRList.cpp:2397

static cl::opt< bool > DisableSchedCriticalPath("disable-sched-critical-path", cl::Hidden, cl::init(false), cl::desc("Disable critical path priority in sched=list-ilp"))

static cl::opt< bool > Disable2AddrHack("disable-2addr-hack", cl::Hidden, cl::init(true), cl::desc("Disable scheduler's two-address hack"))

static RegisterScheduler ILPListDAGScheduler("list-ilp", "Bottom-up register pressure aware list scheduling " "which tries to balance ILP and register pressure", createILPListDAGScheduler)

static void resetVRegCycle(SUnit *SU)

Definition ScheduleDAGRRList.cpp:2444

static RegisterScheduler hybridListDAGScheduler("list-hybrid", "Bottom-up register pressure aware list scheduling " "which tries to balance latency and register pressure", createHybridListDAGScheduler)

static bool canClobberReachingPhysRegUse(const SUnit *DepSU, const SUnit *SU, ScheduleDAGRRList *scheduleDAG, const TargetInstrInfo *TII, const TargetRegisterInfo *TRI)

canClobberReachingPhysRegUse - True if SU would clobber one of it's successor's explicit physregs who...

Definition ScheduleDAGRRList.cpp:2856

static cl::opt< bool > DisableSchedPhysRegJoin("disable-sched-physreg-join", cl::Hidden, cl::init(false), cl::desc("Disable physreg def-use affinity"))

static bool canClobberPhysRegDefs(const SUnit *SuccSU, const SUnit *SU, const TargetInstrInfo *TII, const TargetRegisterInfo *TRI)

canClobberPhysRegDefs - True if SU would clobber one of SuccSU's physical register defs.

Definition ScheduleDAGRRList.cpp:2892

static cl::opt< unsigned > AvgIPC("sched-avg-ipc", cl::Hidden, cl::init(1), cl::desc("Average inst/cycle when no target itinerary exists."))

static void GetCostForDef(const ScheduleDAGSDNodes::RegDefIter &RegDefPos, const TargetLowering *TLI, const TargetInstrInfo *TII, const TargetRegisterInfo *TRI, unsigned &RegClass, unsigned &Cost, const MachineFunction &MF)

GetCostForDef - Looks up the register class and cost for a given definition.

Definition ScheduleDAGRRList.cpp:310

static bool BURRSort(SUnit *left, SUnit *right, RegReductionPQBase *SPQ)

Definition ScheduleDAGRRList.cpp:2541

static cl::opt< bool > DisableSchedRegPressure("disable-sched-reg-pressure", cl::Hidden, cl::init(false), cl::desc("Disable regpressure priority in sched=list-ilp"))

static bool BUHasStall(SUnit *SU, int Height, RegReductionPQBase *SPQ)

Definition ScheduleDAGRRList.cpp:2480

static void initVRegCycle(SUnit *SU)

Definition ScheduleDAGRRList.cpp:2425

static constexpr unsigned RegSequenceCost

Definition ScheduleDAGRRList.cpp:304

static cl::opt< int > MaxReorderWindow("max-sched-reorder", cl::Hidden, cl::init(6), cl::desc("Number of instructions to allow ahead of the critical path " "in sched=list-ilp"))

static SDNode * FindCallSeqStart(SDNode *N, unsigned &NestLevel, unsigned &MaxNest, const TargetInstrInfo *TII)

FindCallSeqStart - Starting from the (lowered) CALLSEQ_END node, locate the corresponding (lowered) C...

Definition ScheduleDAGRRList.cpp:491

static bool isOperandOf(const SUnit *SU, SDNode *N)

Definition ScheduleDAGRRList.cpp:972

static cl::opt< bool > DisableSchedVRegCycle("disable-sched-vrcycle", cl::Hidden, cl::init(false), cl::desc("Disable virtual register cycle interference checks"))

static int checkSpecialNodes(const SUnit *left, const SUnit *right)

Definition ScheduleDAGRRList.cpp:1941

static cl::opt< bool > DisableSchedLiveUses("disable-sched-live-uses", cl::Hidden, cl::init(true), cl::desc("Disable live use priority in sched=list-ilp"))

static const uint32_t * getNodeRegMask(const SDNode *N)

getNodeRegMask - Returns the register mask attached to an SDNode, if any.

Definition ScheduleDAGRRList.cpp:1336

static unsigned closestSucc(const SUnit *SU)

closestSucc - Returns the scheduled cycle of the successor which is closest to the current cycle.

Definition ScheduleDAGRRList.cpp:2346

static bool hasVRegCycleUse(const SUnit *SU)

Definition ScheduleDAGRRList.cpp:2461

static cl::opt< bool > DisableSchedHeight("disable-sched-height", cl::Hidden, cl::init(false), cl::desc("Disable scheduled-height priority in sched=list-ilp"))

static RegisterScheduler burrListDAGScheduler("list-burr", "Bottom-up register reduction list scheduling", createBURRListDAGScheduler)

static unsigned calcMaxScratches(const SUnit *SU)

calcMaxScratches - Returns an cost estimate of the worse case requirement for scratch registers,...

Definition ScheduleDAGRRList.cpp:2364

static unsigned CalcNodeSethiUllmanNumber(const SUnit *SU, std::vector< unsigned > &SUNumbers)

CalcNodeSethiUllmanNumber - Compute Sethi Ullman number.

Definition ScheduleDAGRRList.cpp:1952

static int BUCompareLatency(SUnit *left, SUnit *right, bool checkPref, RegReductionPQBase *SPQ)

Definition ScheduleDAGRRList.cpp:2490

static void CheckForLiveRegDefMasked(SUnit *SU, const uint32_t *RegMask, ArrayRef< SUnit * > LiveRegDefs, SmallSet< unsigned, 4 > &RegAdded, SmallVectorImpl< unsigned > &LRegs)

CheckForLiveRegDefMasked - Check for any live physregs that are clobbered by RegMask,...

Definition ScheduleDAGRRList.cpp:1321

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)

This file describes how to lower LLVM code to machine code.

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

size_t size() const

size - Get the array size.

bool empty() const

empty - Check if the array is empty.

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

unsigned getNumOperands() const

Return the number of declared MachineOperands for this MachineInstruction.

ArrayRef< MCOperandInfo > operands() const

bool hasOptionalDef() const

Set if this instruction has an optional definition, e.g.

unsigned getNumDefs() const

Return the number of MachineOperands that are register definitions.

int getOperandConstraint(unsigned OpNum, MCOI::OperandConstraint Constraint) const

Returns the value of the specified operand constraint if it is present.

ArrayRef< MCPhysReg > implicit_defs() const

Return a list of registers that are potentially written by any instance of this machine instruction.

bool isCommutable() const

Return true if this may be a 2- or 3-address instruction (of the form "X = op Y, Z,...

const MCInstrDesc & get(unsigned Opcode) const

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

MCRegAliasIterator enumerates all registers aliasing Reg.

Wrapper class representing physical registers. Should be passed by value.

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.

static bool clobbersPhysReg(const uint32_t *RegMask, MCRegister PhysReg)

clobbersPhysReg - Returns true if this RegMask clobbers PhysReg.

const TargetRegisterClass * getRegClass(Register Reg) const

Return the register class of the specified virtual register.

Wrapper class representing virtual and physical registers.

constexpr bool isPhysical() const

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

Represents one node in the SelectionDAG.

bool isMachineOpcode() const

Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode.

int getNodeId() const

Return the unique node id.

unsigned getOpcode() const

Return the SelectionDAG opcode value for this node.

unsigned getIROrder() const

Return the node ordering.

void setNodeId(int Id)

Set unique node id.

MVT getSimpleValueType(unsigned ResNo) const

Return the type of a specified result as a simple type.

unsigned getNumValues() const

Return the number of values defined/returned by this operator.

unsigned getMachineOpcode() const

This may only be called if isMachineOpcode returns true.

const SDValue & getOperand(unsigned Num) const

uint64_t getConstantOperandVal(unsigned Num) const

Helper method returns the integer value of a ConstantSDNode operand.

LLVM_ABI bool hasAnyUseOfValue(unsigned Value) const

Return true if there are any use of the indicated value.

SDNode * getGluedNode() const

If this node has a glue operand, return the node to which the glue operand points.

Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.

SDNode * getNode() const

get the SDNode which holds the desired result

@ Data

Regular data dependence (aka true-dependence).

@ Artificial

Arbitrary strong DAG edge (no real dependence).

unsigned getLatency() const

Returns the latency value for this edge, which roughly means the minimum number of cycles that must e...

bool isAssignedRegDep() const

Tests if this is a Data dependence that is associated with a register.

bool isArtificial() const

Tests if this is an Order dependence that is marked as "artificial", meaning it isn't necessary for c...

bool isCtrl() const

Shorthand for getKind() != SDep::Data.

Register getReg() const

Returns the register associated with this edge.

Scheduling unit. This is a node in the scheduling DAG.

bool isCall

Is a function call.

LLVM_ABI void setHeightToAtLeast(unsigned NewHeight)

If NewHeight is greater than this node's height value, set it to be the new height value.

unsigned NodeQueueId

Queue id of node.

unsigned NodeNum

Entry # of node in the node vector.

bool hasPhysRegClobbers

Has any physreg defs, used or not.

bool isCallOp

Is a function call operand.

const TargetRegisterClass * CopyDstRC

Is a special copy node if != nullptr.

unsigned getHeight() const

Returns the height of this node, which is the length of the maximum path down to any node which has n...

LLVM_ABI void setHeightDirty()

Sets a flag in this node to indicate that its stored Height value will require recomputation the next...

bool isSucc(const SUnit *N) const

Tests if node N is a successor of this node.

LLVM_ABI void removePred(const SDep &D)

Removes the specified edge as a pred of the current node if it exists.

unsigned short Latency

Node latency.

unsigned short NumRegDefsLeft

bool isPending

True once pending.

unsigned getDepth() const

Returns the depth of this node, which is the length of the maximum path up to any node which has no p...

bool isScheduled

True once scheduled.

bool isAvailable

True once available.

bool isScheduleLow

True if preferable to schedule low.

bool hasPhysRegDefs

Has physreg defs that are being used.

SmallVector< SDep, 4 > Succs

All sunit successors.

Sched::Preference SchedulingPref

Scheduling preference.

const TargetRegisterClass * CopySrcRC

SDNode * getNode() const

Returns the representative SDNode for this SUnit.

bool isTwoAddress

Is a two-address instruction.

bool isCommutable

Is a commutable instruction.

bool isVRegCycle

May use and def the same vreg.

SmallVector< SDep, 4 > Preds

All sunit predecessors.

LLVM_ABI bool addPred(const SDep &D, bool Required=true)

Adds the specified edge as a pred of the current node if not already.

RegDefIter - In place iteration over the values defined by an SUnit.

const SDNode * GetNode() const

ScheduleDAGSDNodes - A ScheduleDAG for scheduling SDNode-based DAGs.

This class can compute a topological ordering for SUnits and provides methods for dynamically updatin...

void MarkDirty()

Mark the ordering as temporarily broken, after a new node has been added.

virtual void dumpNode(const SUnit &SU) const =0

HazardRecognizer - This determines whether or not an instruction can be issued this cycle,...

unsigned getMaxLookAhead() const

virtual void RecedeCycle()

RecedeCycle - This callback is invoked whenever the next bottom-up instruction to be scheduled cannot...

virtual void Reset()

Reset - This callback is invoked when a new block of instructions is about to be schedule.

virtual void EmitInstruction(SUnit *)

EmitInstruction - This callback is invoked when an instruction is emitted, to advance the hazard stat...

virtual bool atIssueLimit() const

atIssueLimit - Return true if no more instructions may be issued in this cycle.

virtual HazardType getHazardType(SUnit *, int Stalls=0)

getHazardType - Return the hazard type of emitting this node.

This interface is used to plug different priorities computation algorithms into the list scheduler.

void setCurCycle(unsigned Cycle)

virtual void remove(SUnit *SU)=0

virtual void releaseState()=0

virtual void scheduledNode(SUnit *)

As each node is scheduled, this method is invoked.

virtual bool tracksRegPressure() const

virtual void dump(ScheduleDAG *) const

bool hasReadyFilter() const

virtual void initNodes(std::vector< SUnit > &SUnits)=0

virtual bool empty() const =0

virtual void unscheduledNode(SUnit *)

virtual void addNode(const SUnit *SU)=0

virtual void updateNode(const SUnit *SU)=0

virtual void push(SUnit *U)=0

SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...

const TargetLowering * TLI

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

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...

reference emplace_back(ArgTypes &&... Args)

void push_back(const T &Elt)

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

TargetInstrInfo - Interface to description of machine instruction set.

virtual bool canCopyGluedNodeDuringSchedule(SDNode *N) const

Return true if the given SDNode can be copied during scheduling even if it has glue.

unsigned getCallFrameSetupOpcode() const

These methods return the opcode of the frame setup/destroy instructions if they exist (-1 otherwise).

virtual bool unfoldMemoryOperand(MachineFunction &MF, MachineInstr &MI, Register Reg, bool UnfoldLoad, bool UnfoldStore, SmallVectorImpl< MachineInstr * > &NewMIs) const

unfoldMemoryOperand - Separate a single instruction which folded a load or a store or a load and a st...

unsigned getCallFrameDestroyOpcode() const

virtual uint8_t getRepRegClassCostFor(MVT VT) const

Return the cost of the 'representative' register class for the specified value type.

virtual const TargetRegisterClass * getRepRegClassFor(MVT VT) const

Return the 'representative' register class for the specified value type.

This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...

unsigned getID() const

Return the register class ID number.

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

virtual unsigned getRegPressureLimit(const TargetRegisterClass *RC, MachineFunction &MF) const

Return the register pressure "high water mark" for the specific register class.

TargetSubtargetInfo - Generic base class for all target subtargets.

virtual const TargetInstrInfo * getInstrInfo() const

virtual const TargetRegisterInfo * getRegisterInfo() const =0

Return the target's register information.

#define llvm_unreachable(msg)

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

@ MERGE_VALUES

MERGE_VALUES - This node takes multiple discrete operands and returns them all as its individual resu...

@ CopyFromReg

CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...

@ EntryToken

EntryToken - This is the marker used to indicate the start of a region.

@ CopyToReg

CopyToReg - This node has three operands: a chain, a register number to set to this value,...

@ TokenFactor

TokenFactor - This node takes multiple tokens as input and produces a single token result.

initializer< Ty > init(const Ty &Val)

Sequence

A sequence of states that a pointer may go through in which an objc_retain and objc_release are actua...

NodeAddr< DefNode * > Def

NodeAddr< NodeBase * > Node

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

Remove path.

This is an optimization pass for GlobalISel generic memory operations.

void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)

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

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

void fill(R &&Range, T &&Value)

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

LLVM_ABI ScheduleDAGSDNodes * createBURRListDAGScheduler(SelectionDAGISel *IS, CodeGenOptLevel OptLevel)

createBURRListDAGScheduler - This creates a bottom up register usage reduction list scheduler.

Definition ScheduleDAGRRList.cpp:3145

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

LLVM_ABI ScheduleDAGSDNodes * createHybridListDAGScheduler(SelectionDAGISel *IS, CodeGenOptLevel)

createHybridListDAGScheduler - This creates a bottom up register pressure aware list scheduler that m...

Definition ScheduleDAGRRList.cpp:3173

LLVM_ABI raw_ostream & dbgs()

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

LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)

CodeGenOptLevel

Code generation optimization level.

class LLVM_GSL_OWNER SmallVector

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

LLVM_ABI ScheduleDAGSDNodes * createSourceListDAGScheduler(SelectionDAGISel *IS, CodeGenOptLevel OptLevel)

createSourceListDAGScheduler - This creates a bottom up list scheduler that schedules nodes in source...

Definition ScheduleDAGRRList.cpp:3159

uint16_t MCPhysReg

An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...

DWARFExpression::Operation Op

ArrayRef(const T &OneElt) -> ArrayRef< T >

LLVM_ABI ScheduleDAGSDNodes * createILPListDAGScheduler(SelectionDAGISel *IS, CodeGenOptLevel)

createILPListDAGScheduler - This creates a bottom up register pressure aware list scheduler that trie...

Definition ScheduleDAGRRList.cpp:3188

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

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.

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

Implement std::swap in terms of BitVector swap.