21#define DEBUG_TYPE "execution-deps-fix"
25class ExecutionDomainFixImpl {
33 std::vector<SmallVector<int, 1>> AliasMap;
36 using LiveRegsDVInfo = std::vector<DomainValue *>;
42 OutRegsInfoMap MBBOutRegsInfos;
81 void force(
int rx,
unsigned domain);
118 assert(
Reg < AliasMap.size() &&
"Invalid register");
123DomainValue *ExecutionDomainFixImpl::alloc(
int domain) {
124 DomainValue *dv = Avail.empty() ?
new (
Allocator.Allocate()) DomainValue
125 : Avail.pop_back_val();
128 assert(dv->
Refs == 0 &&
"Reference count wasn't cleared");
129 assert(!dv->
Next &&
"Chained DomainValue shouldn't have been recycled");
133void ExecutionDomainFixImpl::release(DomainValue *DV) {
151DomainValue *ExecutionDomainFixImpl::resolve(DomainValue *&DVRef) {
152 DomainValue *DV = DVRef;
153 if (!DV || !DV->
Next)
168void ExecutionDomainFixImpl::setLiveReg(
int rx, DomainValue *dv) {
170 assert(!LiveRegs.empty() &&
"Must enter basic block first.");
172 if (LiveRegs[rx] == dv)
176 LiveRegs[rx] = retain(dv);
179void ExecutionDomainFixImpl::kill(
int rx) {
181 assert(!LiveRegs.empty() &&
"Must enter basic block first.");
186 LiveRegs[rx] =
nullptr;
189void ExecutionDomainFixImpl::force(
int rx,
unsigned domain) {
191 assert(!LiveRegs.empty() &&
"Must enter basic block first.");
192 if (DomainValue *dv = LiveRegs[rx]) {
196 collapse(dv, domain);
201 assert(LiveRegs[rx] &&
"Not live after collapse?");
202 LiveRegs[rx]->addDomain(domain);
206 setLiveReg(rx, alloc(domain));
210void ExecutionDomainFixImpl::collapse(DomainValue *dv,
unsigned domain) {
219 if (!LiveRegs.empty() && dv->
Refs > 1)
220 for (
unsigned rx = 0; rx != RC->
getNumRegs(); ++rx)
221 if (LiveRegs[rx] == dv)
222 setLiveReg(rx, alloc(domain));
225bool ExecutionDomainFixImpl::merge(DomainValue *
A, DomainValue *
B) {
226 assert(!
A->isCollapsed() &&
"Cannot merge into collapsed");
227 assert(!
B->isCollapsed() &&
"Cannot merge from collapsed");
231 unsigned common =
A->getCommonDomains(
B->AvailableDomains);
234 A->AvailableDomains = common;
235 A->Instrs.append(
B->Instrs.begin(),
B->Instrs.end());
242 for (
unsigned rx = 0; rx != RC->
getNumRegs(); ++rx) {
243 assert(!LiveRegs.empty() &&
"no space allocated for live registers");
244 if (LiveRegs[rx] ==
B)
250void ExecutionDomainFixImpl::enterBasicBlock(
251 const LoopTraversal::TraversedMBBInfo &TraversedMBB) {
253 MachineBasicBlock *
MBB = TraversedMBB.
MBB;
257 if (LiveRegs.empty())
268 assert(
unsigned(pred->getNumber()) < MBBOutRegsInfos.
size() &&
269 "Should have pre-allocated MBBInfos for all MBBs");
270 LiveRegsDVInfo &Incoming = MBBOutRegsInfos[pred->getNumber()];
273 if (Incoming.empty())
276 for (
unsigned rx = 0; rx != RC->
getNumRegs(); ++rx) {
277 DomainValue *pdv = resolve(Incoming[rx]);
286 if (LiveRegs[rx]->isCollapsed()) {
288 unsigned Domain = LiveRegs[rx]->getFirstDomain();
296 merge(LiveRegs[rx], pdv);
302 << (!TraversedMBB.
IsDone ?
": incomplete\n"
303 :
": all preds known\n"));
306void ExecutionDomainFixImpl::leaveBasicBlock(
307 const LoopTraversal::TraversedMBBInfo &TraversedMBB) {
308 assert(!LiveRegs.empty() &&
"Must enter basic block first.");
311 "Unexpected basic block number.");
313 for (DomainValue *OldLiveReg : MBBOutRegsInfos[MBBNumber]) {
316 MBBOutRegsInfos[MBBNumber] = LiveRegs;
320bool ExecutionDomainFixImpl::visitInstr(MachineInstr *
MI) {
322 std::pair<uint16_t, uint16_t> DomP =
TII->getExecutionDomain(*
MI);
325 visitSoftInstr(
MI, DomP.second);
327 visitHardInstr(
MI, DomP.first);
333void ExecutionDomainFixImpl::processDefs(MachineInstr *
MI,
bool Kill) {
334 assert(!
MI->isDebugInstr() &&
"Won't process debug values");
335 const MCInstrDesc &MCID =
MI->getDesc();
339 MachineOperand &MO =
MI->getOperand(i);
344 for (
int rx : regIndices(MO.
getReg())) {
355void ExecutionDomainFixImpl::visitHardInstr(MachineInstr *mi,
unsigned domain) {
363 for (
int rx : regIndices(mo.
getReg())) {
373 for (
int rx : regIndices(mo.
getReg())) {
380void ExecutionDomainFixImpl::visitSoftInstr(MachineInstr *mi,
unsigned mask) {
386 SmallVector<int, 4>
used;
387 if (!LiveRegs.empty())
394 for (
int rx : regIndices(mo.
getReg())) {
395 DomainValue *dv = LiveRegs[rx];
420 TII->setExecutionDomain(*mi, domain);
421 visitHardInstr(mi, domain);
427 SmallVector<int, 4> Regs;
428 for (
int rx : used) {
429 assert(!LiveRegs.empty() &&
"no space allocated for live registers");
430 DomainValue *&LR = LiveRegs[rx];
447 DomainValue *dv =
nullptr;
448 while (!Regs.
empty()) {
459 if (Latest == dv || Latest->
Next)
461 if (
merge(dv, Latest))
466 assert(!LiveRegs.empty() &&
"no space allocated for live registers");
467 if (LiveRegs[i] == Latest)
481 for (
const MachineOperand &mo : mi->
operands()) {
484 for (
int rx : regIndices(mo.
getReg())) {
485 if (!LiveRegs[rx] || (mo.
isDef() && LiveRegs[rx] != dv)) {
493void ExecutionDomainFixImpl::processBasicBlock(
494 const LoopTraversal::TraversedMBBInfo &TraversedMBB) {
495 enterBasicBlock(TraversedMBB);
500 for (MachineInstr &
MI : *TraversedMBB.
MBB) {
501 if (!
MI.isDebugInstr()) {
508 leaveBasicBlock(TraversedMBB);
511bool ExecutionDomainFixImpl::runOnMachineFunction(
516 RC =
TRI->getRegClassToMinimizeDomainCrossings();
518 "getRegClassToMinimizeDomainCrossings in TRI must be implemented for "
519 "targets using ExecutionDomainFix");
523 <<
TRI->getRegClassName(RC) <<
" **********\n");
527 bool anyregs =
false;
529 for (
unsigned Reg : *RC) {
541 if (AliasMap.empty()) {
544 AliasMap.resize(
TRI->getNumRegs());
545 for (
unsigned i = 0, e = RC->getNumRegs(); i != e; ++i)
546 for (MCRegAliasIterator AI(RC->getRegister(i),
TRI,
true); AI.isValid();
548 AliasMap[(*AI).id()].push_back(i);
555 LoopTraversal Traversal;
557 for (
const LoopTraversal::TraversedMBBInfo &TraversedMBB : TraversedMBBOrder)
560 for (
const LiveRegsDVInfo &OutLiveRegs : MBBOutRegsInfos)
561 for (DomainValue *OutLiveReg : OutLiveRegs)
565 MBBOutRegsInfos.clear();
574 "execution-domain-fix",
false,
false)
586 ExecutionDomainFixImpl Impl;
587 return Impl.runOnMachineFunction(MF, [&]() {
596 ExecutionDomainFixImpl Impl;
597 bool Changed = Impl.runOnMachineFunction(
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static constexpr unsigned long long mask(BlockVerifier::State S)
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
const HexagonInstrInfo * TII
static LoopDeletionResult merge(LoopDeletionResult A, LoopDeletionResult B)
return !LiveInRegUnits available(Reg)
Register const TargetRegisterInfo * TRI
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
MachineRegisterInfo & MRI
static bool processBasicBlock(MachineBasicBlock &MBB, BlockStateMap &BlockStates, DirtySuccessorsWorkList &DirtySuccessors, bool IsX86INTR, const TargetInstrInfo *TII)
Loop over all of the instructions in the basic block, inserting vzeroupper instructions before functi...
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represents analyses that only rely on functions' control flow.
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
LLVM_ABI PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
FunctionPass class - This class is used to implement most global optimizations.
bool skipFunction(const Function &F) const
Optional passes call this function to check whether the pass should be skipped.
LLVM_ABI TraversalOrder traverse(MachineFunction &MF)
SmallVector< TraversedMBBInfo, 4 > TraversalOrder
Identifies basic blocks that are part of loops and should to be visited twice and returns efficient t...
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
MCRegister getRegister(unsigned i) const
getRegister - Return the specified register in the class.
unsigned getNumRegs() const
getNumRegs - Return the number of registers in this class.
Wrapper class representing physical registers. Should be passed by value.
An RAII based helper class to modify MachineFunctionProperties when running pass.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
iterator_range< pred_iterator > predecessors()
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
unsigned getNumBlockIDs() const
getNumBlockIDs - Return the number of MBB ID's allocated.
Representation of each machine instruction.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Register getReg() const
getReg - Returns the register number.
LLVM_ABI bool isPhysRegUsed(MCRegister PhysReg, bool SkipRegMaskTest=false) const
Return true if the specified register is modified or read in this function.
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
This class provides the reaching def analysis.
LLVM_ABI int getReachingDef(MachineInstr *MI, Register Reg) const
Provides the instruction id of the closest reaching def instruction of Reg that reaches MI,...
constexpr unsigned id() const
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
A BumpPtrAllocator that allows only elements of a specific type to be allocated.
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
An efficient, type-erasing, non-owning reference to a callable.
A range adaptor for a pair of iterators.
Pass manager infrastructure for declaring and invalidating analyses.
bool used(const UsedT *U, size_t I)
NodeAddr< DefNode * > Def
This is an optimization pass for GlobalISel generic memory operations.
@ Kill
The last use of a register.
LLVM_ABI FunctionPass * createExecutionDomainFixLegacyPass()
Minimizes execution domain crossings for specific register classes.
auto partition_point(R &&Range, Predicate P)
Binary search for the first iterator in a range where a predicate is false.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
MCRegisterClass TargetRegisterClass
A DomainValue is a bit like LiveIntervals' ValNo, but it also keeps track of execution domains.
unsigned getCommonDomains(unsigned mask) const
Return bitmask of domains that are available and in mask.
void clear()
Clear this DomainValue and point to next which has all its data.
SmallVector< MachineInstr *, 8 > Instrs
Twiddleable instructions using or defining these registers.
void setSingleDomain(unsigned domain)
bool isCollapsed() const
A collapsed DomainValue has no instructions to twiddle - it simply keeps track of the domains where t...
DomainValue * Next
Pointer to the next DomainValue in a chain.
void addDomain(unsigned domain)
Mark domain as available.
unsigned AvailableDomains
Bitmask of available domains.
unsigned Refs
Basic reference counting.
unsigned getFirstDomain() const
First domain available.
bool hasDomain(unsigned domain) const
Is domain available?
MachineBasicBlock * MBB
The basic block.
bool IsDone
True if the block that is ready for its final round of processing.
bool PrimaryPass
True if this is the first time we process the basic block.