LLVM: lib/Target/AMDGPU/R600Packetizer.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

23

24using namespace llvm;

25

26#define DEBUG_TYPE "packets"

27

28namespace {

29

31

32public:

33 static char ID;

35

36 void getAnalysisUsage(AnalysisUsage &AU) const override {

43 }

44

45 StringRef getPassName() const override { return "R600 Packetizer"; }

46

48};

49

51private:

54 bool VLIW5;

55 bool ConsideredInstUsesAlreadyWrittenVectorElement;

56

58 return TRI.getHWRegChan(MI.getOperand(0).getReg());

59 }

60

61

62

64 const {

66 I--;

67 if (TII->isALUInstr(I->getOpcode()) && I->isBundle())

68 return Result;

70 if (I->isBundle())

71 BI++;

72 int LastDstChan = -1;

73 do {

74 bool isTrans = false;

75 int BISlot = getSlot(*BI);

76 if (LastDstChan >= BISlot)

77 isTrans = true;

78 LastDstChan = BISlot;

79 if (TII->isPredicated(*BI))

80 continue;

81 int OperandIdx = TII->getOperandIdx(BI->getOpcode(), R600::OpName::write);

82 if (OperandIdx > -1 && BI->getOperand(OperandIdx).getImm() == 0)

83 continue;

84 int DstIdx = TII->getOperandIdx(BI->getOpcode(), R600::OpName::dst);

85 if (DstIdx == -1) {

86 continue;

87 }

88 Register Dst = BI->getOperand(DstIdx).getReg();

89 if (isTrans || TII->isTransOnly(*BI)) {

90 Result[Dst] = R600::PS;

91 continue;

92 }

93 if (BI->getOpcode() == R600::DOT4_r600 ||

94 BI->getOpcode() == R600::DOT4_eg) {

95 Result[Dst] = R600::PV_X;

96 continue;

97 }

98 if (Dst == R600::OQAP) {

99 continue;

100 }

101 unsigned PVReg = 0;

102 switch (TRI.getHWRegChan(Dst)) {

103 case 0:

104 PVReg = R600::PV_X;

105 break;

106 case 1:

107 PVReg = R600::PV_Y;

108 break;

109 case 2:

110 PVReg = R600::PV_Z;

111 break;

112 case 3:

113 PVReg = R600::PV_W;

114 break;

115 default:

117 }

118 Result[Dst] = PVReg;

119 } while ((++BI)->isBundledWithPred());

120 return Result;

121 }

122

124 const {

125 const R600::OpName Ops[] = {R600::OpName::src0, R600::OpName::src1,

126 R600::OpName::src2};

127 for (R600::OpName Op : Ops) {

128 int OperandIdx = TII->getOperandIdx(MI.getOpcode(), Op);

129 if (OperandIdx < 0)

130 continue;

131 Register Src = MI.getOperand(OperandIdx).getReg();

133 if (It != PVs.end())

134 MI.getOperand(OperandIdx).setReg(It->second);

135 }

136 }

137public:

138

142 TII(ST.getInstrInfo()),

143 TRI(TII->getRegisterInfo()) {

144 VLIW5 = !ST.hasCaymanISA();

145 }

146

147

148 void initPacketizerState() override {

149 ConsideredInstUsesAlreadyWrittenVectorElement = false;

150 }

151

152

155 return false;

156 }

157

158

159

160 bool isSoloInstruction(const MachineInstr &MI) override {

161 if (TII->isVector(MI))

162 return true;

163 if (TII->isALUInstr(MI.getOpcode()))

164 return true;

165 if (MI.getOpcode() == R600::GROUP_BARRIER)

166 return true;

167

168

169 return TII->isLDSInstr(MI.getOpcode());

170 }

171

172

173

174 bool isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ) override {

176 if (getSlot(*MII) == getSlot(*MIJ))

177 ConsideredInstUsesAlreadyWrittenVectorElement = true;

178

179 int OpI = TII->getOperandIdx(MII->getOpcode(), R600::OpName::pred_sel),

180 OpJ = TII->getOperandIdx(MIJ->getOpcode(), R600::OpName::pred_sel);

182 PredJ = (OpJ > -1)?MIJ->getOperand(OpJ).getReg() : Register();

183 if (PredI != PredJ)

184 return false;

185 if (SUJ->isSucc(SUI)) {

186 for (const SDep &Dep : SUJ->Succs) {

188 continue;

190 continue;

192 if (MII->getOperand(0).getReg() != MIJ->getOperand(0).getReg())

193 continue;

194 return false;

195 }

196 }

197

198 bool ARDef =

199 TII->definesAddressRegister(*MII) || TII->definesAddressRegister(*MIJ);

200 bool ARUse =

201 TII->usesAddressRegister(*MII) || TII->usesAddressRegister(*MIJ);

202

203 return !ARDef || !ARUse;

204 }

205

206

207

208 bool isLegalToPruneDependencies(SUnit *SUI, SUnit *SUJ) override {

209 return false;

210 }

211

212 void setIsLastBit(MachineInstr *MI, unsigned Bit) const {

213 unsigned LastOp = TII->getOperandIdx(MI->getOpcode(), R600::OpName::last);

214 MI->getOperand(LastOp).setImm(Bit);

215 }

216

219 std::vectorR600InstrInfo::BankSwizzle &BS,

220 bool &isTransSlot) {

221 isTransSlot = TII->isTransOnly(MI);

222 assert (!isTransSlot || VLIW5);

223

224

225 if (!isTransSlot && !CurrentPacketMIs.empty()) {

226 if (getSlot(MI) <= getSlot(*CurrentPacketMIs.back())) {

227 if (ConsideredInstUsesAlreadyWrittenVectorElement &&

228 TII->isVectorOnly(MI) && VLIW5) {

229 isTransSlot = true;

231 dbgs() << "Considering as Trans Inst :";

232 MI.dump();

233 });

234 }

235 else

236 return false;

237 }

238 }

239

240

241 CurrentPacketMIs.push_back(&MI);

242 if (TII->fitsConstReadLimitations(CurrentPacketMIs)) {

244 dbgs() << "Couldn't pack :\n";

245 MI.dump();

246 dbgs() << "with the following packets :\n";

247 for (unsigned i = 0, e = CurrentPacketMIs.size() - 1; i < e; i++) {

248 CurrentPacketMIs[i]->dump();

249 dbgs() << "\n";

250 }

251 dbgs() << "because of Consts read limitations\n";

252 });

253 CurrentPacketMIs.pop_back();

254 return false;

255 }

256

257

258 if (TII->fitsReadPortLimitations(CurrentPacketMIs,

259 PV, BS, isTransSlot)) {

261 dbgs() << "Couldn't pack :\n";

262 MI.dump();

263 dbgs() << "with the following packets :\n";

264 for (unsigned i = 0, e = CurrentPacketMIs.size() - 1; i < e; i++) {

265 CurrentPacketMIs[i]->dump();

266 dbgs() << "\n";

267 }

268 dbgs() << "because of Read port limitations\n";

269 });

270 CurrentPacketMIs.pop_back();

271 return false;

272 }

273

274

275 if (isTransSlot && TII->readsLDSSrcReg(MI))

276 return false;

277

278 CurrentPacketMIs.pop_back();

279 return true;

280 }

281

284 CurrentPacketMIs.empty() ? &MI : CurrentPacketMIs.front();

286 getPreviousVector(FirstInBundle);

287 std::vectorR600InstrInfo::BankSwizzle BS;

288 bool isTransSlot;

289

290 if (isBundlableWithCurrentPMI(MI, PV, BS, isTransSlot)) {

291 for (unsigned i = 0, e = CurrentPacketMIs.size(); i < e; i++) {

293 unsigned Op = TII->getOperandIdx(MI->getOpcode(),

294 R600::OpName::bank_swizzle);

295 MI->getOperand(Op).setImm(BS[i]);

296 }

297 unsigned Op =

298 TII->getOperandIdx(MI.getOpcode(), R600::OpName::bank_swizzle);

299 MI.getOperand(Op).setImm(BS.back());

300 if (!CurrentPacketMIs.empty())

301 setIsLastBit(CurrentPacketMIs.back(), 0);

302 substitutePV(MI, PV);

304 if (isTransSlot) {

305 endPacket(std::next(It)->getParent(), std::next(It));

306 }

307 return It;

308 }

309 endPacket(MI.getParent(), MI);

310 if (TII->isTransOnly(MI))

311 return MI;

313 }

314};

315

316bool R600Packetizer::runOnMachineFunction(MachineFunction &Fn) {

319

320 MachineLoopInfo &MLI = getAnalysis().getLI();

321

323

324 if (II->Itineraries == nullptr)

325 return false;

326

327

328 R600PacketizerList Packetizer(Fn, ST, MLI);

329

330

331 assert(Packetizer.getResourceTracker() && "Empty DFA table!");

333

334 if (Packetizer.getResourceTracker()->getInstrItins()->isEmpty())

335 return false;

336

337

338

339

340

341

342

343

344

345

346

349 if (MI.isKill() || MI.getOpcode() == R600::IMPLICIT_DEF ||

350 (MI.getOpcode() == R600::CF_ALU && MI.getOperand(8).getImm()))

352 }

353 }

354

355

357 MBB != MBBe; ++MBB) {

358

359 unsigned RemainingCount = MBB->size();

361 RegionEnd != MBB->begin();) {

362

363

365 for(;I != MBB->begin(); --I, --RemainingCount) {

366 if (TII->isSchedulingBoundary(*std::prev(I), &*MBB, Fn))

367 break;

368 }

369 I = MBB->begin();

370

371

372 if (I == RegionEnd) {

373 RegionEnd = std::prev(RegionEnd);

374 --RemainingCount;

375 continue;

376 }

377

378 if (I == std::prev(RegionEnd)) {

379 RegionEnd = std::prev(RegionEnd);

380 continue;

381 }

382

384 RegionEnd = I;

385 }

386 }

387

388 return true;

389

390}

391

392}

393

395 "R600 Packetizer", false, false)

398

399char R600Packetizer::ID = 0;

400

402

404 return new R600Packetizer();

405}

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

const TargetInstrInfo & TII

static const Function * getParent(const Value *V)

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

Register const TargetRegisterInfo * TRI

Promote Memory to Register

uint64_t IntrinsicInst * II

#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)

#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)

Provides R600 specific target descriptions.

R600 Packetizer

Definition R600Packetizer.cpp:397

AMDGPU R600 specific subclass of TargetSubtarget.

Represent the analysis usage information of a pass.

AnalysisUsage & addRequired()

AnalysisUsage & addPreserved()

Add the specified Pass class to the set of analyses preserved by this pass.

LLVM_ABI void setPreservesCFG()

This function should be called by the pass, iff they do not:

iterator find(const_arg_type_t< KeyT > Val)

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

Itinerary data supplied by a subtarget to be used by a target.

Instructions::iterator instr_iterator

MachineInstrBundleIterator< MachineInstr > iterator

Analysis pass which computes a MachineDominatorTree.

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

void getAnalysisUsage(AnalysisUsage &AU) const override

getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.

const TargetSubtargetInfo & getSubtarget() const

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

BasicBlockListType::iterator iterator

Representation of each machine instruction.

unsigned getOpcode() const

Returns the opcode of this MachineInstr.

const MachineOperand & getOperand(unsigned i) const

Register getReg() const

getReg - Returns the register number.

Wrapper class representing virtual and physical registers.

Kind getKind() const

Returns an enum value representing the kind of the dependence.

@ Output

A register output-dependence (aka WAW).

@ Anti

A register anti-dependence (aka WAR).

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

bool isSucc(const SUnit *N) const

Tests if node N is a successor of this node.

SmallVector< SDep, 4 > Succs

All sunit successors.

MachineInstr * getInstr() const

Returns the representative MachineInstr for this SUnit.

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

virtual MachineBasicBlock::iterator addToPacket(MachineInstr &MI)

#define llvm_unreachable(msg)

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

unsigned ID

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

This is an optimization pass for GlobalISel generic memory operations.

char & R600PacketizerID

Definition R600Packetizer.cpp:401

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

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

FunctionPass * createR600Packetizer()

Definition R600Packetizer.cpp:403

LLVM_ABI raw_ostream & dbgs()

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

DWARFExpression::Operation Op