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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

34#include

35#include

36

37using namespace llvm;

38

39#define DEBUG_TYPE "post-RA-sched"

40

43 : MF(MFi), MRI(MF.getRegInfo()), TII(MF.getSubtarget().getInstrInfo()),

44 TRI(MF.getSubtarget().getRegisterInfo()), RegClassInfo(RCI),

45 Classes(TRI->getNumRegs(), nullptr), KillIndices(TRI->getNumRegs(), 0),

46 DefIndices(TRI->getNumRegs(), 0), KeepRegs(TRI->getNumRegs(), false) {}

47

49

51 const unsigned BBSize = BB->size();

52 for (unsigned i = 1, e = TRI->getNumRegs(); i != e; ++i) {

53

54 Classes[i] = nullptr;

55

56

57 KillIndices[i] = ~0u;

58 DefIndices[i] = BBSize;

59 }

60

61

62 KeepRegs.reset();

63

65

66

68 for (const auto &LI : Succ->liveins()) {

72 KillIndices[Reg.id()] = BBSize;

73 DefIndices[Reg.id()] = ~0u;

74 }

75 }

76

77

78

79

82 for (const MCPhysReg *I = MF.getRegInfo().getCalleeSavedRegs(); *I;

83 ++I) {

84 unsigned Reg = *I;

85 if (!IsReturnBlock && !Pristine.test(Reg))

86 continue;

90 KillIndices[Reg.id()] = BBSize;

91 DefIndices[Reg.id()] = ~0u;

92 }

93 }

94}

95

100

102 unsigned InsertPosIndex) {

103

104

105

106

107

108

109

110 if (MI.isDebugInstr() || MI.isKill())

111 return;

112 assert(Count < InsertPosIndex && "Instruction index out of expected range!");

113

114 for (unsigned Reg = 1; Reg != TRI->getNumRegs(); ++Reg) {

115 if (KillIndices[Reg] != ~0u) {

116

117

118

120 KillIndices[Reg] = Count;

121 } else if (DefIndices[Reg] < InsertPosIndex && DefIndices[Reg] >= Count) {

122

123

124

125

127

128

129

130 DefIndices[Reg] = InsertPosIndex;

131 }

132 }

133

134 PrescanInstruction(MI);

135 ScanInstruction(MI, Count);

136}

137

138

139

142 unsigned NextDepth = 0;

143

145 const SUnit *PredSU = P.getSUnit();

146 unsigned PredLatency = P.getLatency();

147 unsigned PredTotalLatency = PredSU->getDepth() + PredLatency;

148

149

150 if (NextDepth < PredTotalLatency ||

151 (NextDepth == PredTotalLatency && P.getKind() == SDep::Anti)) {

152 NextDepth = PredTotalLatency;

154 }

155 }

157}

158

159void CriticalAntiDepBreaker::PrescanInstruction(MachineInstr &MI) {

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176 bool Special =

177 MI.isCall() || MI.hasExtraSrcRegAllocReq() || TII->isPredicated(MI);

178

179

180

181 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {

182 MachineOperand &MO = MI.getOperand(i);

183 if (!MO.isReg()) continue;

185 if (Reg)

186 continue;

187 const TargetRegisterClass *NewRC = nullptr;

188

189 if (i < MI.getDesc().getNumOperands())

190 NewRC = TII->getRegClass(MI.getDesc(), i);

191

192

193

194 if (!Classes[Reg.id()] && NewRC)

195 Classes[Reg.id()] = NewRC;

196 else if (!NewRC || Classes[Reg.id()] != NewRC)

197 Classes[Reg.id()] = reinterpret_cast<TargetRegisterClass *>(-1);

198

199

200 for (MCRegAliasIterator AI(Reg, TRI, false); AI.isValid(); ++AI) {

201

202

203

204 unsigned AliasReg = (*AI).id();

205 if (Classes[AliasReg]) {

206 Classes[AliasReg] = reinterpret_cast<TargetRegisterClass *>(-1);

207 Classes[Reg.id()] = reinterpret_cast<TargetRegisterClass *>(-1);

208 }

209 }

210

211

212 if (Classes[Reg.id()] != reinterpret_cast<TargetRegisterClass *>(-1))

213 RegRefs.emplace(Reg, &MO);

214

215 if (MO.isUse() && Special) {

216 if (!KeepRegs.test(Reg.id())) {

218 KeepRegs.set(SubReg);

219 }

220 }

221 }

222

223 for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) {

224 const MachineOperand &MO = MI.getOperand(I);

225 if (!MO.isReg()) continue;

228 continue;

229

230

231

232

233

234

235

236

237

238

239 if (MI.isRegTiedToUseOperand(I) &&

240 Classes[Reg.id()] == reinterpret_cast<TargetRegisterClass *>(-1)) {

242 KeepRegs.set(SubReg);

243 }

244 for (MCPhysReg SuperReg : TRI->superregs(Reg)) {

245 KeepRegs.set(SuperReg);

246 }

247 }

248 }

249}

250

251void CriticalAntiDepBreaker::ScanInstruction(MachineInstr &MI, unsigned Count) {

252

253

254

255 assert(MI.isKill() && "Attempting to scan a kill instruction");

256

257 if (!TII->isPredicated(MI)) {

258

259

260 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {

261 MachineOperand &MO = MI.getOperand(i);

262

264 auto ClobbersPhysRegAndSubRegs = [&](unsigned PhysReg) {

265 return all_of(TRI->subregs_inclusive(PhysReg),

266 [&](MCPhysReg SR) { return MO.clobbersPhysReg(SR); });

267 };

268

269 for (unsigned i = 1, e = TRI->getNumRegs(); i != e; ++i) {

270 if (ClobbersPhysRegAndSubRegs(i)) {

271 DefIndices[i] = Count;

272 KillIndices[i] = ~0u;

273 KeepRegs.reset(i);

274 Classes[i] = nullptr;

275 RegRefs.erase(i);

276 }

277 }

278 }

279

280 if (!MO.isReg()) continue;

282 if (Reg)

283 continue;

284 if (!MO.isDef()) continue;

285

286

287 if (MI.isRegTiedToUseOperand(i))

288 continue;

289

290

291

292 bool Keep = KeepRegs.test(Reg.id());

293

294

295

296 for (MCPhysReg SubregReg : TRI->subregs_inclusive(Reg)) {

297 DefIndices[SubregReg] = Count;

298 KillIndices[SubregReg] = ~0u;

299 Classes[SubregReg] = nullptr;

300 RegRefs.erase(SubregReg);

302 KeepRegs.reset(SubregReg);

303 }

304

306 Classes[SR] = reinterpret_cast<TargetRegisterClass *>(-1);

307 }

308 }

309 for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {

310 MachineOperand &MO = MI.getOperand(i);

311 if (!MO.isReg()) continue;

313 if (Reg)

314 continue;

315 if (!MO.isUse()) continue;

316

317 const TargetRegisterClass *NewRC = nullptr;

318 if (i < MI.getDesc().getNumOperands())

319 NewRC = TII->getRegClass(MI.getDesc(), i);

320

321

322

323 if (!Classes[Reg.id()] && NewRC)

324 Classes[Reg.id()] = NewRC;

325 else if (!NewRC || Classes[Reg.id()] != NewRC)

326 Classes[Reg.id()] = reinterpret_cast<TargetRegisterClass *>(-1);

327

328 RegRefs.emplace(Reg, &MO);

329

330

331

332 for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) {

333 MCRegister AliasReg = *AI;

334 if (KillIndices[AliasReg.id()] == ~0u) {

335 KillIndices[AliasReg.id()] = Count;

336 DefIndices[AliasReg.id()] = ~0u;

337 }

338 }

339 }

340}

341

342

343

344

345

346

347

348

349

350

351

352

353bool CriticalAntiDepBreaker::isNewRegClobberedByRefs(RegRefIter RegRefBegin,

354 RegRefIter RegRefEnd,

356 for (RegRefIter I = RegRefBegin; I != RegRefEnd; ++I ) {

357 MachineOperand *RefOper = I->second;

358

359

360

361

363 return true;

364

365

367 for (const MachineOperand &CheckOper : MI->operands()) {

368 if (CheckOper.isRegMask() && CheckOper.clobbersPhysReg(NewReg))

369 return true;

370

371 if (!CheckOper.isReg() || !CheckOper.isDef() ||

372 CheckOper.getReg() != NewReg)

373 continue;

374

375

376

377 if (RefOper->isDef())

378 return true;

379

380

381

382 if (CheckOper.isEarlyClobber())

383 return true;

384

385

386

387 if (MI->isInlineAsm())

388 return true;

389 }

390 }

391 return false;

392}

393

394MCRegister CriticalAntiDepBreaker::findSuitableFreeRegister(

395 RegRefIter RegRefBegin, RegRefIter RegRefEnd, MCRegister AntiDepReg,

399 for (MCRegister NewReg : Order) {

400

401 if (NewReg == AntiDepReg) continue;

402

403

404

405 if (NewReg == LastNewReg) continue;

406

407

408

409 if (isNewRegClobberedByRefs(RegRefBegin, RegRefEnd, NewReg)) continue;

410

411

412 assert(((KillIndices[AntiDepReg.id()] == ~0u) !=

413 (DefIndices[AntiDepReg.id()] == ~0u)) &&

414 "Kill and Def maps aren't consistent for AntiDepReg!");

415 assert(((KillIndices[NewReg.id()] == ~0u) !=

416 (DefIndices[NewReg.id()] == ~0u)) &&

417 "Kill and Def maps aren't consistent for NewReg!");

418 if (KillIndices[NewReg.id()] != ~0u ||

419 Classes[NewReg.id()] == reinterpret_cast<TargetRegisterClass *>(-1) ||

420 KillIndices[AntiDepReg.id()] > DefIndices[NewReg.id()])

421 continue;

422

423 bool Forbidden = false;

425 if (TRI->regsOverlap(NewReg, R)) {

426 Forbidden = true;

427 break;

428 }

429 if (Forbidden) continue;

430 return NewReg;

431 }

432

433

434 return MCRegister();

435}

436

441 unsigned InsertPosIndex,

443

444

445 if (SUnits.empty()) return 0;

446

447

448

449

450

452

453

454 const SUnit *Max = nullptr;

455 for (const SUnit &SU : SUnits) {

456 MISUnitMap[SU.getInstr()] = &SU;

457 if (!Max || SU.getDepth() + SU.Latency > Max->getDepth() + Max->Latency)

458 Max = &SU;

459 }

460 assert(Max && "Failed to find bottom of the critical path");

461

462#ifndef NDEBUG

463 {

464 LLVM_DEBUG(dbgs() << "Critical path has total latency "

465 << (Max->getDepth() + Max->Latency) << "\n");

467 for (unsigned Reg = 1; Reg < TRI->getNumRegs(); ++Reg) {

468 if (KillIndices[Reg] == ~0u)

470 }

472 }

473#endif

474

475

476

477 const SUnit *CriticalPathSU = Max;

479

480

481

482

483

484

485

486

487

488

489

490

491

492

493

494

495

496

497

498

499

500

501

502

503

504

505

506

507

508

509

510

511

512

513

514

515

516

517

518

519

520

521 std::vector LastNewReg(TRI->getNumRegs(), MCRegister());

522

523

524

525

526 unsigned Broken = 0;

527 unsigned Count = InsertPosIndex - 1;

530

531

532

533

534

535

536

537 if (MI.isDebugInstr() || MI.isKill())

538 continue;

539

540

541

542

543

544

545

546

547

548

549

550

551

552

554 if (&MI == CriticalPathMI) {

556 const SUnit *NextSU = Edge->getSUnit();

557

558

560 AntiDepReg = Edge->getReg().asMCReg();

561 assert(AntiDepReg && "Anti-dependence on reg0?");

562 if (!MRI.isAllocatable(AntiDepReg))

563

565 else if (KeepRegs.test(AntiDepReg.id()))

566

567

569 else {

570

571

572

573

574

575

576

577

578 for (const SDep &P : CriticalPathSU->Preds)

579 if (P.getSUnit() == NextSU

580 ? (P.getKind() != SDep::Anti || P.getReg() != AntiDepReg)

582 P.getReg() == AntiDepReg)) {

584 break;

585 }

586 }

587 }

588 CriticalPathSU = NextSU;

589 CriticalPathMI = CriticalPathSU->getInstr();

590 } else {

591

592 CriticalPathSU = nullptr;

593 CriticalPathMI = nullptr;

594 }

595 }

596

597 PrescanInstruction(MI);

598

600

601

602

603

604 if (MI.isCall() || MI.hasExtraDefRegAllocReq() || TII->isPredicated(MI))

605

606

608 else if (AntiDepReg) {

609

610

611

612

614 if (!MO.isReg()) continue;

616 if (!Reg)

617 continue;

618 if (MO.isUse() && TRI->regsOverlap(AntiDepReg, Reg)) {

620 break;

621 }

622 if (MO.isDef() && Reg != AntiDepReg)

624 }

625 }

626

627

628

630 AntiDepReg ? Classes[AntiDepReg.id()] : nullptr;

631 assert((!AntiDepReg || RC != nullptr) &&

632 "Register should be live if it's causing an anti-dependence!");

635

636

637

638

639

640 if (AntiDepReg) {

641 std::pair<std::multimap<MCRegister, MachineOperand *>::iterator,

642 std::multimap<MCRegister, MachineOperand *>::iterator>

643 Range = RegRefs.equal_range(AntiDepReg);

644 if (MCRegister NewReg = findSuitableFreeRegister(

645 Range.first, Range.second, AntiDepReg,

646 LastNewReg[AntiDepReg.id()], RC, ForbidRegs)) {

647 LLVM_DEBUG(dbgs() << "Breaking anti-dependence edge on "

648 << printReg(AntiDepReg, TRI) << " with "

649 << RegRefs.count(AntiDepReg) << " references"

650 << " using " << printReg(NewReg, TRI) << "!\n");

651

652

653

654 for (std::multimap<MCRegister, MachineOperand *>::iterator

656 QE = Range.second;

657 Q != QE; ++Q) {

658 Q->second->setReg(NewReg);

659

660

661

662 const SUnit *SU = MISUnitMap[Q->second->getParent()];

663 if (!SU) continue;

665 AntiDepReg, NewReg);

666 }

667

668

669

670

671 Classes[NewReg.id()] = Classes[AntiDepReg.id()];

672 DefIndices[NewReg.id()] = DefIndices[AntiDepReg.id()];

673 KillIndices[NewReg.id()] = KillIndices[AntiDepReg.id()];

674 assert(((KillIndices[NewReg.id()] == ~0u) !=

675 (DefIndices[NewReg.id()] == ~0u)) &&

676 "Kill and Def maps aren't consistent for NewReg!");

677

678 Classes[AntiDepReg.id()] = nullptr;

679 DefIndices[AntiDepReg.id()] = KillIndices[AntiDepReg.id()];

680 KillIndices[AntiDepReg.id()] = ~0u;

681 assert(((KillIndices[AntiDepReg.id()] == ~0u) !=

682 (DefIndices[AntiDepReg.id()] == ~0u)) &&

683 "Kill and Def maps aren't consistent for AntiDepReg!");

684

685 RegRefs.erase(AntiDepReg);

686 LastNewReg[AntiDepReg.id()] = NewReg;

687 ++Broken;

688 }

689 }

690

691 ScanInstruction(MI, Count);

692 }

693

694 return Broken;

695}

696

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

static const SUnit * CriticalPathStep(const SUnit *SU)

CriticalPathStep - Return the next SUnit after SU on the bottom-up critical path.

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

This file defines the DenseMap class.

Promote Memory to Register

ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))

This file defines the SmallVector class.

This class works in conjunction with the post-RA scheduler to rename registers to break register anti...

void UpdateDbgValues(const DbgValueVector &DbgValues, MachineInstr *ParentMI, MCRegister OldReg, MCRegister NewReg)

Update all DBG_VALUE instructions that may be affected by the dependency breaker's update of ParentMI...

std::vector< std::pair< MachineInstr *, MachineInstr * > > DbgValueVector

bool test(unsigned Idx) const

void clear()

clear - Removes all bits from the bitvector.

~CriticalAntiDepBreaker() override

unsigned BreakAntiDependencies(const std::vector< SUnit > &SUnits, MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End, unsigned InsertPosIndex, DbgValueVector &DbgValues) override

Identifiy anti-dependencies along the critical path of the ScheduleDAG and break them by renaming reg...

Definition CriticalAntiDepBreaker.cpp:438

void FinishBlock() override

Finish anti-dep breaking for a basic block.

Definition CriticalAntiDepBreaker.cpp:96

void Observe(MachineInstr &MI, unsigned Count, unsigned InsertPosIndex) override

Update liveness information to account for the current instruction, which will not be scheduled.

Definition CriticalAntiDepBreaker.cpp:101

void StartBlock(MachineBasicBlock *BB) override

Initialize anti-dep breaking for a new basic block.

Definition CriticalAntiDepBreaker.cpp:50

CriticalAntiDepBreaker(MachineFunction &MFi, const RegisterClassInfo &RCI)

Definition CriticalAntiDepBreaker.cpp:41

MCRegAliasIterator enumerates all registers aliasing Reg.

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

constexpr unsigned id() const

bool isReturnBlock() const

Convenience function that returns true if the block ends in a return instruction.

iterator_range< succ_iterator > successors()

MachineInstrBundleIterator< MachineInstr > iterator

The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.

LLVM_ABI BitVector getPristineRegs(const MachineFunction &MF) const

Return a set of physical registers that are pristine.

Representation of each machine instruction.

MachineOperand class - Representation of each machine instruction operand.

bool isReg() const

isReg - Tests if this is a MO_Register operand.

bool isRegMask() const

isRegMask - Tests if this is a MO_RegisterMask operand.

MachineInstr * getParent()

getParent - Return the instruction that this operand belongs to.

bool isEarlyClobber() const

Register getReg() const

getReg - Returns the register number.

Wrapper class representing virtual and physical registers.

constexpr bool isValid() const

constexpr unsigned id() const

@ Anti

A register anti-dependence (aka WAR).

@ Data

Regular data dependence (aka true-dependence).

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

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

SmallVector< SDep, 4 > Preds

All sunit predecessors.

MachineInstr * getInstr() const

Returns the representative MachineInstr for this SUnit.

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.

This is an optimization pass for GlobalISel generic memory operations.

bool all_of(R &&range, UnaryPredicate P)

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

LLVM_ABI raw_ostream & dbgs()

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

FunctionAddr VTableAddr Count

uint16_t MCPhysReg

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

FunctionAddr VTableAddr Next

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

AntiDepBreaker * createCriticalAntiDepBreaker(MachineFunction &MFi, const RegisterClassInfo &RCI)

Definition CriticalAntiDepBreaker.cpp:698

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.

@ Keep

No function return thunk.