LLVM: lib/MCA/Stages/InOrderIssueStage.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

19

20#define DEBUG_TYPE "llvm-mca"

21namespace llvm {

22namespace mca {

23

29

35

38 return;

39

41 return;

42

44}

45

49 : STI(STI), PRF(PRF), RM(STI.getSchedModel()), CB(CB), LSU(LSU),

50 NumIssued(), CarryOver(), Bandwidth(), LastWriteBackCycle() {}

51

53 return STI.getSchedModel().IssueWidth;

54}

55

57 return !IssuedInst.empty() || SI.isValid() || CarriedOver;

58}

59

61 if (SI.isValid() || CarriedOver)

62 return false;

63

66

67 bool ShouldCarryOver = NumMicroOps > getIssueWidth();

68 if (Bandwidth < NumMicroOps && !ShouldCarryOver)

69 return false;

70

71

72

74 return false;

75

76 return true;

77}

78

80 if (RM.checkAvailability(IR.getInstruction()->getDesc())) {

82 return true;

83 }

84

85 return false;

86}

87

89 unsigned FirstWBCycle = IR.getInstruction()->getLatency();

90 for (const WriteState &WS : IR.getInstruction()->getDefs()) {

91 int CyclesLeft = WS.getCyclesLeft();

93 CyclesLeft = WS.getLatency();

94 if (CyclesLeft < 0)

95 CyclesLeft = 0;

96 FirstWBCycle = std::min(FirstWBCycle, (unsigned)CyclesLeft);

97 }

98 return FirstWBCycle;

99}

100

101

102

106 for (const ReadState &RS : IR.getInstruction()->getUses()) {

110 }

111

112 return 0;

113}

114

115bool InOrderIssueStage::canExecute(const InstRef &IR) {

116 assert(SI.getCyclesLeft() && "Should not have reached this code!");

117 assert(SI.isValid() && "Should not have reached this code!");

118

121 return false;

122 }

123

126 return false;

127 }

128

129 if (IR.getInstruction()->isMemOp() && !LSU.isReady(IR)) {

130

131

133 return false;

134 }

135

136 if (unsigned CustomStallCycles = CB.checkCustomHazard(IssuedInst, IR)) {

138 return false;

139 }

140

141 if (LastWriteBackCycle) {

142 if (IR.getInstruction()->getRetireOOO()) {

144

145 if (NextWriteBackCycle < LastWriteBackCycle) {

146 SI.update(IR, LastWriteBackCycle - NextWriteBackCycle,

148 return false;

149 }

150 }

151 }

152

153 return true;

154}

155

157 unsigned SourceIndex,

161

164

167}

168

169void InOrderIssueStage::notifyInstructionIssued(const InstRef &IR,

174

176}

177

178void InOrderIssueStage::notifyInstructionDispatched(

179 const InstRef &IR, unsigned Ops, ArrayRef UsedRegs) {

181 HWInstructionDispatchedEvent(IR, UsedRegs, Ops));

182

184}

185

186void InOrderIssueStage::notifyInstructionExecuted(const InstRef &IR) {

189 LLVM_DEBUG(dbgs() << "[E] Instruction #" << IR << " is executed\n");

190}

191

192void InOrderIssueStage::notifyInstructionRetired(const InstRef &IR,

193 ArrayRef FreedRegs) {

196}

197

202

204 return E;

205

206 if (SI.isValid())

207 notifyStallEvent();

208

210}

211

214 unsigned SourceIndex = IR.getSourceIndex();

216

217 if (!canExecute(IR)) {

218 LLVM_DEBUG(dbgs() << "[N] Stalled #" << SI.getInstruction() << " for "

219 << SI.getCyclesLeft() << " cycles\n");

220 Bandwidth = 0;

222 }

223

226

229

231 notifyInstructionDispatched(IR, NumMicroOps, UsedRegs);

232

234 RM.issueInstruction(Desc, UsedResources);

236

239

240

243 Use.first.first = RM.resolveResourceMask(Mask);

244 }

245 notifyInstructionIssued(IR, UsedResources);

246

247 bool ShouldCarryOver = NumMicroOps > Bandwidth;

248 if (ShouldCarryOver) {

249 CarryOver = NumMicroOps - Bandwidth;

250 CarriedOver = IR;

251 Bandwidth = 0;

252 NumIssued += Bandwidth;

254 } else {

255 NumIssued += NumMicroOps;

256 Bandwidth = IS.getEndGroup() ? 0 : Bandwidth - NumMicroOps;

257 }

258

259

260

261

262

263 if (IS.isExecuted() && !ShouldCarryOver) {

264 PRF.onInstructionExecuted(&IS);

265 LSU.onInstructionExecuted(IR);

266 notifyInstructionExecuted(IR);

267

268 retireInstruction(IR);

269 return llvm::ErrorSuccess();

270 }

271

272 IssuedInst.push_back(IR);

273

274 if (IR.getInstruction()->getRetireOOO())

276

277 return llvm::ErrorSuccess();

278}

279

280void InOrderIssueStage::updateIssuedInst() {

281

282

283 unsigned NumExecuted = 0;

284 for (auto I = IssuedInst.begin(), E = IssuedInst.end();

285 I != (E - NumExecuted);) {

286 InstRef &IR = *I;

288

290 if (!IS.isExecuted()) {

292 << " is still executing\n");

293 ++I;

294 continue;

295 }

296

297

298

299

300 if (!CarriedOver) {

301 PRF.onInstructionExecuted(&IS);

302 LSU.onInstructionExecuted(IR);

303 notifyInstructionExecuted(IR);

304

305 retireInstruction(*I);

306 }

307

308 ++NumExecuted;

309

310 std::iter_swap(I, E - NumExecuted);

311 }

312

313 if (NumExecuted)

314 IssuedInst.resize(IssuedInst.size() - NumExecuted);

315}

316

317void InOrderIssueStage::updateCarriedOver() {

318 if (!CarriedOver)

319 return;

320

321 assert(!SI.isValid() && "A stalled instruction cannot be carried over.");

322

323 if (CarryOver > Bandwidth) {

324 CarryOver -= Bandwidth;

325 Bandwidth = 0;

326 LLVM_DEBUG(dbgs() << "[N] Carry over (" << CarryOver << "uops left) #"

327 << CarriedOver << " \n");

328 return;

329 }

330

331 LLVM_DEBUG(dbgs() << "[N] Carry over (complete) #" << CarriedOver << " \n");

332

333 if (CarriedOver.getInstruction()->getEndGroup())

334 Bandwidth = 0;

335 else

336 Bandwidth -= CarryOver;

337

338

339

340 if (CarriedOver.getInstruction()->isExecuted()) {

341 PRF.onInstructionExecuted(CarriedOver.getInstruction());

342 LSU.onInstructionExecuted(CarriedOver);

343 notifyInstructionExecuted(CarriedOver);

344

345 retireInstruction(CarriedOver);

346 }

347

348 CarriedOver = InstRef();

349 CarryOver = 0;

350}

351

352void InOrderIssueStage::retireInstruction(InstRef &IR) {

354 IS.retire();

355

356 llvm::SmallVector<unsigned, 4> FreedRegs(PRF.getNumRegisterFiles());

357 for (const WriteState &WS : IS.getDefs())

358 PRF.removeRegisterWrite(WS, FreedRegs);

359

360 if (IS.isMemOp())

361 LSU.onInstructionRetired(IR);

362

363 notifyInstructionRetired(IR, FreedRegs);

364}

365

366void InOrderIssueStage::notifyStallEvent() {

367 assert(SI.getCyclesLeft() && "A zero cycles stall?");

368 assert(SI.isValid() && "Invalid stall information found!");

369

370 const InstRef &IR = SI.getInstruction();

371

372 switch (SI.getStallKind()) {

373 default:

374 break;

380 break;

381 }

387 break;

388 }

392 break;

393 }

394 }

395}

396

398 NumIssued = 0;

400

401 PRF.cycleStart();

402 LSU.cycleEvent();

403

404

406 RM.cycleEvent(Freed);

407

408 updateIssuedInst();

409

410

411 updateCarriedOver();

412

413

414 if (SI.isValid()) {

415 if (!SI.getCyclesLeft()) {

416

417

418

419 InstRef IR = SI.getInstruction();

420 SI.clear();

421

423 return E;

424 }

425

426 if (SI.getCyclesLeft()) {

427

428

429 notifyStallEvent();

430 Bandwidth = 0;

432 }

433 }

434

437}

438

440 PRF.cycleEnd();

441 SI.cycleEnd();

442

443 if (LastWriteBackCycle > 0)

444 --LastWriteBackCycle;

445

447}

448

449}

450}

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

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

InOrderIssueStage implements an in-order execution pipeline.

const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]

A Load/Store unit class that models load/store queues and that implements a simple weak memory consis...

Legalize the Machine IR a function s Machine IR

This file defines abstractions used by the Pipeline to model register reads, register writes and inst...

StandardInstrumentations SI(Mod->getContext(), Debug, VerifyEach)

This file defines a register mapping file class.

This file simulates the hardware responsible for retiring instructions.

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

Subclass of Error for the sole purpose of identifying the success path in the type system.

Lightweight error class with error context and mandatory checking.

Generic base class for all target subtargets.

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

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

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

Class which can be overriden by targets to enforce instruction dependencies and behaviours that aren'...

bool hasWorkToComplete() const override

Returns true if some instructions are still executing this stage.

Definition InOrderIssueStage.cpp:56

Error cycleEnd() override

Called once at the end of each cycle.

Definition InOrderIssueStage.cpp:439

Error execute(InstRef &IR) override

The primary action that this stage performs on instruction IR.

Definition InOrderIssueStage.cpp:198

bool isAvailable(const InstRef &) const override

Returns true if it can execute IR during this cycle.

Definition InOrderIssueStage.cpp:60

unsigned getIssueWidth() const

Definition InOrderIssueStage.cpp:52

Error cycleStart() override

Called once at the start of each cycle.

Definition InOrderIssueStage.cpp:397

An InstRef contains both a SourceMgr index and Instruction pair.

unsigned getNumMicroOps() const

const InstrDesc & getDesc() const

SmallVectorImpl< WriteState > & getDefs()

SmallVectorImpl< ReadState > & getUses()

bool getBeginGroup() const

An instruction propagated through the simulated instruction pipeline.

LLVM_ABI void cycleEvent()

bool isEliminated() const

int getCyclesLeft() const

LLVM_ABI void execute(unsigned IID)

void setLSUTokenID(unsigned LSUTok)

LLVM_ABI void dispatch(unsigned RCUTokenID)

Abstract base interface for LS (load/store) units in llvm-mca.

virtual void onInstructionIssued(const InstRef &IR)=0

Tracks register operand latency in cycles.

Manages hardware register files, and tracks register definitions for register renaming purposes.

void addRegisterWrite(WriteRef Write, MutableArrayRef< unsigned > UsedPhysRegs)

unsigned getNumRegisterFiles() const

RAWHazard checkRAWHazards(const MCSubtargetInfo &STI, const ReadState &RS) const

void addRegisterRead(ReadState &RS, const MCSubtargetInfo &STI) const

void notifyEvent(const EventT &Event) const

Notify listeners of a particular hardware event.

A reference to a register write.

Tracks uses of a register definition (e.g.

static void addRegisterReadWrite(RegisterFile &PRF, Instruction &IS, unsigned SourceIndex, const MCSubtargetInfo &STI, SmallVectorImpl< unsigned > &UsedRegs)

Definition InOrderIssueStage.cpp:156

static bool hasResourceHazard(const ResourceManager &RM, const InstRef &IR)

Definition InOrderIssueStage.cpp:79

static unsigned findFirstWriteBackCycle(const InstRef &IR)

Definition InOrderIssueStage.cpp:88

std::pair< ResourceRef, ReleaseAtCycles > ResourceUse

static unsigned checkRegisterHazard(const RegisterFile &PRF, const MCSubtargetInfo &STI, const InstRef &IR)

Return a number of cycles left until register requirements of the instructions are met.

Definition InOrderIssueStage.cpp:103

constexpr int UNKNOWN_CYCLES

friend class Instruction

Iterator for Instructions in a `BasicBlock.

This is an optimization pass for GlobalISel generic memory operations.

LLVM_ABI raw_ostream & dbgs()

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

An instruction descriptor.

bool hasUnknownCycles() const

static const unsigned UnhandledTokenID

void clear()

Definition InOrderIssueStage.cpp:24

void cycleEnd()

Definition InOrderIssueStage.cpp:36

void update(const InstRef &Inst, unsigned Cycles, StallKind SK)

Definition InOrderIssueStage.cpp:30