LLVM: lib/Target/RISCV/RISCVInsertWriteVXRM.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
32#include
33
34using namespace llvm;
35
36#define DEBUG_TYPE "riscv-insert-write-vxrm"
37#define RISCV_INSERT_WRITE_VXRM_NAME "RISC-V Insert Write VXRM Pass"
38
39namespace {
40
41class VXRMInfo {
43
46 Static,
49
50public:
51 VXRMInfo() = default;
52
53 static VXRMInfo getUnknown() {
54 VXRMInfo Info;
55 Info.setUnknown();
57 }
58
60 void setUnknown() { State = Unknown; }
61 bool isUnknown() const { return State == Unknown; }
62
63 bool isStatic() const { return State == Static; }
64
65 void setVXRMImm(unsigned Imm) {
66 assert(Imm <= 3 && "Unexpected VXRM value");
67 VXRMImm = Imm;
68 State = Static;
69 }
70 unsigned getVXRMImm() const {
71 assert(isStatic() && VXRMImm <= 3 && "Unexpected state");
72 return VXRMImm;
73 }
74
76
77 if (State != Other.State)
78 return false;
79
80 if (isStatic())
81 return VXRMImm == Other.VXRMImm;
82
83 assert((isValid() || isUnknown()) && "Unexpected state");
84 return true;
85 }
86
88
89
90
92
93 if (.isValid())
94 return *this;
95
96
99
100
101 if (isUnknown() || Other.isUnknown())
102 return VXRMInfo::getUnknown();
103
104
105 if (*this == Other)
106 return *this;
107
108
109 return VXRMInfo::getUnknown();
110 }
111
112
113
114
115
116
117
118 VXRMInfo intersectAnticipated(const VXRMInfo &Other) const {
119
120 if (.isValid())
121 return *this;
122
123
126
127
128 if (isUnknown())
130 if (Other.isUnknown())
131 return *this;
132
133
134 if (*this == Other)
135 return *this;
136
137
138 return VXRMInfo::getUnknown();
139 }
140
141#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
142
145 dbgs() << "\n";
146 }
147
149 OS << '{';
151 OS << "Uninitialized";
152 else if (isUnknown())
153 OS << "Unknown";
154 else
155 OS << getVXRMImm();
156 OS << '}';
157 }
158#endif
159};
160
161#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
164 V.print(OS);
165 return OS;
166}
167#endif
168
170
171 VXRMInfo VXRMUse;
172
173
174 VXRMInfo VXRMOut;
175
176
177 VXRMInfo AvailableIn;
178
179
180 VXRMInfo AvailableOut;
181
182
183 VXRMInfo AnticipatedIn;
184
185
186 VXRMInfo AnticipatedOut;
187
188
189 bool InQueue;
190
192};
193
196
197 std::vector BlockInfo;
198 std::queue<const MachineBasicBlock *> WorkList;
199
200public:
201 static char ID;
202
204
206
207 void getAnalysisUsage(AnalysisUsage &AU) const override {
210 }
211
212 StringRef getPassName() const override {
214 }
215
216private:
221};
222
223}
224
225char RISCVInsertWriteVXRM::ID = 0;
226
228 false, false)
229
231 BlockData &BBInfo = BlockInfo[MBB.getNumber()];
232
233 bool NeedVXRMWrite = false;
236 if (VXRMIdx >= 0 && !RISCVInstrInfo::ignoresVXRM(MI)) {
237 unsigned NewVXRMImm = MI.getOperand(VXRMIdx).getImm();
238
239 if (!BBInfo.VXRMUse.isValid())
240 BBInfo.VXRMUse.setVXRMImm(NewVXRMImm);
241
242 BBInfo.VXRMOut.setVXRMImm(NewVXRMImm);
243 NeedVXRMWrite = true;
244 continue;
245 }
246
247 if (MI.isCall() || MI.isInlineAsm() ||
248 MI.modifiesRegister(RISCV::VXRM, nullptr)) {
249 if (!BBInfo.VXRMUse.isValid())
250 BBInfo.VXRMUse.setUnknown();
251
252 BBInfo.VXRMOut.setUnknown();
253 }
254 }
255
256 return NeedVXRMWrite;
257}
258
260 BlockData &BBInfo = BlockInfo[MBB.getNumber()];
261
262 BBInfo.InQueue = false;
263
267 } else {
270 }
271
272
274 return;
275
276 if (Available != BBInfo.AvailableIn) {
279 << " changed to " << BBInfo.AvailableIn << "\n");
280 }
281
282 if (BBInfo.VXRMOut.isValid())
284
285 if (Available == BBInfo.AvailableOut)
286 return;
287
290 << " changed to " << BBInfo.AvailableOut << "\n");
291
292
294 if (!BlockInfo[S->getNumber()].InQueue) {
295 BlockInfo[S->getNumber()].InQueue = true;
296 WorkList.push(S);
297 }
298 }
299}
300
301void RISCVInsertWriteVXRM::computeAnticipated(const MachineFunction &MF, const MachineBasicBlock &MBB) {
302 BlockData &BBInfo = BlockInfo[MBB.getNumber()];
303 const RISCVSubtarget &ST = MF.getSubtarget();
304
305 BBInfo.InQueue = false;
306
307 VXRMInfo Anticipated;
309 Anticipated.setUnknown();
310 } else {
311 for (const MachineBasicBlock *S : MBB.successors())
312 if (ST.hasVXRMPipelineFlush())
313 Anticipated =
314 Anticipated.intersectAnticipated(BlockInfo[S->getNumber()].AnticipatedIn);
315 else
316 Anticipated =
317 Anticipated.intersect(BlockInfo[S->getNumber()].AnticipatedIn);
318 }
319
320
321 if (!Anticipated.isValid())
322 return;
323
324 if (Anticipated != BBInfo.AnticipatedOut) {
325 BBInfo.AnticipatedOut = Anticipated;
327 << " changed to " << BBInfo.AnticipatedOut << "\n");
328 }
329
330
331 if (BBInfo.VXRMUse.isValid())
332 Anticipated = BBInfo.VXRMUse;
333
334 if (Anticipated == BBInfo.AnticipatedIn)
335 return;
336
337 BBInfo.AnticipatedIn = Anticipated;
339 << " changed to " << BBInfo.AnticipatedIn << "\n");
340
341
343 if (!BlockInfo[P->getNumber()].InQueue) {
344 BlockInfo[P->getNumber()].InQueue = true;
345 WorkList.push(P);
346 }
347 }
348}
349
350void RISCVInsertWriteVXRM::emitWriteVXRM(MachineBasicBlock &MBB) {
351 const BlockData &BBInfo = BlockInfo[MBB.getNumber()];
352
353 VXRMInfo Info = BBInfo.AvailableIn;
354
355
356
357 bool PendingInsert = false;
358
359
360 if (BBInfo.AnticipatedIn.isStatic()) {
361
363 PendingInsert = true;
364 } else {
365
366
367
368
369
371 const BlockData &PInfo = BlockInfo[P->getNumber()];
372
373 if (PInfo.AvailableOut.isStatic() &&
374 PInfo.AvailableOut.getVXRMImm() ==
375 BBInfo.AnticipatedIn.getVXRMImm())
376 continue;
377
378
379
380 if (PInfo.AnticipatedOut.isStatic() &&
381 PInfo.AnticipatedOut.getVXRMImm() ==
382 BBInfo.AnticipatedIn.getVXRMImm())
383 continue;
384 PendingInsert = true;
385 break;
386 }
387 }
388
389 Info = BBInfo.AnticipatedIn;
390 }
391
392 for (MachineInstr &MI : MBB) {
394 if (VXRMIdx >= 0 && !RISCVInstrInfo::ignoresVXRM(MI)) {
395 unsigned NewVXRMImm = MI.getOperand(VXRMIdx).getImm();
396
397 if (PendingInsert || .isStatic() ||
398 Info.getVXRMImm() != NewVXRMImm) {
399 assert((!PendingInsert ||
400 (Info.isStatic() && Info.getVXRMImm() == NewVXRMImm)) &&
401 "Pending VXRM insertion mismatch");
405 PendingInsert = false;
406 }
407
409 true));
410 Info.setVXRMImm(NewVXRMImm);
411 continue;
412 }
413
414 if (MI.isCall() || MI.isInlineAsm() ||
415 MI.modifiesRegister(RISCV::VXRM, nullptr))
416 Info.setUnknown();
417 }
418
419
420
421
422
423
424 if (PendingInsert ||
425 (BBInfo.AnticipatedOut.isStatic() &&
426 (.isStatic() ||
427 Info.getVXRMImm() != BBInfo.AnticipatedOut.getVXRMImm()))) {
428 assert((!PendingInsert ||
429 (Info.isStatic() && BBInfo.AnticipatedOut.isStatic() &&
430 Info.getVXRMImm() == BBInfo.AnticipatedOut.getVXRMImm())) &&
431 "Pending VXRM insertion mismatch");
433 << " changing to " << BBInfo.AnticipatedOut << "\n");
435 TII->get(RISCV::WriteVXRMImm))
436 .addImm(BBInfo.AnticipatedOut.getVXRMImm());
437 }
438}
439
440bool RISCVInsertWriteVXRM::runOnMachineFunction(MachineFunction &MF) {
441
442 const RISCVSubtarget &ST = MF.getSubtarget();
443 if (.hasVInstructions())
444 return false;
445
447
448 assert(BlockInfo.empty() && "Expect empty block infos");
450
451
452 bool NeedVXRMChange = false;
453 for (const MachineBasicBlock &MBB : MF)
454 NeedVXRMChange |= computeVXRMChanges(MBB);
455
456 if (!NeedVXRMChange) {
457 BlockInfo.clear();
458 return false;
459 }
460
461
462 for (const MachineBasicBlock &MBB : MF) {
463 WorkList.push(&MBB);
465 }
466 while (!WorkList.empty()) {
467 const MachineBasicBlock &MBB = *WorkList.front();
468 WorkList.pop();
469 computeAvailable(MBB);
470 }
471
472
474 WorkList.push(&MBB);
476 }
477 while (!WorkList.empty()) {
478 const MachineBasicBlock &MBB = *WorkList.front();
479 WorkList.pop();
480 computeAnticipated(MF, MBB);
481 }
482
483
484 for (MachineBasicBlock &MBB : MF)
485 emitWriteVXRM(MBB);
486
487 BlockInfo.clear();
488
489 return true;
490}
491
493 return new RISCVInsertWriteVXRM();
494}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
const TargetInstrInfo & TII
Analysis containing CSE Info
#define LLVM_ATTRIBUTE_USED
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
@ Available
We know the block is fully available. This is a fixpoint.
static Interval intersect(const Interval &I1, const Interval &I2)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
#define RISCV_INSERT_WRITE_VXRM_NAME
Definition RISCVInsertWriteVXRM.cpp:37
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
Represent the analysis usage information of a pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
FunctionPass class - This class is used to implement most global optimizations.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI bool isEntryBlock() const
Returns true if this is the entry block of the function.
iterator_range< succ_iterator > successors()
iterator_range< pred_iterator > predecessors()
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.
unsigned getNumBlockIDs() const
getNumBlockIDs - Return the number of MBB ID's allocated.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
Representation of each machine instruction.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
virtual void print(raw_ostream &OS, const Module *M) const
print - Print out the internal state of the pass.
StringRef - Represent a constant reference to a string, i.e.
TargetInstrInfo - Interface to description of machine instruction set.
This class implements an extremely fast bulk output stream that can only output to a stream.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
static int getVXRMOpNum(const MCInstrDesc &Desc)
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool operator!=(uint64_t V1, const APInt &V2)
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
auto reverse(ContainerTy &&C)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
FunctionPass * createRISCVInsertWriteVXRMPass()
Definition RISCVInsertWriteVXRM.cpp:492
LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.