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 (->isALUInstr(I->getOpcode()) &&
->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 {
162 return true;
163 if (->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 ->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 (->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 (->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);
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 && .getOperand(8).getImm()))
352 }
353 }
354
355
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 }
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