40#define DEBUG_TYPE "riscv-insert-write-vxrm"
41#define RISCV_INSERT_WRITE_VXRM_NAME "RISC-V Insert Write VXRM Pass"
57 static VXRMInfo getUnknown() {
64 void setUnknown() { State =
Unknown; }
65 bool isUnknown()
const {
return State ==
Unknown; }
67 bool isStatic()
const {
return State == Static; }
69 void setVXRMImm(
unsigned Imm) {
70 assert(
Imm <= 3 &&
"Unexpected VXRM value");
74 unsigned getVXRMImm()
const {
75 assert(isStatic() && VXRMImm <= 3 &&
"Unexpected state");
81 if (State !=
Other.State)
85 return VXRMImm ==
Other.VXRMImm;
105 if (isUnknown() ||
Other.isUnknown())
106 return VXRMInfo::getUnknown();
113 return VXRMInfo::getUnknown();
122 VXRMInfo intersectAnticipated(
const VXRMInfo &
Other)
const {
124 if (!
Other.isValid())
134 if (
Other.isUnknown())
142 return VXRMInfo::getUnknown();
145#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
155 OS <<
"Uninitialized";
156 else if (isUnknown())
165#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
181 VXRMInfo AvailableIn;
184 VXRMInfo AvailableOut;
187 VXRMInfo AnticipatedIn;
190 VXRMInfo AnticipatedOut;
198class RISCVInsertWriteVXRMImpl {
202 std::vector<BlockData> BlockInfo;
203 std::queue<const MachineBasicBlock *> WorkList;
237char RISCVInsertWriteVXRMLegacy::ID = 0;
242bool RISCVInsertWriteVXRMImpl::computeVXRMChanges(
246 bool NeedVXRMWrite =
false;
249 if (VXRMIdx >= 0 && !RISCVInstrInfo::ignoresVXRM(
MI)) {
250 unsigned NewVXRMImm =
MI.getOperand(VXRMIdx).getImm();
252 if (!BBInfo.VXRMUse.isValid())
253 BBInfo.VXRMUse.setVXRMImm(NewVXRMImm);
255 BBInfo.VXRMOut.setVXRMImm(NewVXRMImm);
256 NeedVXRMWrite =
true;
260 if (
MI.isCall() ||
MI.isInlineAsm() ||
261 MI.modifiesRegister(RISCV::VXRM,
nullptr)) {
262 if (!BBInfo.VXRMUse.isValid())
263 BBInfo.VXRMUse.setUnknown();
265 BBInfo.VXRMOut.setUnknown();
269 return NeedVXRMWrite;
275 BBInfo.InQueue =
false;
292 <<
" changed to " << BBInfo.AvailableIn <<
"\n");
295 if (BBInfo.VXRMOut.isValid())
303 <<
" changed to " << BBInfo.AvailableOut <<
"\n");
307 if (!BlockInfo[S->getNumber()].InQueue) {
308 BlockInfo[S->getNumber()].InQueue =
true;
314void RISCVInsertWriteVXRMImpl::computeAnticipated(
319 BBInfo.InQueue =
false;
321 VXRMInfo Anticipated;
323 Anticipated.setUnknown();
334 Anticipated.intersectAnticipated(BlockInfo[S->getNumber()].AnticipatedIn);
337 Anticipated.intersect(BlockInfo[S->getNumber()].AnticipatedIn);
341 if (!Anticipated.isValid())
344 if (Anticipated != BBInfo.AnticipatedOut) {
345 BBInfo.AnticipatedOut = Anticipated;
347 <<
" changed to " << BBInfo.AnticipatedOut <<
"\n");
351 if (BBInfo.VXRMUse.isValid())
352 Anticipated = BBInfo.VXRMUse;
354 if (Anticipated == BBInfo.AnticipatedIn)
357 BBInfo.AnticipatedIn = Anticipated;
359 <<
" changed to " << BBInfo.AnticipatedIn <<
"\n");
363 if (!BlockInfo[
P->getNumber()].InQueue) {
364 BlockInfo[
P->getNumber()].InQueue =
true;
370void RISCVInsertWriteVXRMImpl::emitWriteVXRM(MachineBasicBlock &
MBB) {
373 VXRMInfo
Info = BBInfo.AvailableIn;
377 bool PendingInsert =
false;
380 if (BBInfo.AnticipatedIn.isStatic()) {
383 PendingInsert =
true;
391 const BlockData &PInfo = BlockInfo[
P->getNumber()];
393 if (PInfo.AvailableOut.isStatic() &&
394 PInfo.AvailableOut.getVXRMImm() ==
395 BBInfo.AnticipatedIn.getVXRMImm())
400 if (PInfo.AnticipatedOut.isStatic() &&
401 PInfo.AnticipatedOut.getVXRMImm() ==
402 BBInfo.AnticipatedIn.getVXRMImm())
404 PendingInsert =
true;
409 Info = BBInfo.AnticipatedIn;
412 for (MachineInstr &
MI :
MBB) {
414 if (VXRMIdx >= 0 && !RISCVInstrInfo::ignoresVXRM(
MI)) {
415 unsigned NewVXRMImm =
MI.getOperand(VXRMIdx).getImm();
417 if (PendingInsert || !
Info.isStatic() ||
418 Info.getVXRMImm() != NewVXRMImm) {
420 (
Info.isStatic() &&
Info.getVXRMImm() == NewVXRMImm)) &&
421 "Pending VXRM insertion mismatch");
425 PendingInsert =
false;
430 Info.setVXRMImm(NewVXRMImm);
434 if (
MI.isCall() ||
MI.isInlineAsm() ||
435 MI.modifiesRegister(RISCV::VXRM,
nullptr))
445 (BBInfo.AnticipatedOut.isStatic() &&
447 Info.getVXRMImm() != BBInfo.AnticipatedOut.getVXRMImm()))) {
449 (
Info.isStatic() && BBInfo.AnticipatedOut.isStatic() &&
450 Info.getVXRMImm() == BBInfo.AnticipatedOut.getVXRMImm())) &&
451 "Pending VXRM insertion mismatch");
453 <<
" changing to " << BBInfo.AnticipatedOut <<
"\n");
455 TII->get(RISCV::WriteVXRMImm))
456 .
addImm(BBInfo.AnticipatedOut.getVXRMImm());
460bool RISCVInsertWriteVXRMImpl::runOnMachineFunction(
464 if (!
ST.hasVInstructions())
467 TII =
ST.getInstrInfo();
472 assert(BlockInfo.empty() &&
"Expect empty block infos");
476 bool NeedVXRMChange =
false;
477 for (
const MachineBasicBlock &
MBB : MF)
478 NeedVXRMChange |= computeVXRMChanges(
MBB);
480 if (!NeedVXRMChange) {
486 for (
const MachineBasicBlock &
MBB : MF) {
490 while (!WorkList.empty()) {
491 const MachineBasicBlock &
MBB = *WorkList.front();
493 computeAvailable(
MBB);
501 while (!WorkList.empty()) {
502 const MachineBasicBlock &
MBB = *WorkList.front();
504 computeAnticipated(MF,
MBB);
508 for (MachineBasicBlock &
MBB : MF)
517 return new RISCVInsertWriteVXRMLegacy();
520bool RISCVInsertWriteVXRMLegacy::runOnMachineFunction(
MachineFunction &MF) {
521 RISCVInsertWriteVXRMImpl Impl;
522 return Impl.runOnMachineFunction(MF, [&]() {
523 auto *MLIWrapper = getAnalysisIfAvailable<MachineLoopInfoWrapperPass>();
524 return MLIWrapper ? &MLIWrapper->getLI() :
nullptr;
531 RISCVInsertWriteVXRMImpl Impl;
532 bool Changed = Impl.runOnMachineFunction(
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#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.
const HexagonInstrInfo * TII
static Interval intersect(const Interval &I1, const Interval &I2)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
#define RISCV_INSERT_WRITE_VXRM_NAME
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addUsedIfAvailable()
Add the specified Pass class to the set of analyses used by this pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Represents analyses that only rely on functions' control flow.
FunctionPass class - This class is used to implement most global optimizations.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
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.
Analysis pass that exposes the MachineLoopInfo for a machine function.
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)
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
Represent a constant reference to a string, i.e.
TargetInstrInfo - Interface to description of machine instruction set.
An efficient, type-erasing, non-owning reference to a callable.
This class implements an extremely fast bulk output stream that can only output to a stream.
Pass manager infrastructure for declaring and invalidating analyses.
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.
@ Unknown
Not known to have no common set bits.
bool operator!=(uint64_t V1, const APInt &V2)
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
auto reverse(ContainerTy &&C)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createRISCVInsertWriteVXRMLegacyPass()
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.