LLVM: lib/Target/SystemZ/SystemZHazardRecognizer.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

32

33using namespace llvm;

34

35#define DEBUG_TYPE "machine-scheduler"

36

37

38

39

41 cl::desc("The OOO window for processor "

42 "resources during scheduling."),

44

45unsigned SystemZHazardRecognizer::

46getNumDecoderSlots(SUnit *SU) const {

48 if (!SC->isValid())

49 return 0;

50

51 assert((SC->NumMicroOps != 2 || (SC->BeginGroup && !SC->EndGroup)) &&

52 "Only cracked instruction can have 2 uops.");

53 assert((SC->NumMicroOps < 3 || (SC->BeginGroup && SC->EndGroup)) &&

54 "Expanded instructions always group alone.");

55 assert((SC->NumMicroOps < 3 || (SC->NumMicroOps % 3 == 0)) &&

56 "Expanded instructions fill the group(s).");

57

58 return SC->NumMicroOps;

59}

60

61unsigned SystemZHazardRecognizer::getCurrCycleIdx(SUnit *SU) const {

62 unsigned Idx = CurrGroupSize;

63 if (GrpCount % 2)

65

66 if (SU != nullptr && !fitsIntoCurrentGroup(SU)) {

67 if (Idx == 1 || Idx == 2)

69 else if (Idx == 4 || Idx == 5)

71 }

72

73 return Idx;

74}

75

78 return (fitsIntoCurrentGroup(SU) ? NoHazard : Hazard);

79}

80

82 CurrGroupSize = 0;

83 CurrGroupHas4RegOps = false;

84 clearProcResCounters();

85 GrpCount = 0;

86 LastFPdOpCycleIdx = UINT_MAX;

87 LastEmittedMI = nullptr;

89}

90

91bool

92SystemZHazardRecognizer::fitsIntoCurrentGroup(SUnit *SU) const {

94 if (!SC->isValid())

95 return true;

96

97

98

99 if (SC->BeginGroup)

100 return (CurrGroupSize == 0);

101

102

103 assert ((CurrGroupSize < 2 || !CurrGroupHas4RegOps) &&

104 "Current decoder group is already full!");

105 if (CurrGroupSize == 2 && has4RegOps(SU->getInstr()))

106 return false;

107

108

109

110

111 assert ((getNumDecoderSlots(SU) <= 1) && (CurrGroupSize < 3) &&

112 "Expected normal instruction to fit in non-full group!");

113

114 return true;

115}

116

117bool SystemZHazardRecognizer::has4RegOps(const MachineInstr *MI) const {

121 unsigned Count = 0;

122 for (unsigned OpIdx = 0; OpIdx < MID.getNumOperands(); OpIdx++) {

124 if (RC == nullptr)

125 continue;

128 continue;

129 Count++;

130 }

131 return Count >= 4;

132}

133

134void SystemZHazardRecognizer::nextGroup() {

135 if (CurrGroupSize == 0)

136 return;

137

140

141 int NumGroups = ((CurrGroupSize > 3) ? (CurrGroupSize / 3) : 1);

142 assert((CurrGroupSize <= 3 || CurrGroupSize % 3 == 0) &&

143 "Current decoder group bad.");

144

145

146 CurrGroupSize = 0;

147 CurrGroupHas4RegOps = false;

148

149 GrpCount += ((unsigned) NumGroups);

150

151

153 ProcResourceCounters[i] = ((ProcResourceCounters[i] > NumGroups)

154 ? (ProcResourceCounters[i] - NumGroups)

155 : 0);

156

157

158 if (CriticalResourceIdx != UINT_MAX &&

159 (ProcResourceCounters[CriticalResourceIdx] <=

161 CriticalResourceIdx = UINT_MAX;

162

164}

165

166#ifndef NDEBUG

168 OS << "SU(" << SU->NodeNum << "):";

170

172 if (!SC->isValid())

173 return;

174

180 std::string FU(PRD.Name);

181

182 FU = FU.substr(FU.find('_') + 1);

183 size_t Pos = FU.find("Unit");

184 if (Pos != std:🧵:npos)

185 FU.resize(Pos);

186 if (FU == "LS")

187 FU = "LSU";

188 OS << "/" << FU;

189

190 if (PI->ReleaseAtCycle> 1)

191 OS << "(" << PI->ReleaseAtCycle << "cyc)";

192 }

193

194 if (SC->NumMicroOps > 1)

195 OS << "/" << SC->NumMicroOps << "uops";

196 if (SC->BeginGroup && SC->EndGroup)

197 OS << "/GroupsAlone";

198 else if (SC->BeginGroup)

199 OS << "/BeginsGroup";

200 else if (SC->EndGroup)

201 OS << "/EndsGroup";

203 OS << "/Unbuffered";

204 if (has4RegOps(SU->getInstr()))

205 OS << "/4RegOps";

206}

207

209 dbgs() << "++ " << Msg;

210 dbgs() << ": ";

211

213 dbgs() << " \n";

214 else {

216 dbgs() << " (" << CurrGroupSize << " decoder slot"

217 << (CurrGroupSize > 1 ? "s":"")

218 << (CurrGroupHas4RegOps ? ", 4RegOps" : "")

219 << ")\n";

220 }

221}

222

224 bool any = false;

225

227 if (ProcResourceCounters[i] > 0) {

228 any = true;

229 break;

230 }

231

232 if (!any)

233 return;

234

235 dbgs() << "++ | Resource counters: ";

237 if (ProcResourceCounters[i] > 0)

239 << ":" << ProcResourceCounters[i] << " ";

240 dbgs() << "\n";

241

242 if (CriticalResourceIdx != UINT_MAX)

243 dbgs() << "++ | Critical resource: "

245 << "\n";

246}

247

250 dbgs() << "++ | Current cycle index: "

251 << getCurrCycleIdx() << "\n";

253 if (LastFPdOpCycleIdx != UINT_MAX)

254 dbgs() << "++ | Last FPd cycle index: " << LastFPdOpCycleIdx << "\n";

255}

256

257#endif

258

259void SystemZHazardRecognizer::clearProcResCounters() {

261 CriticalResourceIdx = UINT_MAX;

262}

263

265 return (MI->isBranch() || MI->isReturn() ||

266 MI->getOpcode() == SystemZ::CondTrap);

267}

268

269

274 dbgs() << "\n";);

276

277

278

279 if (!fitsIntoCurrentGroup(SU))

280 nextGroup();

281

284

285 LastEmittedMI = SU->getInstr();

286

287

289 LLVM_DEBUG(dbgs() << "++ Clearing state after call.\n";);

291 LastEmittedMI = SU->getInstr();

292 return;

293 }

294

295

299

301 continue;

302 int &CurrCounter =

303 ProcResourceCounters[PI->ProcResourceIdx];

304 CurrCounter += PI->ReleaseAtCycle;

305

307 (CriticalResourceIdx == UINT_MAX ||

308 (PI->ProcResourceIdx != CriticalResourceIdx &&

309 CurrCounter >

310 ProcResourceCounters[CriticalResourceIdx]))) {

312 dbgs() << "++ New critical resource: "

314 << "\n";);

315 CriticalResourceIdx = PI->ProcResourceIdx;

316 }

317 }

318

319

321 LastFPdOpCycleIdx = getCurrCycleIdx(SU);

322 LLVM_DEBUG(dbgs() << "++ Last FPd cycle index: " << LastFPdOpCycleIdx

323 << "\n";);

324 }

325

326

327

328 CurrGroupSize += getNumDecoderSlots(SU);

329 CurrGroupHas4RegOps |= has4RegOps(SU->getInstr());

330 unsigned GroupLim = (CurrGroupHas4RegOps ? 2 : 3);

331 assert((CurrGroupSize <= GroupLim || CurrGroupSize == getNumDecoderSlots(SU))

332 && "SU does not fit into decoder group!");

333

334

335

336 if (CurrGroupSize >= GroupLim || SC->EndGroup)

337 nextGroup();

338}

339

342 if (!SC->isValid())

343 return 0;

344

345

346

347 if (SC->BeginGroup) {

348 if (CurrGroupSize)

349 return 3 - CurrGroupSize;

350 return -1;

351 }

352

353

354

355 if (SC->EndGroup) {

356 unsigned resultingGroupSize =

357 (CurrGroupSize + getNumDecoderSlots(SU));

358 if (resultingGroupSize < 3)

359 return (3 - resultingGroupSize);

360 return -1;

361 }

362

363

364 if (CurrGroupSize == 2 && has4RegOps(SU->getInstr()))

365 return 1;

366

367

368 return 0;

369}

370

371bool SystemZHazardRecognizer::isFPdOpPreferred_distance(SUnit *SU) const {

373

374 if (LastFPdOpCycleIdx == UINT_MAX)

375 return true;

376

377

378

379

380 unsigned SUCycleIdx = getCurrCycleIdx(SU);

381 if (LastFPdOpCycleIdx > SUCycleIdx)

382 return ((LastFPdOpCycleIdx - SUCycleIdx) == 3);

383 return ((SUCycleIdx - LastFPdOpCycleIdx) == 3);

384}

385

388 int Cost = 0;

389

391 if (!SC->isValid())

392 return 0;

393

394

395

397 Cost = (isFPdOpPreferred_distance(SU) ? INT_MIN : INT_MAX);

398

399 else if (CriticalResourceIdx != UINT_MAX) {

403 if (PI->ProcResourceIdx == CriticalResourceIdx)

404 Cost = PI->ReleaseAtCycle;

405 }

406

408}

409

411 bool TakenBranch) {

412

414

415

417

423 case 0:

425 break;

426 case 1:

428 break;

429 default:

430 break;

431 }

432 }

433

434 unsigned GroupSizeBeforeEmit = CurrGroupSize;

436

438

439 if (GroupSizeBeforeEmit == 1)

440 nextGroup();

441 }

442

443 if (TakenBranch && CurrGroupSize > 0)

444 nextGroup();

445

447 "Scheduler: unhandled terminator!");

448}

449

452

453 CurrGroupSize = Incoming->CurrGroupSize;

455

456

457 ProcResourceCounters = Incoming->ProcResourceCounters;

458 CriticalResourceIdx = Incoming->CriticalResourceIdx;

459

460

461 LastFPdOpCycleIdx = Incoming->LastFPdOpCycleIdx;

462 GrpCount = Incoming->GrpCount;

463}

Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx

unsigned const TargetRegisterInfo * TRI

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

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

static bool isBranchRetTrap(MachineInstr *MI)

static cl::opt< int > ProcResCostLim("procres-cost-lim", cl::Hidden, cl::desc("The OOO window for processor " "resources during scheduling."), cl::init(8))

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.

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.

Representation of each machine instruction.

unsigned getOpcode() const

Returns the opcode of this MachineInstr.

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

bool isCall

Is a function call.

unsigned NodeNum

Entry # of node in the node vector.

bool isUnbuffered

Uses an unbuffered resource.

bool hasReservedResource

Uses a reserved resource.

MachineInstr * getInstr() const

Returns the representative MachineInstr for this SUnit.

void assign(size_type NumElts, ValueParamT Elt)

SystemZHazardRecognizer maintains the state for one MBB during scheduling.

int groupingCost(SUnit *SU) const

Return the cost of decoder grouping for SU.

void dumpProcResourceCounters() const

void emitInstruction(MachineInstr *MI, bool TakenBranch=false)

Wrap a non-scheduled instruction in an SU and emit it.

const MCSchedClassDesc * getSchedClass(SUnit *SU) const

Resolves and cache a resolved scheduling class for an SUnit.

void copyState(SystemZHazardRecognizer *Incoming)

Copy counters from end of single predecessor.

void Reset() override

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

void dumpSU(SUnit *SU, raw_ostream &OS) const

HazardType getHazardType(SUnit *SU, int Stalls=0) override

getHazardType - Return the hazard type of emitting this node.

void dumpCurrGroup(std::string Msg="") const

int resourcesCost(SUnit *SU)

Return the cost of SU in regards to processor resources usage.

void EmitInstruction(SUnit *SU) override

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

const SystemZRegisterInfo & getRegisterInfo() const

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

ProcResIter getWriteProcResEnd(const MCSchedClassDesc *SC) const

const MCSchedClassDesc * resolveSchedClass(const MachineInstr *MI) const

Return the MCSchedClassDesc for this instruction.

const MCProcResourceDesc * getProcResource(unsigned PIdx) const

Get a processor resource by ID for convenience.

unsigned getNumProcResourceKinds() const

Get the number of kinds of resources for this target.

ProcResIter getWriteProcResBegin(const MCSchedClassDesc *SC) const

This class implements an extremely fast bulk output stream that can only output to a stream.

A raw_ostream that writes to an std::string.

initializer< Ty > init(const Ty &Val)

This is an optimization pass for GlobalISel generic memory operations.

iterator_range< T > make_range(T x, T y)

Convenience function for iterating over sub-ranges.

raw_ostream & dbgs()

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

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

Define a kind of processor resource that will be modeled by the scheduler.

Summarize the scheduling resources required for an instruction of a particular scheduling class.

Identify one of the processor resource kinds consumed by a particular scheduling class for the specif...